[commit: ghc] master: Satisfy the invariant on CmmUnsafeForeignCall arguments (321941a)
Simon Marlow
marlowsd at gmail.com
Wed Mar 6 11:17:16 CET 2013
Repository : http://darcs.haskell.org/ghc.git/
On branch : master
http://hackage.haskell.org/trac/ghc/changeset/321941a8ebe25192cdeece723e1058f2f47809ea
>---------------------------------------------------------------
commit 321941a8ebe25192cdeece723e1058f2f47809ea
Author: Simon Marlow <marlowsd at gmail.com>
Date: Tue Mar 5 12:35:23 2013 +0000
Satisfy the invariant on CmmUnsafeForeignCall arguments
There was potentially a bug here, but no actual failures were
identified in the wild.
See Note [Register Parameter Passing]
>---------------------------------------------------------------
compiler/codeGen/StgCmmForeign.hs | 53 +++++++++++++++++----------------------
1 file changed, 23 insertions(+), 30 deletions(-)
diff --git a/compiler/codeGen/StgCmmForeign.hs b/compiler/codeGen/StgCmmForeign.hs
index aef1e4f..30bd463 100644
--- a/compiler/codeGen/StgCmmForeign.hs
+++ b/compiler/codeGen/StgCmmForeign.hs
@@ -204,23 +204,26 @@ emitForeignCall safety results target args
dflags <- getDynFlags
let (caller_save, caller_load) = callerSaveVolatileRegs dflags
emit caller_save
- emit $ mkUnsafeCall target results args
+ target' <- load_target_into_temp target
+ args' <- mapM maybe_assign_temp args
+ emit $ mkUnsafeCall target' results args'
emit caller_load
return AssignedDirectly
| otherwise = do
dflags <- getDynFlags
updfr_off <- getUpdFrameOff
- temp_target <- load_target_into_temp target
+ target' <- load_target_into_temp target
+ args' <- mapM maybe_assign_temp args
k <- newLabelC
let (off, _, copyout) = copyInOflow dflags NativeReturn (Young k) results []
-- see Note [safe foreign call convention]
emit $
( mkStore (CmmStackSlot (Young k) (widthInBytes (wordWidth dflags)))
(CmmLit (CmmBlock k))
- <*> mkLast (CmmForeignCall { tgt = temp_target
+ <*> mkLast (CmmForeignCall { tgt = target'
, res = results
- , args = args
+ , args = args'
, succ = k
, updfr = updfr_off
, intrbl = playInterruptible safety })
@@ -229,22 +232,6 @@ emitForeignCall safety results target args
)
return (ReturnedTo k off)
-
-{-
--- THINK ABOUT THIS (used to happen)
--- we might need to load arguments into temporaries before
--- making the call, because certain global registers might
--- overlap with registers that the C calling convention uses
--- for passing arguments.
>---------------------------------------------------------------
--- This is a HACK; really it should be done in the back end, but
--- it's easier to generate the temporaries here.
-load_args_into_temps = mapM arg_assign_temp
- where arg_assign_temp (e,hint) = do
- tmp <- maybe_assign_temp e
- return (tmp,hint)
--}
-
load_target_into_temp :: ForeignTarget -> FCode ForeignTarget
load_target_into_temp (ForeignTarget expr conv) = do
tmp <- maybe_assign_temp expr
@@ -252,17 +239,23 @@ load_target_into_temp (ForeignTarget expr conv) = do
load_target_into_temp other_target@(PrimTarget _) =
return other_target
+-- What we want to do here is create a new temporary for the foreign
+-- call argument if it is not safe to use the expression directly,
+-- because the expression mentions caller-saves GlobalRegs (see
+-- Note [Register Parameter Passing]).
+--
+-- However, we can't pattern-match on the expression here, because
+-- this is used in a loop by CmmParse, and testing the expression
+-- results in a black hole. So we always create a temporary, and rely
+-- on CmmSink to clean it up later. (Yuck, ToDo). The generated code
+-- ends up being the same, at least for the RTS .cmm code.
+--
maybe_assign_temp :: CmmExpr -> FCode CmmExpr
-maybe_assign_temp e
- | hasNoGlobalRegs e = return e
- | otherwise = do
- dflags <- getDynFlags
- -- don't use assignTemp, it uses its own notion of "trivial"
- -- expressions, which are wrong here.
- -- this is a NonPtr because it only duplicates an existing
- reg <- newTemp (cmmExprType dflags e) --TODO FIXME NOW
- emitAssign (CmmLocal reg) e
- return (CmmReg (CmmLocal reg))
+maybe_assign_temp e = do
+ dflags <- getDynFlags
+ reg <- newTemp (cmmExprType dflags e)
+ emitAssign (CmmLocal reg) e
+ return (CmmReg (CmmLocal reg))
-- -----------------------------------------------------------------------------
-- Save/restore the thread state in the TSO
More information about the ghc-commits
mailing list