-selectContinuationFormat :: UniqFM {-BlockId-} CmmParam -> UniqFM {-BlockId-} CmmLive -> UniqFM {-BlockId-} ContinuationFormat
-selectContinuationFormat param live = mapUFM (map Just . uniqSetToList) live
-
-transformReturn block_infos formats (BasicBlock ident stmts) =
- case last $ init stmts of
- CmmReturn arguments ->
- BasicBlock ident $ (init $ init stmts) ++
- [CmmJump (CmmReg spReg) arguments]
- -- TODO: tail calls
- -- TODO: return direct at the end of a block
- _ -> BasicBlock ident stmts
-
-destructContinuation :: UniqFM {-BlockId-} CPSBlockInfo -> UniqFM {-BlockId-} ContinuationFormat -> CmmBasicBlock -> CmmBasicBlock
-destructContinuation block_infos formats (BasicBlock ident stmts) =
- case info of
- ControlBlock -> BasicBlock ident stmts
- ContinuationBlock _ -> BasicBlock ident (unpack_continuation ++ stmts)
- where
- info = lookupWithDefaultUFM block_infos (panic $ "info: unknown block " ++ (showSDoc $ ppr $ getUnique ident)) ident
- format = lookupWithDefaultUFM formats (panic $ "format: unknown block " ++ (showSDoc $ ppr $ getUnique ident)) ident
- unpack_continuation = CmmAssign spReg (CmmRegOff spReg frame_size) :
- [CmmAssign (CmmLocal reg) (CmmLoad (CmmRegOff spReg (i*stack_slot_size)) (localRegRep reg))
- | (i, Just reg) <- zip [1..] format]
- frame_size = stack_header_size + stack_slot_size * (length format)
- stack_header_size = stack_slot_size -- TODO: check if this could be different than stack_slot_size
- stack_slot_size = 4 -- TODO: find actual variables to be used instead of this
-
-constructContinuation :: UniqFM {-BlockId-} CPSBlockInfo -> UniqFM {-BlockId-} ContinuationFormat -> CmmBasicBlock -> CmmBasicBlock
-constructContinuation block_infos formats (BasicBlock ident stmts) =
- case last $ init stmts of
- -- TODO: global_saves
- --CmmCall (CmmForeignCall target CmmCallConv) results arguments (Just []) -> --TODO: handle globals
- CmmCall (CmmForeignCall target CmmCallConv) results arguments _ ->
- BasicBlock ident $
- init (init stmts) ++
- pack_continuation ++
- [CmmJump target arguments]
- CmmCall target results arguments _ -> panic "unimplemented CmmCall"
- _ -> BasicBlock ident $ (init stmts) ++ build_block_branch
- where
- info = lookupWithDefaultUFM block_infos (panic $ "info: unknown block " ++ (showSDoc $ ppr $ getUnique next_block)) next_block
- format = lookupWithDefaultUFM formats (panic $ "format: unknown block " ++ (showSDoc $ ppr $ getUnique next_block)) next_block
- next_block = case last stmts of
- CmmBranch next -> next
- -- TODO: blocks with jump at end
- -- TODO: blocks with return at end
- _ -> panic "basic block without a branch at the end (unimplemented)"
- next_block_as_proc_expr = CmmLit $ CmmLabel $ mkReturnPtLabel $ getUnique next_block
- pack_continuation = CmmAssign spReg (CmmRegOff spReg (-frame_size)) :
- CmmStore (CmmReg spReg) next_block_as_proc_expr :
- [CmmStore (CmmRegOff spReg (i*stack_slot_size)) (CmmReg $ CmmLocal reg)
- | (i, Just reg) <- zip [1..] format]
- frame_size = stack_header_size + stack_slot_size * (length format)
- stack_header_size = stack_slot_size -- TODO: check if this could be different than stack_slot_size (e.g. fixedHdrSize depends on PAR and GRAN)
- stack_slot_size = 4 -- TODO: find actual variables to be used instead of this (e.g. cgRepSizeW)
- block_needs_call = True -- TODO: use a table (i.e. proc-point)
- build_block_branch =
- if block_needs_call
- then [CmmJump next_block_as_proc_expr [] {- TODO: pass live -}] {- NOTE: a block can never be both a continuation and a controll block -}
- else [CmmBranch next_block]
-
--- TODO: TBD when to adjust the stack
-
-cpsProc :: CmmTop -> CPS [CmmTop]
-cpsProc x@(CmmData _ _) = return [x]
-cpsProc x@(CmmProc info_table ident params blocks) = do
- broken_blocks <- liftM concat $ mapM breakBlock blocks
- let live = cmmLiveness (map snd broken_blocks)
- let blocks_with_live = map (cmmLivenessComment live . snd) broken_blocks
- let formats = selectContinuationFormat (undefined {-TODO-}) live
- let block_infos = listToUFM $ map (\(info, block) -> (blockId block, info)) broken_blocks
- let blocks_with_live' = map (constructContinuation block_infos formats) blocks_with_live
- let blocks_with_live'' = map (destructContinuation block_infos formats) blocks_with_live'
- let blocks_with_live''' = map (transformReturn block_infos formats) blocks_with_live''
-
- return $ [CmmProc info_table ident params blocks_with_live''']