module PprCmm
( module PprCmmDecl
, module PprCmmExpr
)
where
import GhcPrelude hiding (succ)
import CLabel
import Cmm
import CmmUtils
import CmmSwitch
import DynFlags
import FastString
import Outputable
import PprCmmDecl
import PprCmmExpr
import Util
import BasicTypes
import Hoopl.Block
import Hoopl.Graph
instance Outputable CmmStackInfo where
ppr = pprStackInfo
instance Outputable CmmTopInfo where
ppr = pprTopInfo
instance Outputable (CmmNode e x) where
ppr = pprNode
instance Outputable Convention where
ppr = pprConvention
instance Outputable ForeignConvention where
ppr = pprForeignConvention
instance Outputable ForeignTarget where
ppr = pprForeignTarget
instance Outputable CmmReturnInfo where
ppr = pprReturnInfo
instance Outputable (Block CmmNode C C) where
ppr = pprBlock
instance Outputable (Block CmmNode C O) where
ppr = pprBlock
instance Outputable (Block CmmNode O C) where
ppr = pprBlock
instance Outputable (Block CmmNode O O) where
ppr = pprBlock
instance Outputable (Graph CmmNode e x) where
ppr = pprGraph
instance Outputable CmmGraph where
ppr = pprCmmGraph
pprStackInfo :: CmmStackInfo -> SDoc
pprStackInfo (StackInfo {arg_space=arg_space, updfr_space=updfr_space}) =
text "arg_space: " <> ppr arg_space <+>
text "updfr_space: " <> ppr updfr_space
pprTopInfo :: CmmTopInfo -> SDoc
pprTopInfo (TopInfo {info_tbls=info_tbl, stack_info=stack_info}) =
vcat [text "info_tbls: " <> ppr info_tbl,
text "stack_info: " <> ppr stack_info]
pprBlock :: IndexedCO x SDoc SDoc ~ SDoc
=> Block CmmNode e x -> IndexedCO e SDoc SDoc
pprBlock block
= foldBlockNodesB3 ( ($$) . ppr
, ($$) . (nest 4) . ppr
, ($$) . (nest 4) . ppr
)
block
empty
pprGraph :: Graph CmmNode e x -> SDoc
pprGraph GNil = empty
pprGraph (GUnit block) = ppr block
pprGraph (GMany entry body exit)
= text "{"
$$ nest 2 (pprMaybeO entry $$ (vcat $ map ppr $ bodyToBlockList body) $$ pprMaybeO exit)
$$ text "}"
where pprMaybeO :: Outputable (Block CmmNode e x)
=> MaybeO ex (Block CmmNode e x) -> SDoc
pprMaybeO NothingO = empty
pprMaybeO (JustO block) = ppr block
pprCmmGraph :: CmmGraph -> SDoc
pprCmmGraph g
= text "{" <> text "offset"
$$ nest 2 (vcat $ map ppr blocks)
$$ text "}"
where blocks = revPostorder g
pprConvention :: Convention -> SDoc
pprConvention (NativeNodeCall {}) = text "<native-node-call-convention>"
pprConvention (NativeDirectCall {}) = text "<native-direct-call-convention>"
pprConvention (NativeReturn {}) = text "<native-ret-convention>"
pprConvention Slow = text "<slow-convention>"
pprConvention GC = text "<gc-convention>"
pprForeignConvention :: ForeignConvention -> SDoc
pprForeignConvention (ForeignConvention c args res ret _ _) =
doubleQuotes (ppr c) <+> text "arg hints: " <+> ppr args <+> text " result hints: " <+> ppr res <+> ppr ret
pprReturnInfo :: CmmReturnInfo -> SDoc
pprReturnInfo CmmMayReturn = empty
pprReturnInfo CmmNeverReturns = text "never returns"
pprForeignTarget :: ForeignTarget -> SDoc
pprForeignTarget (ForeignTarget fn c) = ppr c <+> ppr_target fn
where
ppr_target :: CmmExpr -> SDoc
ppr_target t@(CmmLit _) = ppr t
ppr_target fn' = parens (ppr fn')
pprForeignTarget (PrimTarget op)
= ppr
(CmmLabel (mkForeignLabel
(mkFastString (show op))
Nothing ForeignLabelInThisPackage IsFunction))
pprNode :: CmmNode e x -> SDoc
pprNode node = pp_node <+> pp_debug
where
pp_node :: SDoc
pp_node = sdocWithDynFlags $ \dflags -> case node of
CmmEntry id tscope -> lbl <> colon <+>
(sdocWithDynFlags $ \dflags ->
ppUnless (gopt Opt_SuppressTicks dflags) (text "//" <+> ppr tscope))
where
lbl = if gopt Opt_SuppressUniques dflags
then text "_lbl_"
else ppr id
CmmComment s -> text "//" <+> ftext s
CmmTick t -> ppUnless (gopt Opt_SuppressTicks dflags) $
text "//tick" <+> ppr t
CmmUnwind regs ->
text "unwind "
<> commafy (map (\(r,e) -> ppr r <+> char '=' <+> ppr e) regs) <> semi
CmmAssign reg expr -> ppr reg <+> equals <+> ppr expr <> semi
CmmStore lv expr -> rep <> brackets(ppr lv) <+> equals <+> ppr expr <> semi
where
rep = sdocWithDynFlags $ \dflags ->
ppr ( cmmExprType dflags expr )
CmmUnsafeForeignCall target results args ->
hsep [ ppUnless (null results) $
parens (commafy $ map ppr results) <+> equals,
text "call",
ppr target <> parens (commafy $ map ppr args) <> semi]
CmmBranch ident -> text "goto" <+> ppr ident <> semi
CmmCondBranch expr t f l ->
hsep [ text "if"
, parens(ppr expr)
, case l of
Nothing -> empty
Just b -> parens (text "likely:" <+> ppr b)
, text "goto"
, ppr t <> semi
, text "else goto"
, ppr f <> semi
]
CmmSwitch expr ids ->
hang (hsep [ text "switch"
, range
, if isTrivialCmmExpr expr
then ppr expr
else parens (ppr expr)
, text "{"
])
4 (vcat (map ppCase cases) $$ def) $$ rbrace
where
(cases, mbdef) = switchTargetsFallThrough ids
ppCase (is,l) = hsep
[ text "case"
, commafy $ map integer is
, text ": goto"
, ppr l <> semi
]
def | Just l <- mbdef = hsep
[ text "default:"
, braces (text "goto" <+> ppr l <> semi)
]
| otherwise = empty
range = brackets $ hsep [integer lo, text "..", integer hi]
where (lo,hi) = switchTargetsRange ids
CmmCall tgt k regs out res updfr_off ->
hcat [ text "call", space
, pprFun tgt, parens (interpp'SP regs), space
, returns <+>
text "args: " <> ppr out <> comma <+>
text "res: " <> ppr res <> comma <+>
text "upd: " <> ppr updfr_off
, semi ]
where pprFun f@(CmmLit _) = ppr f
pprFun f = parens (ppr f)
returns
| Just r <- k = text "returns to" <+> ppr r <> comma
| otherwise = empty
CmmForeignCall {tgt=t, res=rs, args=as, succ=s, ret_args=a, ret_off=u, intrbl=i} ->
hcat $ if i then [text "interruptible", space] else [] ++
[ text "foreign call", space
, ppr t, text "(...)", space
, text "returns to" <+> ppr s
<+> text "args:" <+> parens (ppr as)
<+> text "ress:" <+> parens (ppr rs)
, text "ret_args:" <+> ppr a
, text "ret_off:" <+> ppr u
, semi ]
pp_debug :: SDoc
pp_debug =
if not debugIsOn then empty
else case node of
CmmEntry {} -> empty
CmmComment {} -> empty
CmmTick {} -> empty
CmmUnwind {} -> text " // CmmUnwind"
CmmAssign {} -> text " // CmmAssign"
CmmStore {} -> text " // CmmStore"
CmmUnsafeForeignCall {} -> text " // CmmUnsafeForeignCall"
CmmBranch {} -> text " // CmmBranch"
CmmCondBranch {} -> text " // CmmCondBranch"
CmmSwitch {} -> text " // CmmSwitch"
CmmCall {} -> text " // CmmCall"
CmmForeignCall {} -> text " // CmmForeignCall"
commafy :: [SDoc] -> SDoc
commafy xs = hsep $ punctuate comma xs