More CPP removal: pprDynamicLinkerAsmLabel in CLabel
[ghc.git] / compiler / cmm / OldCmm.hs
1 -----------------------------------------------------------------------------
2 --
3 -- Old-style Cmm data types
4 --
5 -- (c) The University of Glasgow 2004-2006
6 --
7 -----------------------------------------------------------------------------
8
9 module OldCmm (
10 CmmGroup, GenCmmGroup, RawCmmGroup, CmmDecl, RawCmmDecl,
11 ListGraph(..),
12 CmmInfo(..), UpdateFrame(..), CmmInfoTable(..), ClosureTypeInfo(..),
13 CmmStatic(..), CmmStatics(..), CmmFormal, CmmActual,
14 cmmMapGraph, cmmTopMapGraph,
15 GenBasicBlock(..), CmmBasicBlock, blockId, blockStmts, mapBlockStmts,
16 CmmStmt(..), CmmReturnInfo(..), CmmHinted(..),
17 HintedCmmFormal, HintedCmmActual,
18 CmmSafety(..), CmmCallTarget(..),
19 New.GenCmmDecl(..),
20 New.ForeignHint(..),
21 module CmmExpr,
22 Section(..),
23 ProfilingInfo(..), C_SRT(..)
24 ) where
25
26 #include "HsVersions.h"
27
28 import qualified Cmm as New
29 import Cmm ( CmmInfoTable(..), GenCmmGroup, CmmStatics(..), GenCmmDecl(..),
30 CmmFormal, CmmActual, Section(..), CmmStatic(..),
31 ProfilingInfo(..), ClosureTypeInfo(..) )
32
33 import BlockId
34 import CmmExpr
35 import ForeignCall
36 import ClosureInfo
37 import FastString
38
39
40 -- A [[BlockId]] is a local label.
41 -- Local labels must be unique within an entire compilation unit, not
42 -- just a single top-level item, because local labels map one-to-one
43 -- with assembly-language labels.
44
45 -----------------------------------------------------------------------------
46 -- Info Tables
47 -----------------------------------------------------------------------------
48
49 data CmmInfo
50 = CmmInfo
51 (Maybe BlockId) -- GC target. Nothing <=> CPS won't do stack check
52 -- JD: NOT USED BY NEW CODE GEN
53 (Maybe UpdateFrame) -- Update frame
54 CmmInfoTable -- Info table
55
56 -- | A frame that is to be pushed before entry to the function.
57 -- Used to handle 'update' frames.
58 data UpdateFrame =
59 UpdateFrame
60 CmmExpr -- Frame header. Behaves like the target of a 'jump'.
61 [CmmExpr] -- Frame remainder. Behaves like the arguments of a 'jump'.
62
63 -----------------------------------------------------------------------------
64 -- Cmm, CmmDecl, CmmBasicBlock
65 -----------------------------------------------------------------------------
66
67 -- A file is a list of top-level chunks. These may be arbitrarily
68 -- re-orderd during code generation.
69
70 -- | A control-flow graph represented as a list of extended basic blocks.
71 newtype ListGraph i = ListGraph [GenBasicBlock i]
72 -- ^ Code, may be empty. The first block is the entry point. The
73 -- order is otherwise initially unimportant, but at some point the
74 -- code gen will fix the order.
75
76 -- BlockIds must be unique across an entire compilation unit, since
77 -- they are translated to assembly-language labels, which scope
78 -- across a whole compilation unit.
79
80 -- | Cmm with the info table as a data type
81 type CmmGroup = GenCmmGroup CmmStatics CmmInfo (ListGraph CmmStmt)
82 type CmmDecl = GenCmmDecl CmmStatics CmmInfo (ListGraph CmmStmt)
83
84 -- | Cmm with the info tables converted to a list of 'CmmStatic' along with the info
85 -- table label. If we are building without tables-next-to-code there will be no statics
86 --
87 -- INVARIANT: if there is an info table, it has at least one CmmStatic
88 type RawCmmGroup = GenCmmGroup CmmStatics (Maybe CmmStatics) (ListGraph CmmStmt)
89 type RawCmmDecl = GenCmmDecl CmmStatics (Maybe CmmStatics) (ListGraph CmmStmt)
90
91
92 -- A basic block containing a single label, at the beginning.
93 -- The list of basic blocks in a top-level code block may be re-ordered.
94 -- Fall-through is not allowed: there must be an explicit jump at the
95 -- end of each basic block, but the code generator might rearrange basic
96 -- blocks in order to turn some jumps into fallthroughs.
97
98 data GenBasicBlock i = BasicBlock BlockId [i]
99 type CmmBasicBlock = GenBasicBlock CmmStmt
100
101 instance UserOfLocalRegs i => UserOfLocalRegs (GenBasicBlock i) where
102 foldRegsUsed f set (BasicBlock _ l) = foldRegsUsed f set l
103
104 blockId :: GenBasicBlock i -> BlockId
105 -- The branch block id is that of the first block in
106 -- the branch, which is that branch's entry point
107 blockId (BasicBlock blk_id _ ) = blk_id
108
109 blockStmts :: GenBasicBlock i -> [i]
110 blockStmts (BasicBlock _ stmts) = stmts
111
112
113 mapBlockStmts :: (i -> i') -> GenBasicBlock i -> GenBasicBlock i'
114 mapBlockStmts f (BasicBlock id bs) = BasicBlock id (map f bs)
115 ----------------------------------------------------------------
116 -- graph maps
117 ----------------------------------------------------------------
118
119 cmmMapGraph :: (g -> g') -> GenCmmGroup d h g -> GenCmmGroup d h g'
120 cmmTopMapGraph :: (g -> g') -> GenCmmDecl d h g -> GenCmmDecl d h g'
121
122 cmmMapGraph f tops = map (cmmTopMapGraph f) tops
123 cmmTopMapGraph f (CmmProc h l g) = CmmProc h l (f g)
124 cmmTopMapGraph _ (CmmData s ds) = CmmData s ds
125
126 data CmmReturnInfo = CmmMayReturn
127 | CmmNeverReturns
128 deriving ( Eq )
129
130 -----------------------------------------------------------------------------
131 -- CmmStmt
132 -- A "statement". Note that all branches are explicit: there are no
133 -- control transfers to computed addresses, except when transfering
134 -- control to a new function.
135 -----------------------------------------------------------------------------
136
137 data CmmStmt -- Old-style
138 = CmmNop
139 | CmmComment FastString
140
141 | CmmAssign CmmReg CmmExpr -- Assign to register
142
143 | CmmStore CmmExpr CmmExpr -- Assign to memory location. Size is
144 -- given by cmmExprType of the rhs.
145
146 | CmmCall -- A call (foreign, native or primitive), with
147 CmmCallTarget
148 [HintedCmmFormal] -- zero or more results
149 [HintedCmmActual] -- zero or more arguments
150 CmmSafety -- whether to build a continuation
151 CmmReturnInfo
152 -- Some care is necessary when handling the arguments of these, see
153 -- [Register parameter passing] and the hack in cmm/CmmOpt.hs
154
155 | CmmBranch BlockId -- branch to another BB in this fn
156
157 | CmmCondBranch CmmExpr BlockId -- conditional branch
158
159 | CmmSwitch CmmExpr [Maybe BlockId] -- Table branch
160 -- The scrutinee is zero-based;
161 -- zero -> first block
162 -- one -> second block etc
163 -- Undefined outside range, and when there's a Nothing
164
165 | CmmJump CmmExpr -- Jump to another C-- function,
166 [HintedCmmActual] -- with these parameters. (parameters never used)
167
168 | CmmReturn -- Return from a native C-- function,
169 [HintedCmmActual] -- with these return values. (parameters never used)
170
171 data CmmHinted a = CmmHinted { hintlessCmm :: a, cmmHint :: New.ForeignHint }
172 deriving( Eq )
173
174 type HintedCmmFormal = CmmHinted CmmFormal
175 type HintedCmmActual = CmmHinted CmmActual
176
177 data CmmSafety = CmmUnsafe | CmmSafe C_SRT | CmmInterruptible
178
179 -- | enable us to fold used registers over '[CmmActual]' and '[CmmFormal]'
180 instance UserOfLocalRegs CmmStmt where
181 foldRegsUsed f (set::b) s = stmt s set
182 where
183 stmt :: CmmStmt -> b -> b
184 stmt (CmmNop) = id
185 stmt (CmmComment {}) = id
186 stmt (CmmAssign _ e) = gen e
187 stmt (CmmStore e1 e2) = gen e1 . gen e2
188 stmt (CmmCall target _ es _ _) = gen target . gen es
189 stmt (CmmBranch _) = id
190 stmt (CmmCondBranch e _) = gen e
191 stmt (CmmSwitch e _) = gen e
192 stmt (CmmJump e es) = gen e . gen es
193 stmt (CmmReturn es) = gen es
194
195 gen :: UserOfLocalRegs a => a -> b -> b
196 gen a set = foldRegsUsed f set a
197
198 instance UserOfLocalRegs CmmCallTarget where
199 foldRegsUsed f set (CmmCallee e _) = foldRegsUsed f set e
200 foldRegsUsed _ set (CmmPrim {}) = set
201
202 instance UserOfSlots CmmCallTarget where
203 foldSlotsUsed f set (CmmCallee e _) = foldSlotsUsed f set e
204 foldSlotsUsed _ set (CmmPrim {}) = set
205
206 instance UserOfLocalRegs a => UserOfLocalRegs (CmmHinted a) where
207 foldRegsUsed f set a = foldRegsUsed f set (hintlessCmm a)
208
209 instance UserOfSlots a => UserOfSlots (CmmHinted a) where
210 foldSlotsUsed f set a = foldSlotsUsed f set (hintlessCmm a)
211
212 instance DefinerOfLocalRegs a => DefinerOfLocalRegs (CmmHinted a) where
213 foldRegsDefd f set a = foldRegsDefd f set (hintlessCmm a)
214
215 {-
216 Discussion
217 ~~~~~~~~~~
218
219 One possible problem with the above type is that the only way to do a
220 non-local conditional jump is to encode it as a branch to a block that
221 contains a single jump. This leads to inefficient code in the back end.
222
223 [N.B. This problem will go away when we make the transition to the
224 'zipper' form of control-flow graph, in which both targets of a
225 conditional jump are explicit. ---NR]
226
227 One possible way to fix this would be:
228
229 data CmmStat =
230 ...
231 | CmmJump CmmBranchDest
232 | CmmCondJump CmmExpr CmmBranchDest
233 ...
234
235 data CmmBranchDest
236 = Local BlockId
237 | NonLocal CmmExpr [LocalReg]
238
239 In favour:
240
241 + one fewer constructors in CmmStmt
242 + allows both cond branch and switch to jump to non-local destinations
243
244 Against:
245
246 - not strictly necessary: can already encode as branch+jump
247 - not always possible to implement any better in the back end
248 - could do the optimisation in the back end (but then plat-specific?)
249 - C-- doesn't have it
250 - back-end optimisation might be more general (jump shortcutting)
251
252 So we'll stick with the way it is, and add the optimisation to the NCG.
253 -}
254
255 -----------------------------------------------------------------------------
256 -- CmmCallTarget
257 --
258 -- The target of a CmmCall.
259 -----------------------------------------------------------------------------
260
261 data CmmCallTarget
262 = CmmCallee -- Call a function (foreign or native)
263 CmmExpr -- literal label <=> static call
264 -- other expression <=> dynamic call
265 CCallConv -- The calling convention
266
267 | CmmPrim -- Call a "primitive" (eg. sin, cos)
268 CallishMachOp -- These might be implemented as inline
269 -- code by the backend.
270 deriving Eq