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