1 {-# OPTIONS -Wall -fno-warn-name-shadowing #-}
3 -- This module is pure representation and should be imported only by
4 -- clients that need to manipulate representation and know what
5 -- they're doing. Clients that need to create flow graphs should
6 -- instead import MkZipCfgCmm.
9 ( CmmZ, CmmTopZ, CmmGraph, CmmBlock, CmmAGraph, Middle(..), Last(..), Convention(..)
13 #include "HsVersions.h"
16 import Cmm ( GenCmm(..), GenCmmTop(..), CmmStatic, CmmInfo
17 , CmmCallTarget(..), CmmActuals, CmmFormalsWithoutKinds, CmmFormals
18 , CmmStmt(CmmJump, CmmSwitch) -- imported in order to call ppr
27 import qualified ZipDataflow as DF
32 import Outputable hiding (empty)
33 import qualified Outputable as PP
34 import Prelude hiding (zip, unzip, last)
36 type CmmGraph = LGraph Middle Last
37 type CmmAGraph = AGraph Middle Last
38 type CmmBlock = Block Middle Last
39 type CmmZ = GenCmm CmmStatic CmmInfo CmmGraph
40 type CmmTopZ = GenCmmTop CmmStatic CmmInfo CmmGraph
44 | MidComment FastString
46 | MidAssign CmmReg CmmExpr -- Assign to register
48 | MidStore CmmExpr CmmExpr -- Assign to memory location. Size is
49 -- given by cmmExprRep of the rhs.
51 | MidUnsafeCall -- An "unsafe" foreign call;
52 CmmCallTarget -- just a fat machine instructoin
53 CmmFormals -- zero or more results
54 CmmActuals -- zero or more arguments
56 | CopyIn -- Move parameters or results from conventional locations to registers
57 -- Note [CopyIn invariant]
60 C_SRT -- Static things kept alive by this block
61 | CopyOut Convention CmmFormals
64 = LastReturn CmmActuals -- Return from a function,
65 -- with these return values.
67 | LastJump CmmExpr CmmActuals
68 -- Tail call to another procedure
70 | LastBranch BlockId CmmFormalsWithoutKinds
71 -- To another block in the same procedure
72 -- The parameters are unused at present.
74 | LastCall { -- A call (native or safe foreign)
75 cml_target :: CmmCallTarget,
76 cml_actual :: CmmActuals, -- Zero or more arguments
77 cml_next :: Maybe BlockId } -- BlockId of continuation, if call returns
79 | LastCondBranch { -- conditional branch
81 cml_true, cml_false :: BlockId
84 | LastSwitch CmmExpr [Maybe BlockId] -- Table branch
85 -- The scrutinee is zero-based;
86 -- zero -> first block
87 -- one -> second block etc
88 -- Undefined outside range, and when there's a Nothing
91 = Argument CCallConv -- Used for function formal params
92 | Result CCallConv -- Used for function results
94 | Local -- Used for control transfers within a (pre-CPS) procedure
95 -- All jump sites known, never pushed on the stack (hence no SRT)
96 -- You can choose whatever calling convention
97 -- you please (provided you make sure
98 -- all the call sites agree)!
101 -- ^ In a complete LGraph for a procedure, the [[Exit]] node should not
102 -- appear, but it is useful in a subgraph (e.g., replacement for a node).
105 Note [CopyIn invariant]
106 ~~~~~~~~~~~~~~~~~~~~~~~
107 In principle, CopyIn ought to be a First node, but in practice, the
108 possibility raises all sorts of hairy issues with graph splicing,
109 rewriting, and so on. In the end, NR finds it better to make the
110 placement of CopyIn a dynamic invariant. This change will complicate
111 the dataflow fact for the proc-point calculation, but it should make
112 things easier in many other respects.
115 instance HavingSuccessors Last where
117 fold_succs = fold_cmm_succs
119 instance LastNode Last where
120 mkBranchNode id = LastBranch id []
121 isBranchNode (LastBranch _ []) = True
122 isBranchNode _ = False
123 branchNodeTarget (LastBranch id []) = id
124 branchNodeTarget _ = panic "asked for target of non-branch"
126 cmmSuccs :: Last -> [BlockId]
127 cmmSuccs (LastReturn {}) = []
128 cmmSuccs (LastJump {}) = []
129 cmmSuccs (LastBranch id _) = [id]
130 cmmSuccs (LastCall _ _ (Just id)) = [id]
131 cmmSuccs (LastCall _ _ Nothing) = []
132 cmmSuccs (LastCondBranch _ t f) = [f, t] -- meets layout constraint
133 cmmSuccs (LastSwitch _ edges) = catMaybes edges
135 fold_cmm_succs :: (BlockId -> a -> a) -> Last -> a -> a
136 fold_cmm_succs _f (LastReturn {}) z = z
137 fold_cmm_succs _f (LastJump {}) z = z
138 fold_cmm_succs f (LastBranch id _) z = f id z
139 fold_cmm_succs f (LastCall _ _ (Just id)) z = f id z
140 fold_cmm_succs _f (LastCall _ _ Nothing) z = z
141 fold_cmm_succs f (LastCondBranch _ te fe) z = f te (f fe z)
142 fold_cmm_succs f (LastSwitch _ edges) z = foldl (flip f) z $ catMaybes edges
145 ----------------------------------------------------------------
146 -- prettyprinting (avoids recursive imports)
148 instance Outputable Middle where
151 instance Outputable Last where
154 instance Outputable Convention where
157 instance DF.DebugNodes Middle Last
159 instance Outputable CmmGraph where
160 ppr = pprCmmGraphAsRep
162 pprCmmGraphAsRep :: CmmGraph -> SDoc
163 pprCmmGraphAsRep g = vcat (map ppr_block blocks)
164 where blocks = postorder_dfs g
165 ppr_block (Block id tail) = hang (ppr id <> colon) 4 (ppr tail)
167 pprMiddle :: Middle -> SDoc
168 pprMiddle stmt = (case stmt of
172 CopyIn conv args _ ->
173 if null args then ptext SLIT("empty CopyIn")
174 else commafy (map pprHinted args) <+> equals <+>
175 ptext SLIT("foreign") <+> doubleQuotes(ppr conv) <+> ptext SLIT("...")
178 if null args then PP.empty
179 else ptext SLIT("CopyOut") <+> doubleQuotes(ppr conv) <+>
180 parens (commafy (map pprHinted args))
183 MidComment s -> text "//" <+> ftext s
186 MidAssign reg expr -> ppr reg <+> equals <+> ppr expr <> semi
189 MidStore lv expr -> rep <> brackets(ppr lv) <+> equals <+> ppr expr <> semi
191 rep = ppr ( cmmExprRep expr )
193 -- call "ccall" foo(x, y)[r1, r2];
195 MidUnsafeCall (CmmCallee fn cconv) results args ->
196 hcat [ if null results
198 else parens (commafy $ map ppr results) <>
200 ptext SLIT("call"), space,
201 doubleQuotes(ppr cconv), space,
202 target fn, parens ( commafy $ map ppr args ),
205 target t@(CmmLit _) = ppr t
206 target fn' = parens (ppr fn')
208 MidUnsafeCall (CmmPrim op) results args ->
209 pprMiddle (MidUnsafeCall (CmmCallee (CmmLit lbl) CCallConv) results args)
211 lbl = CmmLabel (mkForeignLabel (mkFastString (show op)) Nothing False)
214 MidNop {} -> text "MidNop"
215 CopyIn {} -> text "CopyIn"
216 CopyOut {} -> text "CopyOut"
217 MidComment {} -> text "MidComment"
218 MidAssign {} -> text "MidAssign"
219 MidStore {} -> text "MidStore"
220 MidUnsafeCall {} -> text "MidUnsafeCall"
223 pprHinted :: Outputable a => (a, MachHint) -> SDoc
224 pprHinted (a, NoHint) = ppr a
225 pprHinted (a, PtrHint) = doubleQuotes (text "address") <+> ppr a
226 pprHinted (a, SignedHint) = doubleQuotes (text "signed") <+> ppr a
227 pprHinted (a, FloatHint) = doubleQuotes (text "float") <+> ppr a
229 pprLast :: Last -> SDoc
230 pprLast stmt = (case stmt of
231 LastBranch ident args -> genBranchWithArgs ident args
232 LastCondBranch expr t f -> genFullCondBranch expr t f
233 LastJump expr params -> ppr $ CmmJump expr params
234 LastReturn results -> hcat [ ptext SLIT("return"), space
235 , parens ( commafy $ map pprHinted results )
237 LastSwitch arg ids -> ppr $ CmmSwitch arg ids
238 LastCall tgt params k -> genCall tgt params k
241 LastBranch {} -> text "LastBranch"
242 LastCondBranch {} -> text "LastCondBranch"
243 LastJump {} -> text "LastJump"
244 LastReturn {} -> text "LastReturn"
245 LastSwitch {} -> text "LastSwitch"
246 LastCall {} -> text "LastCall"
249 genCall :: CmmCallTarget -> CmmActuals -> Maybe BlockId -> SDoc
250 genCall (CmmCallee fn cconv) args k =
251 hcat [ ptext SLIT("foreign"), space
252 , doubleQuotes(ppr cconv), space
253 , target fn, parens ( commafy $ map pprHinted args ), space
254 , case k of Nothing -> ptext SLIT("never returns")
255 Just k -> ptext SLIT("returns to") <+> ppr k
258 target t@(CmmLit _) = ppr t
259 target fn' = parens (ppr fn')
261 genCall (CmmPrim op) args k =
262 hcat [ text "%", text (show op), parens ( commafy $ map pprHinted args ),
263 ptext SLIT("returns to"), space, ppr k,
266 genBranchWithArgs :: (Outputable id, Outputable arg) => id -> [arg] -> SDoc
267 genBranchWithArgs ident [] = ptext SLIT("goto") <+> ppr ident <> semi
268 genBranchWithArgs ident args = ptext SLIT("goto") <+> ppr ident <+>
269 parens (commafy (map ppr args)) <> semi
271 genFullCondBranch :: Outputable id => CmmExpr -> id -> id -> SDoc
272 genFullCondBranch expr t f =
273 hsep [ ptext SLIT("if")
277 , ptext SLIT("else goto")
281 pprConvention :: Convention -> SDoc
282 pprConvention (Argument c) = ppr c
283 pprConvention (Result c) = ppr c
284 pprConvention Local = text "<local>"
286 commafy :: [SDoc] -> SDoc
287 commafy xs = hsep $ punctuate comma xs