+{-# OPTIONS -w #-}
+-- The above warning supression flag is a temporary kludge.
+-- While working on this module you are encouraged to remove it and fix
+-- any warnings in the module. See
+-- http://hackage.haskell.org/trac/ghc/wiki/Commentary/CodingStyle#Warnings
+-- for details
+
----------------------------------------------------------------------------
--
-- Pretty-printing of Cmm as (a superset of) C--
-- A useful example pass over Cmm is in nativeGen/MachCodeGen.hs
--
-module PprCmm (
- writeCmms, pprCmms, pprCmm, pprStmt, pprExpr
- ) where
+module PprCmm
+ ( writeCmms, pprCmms, pprCmm, pprStmt, pprExpr, pprSection, pprStatic, pprLit
+ )
+where
#include "HsVersions.h"
import Cmm
+import CmmExpr
import CmmUtils
import MachOp
import CLabel
import System.IO
import Data.Maybe
-pprCmms :: [Cmm] -> 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
-----------------------------------------------------------------------------
-instance Outputable Cmm where
+instance (Outputable d, Outputable info, Outputable g)
+ => Outputable (GenCmm d info g) where
ppr c = pprCmm c
-instance Outputable CmmTop 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 LocalReg where
+ ppr e = pprLocalReg e
+
instance Outputable GlobalReg where
ppr e = pprGlobalReg e
+instance Outputable CmmStatic where
+ ppr e = pprStatic e
+
+instance Outputable CmmInfo where
+ ppr e = pprInfo e
+
+
+
-----------------------------------------------------------------------------
-pprCmm :: Cmm -> 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. The info tables, if not null, are
--- printed in the style of C--'s 'stackdata' declaration, just inside
--- the proc body, and are labelled with the procedure name ++ "_info".
+-- Top level `procedure' blocks.
--
-pprTop :: CmmTop -> SDoc
-pprTop (CmmProc info lbl params blocks )
+pprTop :: (Outputable d, Outputable info, Outputable i)
+ => GenCmmTop d info i -> SDoc
- = vcat [ pprCLabel lbl <> parens (commafy $ map pprLocalReg params) <+> lbrace
- , nest 8 $ pprInfo info lbl
- , nest 4 $ vcat (map ppr blocks)
- , rbrace ]
+pprTop (CmmProc info lbl params graph )
- where
- pprInfo [] _ = empty
- pprInfo i label =
- (hang (pprCLabel (entryLblToInfoLbl label) <+> lbrace )
- 4 $ vcat (map pprStatic i))
- $$ rbrace
+ = vcat [ pprCLabel lbl <> parens (commafy $ map ppr params) <+> lbrace
+ , nest 8 $ lbrace <+> ppr info $$ rbrace
+ , nest 4 $ ppr graph
+ , rbrace ]
-- --------------------------------------------------------------------------
-- We follow [1], 4.5
-- 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 (CmmSafe srt) = ppr srt
+
+-- --------------------------------------------------------------------------
+-- Info tables. The current pretty printer needs refinement
+-- but will work for now.
+--
+-- 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
+ (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),
+ pprTypeInfo info]
+
+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),
+ 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 (ThunkInfo layout 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]
+pprTypeInfo (ContInfo stack srt) =
+ vcat [ptext SLIT("stack: ") <> ppr stack,
+ ptext SLIT("srt: ") <> ppr srt]
+
+pprUpdateFrame :: UpdateFrame -> SDoc
+pprUpdateFrame (UpdateFrame expr args) =
+ hcat [ ptext SLIT("jump")
+ , space
+ , if isTrivialCmmExpr expr
+ then pprExpr expr
+ else case expr of
+ CmmLoad (CmmReg _) _ -> pprExpr expr
+ _ -> parens (pprExpr expr)
+ , space
+ , parens ( commafy $ map ppr args ) ]
+
-- --------------------------------------------------------------------------
-- 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 _volatile ->
- hcat [ ptext SLIT("call"), space,
+ CmmCall (CmmCallee fn cconv) results args safety ret ->
+ hcat [ if null results
+ then empty
+ else parens (commafy $ map ppr results) <>
+ ptext SLIT(" = "),
+ ptext SLIT("foreign"), space,
doubleQuotes(ppr cconv), space,
target fn, parens ( commafy $ map ppr args ),
- (if null results
- then empty
- else brackets( commafy $ map ppr results)), 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 volatile ->
- pprStmt (CmmCall (CmmForeignCall (CmmLit lbl) CCallConv)
- results args volatile)
+ 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)
--
-- jump foo(a, b, c);
--
-genJump :: CmmExpr -> [(CmmExpr, MachHint)] -> SDoc
+genJump :: CmmExpr -> [CmmHinted CmmExpr] -> SDoc
genJump expr args =
hcat [ ptext SLIT("jump")
else case expr of
CmmLoad (CmmReg _) _ -> pprExpr expr
_ -> parens (pprExpr expr)
- , parens ( commafy $ map ppr args )
+ , space
+ , parens ( commafy $ map pprHinted args )
, semi ]
+pprHinted :: Outputable a => (CmmHinted a) -> SDoc
+pprHinted (CmmHinted a NoHint) = ppr a
+pprHinted (CmmHinted a PtrHint) = quotes(text "address") <+> ppr a
+pprHinted (CmmHinted a SignedHint) = quotes(text "signed") <+> ppr a
+pprHinted (CmmHinted 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 :: [CmmHinted CmmExpr] -> SDoc
genReturn args =
hcat [ ptext SLIT("return")
-- We only print the type of the local reg if it isn't wordRep
--
pprLocalReg :: LocalReg -> SDoc
-pprLocalReg (LocalReg uniq rep)
- = hcat [ char '_', ppr uniq,
- (if rep == wordRep
- then empty else dcolon <> ppr rep) ]
+pprLocalReg (LocalReg uniq rep follow)
+ = hcat [ char '_', ppr uniq, ty ] where
+ ty = if rep == wordRep && follow == GCKindNonPtr
+ then empty
+ else dcolon <> ptr <> ppr rep
+ ptr = if follow == GCKindNonPtr
+ then empty
+ else doubleQuotes (text "ptr")
-- needs to be kept in syn with Cmm.hs.GlobalReg
--
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"))
commafy :: [SDoc] -> SDoc
commafy xs = hsep $ punctuate comma xs
-