X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=compiler%2Fcmm%2FZipCfgCmmRep.hs;h=43e310c80c3f242393496d1d66a344c07481a2b5;hb=74f14cbc3c51135809977b29427c7c6a2af2cc34;hp=05203e54d2a081a8cab3b04aa51d28e099daa6c0;hpb=e6243a818496aad82b6f47511d3bd9bc800f747d;p=ghc-hetmet.git diff --git a/compiler/cmm/ZipCfgCmmRep.hs b/compiler/cmm/ZipCfgCmmRep.hs index 05203e5..43e310c 100644 --- a/compiler/cmm/ZipCfgCmmRep.hs +++ b/compiler/cmm/ZipCfgCmmRep.hs @@ -64,7 +64,7 @@ data Middle | MidStore CmmExpr CmmExpr -- Assign to memory location. Size is -- given by cmmExprType of the rhs. - | MidForeignCall -- A foreign call; + | MidForeignCall -- A foreign call; see Note [Foreign calls] ForeignSafety -- Is it a safe or unsafe call? MidCallTarget -- call target and convention CmmFormals -- zero or more results @@ -87,7 +87,8 @@ data Last 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_args :: ByteOff, -- byte offset for youngest outgoing arg + -- (includes update frame, which must be younger) cml_ret_off :: Maybe UpdFrameOffset} -- stack offset for return (update frames); -- The return offset should be Nothing only if we have to create @@ -141,6 +142,33 @@ data ValueDirection = Arguments | Results -- Arguments go with procedure definitions, jumps, and arguments to calls -- Results go with returns and with results of calls. deriving Eq + +{- Note [Foreign calls] +~~~~~~~~~~~~~~~~~~~~~~~ +A MidForeign call is used *all* foreign calls, both *unsafe* and *safe*. +Unsafe ones are easy: think of them as a "fat machine instruction". + +Safe ones are trickier. A safe foreign call + r = f(x) +ultimately expands to + push "return address" -- Never used to return to; + -- just points an info table + save registers into TSO + call suspendThread + r = f(x) -- Make the call + call resumeThread + restore registers + pop "return address" +We cannot "lower" a safe foreign call to this sequence of Cmms, because +after we've saved Sp all the Cmm optimiser's assumptions are broken. +Furthermore, currently the smart Cmm constructors know the calling +conventions for Haskell, the garbage collector, etc, and "lower" them +so that a LastCall passes no parameters or results. But the smart +constructors do *not* (currently) know the foreign call conventions. + +For these reasons use MidForeignCall for all calls. The only annoying thing +is that a safe foreign call needs an info table. +-} ---------------------------------------------------------------------- ----- Splicing between blocks