- curr_format = maybe unknown_block id $ lookup curr_ident formats
- unknown_block = panic "unknown BlockId in constructContinuation"
- prefix = case entry of
- ControlEntry -> []
- FunctionEntry _ _ -> []
- ContinuationEntry formals ->
- unpack_continuation curr_format
- postfix = case exit of
- FinalBranch next -> [CmmBranch next]
- FinalSwitch expr targets -> [CmmSwitch expr targets]
- FinalReturn arguments ->
- exit_function curr_format
- (CmmLoad (CmmReg spReg) wordRep)
- arguments
- FinalJump target arguments ->
- exit_function curr_format target arguments
- -- TODO: do something about global saves
- FinalCall next (CmmForeignCall target CmmCallConv)
- results arguments saves ->
- pack_continuation curr_format cont_format ++
- [CmmJump target arguments]
- where
- cont_format = maybe unknown_block id $
- lookup (mkReturnPtLabel $ getUnique next) formats
- FinalCall next _ results arguments saves -> panic "unimplemented CmmCall"
-
-constructContinuation2 :: BlockEnv StackFormat -> BrokenBlock
- -> CmmBasicBlock
-constructContinuation2 formats (BrokenBlock ident entry stmts _ exit) =
- BasicBlock ident (prefix++stmts++postfix)
- where
- curr_format = lookupWithDefaultUFM formats unknown_block ident
- unknown_block = panic "unknown BlockId in constructContinuation"
- prefix = case entry of
- ControlEntry -> []
- FunctionEntry _ -> []
- ContinuationEntry formals ->
- unpack_continuation curr_format
- postfix = case exit of
- FinalBranch next -> [CmmBranch next]
- FinalSwitch expr targets -> [CmmSwitch expr targets]
- FinalReturn arguments ->
- exit_function curr_format
- (CmmLoad (CmmReg spReg) wordRep)
- arguments
- FinalJump target arguments ->
- exit_function curr_format target arguments
- -- TODO: do something about global saves
- FinalCall next (CmmForeignCall target CmmCallConv)
- results arguments saves ->
- pack_continuation curr_format cont_format ++
- [CmmJump target arguments]
- where
- cont_format = lookupWithDefaultUFM formats
- unknown_block next
- FinalCall next _ results arguments saves -> panic "unimplemented CmmCall"
-
---------------------------------------------------------------------------------
--- Functions that generate CmmStmt sequences
--- for packing/unpacking continuations
--- and entering/exiting functions
-
-exit_function :: StackFormat -> CmmExpr -> CmmActuals -> [CmmStmt]
-exit_function (StackFormat curr_id curr_frame_size curr_offsets) target arguments
- = adjust_spReg ++ jump where
- adjust_spReg = [
- CmmAssign spReg
- (CmmRegOff spReg (curr_frame_size*wORD_SIZE))]
- jump = [CmmJump target arguments]
-
-enter_function :: WordOff -> [CmmStmt]
-enter_function max_frame_size
- = check_stack_limit where
- check_stack_limit = [
- CmmCondBranch
- (CmmMachOp (MO_U_Lt $ cmmRegRep spReg)
- [CmmRegOff spReg max_frame_size, CmmReg spLimReg])
- gc_block]
- gc_block = undefined -- TODO: get stack and heap checks to go to same
-
--- TODO: fix branches to proc point (we have to insert a new block to marshel the continuation)
-pack_continuation :: StackFormat -> StackFormat -> [CmmStmt]
-pack_continuation (StackFormat curr_id curr_frame_size curr_offsets)
- (StackFormat cont_id cont_frame_size cont_offsets)
- = save_live_values ++ set_stack_header ++ adjust_spReg where
- -- TODO: only save variables when actually needed
- save_live_values =
- [CmmStore
- (CmmRegOff
- spReg (wORD_SIZE*(curr_frame_size - cont_frame_size + offset)))
- (CmmReg reg)
- | (reg, offset) <- cont_offsets]
- set_stack_header = -- TODO: only set when needed
- [CmmStore (CmmRegOff spReg (wORD_SIZE*(curr_frame_size - cont_frame_size))) continuation_function]
- continuation_function = CmmLit $ CmmLabel $ mkReturnPtLabel {-TODO: use the correct function -} $ getUnique cont_id
- adjust_spReg =
- if curr_frame_size == cont_frame_size
- then []
- else [CmmAssign spReg (CmmRegOff spReg ((curr_frame_size - cont_frame_size)*wORD_SIZE))]
-
--- Lazy adjustment of stack headers assumes all blocks
--- that could branch to eachother (i.e. control blocks)
--- have the same stack format (this causes a problem
--- only for proc-point).
-unpack_continuation :: StackFormat -> [CmmStmt]
-unpack_continuation (StackFormat curr_id curr_frame_size curr_offsets)
- = load_live_values where
- -- TODO: only save variables when actually needed
- load_live_values =
- [CmmAssign
- reg
- (CmmLoad (CmmRegOff spReg (wORD_SIZE*offset)) (cmmRegRep reg))
- | (reg, offset) <- curr_offsets]
+ max_size = maximum $
+ 0 : map (continuationMaxStack formats') continuations
+ formats' = map make_format formats
+ make_format (label, (formals, top, stack)) =
+ (label,
+ ContinuationFormat {
+ continuation_formals = formals,
+ continuation_label = top,
+ continuation_frame_size = stack_size stack +
+ if isJust top
+ then label_size
+ else 0,
+ continuation_stack = stack })
+
+ update_frame_size = case update_frame of
+ Nothing -> 0
+ (Just (UpdateFrame _ args))
+ -> label_size + update_size args
+
+ update_size [] = 0
+ update_size (expr:exprs) = width + update_size exprs
+ where
+ width = machRepByteWidth (cmmExprRep expr) `quot` wORD_SIZE
+ -- TODO: it would be better if we had a machRepWordWidth