-- A useful example pass over Cmm is in nativeGen/MachCodeGen.hs
--
-module PprCmm (
- writeCmms, pprCmms, pprCmm, pprStmt, pprExpr
- ) where
-
-#include "HsVersions.h"
+module PprCmm
+ ( writeCmms, pprCmms, pprCmm, pprStmt, pprExpr, pprSection, pprStatic, pprLit
+ )
+where
+import BlockId
import Cmm
import CmmUtils
import MachOp
import System.IO
import Data.Maybe
-pprCmms :: (Outputable info) => [GenCmm CmmStatic info CmmStmt] -> SDoc
+pprCmms :: (Outputable info, Outputable g) => [GenCmm CmmStatic info g] -> SDoc
pprCmms cmms = pprCode CStyle (vcat (intersperse separator $ map ppr cmms))
where
- separator = space $$ ptext SLIT("-------------------") $$ space
+ separator = space $$ ptext (sLit "-------------------") $$ space
writeCmms :: Handle -> [Cmm] -> IO ()
writeCmms handle cmms = printForC handle (pprCmms cmms)
-----------------------------------------------------------------------------
-instance (Outputable info) => Outputable (GenCmm CmmStatic info CmmStmt) where
+instance (Outputable d, Outputable info, Outputable g)
+ => Outputable (GenCmm d info g) where
ppr c = pprCmm c
-instance (Outputable info) => Outputable (GenCmmTop CmmStatic info CmmStmt) where
+instance (Outputable d, Outputable info, Outputable i)
+ => Outputable (GenCmmTop d info i) where
ppr t = pprTop t
-instance Outputable CmmBasicBlock where
+instance (Outputable instr) => Outputable (ListGraph instr) where
+ ppr (ListGraph blocks) = vcat (map ppr blocks)
+
+instance (Outputable instr) => Outputable (GenBasicBlock instr) where
ppr b = pprBBlock b
instance Outputable CmmStmt where
instance Outputable CmmReg where
ppr e = pprReg e
+instance Outputable CmmLit where
+ ppr l = pprLit l
+
instance Outputable LocalReg where
ppr e = pprLocalReg e
+instance Outputable Area where
+ ppr e = pprArea e
+
instance Outputable GlobalReg where
ppr e = pprGlobalReg e
instance Outputable CmmInfo where
ppr e = pprInfo e
+
+
-----------------------------------------------------------------------------
-pprCmm :: (Outputable info) => GenCmm CmmStatic info CmmStmt -> SDoc
+pprCmm :: (Outputable d, Outputable info, Outputable g) => GenCmm d info g -> SDoc
pprCmm (Cmm tops) = vcat $ intersperse (text "") $ map pprTop tops
-- --------------------------------------------------------------------------
-- Top level `procedure' blocks.
--
-pprTop :: (Outputable info) => GenCmmTop CmmStatic info CmmStmt -> SDoc
-pprTop (CmmProc info lbl params blocks )
+pprTop :: (Outputable d, Outputable info, Outputable i)
+ => GenCmmTop d info i -> SDoc
+
+pprTop (CmmProc info lbl params graph )
= vcat [ pprCLabel lbl <> parens (commafy $ map ppr params) <+> lbrace
, nest 8 $ lbrace <+> ppr info $$ rbrace
- , nest 4 $ vcat (map ppr blocks)
+ , nest 4 $ ppr graph
, rbrace ]
-- --------------------------------------------------------------------------
-- section "data" { ... }
--
pprTop (CmmData section ds) =
- (hang (pprSection section <+> lbrace) 4 (vcat (map pprStatic ds)))
+ (hang (pprSection section <+> lbrace) 4 (vcat (map ppr ds)))
$$ rbrace
-- --------------------------------------------------------------------------
instance Outputable CmmSafety where
- ppr CmmUnsafe = ptext SLIT("_unsafe_call_")
+ ppr CmmUnsafe = ptext (sLit "_unsafe_call_")
ppr (CmmSafe srt) = ppr srt
-- --------------------------------------------------------------------------
-- For ideas on how to refine it, they used to be printed in the
-- style of C--'s 'stackdata' declaration, just inside the proc body,
-- and were labelled with the procedure name ++ "_info".
-pprInfo (CmmInfo gc_target update_frame CmmNonInfoTable) =
- vcat [ptext SLIT("gc_target: ") <>
- maybe (ptext SLIT("<none>")) pprBlockId gc_target,
- ptext SLIT("update_frame: ") <>
- maybe (ptext SLIT("<none>")) pprUpdateFrame update_frame]
-pprInfo (CmmInfo gc_target update_frame
+pprInfo :: CmmInfo -> SDoc
+pprInfo (CmmInfo _gc_target update_frame CmmNonInfoTable) =
+ vcat [{-ptext (sLit "gc_target: ") <>
+ maybe (ptext (sLit "<none>")) pprBlockId gc_target,-}
+ ptext (sLit "update_frame: ") <>
+ maybe (ptext (sLit "<none>")) pprUpdateFrame update_frame]
+pprInfo (CmmInfo _gc_target update_frame
(CmmInfoTable (ProfilingInfo closure_type closure_desc) tag info)) =
- vcat [ptext SLIT("gc_target: ") <>
- maybe (ptext SLIT("<none>")) pprBlockId gc_target,
- ptext SLIT("update_frame: ") <>
- maybe (ptext SLIT("<none>")) pprUpdateFrame update_frame,
- ptext SLIT("type: ") <> pprLit closure_type,
- ptext SLIT("desc: ") <> pprLit closure_desc,
- ptext SLIT("tag: ") <> integer (toInteger tag),
+ vcat [{-ptext (sLit "gc_target: ") <>
+ maybe (ptext (sLit "<none>")) pprBlockId gc_target,-}
+ ptext (sLit "update_frame: ") <>
+ maybe (ptext (sLit "<none>")) pprUpdateFrame update_frame,
+ ptext (sLit "type: ") <> pprLit closure_type,
+ ptext (sLit "desc: ") <> pprLit closure_desc,
+ ptext (sLit "tag: ") <> integer (toInteger tag),
pprTypeInfo info]
+pprTypeInfo :: ClosureTypeInfo -> SDoc
pprTypeInfo (ConstrInfo layout constr descr) =
- vcat [ptext SLIT("ptrs: ") <> integer (toInteger (fst layout)),
- ptext SLIT("nptrs: ") <> integer (toInteger (snd layout)),
- ptext SLIT("constructor: ") <> integer (toInteger constr),
+ vcat [ptext (sLit "ptrs: ") <> integer (toInteger (fst layout)),
+ ptext (sLit "nptrs: ") <> integer (toInteger (snd layout)),
+ ptext (sLit "constructor: ") <> integer (toInteger constr),
pprLit descr]
-pprTypeInfo (FunInfo layout srt fun_type arity args slow_entry) =
- vcat [ptext SLIT("ptrs: ") <> integer (toInteger (fst layout)),
- ptext SLIT("nptrs: ") <> integer (toInteger (snd layout)),
- ptext SLIT("srt: ") <> ppr srt,
- ptext SLIT("fun_type: ") <> integer (toInteger fun_type),
- ptext SLIT("arity: ") <> integer (toInteger arity),
- --ptext SLIT("args: ") <> ppr args, -- TODO: needs to be printed
- ptext SLIT("slow: ") <> pprLit slow_entry
+pprTypeInfo (FunInfo layout srt fun_type arity _args slow_entry) =
+ vcat [ptext (sLit "ptrs: ") <> integer (toInteger (fst layout)),
+ ptext (sLit "nptrs: ") <> integer (toInteger (snd layout)),
+ ptext (sLit "srt: ") <> ppr srt,
+ ptext (sLit "fun_type: ") <> integer (toInteger fun_type),
+ ptext (sLit "arity: ") <> integer (toInteger arity),
+ --ptext (sLit "args: ") <> ppr args, -- TODO: needs to be printed
+ ptext (sLit "slow: ") <> pprLit slow_entry
]
pprTypeInfo (ThunkInfo layout srt) =
- vcat [ptext SLIT("ptrs: ") <> integer (toInteger (fst layout)),
- ptext SLIT("nptrs: ") <> integer (toInteger (snd layout)),
- ptext SLIT("srt: ") <> ppr srt]
+ vcat [ptext (sLit "ptrs: ") <> integer (toInteger (fst layout)),
+ ptext (sLit "nptrs: ") <> integer (toInteger (snd layout)),
+ ptext (sLit "srt: ") <> ppr srt]
pprTypeInfo (ThunkSelectorInfo offset srt) =
- vcat [ptext SLIT("ptrs: ") <> integer (toInteger offset),
- ptext SLIT("srt: ") <> ppr srt]
+ vcat [ptext (sLit "ptrs: ") <> integer (toInteger offset),
+ ptext (sLit "srt: ") <> ppr srt]
pprTypeInfo (ContInfo stack srt) =
- vcat [ptext SLIT("stack: ") <> ppr stack,
- ptext SLIT("srt: ") <> ppr srt]
+ vcat [ptext (sLit "stack: ") <> ppr stack,
+ ptext (sLit "srt: ") <> ppr srt]
pprUpdateFrame :: UpdateFrame -> SDoc
pprUpdateFrame (UpdateFrame expr args) =
- hcat [ ptext SLIT("jump")
+ hcat [ ptext (sLit "jump")
, space
, if isTrivialCmmExpr expr
then pprExpr expr
-- --------------------------------------------------------------------------
-- Basic blocks look like assembly blocks.
-- lbl: stmt ; stmt ; ..
-pprBBlock :: CmmBasicBlock -> SDoc
+pprBBlock :: Outputable stmt => GenBasicBlock stmt -> SDoc
pprBBlock (BasicBlock ident stmts) =
hang (pprBlockId ident <> colon) 4 (vcat (map ppr stmts))
-- call "ccall" foo(x, y)[r1, r2];
-- ToDo ppr volatile
- CmmCall (CmmForeignCall fn cconv) results args safety ->
+ CmmCall (CmmCallee fn cconv) results args safety ret ->
hcat [ if null results
then empty
else parens (commafy $ map ppr results) <>
- ptext SLIT(" = "),
- ptext SLIT("call"), space,
+ ptext (sLit " = "),
+ ptext (sLit "foreign"), space,
doubleQuotes(ppr cconv), space,
target fn, parens ( commafy $ map ppr args ),
- brackets (ppr safety), semi ]
+ brackets (ppr safety),
+ case ret of CmmMayReturn -> empty
+ CmmNeverReturns -> ptext (sLit " never returns"),
+ semi ]
where
- target (CmmLit lit) = pprLit lit
- target fn' = parens (ppr fn')
-
- CmmCall (CmmPrim op) results args safety ->
- pprStmt (CmmCall (CmmForeignCall (CmmLit lbl) CCallConv)
- results args safety)
+ ---- With the following three functions, I was going somewhere
+ ---- useful, but I don't remember where. Probably making
+ ---- emitted Cmm output look better. ---NR, 2 May 2008
+ _pp_lhs | null results = empty
+ | otherwise = commafy (map ppr_ar results) <+> equals
+ -- Don't print the hints on a native C-- call
+ ppr_ar arg = case cconv of
+ CmmCallConv -> ppr (kindlessCmm arg)
+ _ -> doubleQuotes (ppr $ cmmKind arg) <+>
+ ppr (kindlessCmm arg)
+ _pp_conv = case cconv of
+ CmmCallConv -> empty
+ _ -> ptext (sLit "foreign") <+> doubleQuotes (ppr cconv)
+
+ target (CmmLit lit) = pprLit lit
+ target fn' = parens (ppr fn')
+
+ CmmCall (CmmPrim op) results args safety ret ->
+ pprStmt (CmmCall (CmmCallee (CmmLit lbl) CCallConv)
+ results args safety ret)
where
lbl = CmmLabel (mkForeignLabel (mkFastString (show op)) Nothing False)
--
genBranch :: BlockId -> SDoc
genBranch ident =
- ptext SLIT("goto") <+> pprBlockId ident <> semi
+ ptext (sLit "goto") <+> pprBlockId ident <> semi
-- --------------------------------------------------------------------------
-- Conditional. [1], section 6.4
--
genCondBranch :: CmmExpr -> BlockId -> SDoc
genCondBranch expr ident =
- hsep [ ptext SLIT("if")
+ hsep [ ptext (sLit "if")
, parens(ppr expr)
- , ptext SLIT("goto")
+ , ptext (sLit "goto")
, pprBlockId ident <> semi ]
-- --------------------------------------------------------------------------
--
-- jump foo(a, b, c);
--
-genJump :: CmmExpr -> [(CmmExpr, MachHint)] -> SDoc
+genJump :: CmmExpr -> [CmmKinded CmmExpr] -> SDoc
genJump expr args =
- hcat [ ptext SLIT("jump")
+ hcat [ ptext (sLit "jump")
, space
, if isTrivialCmmExpr expr
then pprExpr expr
CmmLoad (CmmReg _) _ -> pprExpr expr
_ -> parens (pprExpr expr)
, space
- , parens ( commafy $ map ppr args )
+ , parens ( commafy $ map pprKinded args )
, semi ]
+pprKinded :: Outputable a => (CmmKinded a) -> SDoc
+pprKinded (CmmKinded a NoHint) = ppr a
+pprKinded (CmmKinded a PtrHint) = quotes(text "address") <+> ppr a
+pprKinded (CmmKinded a SignedHint) = quotes(text "signed") <+> ppr a
+pprKinded (CmmKinded a FloatHint) = quotes(text "float") <+> ppr a
+
-- --------------------------------------------------------------------------
-- Return from a function. [1], Section 6.8.2 of version 1.128
--
-- return (a, b, c);
--
-genReturn :: [(CmmExpr, MachHint)] -> SDoc
+genReturn :: [CmmKinded CmmExpr] -> SDoc
genReturn args =
- hcat [ ptext SLIT("return")
+ hcat [ ptext (sLit "return")
, space
, parens ( commafy $ map ppr args )
, semi ]
= let pairs = groupBy snds (zip [0 .. ] maybe_ids )
- in hang (hcat [ ptext SLIT("switch [0 .. ")
+ in hang (hcat [ ptext (sLit "switch [0 .. ")
, int (length maybe_ids - 1)
- , ptext SLIT("] ")
+ , ptext (sLit "] ")
, if isTrivialCmmExpr expr
then pprExpr expr
else parens (pprExpr expr)
- , ptext SLIT(" {")
+ , ptext (sLit " {")
])
4 (vcat ( map caseify pairs )) $$ rbrace
snds a b = (snd a) == (snd b)
caseify :: [(Int,Maybe BlockId)] -> SDoc
- caseify ixs@((i,Nothing):_)
- = ptext SLIT("/* impossible: ") <> hcat (intersperse comma (map (int.fst) ixs))
- <> ptext SLIT(" */")
+ caseify ixs@((_,Nothing):_)
+ = ptext (sLit "/* impossible: ") <> hcat (intersperse comma (map (int.fst) ixs))
+ <> ptext (sLit " */")
caseify as
= let (is,ids) = unzip as
- in hsep [ ptext SLIT("case")
+ in hsep [ ptext (sLit "case")
, hcat (punctuate comma (map int is))
- , ptext SLIT(": goto")
+ , ptext (sLit ": goto")
, pprBlockId (head [ id | Just id <- ids]) <> semi ]
-- --------------------------------------------------------------------------
-- a default conservative behaviour.
-- %nonassoc '>=' '>' '<=' '<' '!=' '=='
+pprExpr1, pprExpr7, pprExpr8 :: CmmExpr -> SDoc
pprExpr1 (CmmMachOp op [x,y]) | Just doc <- infixMachOp1 op
= pprExpr7 x <+> doc <+> pprExpr7 y
pprExpr1 e = pprExpr7 e
-infixMachOp1 (MO_Eq _) = Just (ptext SLIT("=="))
-infixMachOp1 (MO_Ne _) = Just (ptext SLIT("!="))
-infixMachOp1 (MO_Shl _) = Just (ptext SLIT("<<"))
-infixMachOp1 (MO_U_Shr _) = Just (ptext SLIT(">>"))
-infixMachOp1 (MO_U_Ge _) = Just (ptext SLIT(">="))
-infixMachOp1 (MO_U_Le _) = Just (ptext SLIT("<="))
+infixMachOp1, infixMachOp7, infixMachOp8 :: MachOp -> Maybe SDoc
+
+infixMachOp1 (MO_Eq _) = Just (ptext (sLit "=="))
+infixMachOp1 (MO_Ne _) = Just (ptext (sLit "!="))
+infixMachOp1 (MO_Shl _) = Just (ptext (sLit "<<"))
+infixMachOp1 (MO_U_Shr _) = Just (ptext (sLit ">>"))
+infixMachOp1 (MO_U_Ge _) = Just (ptext (sLit ">="))
+infixMachOp1 (MO_U_Le _) = Just (ptext (sLit "<="))
infixMachOp1 (MO_U_Gt _) = Just (char '>')
infixMachOp1 (MO_U_Lt _) = Just (char '<')
infixMachOp1 _ = Nothing
CmmLit lit -> pprLit1 lit
CmmLoad expr rep -> ppr rep <> brackets( ppr expr )
CmmReg reg -> ppr reg
- CmmRegOff reg off -> parens (ppr reg <+> char '+' <+> int off)
+ CmmRegOff reg off -> parens (ppr reg <+> char '+' <+> int off)
+ CmmStackSlot a off -> parens (ppr a <+> char '+' <+> int off)
CmmMachOp mop args -> genMachOp mop args
genMachOp :: MachOp -> [CmmExpr] -> SDoc
CmmLabelDiffOff clbl1 clbl2 i -> pprCLabel clbl1 <> char '-'
<> pprCLabel clbl2 <> ppr_offset i
-pprLit1 lit@(CmmLabelOff clbl i) = parens (pprLit lit)
-pprLit1 lit = pprLit lit
+pprLit1 :: CmmLit -> SDoc
+pprLit1 lit@(CmmLabelOff {}) = parens (pprLit lit)
+pprLit1 lit = pprLit lit
ppr_offset :: Int -> SDoc
ppr_offset i
--
pprStatic :: CmmStatic -> SDoc
pprStatic s = case s of
- CmmStaticLit lit -> nest 4 $ ptext SLIT("const") <+> pprLit lit <> semi
+ CmmStaticLit lit -> nest 4 $ ptext (sLit "const") <+> pprLit lit <> semi
CmmUninitialised i -> nest 4 $ text "I8" <> brackets (int i)
CmmAlign i -> nest 4 $ text "align" <+> int i
CmmDataLabel clbl -> pprCLabel clbl <> colon
pprReg :: CmmReg -> SDoc
pprReg r
= case r of
- CmmLocal local -> pprLocalReg local
+ CmmLocal local -> pprLocalReg local
CmmGlobal global -> pprGlobalReg global
--
pprLocalReg :: LocalReg -> SDoc
pprLocalReg (LocalReg uniq rep follow)
= hcat [ char '_', ppr uniq, ty ] where
- ty = if rep == wordRep && follow == KindNonPtr
+ ty = if rep == wordRep && follow == GCKindNonPtr
then empty
else dcolon <> ptr <> ppr rep
- ptr = if follow == KindNonPtr
+ ptr = if follow == GCKindNonPtr
then empty
else doubleQuotes (text "ptr")
+-- Stack areas
+pprArea :: Area -> SDoc
+pprArea (RegSlot r) = hcat [ text "slot<", ppr r, text ">" ]
+pprArea (CallArea id n n') =
+ hcat [ text "callslot<", ppr id, char '+', ppr n, char '/', ppr n', text ">" ]
+
-- needs to be kept in syn with Cmm.hs.GlobalReg
--
pprGlobalReg :: GlobalReg -> SDoc
FloatReg n -> char 'F' <> int n
DoubleReg n -> char 'D' <> int n
LongReg n -> char 'L' <> int n
- Sp -> ptext SLIT("Sp")
- SpLim -> ptext SLIT("SpLim")
- Hp -> ptext SLIT("Hp")
- HpLim -> ptext SLIT("HpLim")
- CurrentTSO -> ptext SLIT("CurrentTSO")
- CurrentNursery -> ptext SLIT("CurrentNursery")
- HpAlloc -> ptext SLIT("HpAlloc")
- GCEnter1 -> ptext SLIT("stg_gc_enter_1")
- GCFun -> ptext SLIT("stg_gc_fun")
- BaseReg -> ptext SLIT("BaseReg")
- PicBaseReg -> ptext SLIT("PicBaseReg")
+ Sp -> ptext (sLit "Sp")
+ SpLim -> ptext (sLit "SpLim")
+ Hp -> ptext (sLit "Hp")
+ HpLim -> ptext (sLit "HpLim")
+ CurrentTSO -> ptext (sLit "CurrentTSO")
+ CurrentNursery -> ptext (sLit "CurrentNursery")
+ HpAlloc -> ptext (sLit "HpAlloc")
+ GCEnter1 -> ptext (sLit "stg_gc_enter_1")
+ GCFun -> ptext (sLit "stg_gc_fun")
+ BaseReg -> ptext (sLit "BaseReg")
+ PicBaseReg -> ptext (sLit "PicBaseReg")
-- --------------------------------------------------------------------------
-- data sections
--
pprSection :: Section -> SDoc
pprSection s = case s of
- Text -> section <+> doubleQuotes (ptext SLIT("text"))
- Data -> section <+> doubleQuotes (ptext SLIT("data"))
- ReadOnlyData -> section <+> doubleQuotes (ptext SLIT("readonly"))
+ Text -> section <+> doubleQuotes (ptext (sLit "text"))
+ Data -> section <+> doubleQuotes (ptext (sLit "data"))
+ ReadOnlyData -> section <+> doubleQuotes (ptext (sLit "readonly"))
+ ReadOnlyData16 -> section <+> doubleQuotes (ptext (sLit "readonly16"))
RelocatableReadOnlyData
- -> section <+> doubleQuotes (ptext SLIT("relreadonly"))
- UninitialisedData -> section <+> doubleQuotes (ptext SLIT("uninitialised"))
+ -> section <+> doubleQuotes (ptext (sLit "relreadonly"))
+ UninitialisedData -> section <+> doubleQuotes (ptext (sLit "uninitialised"))
OtherSection s' -> section <+> doubleQuotes (text s')
where
- section = ptext SLIT("section")
-
+ section = ptext (sLit "section")
+
-- --------------------------------------------------------------------------
-- Basic block ids
--
-----------------------------------------------------------------------------
commafy :: [SDoc] -> SDoc
-commafy xs = hsep $ punctuate comma xs
-
+commafy xs = fsep $ punctuate comma xs