X-Git-Url: http://git.megacz.com/?p=ghc-hetmet.git;a=blobdiff_plain;f=compiler%2Fcmm%2FZipCfgCmmRep.hs;h=05203e54d2a081a8cab3b04aa51d28e099daa6c0;hp=e030f4bc58a4a0f72c5c171baf4bf24e58cce8df;hb=e6243a818496aad82b6f47511d3bd9bc800f747d;hpb=176fa33f17dd78355cc572e006d2ab26898e2c69 diff --git a/compiler/cmm/ZipCfgCmmRep.hs b/compiler/cmm/ZipCfgCmmRep.hs index e030f4b..05203e5 100644 --- a/compiler/cmm/ZipCfgCmmRep.hs +++ b/compiler/cmm/ZipCfgCmmRep.hs @@ -1,5 +1,3 @@ - - -- This module is pure representation and should be imported only by -- clients that need to manipulate representation and know what -- they're doing. Clients that need to create flow graphs should @@ -7,13 +5,12 @@ module ZipCfgCmmRep ( CmmZ, CmmTopZ, CmmGraph, CmmBlock, CmmAGraph - , Middle(..), Last(..), MidCallTarget(..) - , Convention(..), ForeignConvention(..) + , Middle(..), Last(..), MidCallTarget(..), UpdFrameOffset + , Convention(..), ForeignConvention(..), ForeignSafety(..) , ValueDirection(..), ForeignHint(..) , CmmBackwardFixedPoint, CmmForwardFixedPoint, pprHinted , insertBetween, mapExpMiddle, mapExpLast, mapExpDeepMiddle, mapExpDeepLast - , foldExpMiddle, foldExpLast, foldExpDeepMiddle, foldExpDeepLast - , joinOuts + , foldExpMiddle, foldExpLast, foldExpDeepMiddle, foldExpDeepLast, joinOuts ) where @@ -43,6 +40,7 @@ import Monad import Outputable import Prelude hiding (zip, unzip, last) import qualified Data.List as L +import SMRep (ByteOff) import UniqSupply ---------------------------------------------------------------------- @@ -56,6 +54,8 @@ type CmmTopZ = GenCmmTop CmmStatic CmmInfo CmmGraph type CmmBackwardFixedPoint a = DF.BackwardFixedPoint Middle Last a () type CmmForwardFixedPoint a = DF.ForwardFixedPoint Middle Last a () +type UpdFrameOffset = ByteOff + data Middle = MidComment FastString @@ -64,18 +64,11 @@ data Middle | MidStore CmmExpr CmmExpr -- Assign to memory location. Size is -- given by cmmExprType of the rhs. - | MidUnsafeCall -- An "unsafe" foreign call; - MidCallTarget -- just a fat machine instructoin + | MidForeignCall -- A foreign call; + ForeignSafety -- Is it a safe or unsafe call? + MidCallTarget -- call target and convention 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 deriving Eq data Last @@ -90,13 +83,17 @@ data Last -- zero -> first block -- one -> second block etc -- Undefined outside range, and when there's a Nothing - | LastReturn Int -- Return from a function; values in previous copy middles - | LastJump CmmExpr Int -- Tail call to another procedure; args in a copy middles - | LastCall { -- A call (native or safe foreign); args in copy middles - cml_target :: CmmExpr, -- never a CmmPrim to a CallishMachOp! - cml_cont :: Maybe BlockId,-- BlockId of continuation, if call returns - cml_args :: Int } -- liveness info for outgoing args - -- All the last nodes that pass arguments carry the size of the outgoing CallArea + | LastCall { -- A call (native or safe foreign) + cml_target :: CmmExpr, -- never a CmmPrim to a CallishMachOp! + cml_cont :: Maybe BlockId, + -- BlockId of continuation (Nothing for return or tail call) + cml_args :: ByteOff, -- bytes offset for youngest outgoing arg + cml_ret_off :: Maybe UpdFrameOffset} + -- stack offset for return (update frames); + -- The return offset should be Nothing only if we have to create + -- a new call, e.g. for a procpoint, in which case it's an invariant + -- that the call does not stand for a return or a tail call, + -- and the successor does not need an info table. data MidCallTarget -- The target of a MidUnsafeCall = ForeignTarget -- A foreign procedure @@ -110,6 +107,12 @@ data MidCallTarget -- The target of a MidUnsafeCall data Convention = Native -- Native C-- call/return + | Slow -- Slow entry points: all args pushed on the stack + + | GC -- Entry to the garbage collector: uses the node reg! + + | PrimOp -- Calling prim ops + | Foreign -- Foreign call/return ForeignConvention @@ -128,6 +131,12 @@ data ForeignConvention [ForeignHint] -- Extra info about the result deriving Eq +data ForeignSafety + = Unsafe -- unsafe call + | Safe BlockId -- making infotable requires: 1. label + UpdFrameOffset -- 2. where the upd frame is + deriving Eq + data ValueDirection = Arguments | Results -- Arguments go with procedure definitions, jumps, and arguments to calls -- Results go with returns and with results of calls. @@ -161,13 +170,11 @@ insertBetween b ms succId = insert $ goto_end $ unzip b insert (h, LastOther (LastSwitch e ks)) = do (ids, bs) <- mapAndUnzipM mbNewBlocks ks return (zipht h $ ZLast $ LastOther (LastSwitch e ids), join bs) - insert (_, LastOther (LastCall _ _ _)) = + insert (_, LastOther (LastCall {})) = panic "unimp: insertBetween after a call -- probably not a good idea" - insert (_, LastOther (LastReturn _)) = panic "cannot insert after return" - insert (_, LastOther (LastJump _ _)) = panic "cannot insert after jump" insert (_, LastExit) = panic "cannot insert after exit" newBlocks = do id <- liftM BlockId $ getUniqueM - return $ (id, [Block id Nothing $ + return $ (id, [Block id emptyStackInfo $ foldr ZTail (ZLast (LastOther (LastBranch succId))) ms]) mbNewBlocks (Just k) = if k == succId then liftM lift newBlocks else return (Just k, []) @@ -189,33 +196,28 @@ instance LastNode Last where branchNodeTarget _ = panic "asked for target of non-branch" cmmSuccs :: Last -> [BlockId] -cmmSuccs (LastReturn _) = [] -cmmSuccs (LastJump {}) = [] -cmmSuccs (LastBranch id) = [id] -cmmSuccs (LastCall _ (Just id) _) = [id] -cmmSuccs (LastCall _ Nothing _) = [] -cmmSuccs (LastCondBranch _ t f) = [f, t] -- meets layout constraint -cmmSuccs (LastSwitch _ edges) = catMaybes edges +cmmSuccs (LastBranch id) = [id] +cmmSuccs (LastCall _ Nothing _ _) = [] +cmmSuccs (LastCall _ (Just id) _ _) = [id] +cmmSuccs (LastCondBranch _ t f) = [f, t] -- meets layout constraint +cmmSuccs (LastSwitch _ edges) = catMaybes edges fold_cmm_succs :: (BlockId -> a -> a) -> Last -> a -> a -fold_cmm_succs _f (LastReturn _) z = z -fold_cmm_succs _f (LastJump {}) z = z -fold_cmm_succs f (LastBranch id) z = f id z -fold_cmm_succs f (LastCall _ (Just id) _) z = f id z -fold_cmm_succs _f (LastCall _ Nothing _) z = z -fold_cmm_succs f (LastCondBranch _ te fe) z = f te (f fe z) -fold_cmm_succs f (LastSwitch _ edges) z = foldl (flip f) z $ catMaybes edges +fold_cmm_succs f (LastBranch id) z = f id z +fold_cmm_succs _ (LastCall _ Nothing _ _) z = z +fold_cmm_succs f (LastCall _ (Just id) _ _) z = f id z +fold_cmm_succs f (LastCondBranch _ te fe) z = f te (f fe z) +fold_cmm_succs f (LastSwitch _ edges) z = foldl (flip f) z $ catMaybes edges ---------------------------------------------------------------------- ----- Instance declarations for register use instance UserOfLocalRegs Middle where foldRegsUsed f z m = middle m - where middle (MidComment {}) = z - middle (MidAssign _lhs expr) = fold f z expr - middle (MidStore addr rval) = fold f (fold f z addr) rval - middle (MidUnsafeCall tgt _ args) = fold f (fold f z tgt) args - middle (MidAddToContext ra args) = fold f (fold f z ra) args + where middle (MidComment {}) = z + middle (MidAssign _lhs expr) = fold f z expr + middle (MidStore addr rval) = fold f (fold f z addr) rval + middle (MidForeignCall _ tgt _ args) = fold f (fold f z tgt) args fold f z m = foldRegsUsed f z m -- avoid monomorphism restriction instance UserOfLocalRegs MidCallTarget where @@ -226,22 +228,27 @@ instance UserOfSlots MidCallTarget where foldSlotsUsed _f z (PrimTarget _) = z foldSlotsUsed f z (ForeignTarget e _) = foldSlotsUsed f z e +instance (UserOfLocalRegs a) => UserOfLocalRegs (Maybe a) where + foldRegsUsed f z (Just x) = foldRegsUsed f z x + foldRegsUsed _ z Nothing = z + +instance (UserOfSlots a) => UserOfSlots (Maybe a) where + foldSlotsUsed f z (Just x) = foldSlotsUsed f z x + foldSlotsUsed _ z Nothing = z + instance UserOfLocalRegs Last where foldRegsUsed f z l = last l - where last (LastReturn _) = z - last (LastJump e _) = foldRegsUsed f z e - last (LastBranch _id) = z - last (LastCall tgt _ _) = foldRegsUsed f z tgt + where last (LastBranch _id) = z + last (LastCall tgt _ _ _) = foldRegsUsed f z tgt last (LastCondBranch e _ _) = foldRegsUsed f z e last (LastSwitch e _tbl) = foldRegsUsed f z e instance DefinerOfLocalRegs Middle where foldRegsDefd f z m = middle m - where middle (MidComment {}) = z - middle (MidAssign _lhs _) = fold f z _lhs - middle (MidStore _ _) = z - middle (MidUnsafeCall _ _ _) = z - middle (MidAddToContext _ _) = z + where middle (MidComment {}) = z + middle (MidAssign _lhs _) = fold f z _lhs + middle (MidStore _ _) = z + middle (MidForeignCall _ _ fs _) = fold f z fs fold f z m = foldRegsDefd f z m -- avoid monomorphism restriction instance DefinerOfLocalRegs Last where @@ -253,19 +260,16 @@ instance DefinerOfLocalRegs Last where instance UserOfSlots Middle where foldSlotsUsed f z m = middle m - where middle (MidComment {}) = z - 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 + where middle (MidComment {}) = z + middle (MidAssign _lhs expr) = fold f z expr + middle (MidStore addr rval) = fold f (fold f z addr) rval + middle (MidForeignCall _ tgt _ress args) = fold f (fold f z tgt) args fold f z e = foldSlotsUsed f z e -- avoid monomorphism restriction instance UserOfSlots Last where foldSlotsUsed f z l = last l - where last (LastReturn _) = z - last (LastJump e _) = foldSlotsUsed f z e - last (LastBranch _id) = z - last (LastCall tgt _ _) = foldSlotsUsed f z tgt + where last (LastBranch _id) = z + last (LastCall tgt _ _ _) = foldSlotsUsed f z tgt last (LastCondBranch e _ _) = foldSlotsUsed f z e last (LastSwitch e _tbl) = foldSlotsUsed f z e @@ -275,13 +279,12 @@ instance UserOfSlots l => UserOfSlots (ZLast l) where instance DefinerOfSlots Middle where foldSlotsDefd f z m = middle m - where middle (MidComment {}) = z - middle (MidAssign _ _) = z + where middle (MidComment {}) = z + middle (MidAssign _ _) = z + middle (MidForeignCall {}) = z middle (MidStore (CmmStackSlot a i) e) = f z (a, i, widthInBytes $ typeWidth $ cmmExprType e) - middle (MidStore _ _) = z - middle (MidUnsafeCall _ _ _) = z - middle (MidAddToContext _ _) = z + middle (MidStore _ _) = z instance DefinerOfSlots Last where foldSlotsDefd _ z _ = z @@ -297,32 +300,26 @@ mapExpMiddle :: (CmmExpr -> CmmExpr) -> Middle -> Middle mapExpMiddle _ m@(MidComment _) = m mapExpMiddle exp (MidAssign r e) = MidAssign r (exp e) mapExpMiddle exp (MidStore addr e) = MidStore (exp addr) (exp e) -mapExpMiddle exp (MidUnsafeCall tgt fs as) = - MidUnsafeCall (mapExpMidcall exp tgt) fs (map exp as) -mapExpMiddle exp (MidAddToContext e es) = MidAddToContext (exp e) (map exp es) +mapExpMiddle exp (MidForeignCall s tgt fs as) = + MidForeignCall s (mapExpMidcall exp tgt) fs (map exp as) foldExpMiddle :: (CmmExpr -> z -> z) -> Middle -> z -> z -foldExpMiddle _ (MidComment _) z = z -foldExpMiddle exp (MidAssign _ e) z = exp e z -foldExpMiddle exp (MidStore addr e) z = exp addr $ exp e z -foldExpMiddle exp (MidUnsafeCall tgt _ as) z = foldExpMidcall exp tgt $ foldr exp z as -foldExpMiddle exp (MidAddToContext e es) z = exp e $ foldr exp z es +foldExpMiddle _ (MidComment _) z = z +foldExpMiddle exp (MidAssign _ e) z = exp e z +foldExpMiddle exp (MidStore addr e) z = exp addr $ exp e z +foldExpMiddle exp (MidForeignCall _ tgt _ as) z = foldExpMidcall exp tgt $ foldr exp z as mapExpLast :: (CmmExpr -> CmmExpr) -> Last -> Last -mapExpLast _ l@(LastBranch _) = l -mapExpLast exp (LastCondBranch e ti fi) = LastCondBranch (exp e) ti fi -mapExpLast exp (LastSwitch e tbl) = LastSwitch (exp e) tbl -mapExpLast exp (LastCall tgt mb_id s) = LastCall (exp tgt) mb_id s -mapExpLast exp (LastJump e s) = LastJump (exp e) s -mapExpLast _ (LastReturn s) = LastReturn s +mapExpLast _ l@(LastBranch _) = l +mapExpLast exp (LastCondBranch e ti fi) = LastCondBranch (exp e) ti fi +mapExpLast exp (LastSwitch e tbl) = LastSwitch (exp e) tbl +mapExpLast exp (LastCall tgt mb_id u s) = LastCall (exp tgt) mb_id u s foldExpLast :: (CmmExpr -> z -> z) -> Last -> z -> z foldExpLast _ (LastBranch _) z = z foldExpLast exp (LastCondBranch e _ _) z = exp e z foldExpLast exp (LastSwitch e _) z = exp e z -foldExpLast exp (LastCall tgt _ _) z = exp tgt z -foldExpLast exp (LastJump e _) z = exp e z -foldExpLast _ (LastReturn _) z = z +foldExpLast exp (LastCall tgt _ _ _) z = exp tgt z mapExpMidcall :: (CmmExpr -> CmmExpr) -> MidCallTarget -> MidCallTarget mapExpMidcall exp (ForeignTarget e c) = ForeignTarget (exp e) c @@ -334,8 +331,8 @@ foldExpMidcall _ (PrimTarget _) z = z -- Take a transformer on expressions and apply it recursively. wrapRecExp :: (CmmExpr -> CmmExpr) -> CmmExpr -> CmmExpr -wrapRecExp f (CmmMachOp op es) = f (CmmMachOp op $ map f es) -wrapRecExp f (CmmLoad addr ty) = f (CmmLoad (f addr) ty) +wrapRecExp f (CmmMachOp op es) = f (CmmMachOp op $ map (wrapRecExp f) es) +wrapRecExp f (CmmLoad addr ty) = f (CmmLoad (wrapRecExp f addr) ty) wrapRecExp f e = f e mapExpDeepMiddle :: (CmmExpr -> CmmExpr) -> Middle -> Middle @@ -345,8 +342,8 @@ mapExpDeepLast f = mapExpLast $ wrapRecExp f -- Take a folder on expressions and apply it recursively. wrapRecExpf :: (CmmExpr -> z -> z) -> CmmExpr -> z -> z -wrapRecExpf f e@(CmmMachOp _ es) z = foldr f (f e z) es -wrapRecExpf f e@(CmmLoad addr _) z = f addr (f e z) +wrapRecExpf f e@(CmmMachOp _ es) z = foldr (wrapRecExpf f) (f e z) es +wrapRecExpf f e@(CmmLoad addr _) z = wrapRecExpf f addr (f e z) wrapRecExpf f e z = f e z foldExpDeepMiddle :: (CmmExpr -> z -> z) -> Middle -> z -> z @@ -362,13 +359,11 @@ joinOuts lattice env l = let bot = fact_bot lattice join x y = txVal $ fact_add_to lattice x y in case l of - (LastReturn _) -> bot - (LastJump _ _) -> bot - (LastBranch id) -> env id - (LastCall _ Nothing _) -> bot - (LastCall _ (Just k) _) -> env k - (LastCondBranch _ t f) -> join (env t) (env f) - (LastSwitch _ tbl) -> foldr join bot (map env $ catMaybes tbl) + (LastBranch id) -> env id + (LastCall _ Nothing _ _) -> bot + (LastCall _ (Just k) _ _) -> env k + (LastCondBranch _ t f) -> join (env t) (env f) + (LastSwitch _ tbl) -> foldr join bot (map env $ catMaybes tbl) ---------------------------------------------------------------------- ----- Instance declarations for prettyprinting (avoids recursive imports) @@ -411,30 +406,30 @@ pprMiddle stmt = pp_stmt <+> pp_debug -- call "ccall" foo(x, y)[r1, r2]; -- ToDo ppr volatile - MidUnsafeCall target results args -> + MidForeignCall safety target results args -> hsep [ if null results then empty else parens (commafy $ map ppr results) <+> equals, + ppr_safety safety, ptext $ sLit "call", ppr_call_target target <> parens (commafy $ map ppr args) <> semi] - 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 - MidComment {} -> text "MidComment" - MidAssign {} -> text "MidAssign" - MidStore {} -> text "MidStore" - MidUnsafeCall {} -> text "MidUnsafeCall" - MidAddToContext {} -> text "MidAddToContext" + MidComment {} -> text "MidComment" + MidAssign {} -> text "MidAssign" + MidStore {} -> text "MidStore" + MidForeignCall {} -> text "MidForeignCall" ppr_fc :: ForeignConvention -> SDoc ppr_fc (ForeignConvention c _ _) = doubleQuotes (ppr c) +ppr_safety :: ForeignSafety -> SDoc +ppr_safety (Safe bid upd) = text "safe<" <> ppr bid <> text ", " <> ppr upd <> text ">" +ppr_safety Unsafe = text "unsafe" + ppr_call_target :: MidCallTarget -> SDoc ppr_call_target (ForeignTarget fn c) = ppr_fc c <+> ppr_target fn ppr_call_target (PrimTarget op) = ppr (CmmLabel (mkForeignLabel (mkFastString (show op)) Nothing False)) @@ -452,31 +447,24 @@ pprLast :: Last -> SDoc pprLast stmt = pp_stmt <+> pp_debug where pp_stmt = case stmt of - 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] - LastSwitch arg ids -> ppr $ CmmSwitch arg ids - LastCall tgt k _ -> genBareCall tgt k + LastBranch ident -> ptext (sLit "goto") <+> ppr ident <> semi + LastCondBranch expr t f -> genFullCondBranch expr t f + LastSwitch arg ids -> ppr $ CmmSwitch arg ids + LastCall tgt k off updfr_off -> genBareCall tgt k off updfr_off pp_debug = text " //" <+> case stmt of LastBranch {} -> text "LastBranch" LastCondBranch {} -> text "LastCondBranch" - LastJump {} -> text "LastJump" - LastReturn {} -> text "LastReturn" LastSwitch {} -> text "LastSwitch" LastCall {} -> text "LastCall" -genBareCall :: CmmExpr -> Maybe BlockId -> SDoc -genBareCall fn k = +genBareCall :: CmmExpr -> Maybe BlockId -> Int -> Maybe UpdFrameOffset -> SDoc +genBareCall fn k off updfr_off = 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 + , ptext (sLit "returns to") <+> ppr k <+> parens (ppr off) + , ptext (sLit " with update frame") <+> ppr updfr_off , semi ] - where pprFun :: CmmExpr -> SDoc pprFun f@(CmmLit _) = ppr f @@ -493,7 +481,10 @@ genFullCondBranch expr t f = ] pprConvention :: Convention -> SDoc -pprConvention (Native {}) = empty +pprConvention (Native {}) = text "" +pprConvention Slow = text "" +pprConvention GC = text "" +pprConvention PrimOp = text "" pprConvention (Foreign c) = ppr c pprConvention (Private {}) = text ""