module GHC.StgToCmm.Bind (
cgTopRhsClosure,
cgBind,
emitBlackHoleCode,
pushUpdateFrame, emitUpdateFrame
) where
import GhcPrelude hiding ((<*>))
import GHC.StgToCmm.Expr
import GHC.StgToCmm.Monad
import GHC.StgToCmm.Env
import GHC.StgToCmm.DataCon
import GHC.StgToCmm.Heap
import GHC.StgToCmm.Prof (ldvEnterClosure, enterCostCentreFun, enterCostCentreThunk,
initUpdFrameProf)
import GHC.StgToCmm.Ticky
import GHC.StgToCmm.Layout
import GHC.StgToCmm.Utils
import GHC.StgToCmm.Closure
import GHC.StgToCmm.Foreign (emitPrimCall)
import MkGraph
import CoreSyn ( AltCon(..), tickishIsCode )
import BlockId
import SMRep
import Cmm
import CmmInfo
import CmmUtils
import CLabel
import StgSyn
import CostCentre
import Id
import IdInfo
import Name
import Module
import ListSetOps
import Util
import VarSet
import BasicTypes
import Outputable
import FastString
import DynFlags
import Control.Monad
cgTopRhsClosure :: DynFlags
-> RecFlag
-> Id
-> CostCentreStack
-> UpdateFlag
-> [Id]
-> CgStgExpr
-> (CgIdInfo, FCode ())
cgTopRhsClosure :: DynFlags
-> RecFlag
-> Id
-> CostCentreStack
-> UpdateFlag
-> [Id]
-> CgStgExpr
-> (CgIdInfo, FCode ())
cgTopRhsClosure DynFlags
dflags RecFlag
rec Id
id CostCentreStack
ccs UpdateFlag
upd_flag [Id]
args CgStgExpr
body =
let closure_label :: CLabel
closure_label = Name -> CafInfo -> CLabel
mkLocalClosureLabel (Id -> Name
idName Id
id) (Id -> CafInfo
idCafInfo Id
id)
cg_id_info :: CgIdInfo
cg_id_info = DynFlags -> Id -> LambdaFormInfo -> CmmLit -> CgIdInfo
litIdInfo DynFlags
dflags Id
id LambdaFormInfo
lf_info (CLabel -> CmmLit
CmmLabel CLabel
closure_label)
lf_info :: LambdaFormInfo
lf_info = DynFlags
-> Id
-> TopLevelFlag
-> [NonVoid Id]
-> UpdateFlag
-> [Id]
-> LambdaFormInfo
mkClosureLFInfo DynFlags
dflags Id
id TopLevelFlag
TopLevel [] UpdateFlag
upd_flag [Id]
args
in (CgIdInfo
cg_id_info, DynFlags -> LambdaFormInfo -> CLabel -> FCode ()
gen_code DynFlags
dflags LambdaFormInfo
lf_info CLabel
closure_label)
where
gen_code :: DynFlags -> LambdaFormInfo -> CLabel -> FCode ()
gen_code DynFlags
dflags LambdaFormInfo
_ CLabel
closure_label
| StgApp Id
f [] <- CgStgExpr
body, [Id] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Id]
args, RecFlag -> Bool
isNonRec RecFlag
rec
= do
CgIdInfo
cg_info <- Id -> FCode CgIdInfo
getCgIdInfo Id
f
let closure_rep :: [CmmLit]
closure_rep = DynFlags
-> CmmInfoTable
-> CostCentreStack
-> CafInfo
-> [CmmLit]
-> [CmmLit]
mkStaticClosureFields DynFlags
dflags
CmmInfoTable
indStaticInfoTable CostCentreStack
ccs CafInfo
MayHaveCafRefs
[CmmExpr -> CmmLit
unLit (CgIdInfo -> CmmExpr
idInfoToAmode CgIdInfo
cg_info)]
CLabel -> [CmmLit] -> FCode ()
emitDataLits CLabel
closure_label [CmmLit]
closure_rep
() -> FCode ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
gen_code DynFlags
dflags LambdaFormInfo
lf_info CLabel
_closure_label
= do { let name :: Name
name = Id -> Name
idName Id
id
; Module
mod_name <- FCode Module
getModuleName
; let descr :: String
descr = DynFlags -> Module -> Name -> String
closureDescription DynFlags
dflags Module
mod_name Name
name
closure_info :: ClosureInfo
closure_info = DynFlags
-> Bool
-> Id
-> LambdaFormInfo
-> Int
-> Int
-> String
-> ClosureInfo
mkClosureInfo DynFlags
dflags Bool
True Id
id LambdaFormInfo
lf_info Int
0 Int
0 String
descr
; let fv_details :: [(NonVoid Id, ByteOff)]
header :: ClosureHeader
header = if LambdaFormInfo -> Bool
isLFThunk LambdaFormInfo
lf_info then ClosureHeader
ThunkHeader else ClosureHeader
StdHeader
(Int
_, Int
_, [(NonVoid Id, Int)]
fv_details) = DynFlags
-> ClosureHeader
-> [NonVoid (PrimRep, Id)]
-> (Int, Int, [(NonVoid Id, Int)])
forall a.
DynFlags
-> ClosureHeader
-> [NonVoid (PrimRep, a)]
-> (Int, Int, [(NonVoid a, Int)])
mkVirtHeapOffsets DynFlags
dflags ClosureHeader
header []
; FCode () -> FCode ()
forkClosureBody (Bool
-> Id
-> ClosureInfo
-> CostCentreStack
-> [NonVoid Id]
-> Int
-> CgStgExpr
-> [(NonVoid Id, Int)]
-> FCode ()
closureCodeBody Bool
True Id
id ClosureInfo
closure_info CostCentreStack
ccs
([Id] -> [NonVoid Id]
nonVoidIds [Id]
args) ([Id] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Id]
args) CgStgExpr
body [(NonVoid Id, Int)]
fv_details)
; () -> FCode ()
forall (m :: * -> *) a. Monad m => a -> m a
return () }
unLit :: CmmExpr -> CmmLit
unLit (CmmLit CmmLit
l) = CmmLit
l
unLit CmmExpr
_ = String -> CmmLit
forall a. String -> a
panic String
"unLit"
cgBind :: CgStgBinding -> FCode ()
cgBind :: CgStgBinding -> FCode ()
cgBind (StgNonRec BinderP 'CodeGen
name GenStgRhs 'CodeGen
rhs)
= do { (CgIdInfo
info, FCode CmmAGraph
fcode) <- Id -> GenStgRhs 'CodeGen -> FCode (CgIdInfo, FCode CmmAGraph)
cgRhs Id
BinderP 'CodeGen
name GenStgRhs 'CodeGen
rhs
; CgIdInfo -> FCode ()
addBindC CgIdInfo
info
; CmmAGraph
init <- FCode CmmAGraph
fcode
; CmmAGraph -> FCode ()
emit CmmAGraph
init }
cgBind (StgRec [(BinderP 'CodeGen, GenStgRhs 'CodeGen)]
pairs)
= do { [(CgIdInfo, FCode CmmAGraph)]
r <- [FCode (CgIdInfo, FCode CmmAGraph)]
-> FCode [(CgIdInfo, FCode CmmAGraph)]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence ([FCode (CgIdInfo, FCode CmmAGraph)]
-> FCode [(CgIdInfo, FCode CmmAGraph)])
-> [FCode (CgIdInfo, FCode CmmAGraph)]
-> FCode [(CgIdInfo, FCode CmmAGraph)]
forall a b. (a -> b) -> a -> b
$ (Id -> GenStgRhs 'CodeGen -> FCode (CgIdInfo, FCode CmmAGraph))
-> [(Id, GenStgRhs 'CodeGen)]
-> [FCode (CgIdInfo, FCode CmmAGraph)]
forall a b c. (a -> b -> c) -> [(a, b)] -> [c]
unzipWith Id -> GenStgRhs 'CodeGen -> FCode (CgIdInfo, FCode CmmAGraph)
cgRhs [(Id, GenStgRhs 'CodeGen)]
[(BinderP 'CodeGen, GenStgRhs 'CodeGen)]
pairs
; let ([CgIdInfo]
id_infos, [FCode CmmAGraph]
fcodes) = [(CgIdInfo, FCode CmmAGraph)] -> ([CgIdInfo], [FCode CmmAGraph])
forall a b. [(a, b)] -> ([a], [b])
unzip [(CgIdInfo, FCode CmmAGraph)]
r
; [CgIdInfo] -> FCode ()
addBindsC [CgIdInfo]
id_infos
; ([CmmAGraph]
inits, CmmAGraph
body) <- FCode [CmmAGraph] -> FCode ([CmmAGraph], CmmAGraph)
forall a. FCode a -> FCode (a, CmmAGraph)
getCodeR (FCode [CmmAGraph] -> FCode ([CmmAGraph], CmmAGraph))
-> FCode [CmmAGraph] -> FCode ([CmmAGraph], CmmAGraph)
forall a b. (a -> b) -> a -> b
$ [FCode CmmAGraph] -> FCode [CmmAGraph]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence [FCode CmmAGraph]
fcodes
; CmmAGraph -> FCode ()
emit ([CmmAGraph] -> CmmAGraph
catAGraphs [CmmAGraph]
inits CmmAGraph -> CmmAGraph -> CmmAGraph
<*> CmmAGraph
body) }
cgRhs :: Id
-> CgStgRhs
-> FCode (
CgIdInfo
, FCode CmmAGraph
)
cgRhs :: Id -> GenStgRhs 'CodeGen -> FCode (CgIdInfo, FCode CmmAGraph)
cgRhs Id
id (StgRhsCon CostCentreStack
cc DataCon
con [StgArg]
args)
= Name
-> FCode (CgIdInfo, FCode CmmAGraph)
-> FCode (CgIdInfo, FCode CmmAGraph)
forall a. Name -> FCode a -> FCode a
withNewTickyCounterCon (Id -> Name
idName Id
id) (FCode (CgIdInfo, FCode CmmAGraph)
-> FCode (CgIdInfo, FCode CmmAGraph))
-> FCode (CgIdInfo, FCode CmmAGraph)
-> FCode (CgIdInfo, FCode CmmAGraph)
forall a b. (a -> b) -> a -> b
$
Id
-> Bool
-> CostCentreStack
-> DataCon
-> [NonVoid StgArg]
-> FCode (CgIdInfo, FCode CmmAGraph)
buildDynCon Id
id Bool
True CostCentreStack
cc DataCon
con ([StgArg] -> [NonVoid StgArg]
assertNonVoidStgArgs [StgArg]
args)
cgRhs Id
id (StgRhsClosure XRhsClosure 'CodeGen
fvs CostCentreStack
cc UpdateFlag
upd_flag [BinderP 'CodeGen]
args CgStgExpr
body)
= do DynFlags
dflags <- FCode DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
DynFlags
-> Id
-> CostCentreStack
-> [NonVoid Id]
-> UpdateFlag
-> [Id]
-> CgStgExpr
-> FCode (CgIdInfo, FCode CmmAGraph)
mkRhsClosure DynFlags
dflags Id
id CostCentreStack
cc ([Id] -> [NonVoid Id]
nonVoidIds (DVarSet -> [Id]
dVarSetElems DVarSet
XRhsClosure 'CodeGen
fvs)) UpdateFlag
upd_flag [Id]
[BinderP 'CodeGen]
args CgStgExpr
body
mkRhsClosure :: DynFlags -> Id -> CostCentreStack
-> [NonVoid Id]
-> UpdateFlag
-> [Id]
-> CgStgExpr
-> FCode (CgIdInfo, FCode CmmAGraph)
mkRhsClosure :: DynFlags
-> Id
-> CostCentreStack
-> [NonVoid Id]
-> UpdateFlag
-> [Id]
-> CgStgExpr
-> FCode (CgIdInfo, FCode CmmAGraph)
mkRhsClosure DynFlags
dflags Id
bndr CostCentreStack
_cc
[NonVoid Id
the_fv]
UpdateFlag
upd_flag
[]
CgStgExpr
expr
| let strip :: GenStgExpr p -> GenStgExpr p
strip = (Tickish Id -> Bool) -> GenStgExpr p -> GenStgExpr p
forall (p :: StgPass).
(Tickish Id -> Bool) -> GenStgExpr p -> GenStgExpr p
stripStgTicksTopE (Bool -> Bool
not (Bool -> Bool) -> (Tickish Id -> Bool) -> Tickish Id -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Tickish Id -> Bool
forall id. Tickish id -> Bool
tickishIsCode)
, StgCase (StgApp Id
scrutinee [])
BinderP 'CodeGen
_
(AlgAlt TyCon
_)
[(DataAlt DataCon
_, [BinderP 'CodeGen]
params, CgStgExpr
sel_expr)] <- CgStgExpr -> CgStgExpr
forall (p :: StgPass). GenStgExpr p -> GenStgExpr p
strip CgStgExpr
expr
, StgApp Id
selectee [] <- CgStgExpr -> CgStgExpr
forall (p :: StgPass). GenStgExpr p -> GenStgExpr p
strip CgStgExpr
sel_expr
, Id
the_fv Id -> Id -> Bool
forall a. Eq a => a -> a -> Bool
== Id
scrutinee
, let (Int
_, Int
_, [(NonVoid Id, Int)]
params_w_offsets) = DynFlags
-> [NonVoid (PrimRep, Id)] -> (Int, Int, [(NonVoid Id, Int)])
forall a.
DynFlags
-> [NonVoid (PrimRep, a)] -> (Int, Int, [(NonVoid a, Int)])
mkVirtConstrOffsets DynFlags
dflags ([NonVoid Id] -> [NonVoid (PrimRep, Id)]
addIdReps ([Id] -> [NonVoid Id]
assertNonVoidIds [Id]
[BinderP 'CodeGen]
params))
, Just Int
the_offset <- [(NonVoid Id, Int)] -> NonVoid Id -> Maybe Int
forall a b. Eq a => Assoc a b -> a -> Maybe b
assocMaybe [(NonVoid Id, Int)]
params_w_offsets (Id -> NonVoid Id
forall a. a -> NonVoid a
NonVoid Id
selectee)
, let offset_into_int :: Int
offset_into_int = DynFlags -> Int -> Int
bytesToWordsRoundUp DynFlags
dflags Int
the_offset
Int -> Int -> Int
forall a. Num a => a -> a -> a
- DynFlags -> Int
fixedHdrSizeW DynFlags
dflags
, Int
offset_into_int Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= DynFlags -> Int
mAX_SPEC_SELECTEE_SIZE DynFlags
dflags
=
let lf_info :: LambdaFormInfo
lf_info = Id -> Int -> Bool -> LambdaFormInfo
mkSelectorLFInfo Id
bndr Int
offset_into_int (UpdateFlag -> Bool
isUpdatable UpdateFlag
upd_flag)
in Id
-> LambdaFormInfo -> [StgArg] -> FCode (CgIdInfo, FCode CmmAGraph)
cgRhsStdThunk Id
bndr LambdaFormInfo
lf_info [Id -> StgArg
StgVarArg Id
the_fv]
mkRhsClosure DynFlags
dflags Id
bndr CostCentreStack
_cc
[NonVoid Id]
fvs
UpdateFlag
upd_flag
[]
(StgApp Id
fun_id [StgArg]
args)
| [StgArg]
args [StgArg] -> Int -> Bool
forall a. [a] -> Int -> Bool
`lengthIs` (Int
n_fvsInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1)
, (NonVoid Id -> Bool) -> [NonVoid Id] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (PrimRep -> Bool
isGcPtrRep (PrimRep -> Bool) -> (NonVoid Id -> PrimRep) -> NonVoid Id -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Id -> PrimRep
idPrimRep (Id -> PrimRep) -> (NonVoid Id -> Id) -> NonVoid Id -> PrimRep
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NonVoid Id -> Id
forall a. NonVoid a -> a
fromNonVoid) [NonVoid Id]
fvs
, UpdateFlag -> Bool
isUpdatable UpdateFlag
upd_flag
, Int
n_fvs Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= DynFlags -> Int
mAX_SPEC_AP_SIZE DynFlags
dflags
, Bool -> Bool
not (GeneralFlag -> DynFlags -> Bool
gopt GeneralFlag
Opt_SccProfilingOn DynFlags
dflags)
, Id -> Int
idArity Id
fun_id Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
unknownArity
= Id
-> LambdaFormInfo -> [StgArg] -> FCode (CgIdInfo, FCode CmmAGraph)
cgRhsStdThunk Id
bndr LambdaFormInfo
lf_info [StgArg]
payload
where
n_fvs :: Int
n_fvs = [NonVoid Id] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [NonVoid Id]
fvs
lf_info :: LambdaFormInfo
lf_info = Id -> UpdateFlag -> Int -> LambdaFormInfo
mkApLFInfo Id
bndr UpdateFlag
upd_flag Int
n_fvs
payload :: [StgArg]
payload = Id -> StgArg
StgVarArg Id
fun_id StgArg -> [StgArg] -> [StgArg]
forall a. a -> [a] -> [a]
: [StgArg]
args
mkRhsClosure DynFlags
dflags Id
bndr CostCentreStack
cc [NonVoid Id]
fvs UpdateFlag
upd_flag [Id]
args CgStgExpr
body
= do { let lf_info :: LambdaFormInfo
lf_info = DynFlags
-> Id
-> TopLevelFlag
-> [NonVoid Id]
-> UpdateFlag
-> [Id]
-> LambdaFormInfo
mkClosureLFInfo DynFlags
dflags Id
bndr TopLevelFlag
NotTopLevel [NonVoid Id]
fvs UpdateFlag
upd_flag [Id]
args
; (CgIdInfo
id_info, LocalReg
reg) <- Id -> LambdaFormInfo -> FCode (CgIdInfo, LocalReg)
rhsIdInfo Id
bndr LambdaFormInfo
lf_info
; (CgIdInfo, FCode CmmAGraph) -> FCode (CgIdInfo, FCode CmmAGraph)
forall (m :: * -> *) a. Monad m => a -> m a
return (CgIdInfo
id_info, LambdaFormInfo -> LocalReg -> FCode CmmAGraph
gen_code LambdaFormInfo
lf_info LocalReg
reg) }
where
gen_code :: LambdaFormInfo -> LocalReg -> FCode CmmAGraph
gen_code LambdaFormInfo
lf_info LocalReg
reg
= do {
; let reduced_fvs :: [NonVoid Id]
reduced_fvs = (NonVoid Id -> Bool) -> [NonVoid Id] -> [NonVoid Id]
forall a. (a -> Bool) -> [a] -> [a]
filter (Id -> NonVoid Id
forall a. a -> NonVoid a
NonVoid Id
bndr NonVoid Id -> NonVoid Id -> Bool
forall a. Eq a => a -> a -> Bool
/=) [NonVoid Id]
fvs
; Module
mod_name <- FCode Module
getModuleName
; DynFlags
dflags <- FCode DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
; let name :: Name
name = Id -> Name
idName Id
bndr
descr :: String
descr = DynFlags -> Module -> Name -> String
closureDescription DynFlags
dflags Module
mod_name Name
name
fv_details :: [(NonVoid Id, ByteOff)]
header :: ClosureHeader
header = if LambdaFormInfo -> Bool
isLFThunk LambdaFormInfo
lf_info then ClosureHeader
ThunkHeader else ClosureHeader
StdHeader
(Int
tot_wds, Int
ptr_wds, [(NonVoid Id, Int)]
fv_details)
= DynFlags
-> ClosureHeader
-> [NonVoid (PrimRep, Id)]
-> (Int, Int, [(NonVoid Id, Int)])
forall a.
DynFlags
-> ClosureHeader
-> [NonVoid (PrimRep, a)]
-> (Int, Int, [(NonVoid a, Int)])
mkVirtHeapOffsets DynFlags
dflags ClosureHeader
header ([NonVoid Id] -> [NonVoid (PrimRep, Id)]
addIdReps [NonVoid Id]
reduced_fvs)
closure_info :: ClosureInfo
closure_info = DynFlags
-> Bool
-> Id
-> LambdaFormInfo
-> Int
-> Int
-> String
-> ClosureInfo
mkClosureInfo DynFlags
dflags Bool
False
Id
bndr LambdaFormInfo
lf_info Int
tot_wds Int
ptr_wds
String
descr
; FCode () -> FCode ()
forkClosureBody (FCode () -> FCode ()) -> FCode () -> FCode ()
forall a b. (a -> b) -> a -> b
$
Bool
-> Id
-> ClosureInfo
-> CostCentreStack
-> [NonVoid Id]
-> Int
-> CgStgExpr
-> [(NonVoid Id, Int)]
-> FCode ()
closureCodeBody Bool
False Id
bndr ClosureInfo
closure_info CostCentreStack
cc ([Id] -> [NonVoid Id]
nonVoidIds [Id]
args)
([Id] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Id]
args) CgStgExpr
body [(NonVoid Id, Int)]
fv_details
; let use_cc :: CmmExpr
use_cc = CmmExpr
cccsExpr; blame_cc :: CmmExpr
blame_cc = CmmExpr
cccsExpr
; CmmAGraph -> FCode ()
emit (FastString -> CmmAGraph
mkComment (FastString -> CmmAGraph) -> FastString -> CmmAGraph
forall a b. (a -> b) -> a -> b
$ String -> FastString
mkFastString String
"calling allocDynClosure")
; let toVarArg :: (NonVoid Id, b) -> (NonVoid StgArg, b)
toVarArg (NonVoid Id
a, b
off) = (StgArg -> NonVoid StgArg
forall a. a -> NonVoid a
NonVoid (Id -> StgArg
StgVarArg Id
a), b
off)
; let info_tbl :: CmmInfoTable
info_tbl = ClosureInfo -> Id -> CostCentreStack -> CmmInfoTable
mkCmmInfo ClosureInfo
closure_info Id
bndr CostCentreStack
currentCCS
; CmmExpr
hp_plus_n <- Maybe Id
-> CmmInfoTable
-> LambdaFormInfo
-> CmmExpr
-> CmmExpr
-> [(NonVoid StgArg, Int)]
-> FCode CmmExpr
allocDynClosure (Id -> Maybe Id
forall a. a -> Maybe a
Just Id
bndr) CmmInfoTable
info_tbl LambdaFormInfo
lf_info CmmExpr
use_cc CmmExpr
blame_cc
(((NonVoid Id, Int) -> (NonVoid StgArg, Int))
-> [(NonVoid Id, Int)] -> [(NonVoid StgArg, Int)]
forall a b. (a -> b) -> [a] -> [b]
map (NonVoid Id, Int) -> (NonVoid StgArg, Int)
forall b. (NonVoid Id, b) -> (NonVoid StgArg, b)
toVarArg [(NonVoid Id, Int)]
fv_details)
; CmmAGraph -> FCode CmmAGraph
forall (m :: * -> *) a. Monad m => a -> m a
return (DynFlags -> LocalReg -> LambdaFormInfo -> CmmExpr -> CmmAGraph
mkRhsInit DynFlags
dflags LocalReg
reg LambdaFormInfo
lf_info CmmExpr
hp_plus_n) }
cgRhsStdThunk
:: Id
-> LambdaFormInfo
-> [StgArg]
-> FCode (CgIdInfo, FCode CmmAGraph)
cgRhsStdThunk :: Id
-> LambdaFormInfo -> [StgArg] -> FCode (CgIdInfo, FCode CmmAGraph)
cgRhsStdThunk Id
bndr LambdaFormInfo
lf_info [StgArg]
payload
= do { (CgIdInfo
id_info, LocalReg
reg) <- Id -> LambdaFormInfo -> FCode (CgIdInfo, LocalReg)
rhsIdInfo Id
bndr LambdaFormInfo
lf_info
; (CgIdInfo, FCode CmmAGraph) -> FCode (CgIdInfo, FCode CmmAGraph)
forall (m :: * -> *) a. Monad m => a -> m a
return (CgIdInfo
id_info, LocalReg -> FCode CmmAGraph
gen_code LocalReg
reg)
}
where
gen_code :: LocalReg -> FCode CmmAGraph
gen_code LocalReg
reg
= Bool -> Name -> FCode CmmAGraph -> FCode CmmAGraph
forall a. Bool -> Name -> FCode a -> FCode a
withNewTickyCounterStdThunk (LambdaFormInfo -> Bool
lfUpdatable LambdaFormInfo
lf_info) (Id -> Name
idName Id
bndr) (FCode CmmAGraph -> FCode CmmAGraph)
-> FCode CmmAGraph -> FCode CmmAGraph
forall a b. (a -> b) -> a -> b
$
do
{
Module
mod_name <- FCode Module
getModuleName
; DynFlags
dflags <- FCode DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
; let header :: ClosureHeader
header = if LambdaFormInfo -> Bool
isLFThunk LambdaFormInfo
lf_info then ClosureHeader
ThunkHeader else ClosureHeader
StdHeader
(Int
tot_wds, Int
ptr_wds, [(NonVoid StgArg, Int)]
payload_w_offsets)
= DynFlags
-> ClosureHeader
-> [NonVoid (PrimRep, StgArg)]
-> (Int, Int, [(NonVoid StgArg, Int)])
forall a.
DynFlags
-> ClosureHeader
-> [NonVoid (PrimRep, a)]
-> (Int, Int, [(NonVoid a, Int)])
mkVirtHeapOffsets DynFlags
dflags ClosureHeader
header
([NonVoid StgArg] -> [NonVoid (PrimRep, StgArg)]
addArgReps ([StgArg] -> [NonVoid StgArg]
nonVoidStgArgs [StgArg]
payload))
descr :: String
descr = DynFlags -> Module -> Name -> String
closureDescription DynFlags
dflags Module
mod_name (Id -> Name
idName Id
bndr)
closure_info :: ClosureInfo
closure_info = DynFlags
-> Bool
-> Id
-> LambdaFormInfo
-> Int
-> Int
-> String
-> ClosureInfo
mkClosureInfo DynFlags
dflags Bool
False
Id
bndr LambdaFormInfo
lf_info Int
tot_wds Int
ptr_wds
String
descr
; let use_cc :: CmmExpr
use_cc = CmmExpr
cccsExpr; blame_cc :: CmmExpr
blame_cc = CmmExpr
cccsExpr
; let info_tbl :: CmmInfoTable
info_tbl = ClosureInfo -> Id -> CostCentreStack -> CmmInfoTable
mkCmmInfo ClosureInfo
closure_info Id
bndr CostCentreStack
currentCCS
; CmmExpr
hp_plus_n <- Maybe Id
-> CmmInfoTable
-> LambdaFormInfo
-> CmmExpr
-> CmmExpr
-> [(NonVoid StgArg, Int)]
-> FCode CmmExpr
allocDynClosure (Id -> Maybe Id
forall a. a -> Maybe a
Just Id
bndr) CmmInfoTable
info_tbl LambdaFormInfo
lf_info
CmmExpr
use_cc CmmExpr
blame_cc [(NonVoid StgArg, Int)]
payload_w_offsets
; CmmAGraph -> FCode CmmAGraph
forall (m :: * -> *) a. Monad m => a -> m a
return (DynFlags -> LocalReg -> LambdaFormInfo -> CmmExpr -> CmmAGraph
mkRhsInit DynFlags
dflags LocalReg
reg LambdaFormInfo
lf_info CmmExpr
hp_plus_n) }
mkClosureLFInfo :: DynFlags
-> Id
-> TopLevelFlag
-> [NonVoid Id]
-> UpdateFlag
-> [Id]
-> LambdaFormInfo
mkClosureLFInfo :: DynFlags
-> Id
-> TopLevelFlag
-> [NonVoid Id]
-> UpdateFlag
-> [Id]
-> LambdaFormInfo
mkClosureLFInfo DynFlags
dflags Id
bndr TopLevelFlag
top [NonVoid Id]
fvs UpdateFlag
upd_flag [Id]
args
| [Id] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Id]
args =
Type -> TopLevelFlag -> [Id] -> UpdateFlag -> LambdaFormInfo
mkLFThunk (Id -> Type
idType Id
bndr) TopLevelFlag
top ((NonVoid Id -> Id) -> [NonVoid Id] -> [Id]
forall a b. (a -> b) -> [a] -> [b]
map NonVoid Id -> Id
forall a. NonVoid a -> a
fromNonVoid [NonVoid Id]
fvs) UpdateFlag
upd_flag
| Bool
otherwise =
TopLevelFlag -> [Id] -> [Id] -> ArgDescr -> LambdaFormInfo
mkLFReEntrant TopLevelFlag
top ((NonVoid Id -> Id) -> [NonVoid Id] -> [Id]
forall a b. (a -> b) -> [a] -> [b]
map NonVoid Id -> Id
forall a. NonVoid a -> a
fromNonVoid [NonVoid Id]
fvs) [Id]
args (DynFlags -> [Id] -> ArgDescr
mkArgDescr DynFlags
dflags [Id]
args)
closureCodeBody :: Bool
-> Id
-> ClosureInfo
-> CostCentreStack
-> [NonVoid Id]
-> Int
-> CgStgExpr
-> [(NonVoid Id, ByteOff)]
-> FCode ()
closureCodeBody :: Bool
-> Id
-> ClosureInfo
-> CostCentreStack
-> [NonVoid Id]
-> Int
-> CgStgExpr
-> [(NonVoid Id, Int)]
-> FCode ()
closureCodeBody Bool
top_lvl Id
bndr ClosureInfo
cl_info CostCentreStack
cc [NonVoid Id]
_args Int
arity CgStgExpr
body [(NonVoid Id, Int)]
fv_details
| Int
arity Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0
= Bool -> Bool -> Name -> FCode () -> FCode ()
forall a. Bool -> Bool -> Name -> FCode a -> FCode a
withNewTickyCounterThunk
(ClosureInfo -> Bool
isStaticClosure ClosureInfo
cl_info)
(ClosureInfo -> Bool
closureUpdReqd ClosureInfo
cl_info)
(ClosureInfo -> Name
closureName ClosureInfo
cl_info) (FCode () -> FCode ()) -> FCode () -> FCode ()
forall a b. (a -> b) -> a -> b
$
Bool
-> Id
-> LambdaFormInfo
-> CmmInfoTable
-> [NonVoid Id]
-> ((Int, LocalReg, [LocalReg]) -> FCode ())
-> FCode ()
emitClosureProcAndInfoTable Bool
top_lvl Id
bndr LambdaFormInfo
lf_info CmmInfoTable
info_tbl [] (((Int, LocalReg, [LocalReg]) -> FCode ()) -> FCode ())
-> ((Int, LocalReg, [LocalReg]) -> FCode ()) -> FCode ()
forall a b. (a -> b) -> a -> b
$
\(Int
_, LocalReg
node, [LocalReg]
_) -> ClosureInfo
-> [(NonVoid Id, Int)]
-> CostCentreStack
-> LocalReg
-> Int
-> CgStgExpr
-> FCode ()
thunkCode ClosureInfo
cl_info [(NonVoid Id, Int)]
fv_details CostCentreStack
cc LocalReg
node Int
arity CgStgExpr
body
where
lf_info :: LambdaFormInfo
lf_info = ClosureInfo -> LambdaFormInfo
closureLFInfo ClosureInfo
cl_info
info_tbl :: CmmInfoTable
info_tbl = ClosureInfo -> Id -> CostCentreStack -> CmmInfoTable
mkCmmInfo ClosureInfo
cl_info Id
bndr CostCentreStack
cc
closureCodeBody Bool
top_lvl Id
bndr ClosureInfo
cl_info CostCentreStack
cc [NonVoid Id]
args Int
arity CgStgExpr
body [(NonVoid Id, Int)]
fv_details
=
Bool -> Name -> [NonVoid Id] -> FCode () -> FCode ()
forall a. Bool -> Name -> [NonVoid Id] -> FCode a -> FCode a
withNewTickyCounterFun
(ClosureInfo -> Bool
closureSingleEntry ClosureInfo
cl_info)
(ClosureInfo -> Name
closureName ClosureInfo
cl_info)
[NonVoid Id]
args (FCode () -> FCode ()) -> FCode () -> FCode ()
forall a b. (a -> b) -> a -> b
$ do {
; let
lf_info :: LambdaFormInfo
lf_info = ClosureInfo -> LambdaFormInfo
closureLFInfo ClosureInfo
cl_info
info_tbl :: CmmInfoTable
info_tbl = ClosureInfo -> Id -> CostCentreStack -> CmmInfoTable
mkCmmInfo ClosureInfo
cl_info Id
bndr CostCentreStack
cc
; Bool
-> Id
-> LambdaFormInfo
-> CmmInfoTable
-> [NonVoid Id]
-> ((Int, LocalReg, [LocalReg]) -> FCode ())
-> FCode ()
emitClosureProcAndInfoTable Bool
top_lvl Id
bndr LambdaFormInfo
lf_info CmmInfoTable
info_tbl [NonVoid Id]
args (((Int, LocalReg, [LocalReg]) -> FCode ()) -> FCode ())
-> ((Int, LocalReg, [LocalReg]) -> FCode ()) -> FCode ()
forall a b. (a -> b) -> a -> b
$
\(Int
_offset, LocalReg
node, [LocalReg]
arg_regs) -> do
{ Id -> ClosureInfo -> [LocalReg] -> FCode ()
mkSlowEntryCode Id
bndr ClosureInfo
cl_info [LocalReg]
arg_regs
; DynFlags
dflags <- FCode DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
; let node_points :: Bool
node_points = DynFlags -> LambdaFormInfo -> Bool
nodeMustPointToIt DynFlags
dflags LambdaFormInfo
lf_info
node' :: Maybe LocalReg
node' = if Bool
node_points then LocalReg -> Maybe LocalReg
forall a. a -> Maybe a
Just LocalReg
node else Maybe LocalReg
forall a. Maybe a
Nothing
; BlockId
loop_header_id <- FCode BlockId
forall (m :: * -> *). MonadUnique m => m BlockId
newBlockId
; SelfLoopInfo -> FCode () -> FCode ()
forall a. SelfLoopInfo -> FCode a -> FCode a
withSelfLoop (Id
bndr, BlockId
loop_header_id, [LocalReg]
arg_regs) (FCode () -> FCode ()) -> FCode () -> FCode ()
forall a b. (a -> b) -> a -> b
$ do
{
; ClosureInfo
-> Maybe LocalReg -> Int -> [LocalReg] -> FCode () -> FCode ()
entryHeapCheck ClosureInfo
cl_info Maybe LocalReg
node' Int
arity [LocalReg]
arg_regs (FCode () -> FCode ()) -> FCode () -> FCode ()
forall a b. (a -> b) -> a -> b
$ do
{
Bool -> FCode () -> FCode ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
node_points (ClosureInfo -> CmmReg -> FCode ()
ldvEnterClosure ClosureInfo
cl_info (LocalReg -> CmmReg
CmmLocal LocalReg
node))
; ClosureInfo -> FCode ()
tickyEnterFun ClosureInfo
cl_info
; CostCentreStack -> CmmExpr -> FCode ()
enterCostCentreFun CostCentreStack
cc
(MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp (DynFlags -> MachOp
mo_wordSub DynFlags
dflags)
[ CmmReg -> CmmExpr
CmmReg (LocalReg -> CmmReg
CmmLocal LocalReg
node)
, DynFlags -> Int -> CmmExpr
mkIntExpr DynFlags
dflags (DynFlags -> ClosureInfo -> Int
funTag DynFlags
dflags ClosureInfo
cl_info) ])
; [(LocalReg, Int)]
fv_bindings <- ((NonVoid Id, Int) -> FCode (LocalReg, Int))
-> [(NonVoid Id, Int)] -> FCode [(LocalReg, Int)]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (NonVoid Id, Int) -> FCode (LocalReg, Int)
bind_fv [(NonVoid Id, Int)]
fv_details
; Bool -> FCode () -> FCode ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
node_points (FCode () -> FCode ()) -> FCode () -> FCode ()
forall a b. (a -> b) -> a -> b
$ LocalReg -> LambdaFormInfo -> [(LocalReg, Int)] -> FCode ()
load_fvs LocalReg
node LambdaFormInfo
lf_info [(LocalReg, Int)]
fv_bindings
; FCode ReturnKind -> FCode ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (FCode ReturnKind -> FCode ()) -> FCode ReturnKind -> FCode ()
forall a b. (a -> b) -> a -> b
$ CgStgExpr -> FCode ReturnKind
cgExpr CgStgExpr
body
}}}
}
bind_fv :: (NonVoid Id, ByteOff) -> FCode (LocalReg, ByteOff)
bind_fv :: (NonVoid Id, Int) -> FCode (LocalReg, Int)
bind_fv (NonVoid Id
id, Int
off) = do { LocalReg
reg <- NonVoid Id -> FCode LocalReg
rebindToReg NonVoid Id
id; (LocalReg, Int) -> FCode (LocalReg, Int)
forall (m :: * -> *) a. Monad m => a -> m a
return (LocalReg
reg, Int
off) }
load_fvs :: LocalReg -> LambdaFormInfo -> [(LocalReg, ByteOff)] -> FCode ()
load_fvs :: LocalReg -> LambdaFormInfo -> [(LocalReg, Int)] -> FCode ()
load_fvs LocalReg
node LambdaFormInfo
lf_info = ((LocalReg, Int) -> FCode ()) -> [(LocalReg, Int)] -> FCode ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (\ (LocalReg
reg, Int
off) ->
do DynFlags
dflags <- FCode DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
let tag :: Int
tag = DynFlags -> LambdaFormInfo -> Int
lfDynTag DynFlags
dflags LambdaFormInfo
lf_info
CmmAGraph -> FCode ()
emit (CmmAGraph -> FCode ()) -> CmmAGraph -> FCode ()
forall a b. (a -> b) -> a -> b
$ DynFlags -> LocalReg -> LocalReg -> Int -> Int -> CmmAGraph
mkTaggedObjectLoad DynFlags
dflags LocalReg
reg LocalReg
node Int
off Int
tag)
mkSlowEntryCode :: Id -> ClosureInfo -> [LocalReg] -> FCode ()
mkSlowEntryCode :: Id -> ClosureInfo -> [LocalReg] -> FCode ()
mkSlowEntryCode Id
bndr ClosureInfo
cl_info [LocalReg]
arg_regs
| Just (Int
_, ArgGen Liveness
_) <- ClosureInfo -> Maybe (Int, ArgDescr)
closureFunInfo ClosureInfo
cl_info
= do DynFlags
dflags <- FCode DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
let node :: LocalReg
node = DynFlags -> NonVoid Id -> LocalReg
idToReg DynFlags
dflags (Id -> NonVoid Id
forall a. a -> NonVoid a
NonVoid Id
bndr)
slow_lbl :: CLabel
slow_lbl = ClosureInfo -> CLabel
closureSlowEntryLabel ClosureInfo
cl_info
fast_lbl :: CLabel
fast_lbl = DynFlags -> ClosureInfo -> CLabel
closureLocalEntryLabel DynFlags
dflags ClosureInfo
cl_info
jump :: CmmAGraph
jump = DynFlags -> Convention -> CmmExpr -> [CmmExpr] -> Int -> CmmAGraph
mkJump DynFlags
dflags Convention
NativeNodeCall
(CLabel -> CmmExpr
mkLblExpr CLabel
fast_lbl)
((LocalReg -> CmmExpr) -> [LocalReg] -> [CmmExpr]
forall a b. (a -> b) -> [a] -> [b]
map (CmmReg -> CmmExpr
CmmReg (CmmReg -> CmmExpr) -> (LocalReg -> CmmReg) -> LocalReg -> CmmExpr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LocalReg -> CmmReg
CmmLocal) (LocalReg
node LocalReg -> [LocalReg] -> [LocalReg]
forall a. a -> [a] -> [a]
: [LocalReg]
arg_regs))
(DynFlags -> Int
initUpdFrameOff DynFlags
dflags)
CmmTickScope
tscope <- FCode CmmTickScope
getTickScope
Convention
-> Maybe CmmInfoTable
-> CLabel
-> [LocalReg]
-> CmmAGraphScoped
-> FCode ()
emitProcWithConvention Convention
Slow Maybe CmmInfoTable
forall a. Maybe a
Nothing CLabel
slow_lbl
(LocalReg
node LocalReg -> [LocalReg] -> [LocalReg]
forall a. a -> [a] -> [a]
: [LocalReg]
arg_regs) (CmmAGraph
jump, CmmTickScope
tscope)
| Bool
otherwise = () -> FCode ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
thunkCode :: ClosureInfo -> [(NonVoid Id, ByteOff)] -> CostCentreStack
-> LocalReg -> Int -> CgStgExpr -> FCode ()
thunkCode :: ClosureInfo
-> [(NonVoid Id, Int)]
-> CostCentreStack
-> LocalReg
-> Int
-> CgStgExpr
-> FCode ()
thunkCode ClosureInfo
cl_info [(NonVoid Id, Int)]
fv_details CostCentreStack
_cc LocalReg
node Int
arity CgStgExpr
body
= do { DynFlags
dflags <- FCode DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
; let node_points :: Bool
node_points = DynFlags -> LambdaFormInfo -> Bool
nodeMustPointToIt DynFlags
dflags (ClosureInfo -> LambdaFormInfo
closureLFInfo ClosureInfo
cl_info)
node' :: Maybe LocalReg
node' = if Bool
node_points then LocalReg -> Maybe LocalReg
forall a. a -> Maybe a
Just LocalReg
node else Maybe LocalReg
forall a. Maybe a
Nothing
; ClosureInfo -> CmmReg -> FCode ()
ldvEnterClosure ClosureInfo
cl_info (LocalReg -> CmmReg
CmmLocal LocalReg
node)
; ClosureInfo
-> Maybe LocalReg -> Int -> [LocalReg] -> FCode () -> FCode ()
entryHeapCheck ClosureInfo
cl_info Maybe LocalReg
node' Int
arity [] (FCode () -> FCode ()) -> FCode () -> FCode ()
forall a b. (a -> b) -> a -> b
$ do
{
; ClosureInfo -> FCode ()
tickyEnterThunk ClosureInfo
cl_info
; Bool -> FCode () -> FCode ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (ClosureInfo -> Bool
blackHoleOnEntry ClosureInfo
cl_info Bool -> Bool -> Bool
&& Bool
node_points)
(LocalReg -> FCode ()
blackHoleIt LocalReg
node)
; ClosureInfo -> LocalReg -> FCode () -> FCode ()
setupUpdate ClosureInfo
cl_info LocalReg
node (FCode () -> FCode ()) -> FCode () -> FCode ()
forall a b. (a -> b) -> a -> b
$
do { CmmExpr -> FCode ()
enterCostCentreThunk (CmmReg -> CmmExpr
CmmReg CmmReg
nodeReg)
; let lf_info :: LambdaFormInfo
lf_info = ClosureInfo -> LambdaFormInfo
closureLFInfo ClosureInfo
cl_info
; [(LocalReg, Int)]
fv_bindings <- ((NonVoid Id, Int) -> FCode (LocalReg, Int))
-> [(NonVoid Id, Int)] -> FCode [(LocalReg, Int)]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (NonVoid Id, Int) -> FCode (LocalReg, Int)
bind_fv [(NonVoid Id, Int)]
fv_details
; LocalReg -> LambdaFormInfo -> [(LocalReg, Int)] -> FCode ()
load_fvs LocalReg
node LambdaFormInfo
lf_info [(LocalReg, Int)]
fv_bindings
; FCode ReturnKind -> FCode ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (FCode ReturnKind -> FCode ()) -> FCode ReturnKind -> FCode ()
forall a b. (a -> b) -> a -> b
$ CgStgExpr -> FCode ReturnKind
cgExpr CgStgExpr
body }}}
blackHoleIt :: LocalReg -> FCode ()
blackHoleIt :: LocalReg -> FCode ()
blackHoleIt LocalReg
node_reg
= CmmExpr -> FCode ()
emitBlackHoleCode (CmmReg -> CmmExpr
CmmReg (LocalReg -> CmmReg
CmmLocal LocalReg
node_reg))
emitBlackHoleCode :: CmmExpr -> FCode ()
emitBlackHoleCode :: CmmExpr -> FCode ()
emitBlackHoleCode CmmExpr
node = do
DynFlags
dflags <- FCode DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
let eager_blackholing :: Bool
eager_blackholing = Bool -> Bool
not (GeneralFlag -> DynFlags -> Bool
gopt GeneralFlag
Opt_SccProfilingOn DynFlags
dflags)
Bool -> Bool -> Bool
&& GeneralFlag -> DynFlags -> Bool
gopt GeneralFlag
Opt_EagerBlackHoling DynFlags
dflags
Bool -> FCode () -> FCode ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
eager_blackholing (FCode () -> FCode ()) -> FCode () -> FCode ()
forall a b. (a -> b) -> a -> b
$ do
DynFlags -> FCode () -> FCode ()
forall a. DynFlags -> FCode a -> FCode ()
whenUpdRemSetEnabled DynFlags
dflags (FCode () -> FCode ()) -> FCode () -> FCode ()
forall a b. (a -> b) -> a -> b
$ CmmExpr -> FCode ()
emitUpdRemSetPushThunk CmmExpr
node
CmmExpr -> CmmExpr -> FCode ()
emitStore (DynFlags -> CmmExpr -> Int -> CmmExpr
cmmOffsetW DynFlags
dflags CmmExpr
node (DynFlags -> Int
fixedHdrSizeW DynFlags
dflags)) CmmExpr
currentTSOExpr
[LocalReg] -> CallishMachOp -> [CmmExpr] -> FCode ()
emitPrimCall [] CallishMachOp
MO_WriteBarrier []
CmmExpr -> CmmExpr -> FCode ()
emitStore CmmExpr
node (CmmReg -> CmmExpr
CmmReg (GlobalReg -> CmmReg
CmmGlobal GlobalReg
EagerBlackholeInfo))
setupUpdate :: ClosureInfo -> LocalReg -> FCode () -> FCode ()
setupUpdate :: ClosureInfo -> LocalReg -> FCode () -> FCode ()
setupUpdate ClosureInfo
closure_info LocalReg
node FCode ()
body
| Bool -> Bool
not (LambdaFormInfo -> Bool
lfUpdatable (ClosureInfo -> LambdaFormInfo
closureLFInfo ClosureInfo
closure_info))
= FCode ()
body
| Bool -> Bool
not (ClosureInfo -> Bool
isStaticClosure ClosureInfo
closure_info)
= if Bool -> Bool
not (ClosureInfo -> Bool
closureUpdReqd ClosureInfo
closure_info)
then do FCode ()
tickyUpdateFrameOmitted; FCode ()
body
else do
FCode ()
tickyPushUpdateFrame
DynFlags
dflags <- FCode DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
let
bh :: Bool
bh = ClosureInfo -> Bool
blackHoleOnEntry ClosureInfo
closure_info Bool -> Bool -> Bool
&&
Bool -> Bool
not (GeneralFlag -> DynFlags -> Bool
gopt GeneralFlag
Opt_SccProfilingOn DynFlags
dflags) Bool -> Bool -> Bool
&&
GeneralFlag -> DynFlags -> Bool
gopt GeneralFlag
Opt_EagerBlackHoling DynFlags
dflags
lbl :: CLabel
lbl | Bool
bh = CLabel
mkBHUpdInfoLabel
| Bool
otherwise = CLabel
mkUpdInfoLabel
CLabel -> CmmExpr -> FCode () -> FCode ()
pushUpdateFrame CLabel
lbl (CmmReg -> CmmExpr
CmmReg (LocalReg -> CmmReg
CmmLocal LocalReg
node)) FCode ()
body
| Bool
otherwise
= do { ClosureInfo -> FCode ()
tickyUpdateBhCaf ClosureInfo
closure_info
; if ClosureInfo -> Bool
closureUpdReqd ClosureInfo
closure_info
then do
{ CmmExpr
upd_closure <- LocalReg -> FCode CmmExpr
link_caf LocalReg
node
; CLabel -> CmmExpr -> FCode () -> FCode ()
pushUpdateFrame CLabel
mkBHUpdInfoLabel CmmExpr
upd_closure FCode ()
body }
else do {FCode ()
tickyUpdateFrameOmitted; FCode ()
body}
}
pushUpdateFrame :: CLabel -> CmmExpr -> FCode () -> FCode ()
pushUpdateFrame :: CLabel -> CmmExpr -> FCode () -> FCode ()
pushUpdateFrame CLabel
lbl CmmExpr
updatee FCode ()
body
= do
Int
updfr <- FCode Int
getUpdFrameOff
DynFlags
dflags <- FCode DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
let
hdr :: Int
hdr = DynFlags -> Int
fixedHdrSize DynFlags
dflags
frame :: Int
frame = Int
updfr Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
hdr Int -> Int -> Int
forall a. Num a => a -> a -> a
+ DynFlags -> Int
sIZEOF_StgUpdateFrame_NoHdr DynFlags
dflags
DynFlags -> CmmExpr -> CLabel -> CmmExpr -> FCode ()
emitUpdateFrame DynFlags
dflags (Area -> Int -> CmmExpr
CmmStackSlot Area
Old Int
frame) CLabel
lbl CmmExpr
updatee
Int -> FCode () -> FCode ()
forall a. Int -> FCode a -> FCode a
withUpdFrameOff Int
frame FCode ()
body
emitUpdateFrame :: DynFlags -> CmmExpr -> CLabel -> CmmExpr -> FCode ()
emitUpdateFrame :: DynFlags -> CmmExpr -> CLabel -> CmmExpr -> FCode ()
emitUpdateFrame DynFlags
dflags CmmExpr
frame CLabel
lbl CmmExpr
updatee = do
let
hdr :: Int
hdr = DynFlags -> Int
fixedHdrSize DynFlags
dflags
off_updatee :: Int
off_updatee = Int
hdr Int -> Int -> Int
forall a. Num a => a -> a -> a
+ DynFlags -> Int
oFFSET_StgUpdateFrame_updatee DynFlags
dflags
CmmExpr -> CmmExpr -> FCode ()
emitStore CmmExpr
frame (CLabel -> CmmExpr
mkLblExpr CLabel
lbl)
CmmExpr -> CmmExpr -> FCode ()
emitStore (DynFlags -> CmmExpr -> Int -> CmmExpr
cmmOffset DynFlags
dflags CmmExpr
frame Int
off_updatee) CmmExpr
updatee
CmmExpr -> FCode ()
initUpdFrameProf CmmExpr
frame
link_caf :: LocalReg
-> FCode CmmExpr
link_caf :: LocalReg -> FCode CmmExpr
link_caf LocalReg
node = do
{ DynFlags
dflags <- FCode DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
; let newCAF_lbl :: CLabel
newCAF_lbl = FastString
-> Maybe Int -> ForeignLabelSource -> FunctionOrData -> CLabel
mkForeignLabel (String -> FastString
fsLit String
"newCAF") Maybe Int
forall a. Maybe a
Nothing
ForeignLabelSource
ForeignLabelInExternalPackage FunctionOrData
IsFunction
; LocalReg
bh <- CmmType -> FCode LocalReg
forall (m :: * -> *). MonadUnique m => CmmType -> m LocalReg
newTemp (DynFlags -> CmmType
bWord DynFlags
dflags)
; [(LocalReg, ForeignHint)]
-> CLabel -> [(CmmExpr, ForeignHint)] -> Bool -> FCode ()
emitRtsCallGen [(LocalReg
bh,ForeignHint
AddrHint)] CLabel
newCAF_lbl
[ (CmmExpr
baseExpr, ForeignHint
AddrHint),
(CmmReg -> CmmExpr
CmmReg (LocalReg -> CmmReg
CmmLocal LocalReg
node), ForeignHint
AddrHint) ]
Bool
False
; Int
updfr <- FCode Int
getUpdFrameOff
; let target :: CmmExpr
target = DynFlags -> CmmExpr -> CmmExpr
entryCode DynFlags
dflags (DynFlags -> CmmExpr -> CmmExpr
closureInfoPtr DynFlags
dflags (CmmReg -> CmmExpr
CmmReg (LocalReg -> CmmReg
CmmLocal LocalReg
node)))
; CmmAGraph -> FCode ()
emit (CmmAGraph -> FCode ()) -> FCode CmmAGraph -> FCode ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< CmmExpr -> CmmAGraph -> FCode CmmAGraph
mkCmmIfThen
(DynFlags -> CmmExpr -> CmmExpr -> CmmExpr
cmmEqWord DynFlags
dflags (CmmReg -> CmmExpr
CmmReg (LocalReg -> CmmReg
CmmLocal LocalReg
bh)) (DynFlags -> CmmExpr
zeroExpr DynFlags
dflags))
(DynFlags -> Convention -> CmmExpr -> [CmmExpr] -> Int -> CmmAGraph
mkJump DynFlags
dflags Convention
NativeNodeCall CmmExpr
target [] Int
updfr)
; CmmExpr -> FCode CmmExpr
forall (m :: * -> *) a. Monad m => a -> m a
return (CmmReg -> CmmExpr
CmmReg (LocalReg -> CmmReg
CmmLocal LocalReg
bh)) }
closureDescription :: DynFlags
-> Module
-> Name
-> String
closureDescription :: DynFlags -> Module -> Name -> String
closureDescription DynFlags
dflags Module
mod_name Name
name
= DynFlags -> SDoc -> String
showSDocDump DynFlags
dflags (Char -> SDoc
char Char
'<' SDoc -> SDoc -> SDoc
<>
(if Name -> Bool
isExternalName Name
name
then Name -> SDoc
forall a. Outputable a => a -> SDoc
ppr Name
name
else Module -> SDoc
pprModule Module
mod_name SDoc -> SDoc -> SDoc
<> Char -> SDoc
char Char
'.' SDoc -> SDoc -> SDoc
<> Name -> SDoc
forall a. Outputable a => a -> SDoc
ppr Name
name) SDoc -> SDoc -> SDoc
<>
Char -> SDoc
char Char
'>')