X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=compiler%2Fcmm%2FZipCfgCmmRep.hs;h=1fda97139ee8981519180f9cf0b42f19079a375a;hb=ba60dc74fdb18fe655cfac605130cf6480116e47;hp=0b93d1a0ea60202759c130c71b0a70bda1aca489;hpb=a47cf360727926e9de57f2ca49b5bc0d96427f56;p=ghc-hetmet.git diff --git a/compiler/cmm/ZipCfgCmmRep.hs b/compiler/cmm/ZipCfgCmmRep.hs index 0b93d1a..1fda971 100644 --- a/compiler/cmm/ZipCfgCmmRep.hs +++ b/compiler/cmm/ZipCfgCmmRep.hs @@ -8,27 +8,33 @@ module ZipCfgCmmRep ( CmmZ, CmmTopZ, CmmGraph, CmmBlock, CmmAGraph, Middle(..), Last(..), Convention(..) , ValueDirection(..) + , pprCmmGraphLikeCmm ) where -#include "HsVersions.h" - import CmmExpr import Cmm ( GenCmm(..), GenCmmTop(..), CmmStatic, CmmInfo - , CmmCallTarget(..), CmmActuals, CmmFormals - , CmmStmt(CmmSwitch) -- imported in order to call ppr + , CmmCallTarget(..), CmmActuals, CmmFormals, CmmHinted(..) + , CmmStmt(..) -- imported in order to call ppr on Switch and to + -- implement pprCmmGraphLikeCmm + , CmmSafety(CmmSafe) -- for pprCmmGraphLikeCmm + , CmmReturnInfo(CmmMayReturn) -- for pprCmmGraphLikeCmm ) import PprCmm() import CLabel +import CmmZipUtil import ClosureInfo import FastString import ForeignCall import MachOp -import qualified ZipDataflow as DF +import qualified ZipCfg as Z +import qualified ZipDataflow0 as DF import ZipCfg import MkZipCfg +import Util +import UniqSet import Maybes import Outputable import Prelude hiding (zip, unzip, last) @@ -55,6 +61,14 @@ data Middle CmmFormals -- zero or more results CmmActuals -- zero or more arguments + | MidAddToContext -- push a frame on the stack; + -- I will return to this frame + CmmExpr -- The frame's return address; it must be + -- preceded by an info table that describes the + -- live variables. + [CmmExpr] -- The frame's live variables, to go on the + -- stack with the first one at the young end + | CopyIn -- Move incoming parameters or results from conventional -- locations to registers. Note [CopyIn invariant] Convention @@ -157,12 +171,13 @@ fold_cmm_succs f (LastSwitch _ edges) z = foldl (flip f) z $ catMaybes edge instance UserOfLocalRegs Middle where foldRegsUsed f z m = middle m where middle (MidComment {}) = z - middle (MidAssign _lhs expr) = foldRegsUsed f z expr - middle (MidStore addr rval) = foldRegsUsed f (foldRegsUsed f z addr) rval - middle (MidUnsafeCall tgt _ress args) = foldRegsUsed f (foldRegsUsed f z tgt) args + middle (MidAssign _lhs expr) = fold f z expr + middle (MidStore addr rval) = fold f (fold f z addr) rval + middle (MidUnsafeCall tgt _ress args) = fold f (fold f z tgt) args + middle (MidAddToContext ra args) = fold f (fold f z ra) args middle (CopyIn _ _formals _) = z - middle (CopyOut _ actuals) = foldRegsUsed f z actuals --- fold = foldRegsUsed + middle (CopyOut _ actuals) = fold f z actuals + fold f z m = foldRegsUsed f z m -- avoid monomorphism restriction instance UserOfLocalRegs Last where foldRegsUsed f z m = last m @@ -173,10 +188,6 @@ instance UserOfLocalRegs Last where last (LastCondBranch e _ _) = foldRegsUsed f z e last (LastSwitch e _tbl) = foldRegsUsed f z e -instance UserOfLocalRegs (ZLast Last) where - foldRegsUsed f z (LastOther l) = foldRegsUsed f z l - foldRegsUsed _f z LastExit = z - ---------------------------------------------------------------------- ----- Instance declarations for prettyprinting (avoids recursive imports) @@ -192,22 +203,21 @@ instance Outputable Convention where instance DF.DebugNodes Middle Last -instance Outputable CmmGraph where - ppr = pprLgraph - debugPpr :: Bool debugPpr = debugIsOn pprMiddle :: Middle -> SDoc -pprMiddle stmt = (case stmt of +pprMiddle stmt = pp_stmt <+> pp_debug + where + pp_stmt = case stmt of CopyIn conv args _ -> - if null args then ptext SLIT("empty CopyIn") + if null args then ptext (sLit "empty CopyIn") else commafy (map pprHinted args) <+> equals <+> - ptext SLIT("foreign") <+> doubleQuotes(ppr conv) <+> ptext SLIT("...") + ptext (sLit "foreign") <+> doubleQuotes(ppr conv) <+> ptext (sLit "...") CopyOut conv args -> - ptext SLIT("next, pass") <+> doubleQuotes(ppr conv) <+> + ptext (sLit "next, pass") <+> doubleQuotes(ppr conv) <+> parens (commafy (map pprHinted args)) -- // text @@ -227,45 +237,53 @@ pprMiddle stmt = (case stmt of hcat [ if null results then empty else parens (commafy $ map ppr results) <> - ptext SLIT(" = "), - ptext SLIT("call"), space, + ptext (sLit " = "), + ptext (sLit "call"), space, doubleQuotes(ppr cconv), space, - target fn, parens ( commafy $ map ppr args ), + ppr_target fn, parens ( commafy $ map ppr args ), semi ] - where - target t@(CmmLit _) = ppr t - target fn' = parens (ppr fn') MidUnsafeCall (CmmPrim op) results args -> pprMiddle (MidUnsafeCall (CmmCallee (CmmLit lbl) CCallConv) results args) where lbl = CmmLabel (mkForeignLabel (mkFastString (show op)) Nothing False) - ) <> - if debugPpr then empty - else text " //" <+> - case stmt of - CopyIn {} -> text "CopyIn" - CopyOut {} -> text "CopyOut" - MidComment {} -> text "MidComment" - MidAssign {} -> text "MidAssign" - MidStore {} -> text "MidStore" - MidUnsafeCall {} -> text "MidUnsafeCall" + MidAddToContext ra args -> + hcat [ ptext (sLit "return via ") + , ppr_target ra, parens (commafy $ map ppr args), semi ] + + pp_debug = + if not debugPpr then empty + else text " //" <+> + case stmt of + CopyIn {} -> text "CopyIn" + CopyOut {} -> text "CopyOut" + MidComment {} -> text "MidComment" + MidAssign {} -> text "MidAssign" + MidStore {} -> text "MidStore" + MidUnsafeCall {} -> text "MidUnsafeCall" + MidAddToContext {} -> text "MidAddToContext" + + +ppr_target :: CmmExpr -> SDoc +ppr_target t@(CmmLit _) = ppr t +ppr_target fn' = parens (ppr fn') -pprHinted :: Outputable a => (a, MachHint) -> SDoc -pprHinted (a, NoHint) = ppr a -pprHinted (a, PtrHint) = doubleQuotes (text "address") <+> ppr a -pprHinted (a, SignedHint) = doubleQuotes (text "signed") <+> ppr a -pprHinted (a, FloatHint) = doubleQuotes (text "float") <+> ppr a + +pprHinted :: Outputable a => CmmHinted a -> SDoc +pprHinted (CmmHinted a NoHint) = ppr a +pprHinted (CmmHinted a PtrHint) = doubleQuotes (text "address") <+> ppr a +pprHinted (CmmHinted a SignedHint) = doubleQuotes (text "signed") <+> ppr a +pprHinted (CmmHinted a FloatHint) = doubleQuotes (text "float") <+> ppr a pprLast :: Last -> SDoc pprLast stmt = (case stmt of - LastBranch ident -> ptext SLIT("goto") <+> ppr ident <> semi + LastBranch ident -> ptext (sLit "goto") <+> ppr ident <> semi LastCondBranch expr t f -> genFullCondBranch expr t f - LastJump expr -> hcat [ ptext SLIT("jump"), space, pprFun expr - , ptext SLIT("(...)"), semi] - LastReturn -> hcat [ ptext SLIT("return"), space - , ptext SLIT("(...)"), semi] + LastJump expr -> hcat [ ptext (sLit "jump"), space, pprFun expr + , ptext (sLit "(...)"), semi] + LastReturn -> hcat [ ptext (sLit "return"), space + , ptext (sLit "(...)"), semi] LastSwitch arg ids -> ppr $ CmmSwitch arg ids LastCall tgt k -> genBareCall tgt k ) <> @@ -281,10 +299,10 @@ pprLast stmt = (case stmt of genBareCall :: CmmExpr -> Maybe BlockId -> SDoc genBareCall fn k = - hcat [ ptext SLIT("call"), space - , pprFun fn, ptext SLIT("(...)"), space - , case k of Nothing -> ptext SLIT("never returns") - Just k -> ptext SLIT("returns to") <+> ppr k + hcat [ ptext (sLit "call"), space + , pprFun fn, ptext (sLit "(...)"), space + , case k of Nothing -> ptext (sLit "never returns") + Just k -> ptext (sLit "returns to") <+> ppr k , semi ] where @@ -294,11 +312,11 @@ pprFun f = parens (ppr f) genFullCondBranch :: Outputable id => CmmExpr -> id -> id -> SDoc genFullCondBranch expr t f = - hsep [ ptext SLIT("if") + hsep [ ptext (sLit "if") , parens(ppr expr) - , ptext SLIT("goto") + , ptext (sLit "goto") , ppr t <> semi - , ptext SLIT("else goto") + , ptext (sLit "else goto") , ppr f <> semi ] @@ -308,3 +326,114 @@ pprConvention (ConventionPrivate {} ) = text "" commafy :: [SDoc] -> SDoc commafy xs = hsep $ punctuate comma xs + + +---------------------------------------------------------------- +-- | The purpose of this function is to print a Cmm zipper graph "as if it were" +-- a Cmm program. The objective is dodgy, so it's unsurprising parts of the +-- code are dodgy as well. + +pprCmmGraphLikeCmm :: CmmGraph -> SDoc +pprCmmGraphLikeCmm g = vcat (swallow blocks) + where blocks = Z.postorder_dfs g + swallow :: [CmmBlock] -> [SDoc] + swallow [] = [] + swallow (Z.Block id t : rest) = tail id [] Nothing t rest + tail id prev' out (Z.ZTail (CopyOut conv args) t) rest = + if isJust out then panic "multiple CopyOut nodes in one basic block" + else + tail id (prev') (Just (conv, args)) t rest + tail id prev' out (Z.ZTail m t) rest = tail id (mid m : prev') out t rest + tail id prev' out (Z.ZLast Z.LastExit) rest = exit id prev' out rest + tail id prev' out (Z.ZLast (Z.LastOther l)) rest = last id prev' out l rest + mid (CopyIn _ [] _) = text "// proc point (no parameters)" + mid m@(CopyIn {}) = ppr m <+> text "(proc point)" + mid m = ppr m + block' id prev' + | id == Z.lg_entry g, entry_has_no_pred = + vcat (text "" : reverse prev') + | otherwise = hang (ppr id <> colon) 4 (vcat (reverse prev')) + last id prev' out l n = + let endblock stmt = block' id (stmt : prev') : swallow n in + case l of + LastBranch tgt -> + case n of + Z.Block id' t : bs + | tgt == id', unique_pred id' + -> tail id prev' out t bs -- optimize out redundant labels + _ -> endblock (ppr $ CmmBranch tgt) + l@(LastCondBranch expr tid fid) -> + let ft id = text "// fall through to " <> ppr id in + case n of + Z.Block id' t : bs + | id' == fid, isNothing out -> + tail id (ft fid : ppr (CmmCondBranch expr tid) : prev') Nothing t bs + | id' == tid, Just e' <- maybeInvertCmmExpr expr, isNothing out-> + tail id (ft tid : ppr (CmmCondBranch e' fid) : prev') Nothing t bs + _ -> endblock $ with_out out l + l@(LastJump {}) -> endblock $ with_out out l + l@(LastReturn {}) -> endblock $ with_out out l + l@(LastSwitch {}) -> endblock $ with_out out l + l@(LastCall _ Nothing) -> endblock $ with_out out l + l@(LastCall tgt (Just k)) + | Z.Block id' (Z.ZTail (CopyIn _ ress srt) t) : bs <- n, + Just (conv, args) <- out, + id' == k -> + let call = CmmCall tgt' ress args (CmmSafe srt) CmmMayReturn + tgt' = CmmCallee tgt (cconv_of_conv conv) + ppcall = ppr call <+> parens (text "ret to" <+> ppr k) + in if unique_pred k then + tail id (ppcall : prev') Nothing t bs + else + endblock (ppcall) + | Z.Block id' t : bs <- n, id' == k, unique_pred k, + Just (conv, args) <- out, + Just (ress, srt) <- findCopyIn t -> + let call = CmmCall tgt' ress args (CmmSafe srt) CmmMayReturn + tgt' = CmmCallee tgt (cconv_of_conv conv) + delayed = + ptext (sLit "// delayed CopyIn follows previous call") + in tail id (delayed : ppr call : prev') Nothing t bs + | otherwise -> endblock $ with_out out l + findCopyIn (Z.ZTail (CopyIn _ ress srt) _) = Just (ress, srt) + findCopyIn (Z.ZTail _ t) = findCopyIn t + findCopyIn (Z.ZLast _) = Nothing + exit id prev' out n = -- highly irregular (assertion violation?) + let endblock stmt = block' id (stmt : prev') : swallow n in + case out of Nothing -> endblock (text "// ") + Just (conv, args) -> endblock (ppr (CopyOut conv args) $$ + text "// ") + preds = zipPreds g + entry_has_no_pred = case Z.lookupBlockEnv preds (Z.lg_entry g) of + Nothing -> True + Just s -> isEmptyUniqSet s + single_preds = + let add b single = + let id = Z.blockId b + in case Z.lookupBlockEnv preds id of + Nothing -> single + Just s -> if sizeUniqSet s == 1 then + Z.extendBlockSet single id + else single + in Z.fold_blocks add Z.emptyBlockSet g + unique_pred id = Z.elemBlockSet id single_preds + cconv_of_conv (ConventionStandard conv _) = conv + cconv_of_conv (ConventionPrivate {}) = CmmCallConv -- XXX totally bogus + +with_out :: Maybe (Convention, CmmActuals) -> Last -> SDoc +with_out Nothing l = ptext (sLit "??no-arguments??") <+> ppr l +with_out (Just (conv, args)) l = last l + where last (LastCall e k) = + hcat [ptext (sLit "... = foreign "), + doubleQuotes(ppr conv), space, + ppr_target e, parens ( commafy $ map ppr args ), + ptext (sLit " \"safe\""), + case k of Nothing -> ptext (sLit " never returns") + Just _ -> empty, + semi ] + last (LastReturn) = ppr (CmmReturn args) + last (LastJump e) = ppr (CmmJump e args) + last l = ppr (CopyOut conv args) $$ ppr l + ppr_target (CmmLit lit) = ppr lit + ppr_target fn' = parens (ppr fn') + commafy xs = hsep $ punctuate comma xs