CmmInfo(..), UpdateFrame(..),
CmmInfoTable(..), ClosureTypeInfo(..), ProfilingInfo(..), ClosureTypeTag,
GenBasicBlock(..), CmmBasicBlock, blockId, blockStmts, mapBlockStmts,
- ReturnInfo(..),
+ CmmReturnInfo(..),
CmmStmt(..), CmmActuals, CmmFormal, CmmFormals, CmmHintFormals,
CmmSafety(..),
CmmCallTarget(..),
[Maybe LocalReg] -- Forced stack parameters
C_SRT
-data ReturnInfo = MayReturn
- | NeverReturns
+data CmmReturnInfo = CmmMayReturn
+ | CmmNeverReturns
-- TODO: These types may need refinement
data ProfilingInfo = ProfilingInfo CmmLit CmmLit -- closure_type, closure_desc
CmmHintFormals -- zero or more results
CmmActuals -- zero or more arguments
CmmSafety -- whether to build a continuation
+ CmmReturnInfo
| CmmBranch BlockId -- branch to another BB in this fn
-- (redundant with ContinuationEntry)
CmmActuals -- ^ Arguments to call
C_SRT -- ^ SRT for the continuation's info table
+ CmmReturnInfo -- ^ Does the function return?
Bool -- ^ True <=> GC block so ignore stack size
| FinalSwitch -- ^ Same as a 'CmmSwitch'
-- Detect this special case to remain an inverse of
-- 'cmmBlockFromBrokenBlock'
- [CmmCall target results arguments (CmmSafe srt),
+ [CmmCall target results arguments (CmmSafe srt) ret,
CmmBranch next_id] ->
([cont_info], [block])
where
ContFormat results srt
(ident `elem` gc_block_idents))
block = do_call current_id entry accum_stmts exits next_id
- target results arguments srt
+ target results arguments srt ret
-- Break the block on safe calls (the main job of this function)
- (CmmCall target results arguments (CmmSafe srt) : stmts) ->
+ (CmmCall target results arguments (CmmSafe srt) ret : stmts) ->
(cont_info : cont_infos, block : blocks)
where
next_id = BlockId $ head uniques
block = do_call current_id entry accum_stmts exits next_id
- target results arguments srt
+ target results arguments srt ret
cont_info = (next_id, -- Entry convention for the
-- continuation of the call
-- Unsafe calls don't need a continuation
-- but they do need to be expanded
- (CmmCall target results arguments CmmUnsafe : stmts) ->
+ (CmmCall target results arguments CmmUnsafe ret : stmts) ->
breakBlock' remaining_uniques current_id entry exits
(accum_stmts ++
arg_stmts ++
caller_save ++
- [CmmCall target results new_args CmmUnsafe] ++
+ [CmmCall target results new_args CmmUnsafe ret] ++
caller_load)
stmts
where
stmts
do_call current_id entry accum_stmts exits next_id
- target results arguments srt =
+ target results arguments srt ret =
BrokenBlock current_id entry accum_stmts (next_id:exits)
- (FinalCall next_id target results arguments srt
+ (FinalCall next_id target results arguments srt ret
(current_id `elem` gc_block_idents))
cond_branch_target (CmmCondBranch _ target) = [target]
adaptBlockToFormat formats unique
block@(BrokenBlock ident entry stmts targets
exit@(FinalCall next target formals
- actuals srt is_gc)) =
+ actuals srt ret is_gc)) =
if format_formals == formals &&
format_srt == srt &&
format_is_gc == is_gc
revised_targets = adaptor_ident : delete next targets
revised_exit = FinalCall
adaptor_ident -- ^ The only part that changed
- target formals actuals srt is_gc
+ target formals actuals srt ret is_gc
adaptor_block = mk_adaptor_block adaptor_ident
(ContinuationEntry (map fst formals) srt is_gc)
FinalReturn arguments -> [CmmReturn arguments]
FinalJump target arguments -> [CmmJump target arguments]
FinalSwitch expr targets -> [CmmSwitch expr targets]
- FinalCall branch_target call_target results arguments srt _ ->
- [CmmCall call_target results arguments (CmmSafe srt),
+ FinalCall branch_target call_target results arguments srt ret _ ->
+ [CmmCall call_target results arguments (CmmSafe srt) ret,
CmmBranch branch_target]
-----------------------------------------------------------------------------
argumentsSize (cmmExprRep . fst) args
final_arg_size (FinalJump _ args) =
argumentsSize (cmmExprRep . fst) args
- final_arg_size (FinalCall next _ _ args _ True) = 0
- final_arg_size (FinalCall next _ _ args _ False) =
+ final_arg_size (FinalCall next _ _ args _ _ True) = 0
+ final_arg_size (FinalCall next _ _ args _ _ False) =
-- We have to account for the stack used when we build a frame
-- for the *next* continuation from *this* continuation
argumentsSize (cmmExprRep . fst) args +
stmt_arg_size (CmmJump _ args) =
argumentsSize (cmmExprRep . fst) args
- stmt_arg_size (CmmCall _ _ _ (CmmSafe _)) =
+ stmt_arg_size (CmmCall _ _ _ (CmmSafe _) _) =
panic "Safe call in processFormats"
stmt_arg_size (CmmReturn _) =
panic "CmmReturn in processFormats"
-- A regular Cmm function call
FinalCall next (CmmCallee target CmmCallConv)
- results arguments _ _ ->
+ results arguments _ _ _ ->
pack_continuation curr_format cont_format ++
tail_call (curr_stack - cont_stack)
target arguments
-- A safe foreign call
FinalCall next (CmmCallee target conv)
- results arguments _ _ ->
+ results arguments _ _ _ ->
target_stmts ++
foreignCall call_uniques' (CmmCallee new_target conv)
results arguments
-- A safe prim call
FinalCall next (CmmPrim target)
- results arguments _ _ ->
+ results arguments _ _ _ ->
foreignCall call_uniques (CmmPrim target)
results arguments
[CmmCall (CmmCallee suspendThread CCallConv)
[ (id,PtrHint) ]
[ (CmmReg (CmmGlobal BaseReg), PtrHint) ]
- CmmUnsafe,
- CmmCall call results new_args CmmUnsafe,
+ CmmUnsafe
+ CmmMayReturn,
+ CmmCall call results new_args CmmUnsafe CmmMayReturn,
CmmCall (CmmCallee resumeThread CCallConv)
[ (new_base, PtrHint) ]
[ (CmmReg (CmmLocal id), PtrHint) ]
- CmmUnsafe,
+ CmmUnsafe
+ CmmMayReturn,
-- Assign the result to BaseReg: we
-- might now have a different Capability!
CmmAssign (CmmGlobal BaseReg) (CmmReg (CmmLocal new_base))] ++
lintCmmExpr l
lintCmmExpr r
return ()
-lintCmmStmt (CmmCall _target _res args _) = mapM_ (lintCmmExpr.fst) args
+lintCmmStmt (CmmCall _target _res args _ _) = mapM_ (lintCmmExpr.fst) args
lintCmmStmt (CmmCondBranch e _id) = lintCmmExpr e >> checkCond e >> return ()
lintCmmStmt (CmmSwitch e _branches) = do
erep <- lintCmmExpr e
(CmmGlobal _) -> id
cmmStmtLive _ (CmmStore expr1 expr2) =
cmmExprLive expr2 . cmmExprLive expr1
-cmmStmtLive _ (CmmCall target results arguments _) =
+cmmStmtLive _ (CmmCall target results arguments _ _) =
target_liveness .
foldr ((.) . cmmExprLive) id (map fst arguments) .
addKilled (mkUniqSet $ cmmHintFormalsToLiveLocals results) where
getStmtUses :: CmmStmt -> UniqFM Int
getStmtUses (CmmAssign _ e) = getExprUses e
getStmtUses (CmmStore e1 e2) = plusUFM_C (+) (getExprUses e1) (getExprUses e2)
-getStmtUses (CmmCall target _ es _)
+getStmtUses (CmmCall target _ es _ _)
= plusUFM_C (+) (uses target) (getExprsUses (map fst es))
where uses (CmmCallee e _) = getExprUses e
uses _ = emptyUFM
inlineStmt :: Unique -> CmmExpr -> CmmStmt -> CmmStmt
inlineStmt u a (CmmAssign r e) = CmmAssign r (inlineExpr u a e)
inlineStmt u a (CmmStore e1 e2) = CmmStore (inlineExpr u a e1) (inlineExpr u a e2)
-inlineStmt u a (CmmCall target regs es srt)
- = CmmCall (infn target) regs es' srt
+inlineStmt u a (CmmCall target regs es srt ret)
+ = CmmCall (infn target) regs es' srt ret
where infn (CmmCallee fn cconv) = CmmCallee fn cconv
infn (CmmPrim p) = CmmPrim p
es' = [ (inlineExpr u a e, hint) | (e,hint) <- es ]
| 'if' bool_expr '{' body '}' else
{ ifThenElse $2 $4 $6 }
-opt_never_returns :: { ReturnInfo }
- : { MayReturn }
- | 'never' 'returns' { NeverReturns }
+opt_never_returns :: { CmmReturnInfo }
+ : { CmmMayReturn }
+ | 'never' 'returns' { CmmNeverReturns }
bool_expr :: { ExtFCode BoolExpr }
: bool_op { $1 }
-> [ExtFCode (CmmExpr,MachHint)]
-> Maybe [GlobalReg]
-> CmmSafety
- -> ReturnInfo
+ -> CmmReturnInfo
-> P ExtCode
-foreignCall conv_string results_code expr_code args_code vols safety _ret
+foreignCall conv_string results_code expr_code args_code vols safety ret
= do convention <- case conv_string of
"C" -> return CCallConv
"C--" -> return CmmCallConv
--code (stmtC (CmmCall (CmmCallee expr convention) results args safety))
case convention of
-- Temporary hack so at least some functions are CmmSafe
- CmmCallConv -> code (stmtC (CmmCall (CmmCallee expr convention) results args safety))
+ CmmCallConv -> code (stmtC (CmmCall (CmmCallee expr convention) results args safety ret))
_ -> case safety of
CmmUnsafe ->
code (emitForeignCall' PlayRisky results
- (CmmCallee expr convention) args vols NoC_SRT)
+ (CmmCallee expr convention) args vols NoC_SRT ret)
CmmSafe srt ->
code (emitForeignCall' (PlaySafe unused) results
- (CmmCallee expr convention) args vols NoC_SRT) where
+ (CmmCallee expr convention) args vols NoC_SRT ret) where
unused = panic "not used by emitForeignCall'"
primCall
case safety of
CmmUnsafe ->
code (emitForeignCall' PlayRisky results
- (CmmPrim p) args vols NoC_SRT)
+ (CmmPrim p) args vols NoC_SRT CmmMayReturn)
CmmSafe srt ->
code (emitForeignCall' (PlaySafe unused) results
- (CmmPrim p) args vols NoC_SRT) where
+ (CmmPrim p) args vols NoC_SRT CmmMayReturn) where
unused = panic "not used by emitForeignCall'"
doStore :: MachRep -> ExtFCode CmmExpr -> ExtFCode CmmExpr -> ExtCode
where
rep = cmmExprRep src
- CmmCall (CmmCallee fn cconv) results args safety ->
+ CmmCall (CmmCallee fn cconv) results args safety _ret ->
-- Controversial: leave this out for now.
-- pprUndef fn $$
ptext SLIT("#undef") <+> pprCLabel lbl
pprUndef _ = empty
- CmmCall (CmmPrim op) results args safety ->
+ CmmCall (CmmPrim op) results args safety _ret ->
pprCall ppr_fn CCallConv results args safety
where
ppr_fn = pprCallishMachOp_for_C op
te_Stmt :: CmmStmt -> TE ()
te_Stmt (CmmAssign r e) = te_Reg r >> te_Expr e
te_Stmt (CmmStore l r) = te_Expr l >> te_Expr r
-te_Stmt (CmmCall _ rs es _) = mapM_ (te_temp.fst) rs >>
+te_Stmt (CmmCall _ rs es _ _) = mapM_ (te_temp.fst) rs >>
mapM_ (te_Expr.fst) es
te_Stmt (CmmCondBranch e _) = te_Expr e
te_Stmt (CmmSwitch e _) = te_Expr e
-- call "ccall" foo(x, y)[r1, r2];
-- ToDo ppr volatile
- CmmCall (CmmCallee fn cconv) results args safety ->
+ CmmCall (CmmCallee fn cconv) results args safety ret ->
hcat [ if null results
then empty
else parens (commafy $ map ppr results) <>
ptext SLIT("call"), space,
doubleQuotes(ppr cconv), space,
target fn, parens ( commafy $ map ppr args ),
- brackets (ppr safety), 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 safety ->
+ CmmCall (CmmPrim op) results args safety ret ->
pprStmt (CmmCall (CmmCallee (CmmLit lbl) CCallConv)
- results args safety)
+ results args safety ret)
where
lbl = CmmLabel (mkForeignLabel (mkFastString (show op)) Nothing False)
= do vols <- getVolatileRegs live
srt <- getSRTInfo
emitForeignCall' safety results
- (CmmCallee cmm_target cconv) call_args (Just vols) srt
+ (CmmCallee cmm_target cconv) call_args (Just vols) srt CmmMayReturn
where
(call_args, cmm_target)
= case target of
-> [(CmmExpr,MachHint)] -- arguments
-> Maybe [GlobalReg] -- live vars, in case we need to save them
-> C_SRT -- the SRT of the calls continuation
+ -> CmmReturnInfo
-> Code
-emitForeignCall' safety results target args vols srt
+emitForeignCall' safety results target args vols srt ret
| not (playSafe safety) = do
temp_args <- load_args_into_temps args
let (caller_save, caller_load) = callerSaveVolatileRegs vols
stmtsC caller_save
- stmtC (CmmCall target results temp_args CmmUnsafe)
+ stmtC (CmmCall target results temp_args CmmUnsafe ret)
stmtsC caller_load
| otherwise = do
stmtC (CmmCall (CmmCallee suspendThread CCallConv)
[ (id,PtrHint) ]
[ (CmmReg (CmmGlobal BaseReg), PtrHint) ]
- CmmUnsafe)
- stmtC (CmmCall temp_target results temp_args CmmUnsafe)
+ CmmUnsafe ret)
+ stmtC (CmmCall temp_target results temp_args CmmUnsafe ret)
stmtC (CmmCall (CmmCallee resumeThread CCallConv)
[ (new_base, PtrHint) ]
[ (CmmReg (CmmLocal id), PtrHint) ]
- CmmUnsafe)
+ CmmUnsafe ret)
-- Assign the result to BaseReg: we
-- might now have a different Capability!
stmtC (CmmAssign (CmmGlobal BaseReg) (CmmReg (CmmLocal new_base)))
]
(Just [])
NoC_SRT -- No SRT b/c we PlayRisky
+ CmmMayReturn
}
where
mod_alloc = mkFastString "hs_hpc_module"
[(CmmReg (CmmGlobal BaseReg), PtrHint), (arg,PtrHint)]
(Just vols)
NoC_SRT -- No SRT b/c we do PlayRisky
+ CmmMayReturn
where
newspark = CmmLit (CmmLabel (mkRtsCodeLabel SLIT("newSpark")))
[(CmmReg (CmmGlobal BaseReg), PtrHint), (mutv,PtrHint)]
(Just vols)
NoC_SRT -- No SRT b/c we do PlayRisky
+ CmmMayReturn
-- #define sizzeofByteArrayzh(r,a) \
-- r = (((StgArrWords *)(a))->words * sizeof(W_))
[(a,NoHint) | a<-args] -- ToDo: hints?
(Just vols)
NoC_SRT -- No SRT b/c we do PlayRisky
+ CmmMayReturn
| Just mop <- translateOp op
= let stmt = CmmAssign (CmmLocal res) (CmmMachOp mop args) in
then getSRTInfo >>= (return . CmmSafe)
else return CmmUnsafe
stmtsC caller_save
- stmtC (CmmCall target res args safety)
+ stmtC (CmmCall target res args safety CmmMayReturn)
stmtsC caller_load
where
(caller_save, caller_load) = callerSaveVolatileRegs vols
-> do addr' <- cmmExprConFold JumpReference addr
return $ CmmJump addr' regs
- CmmCall target regs args srt
+ CmmCall target regs args srt returns
-> do target' <- case target of
CmmCallee e conv -> do
e' <- cmmExprConFold CallReference e
args' <- mapM (\(arg, hint) -> do
arg' <- cmmExprConFold DataReference arg
return (arg', hint)) args
- return $ CmmCall target' regs args' srt
+ return $ CmmCall target' regs args' srt returns
CmmCondBranch test dest
-> do test' <- cmmExprConFold DataReference test
| otherwise -> assignMem_IntCode kind addr src
where kind = cmmExprRep src
- CmmCall target result_regs args _
+ CmmCall target result_regs args _ _
-> genCCall target result_regs args
CmmBranch id -> genBranch id
if localRegRep res == F64
then
- stmtToInstrs (CmmCall target [(res,FloatHint)] args CmmUnsafe)
+ stmtToInstrs (CmmCall target [(res,FloatHint)] args CmmUnsafe CmmMayReturn)
else do
uq <- getUniqueNat
let
tmp = LocalReg uq F64 KindNonPtr
-- in
- code1 <- stmtToInstrs (CmmCall target [(tmp,FloatHint)] args CmmUnsafe)
+ code1 <- stmtToInstrs (CmmCall target [(tmp,FloatHint)] args CmmUnsafe CmmMayReturn)
code2 <- stmtToInstrs (CmmAssign (CmmLocal res) (CmmReg (CmmLocal tmp)))
return (code1 `appOL` code2)
where