From 6281224046c9fc2bba358d42c7688a8314dc5bb6 Mon Sep 17 00:00:00 2001 From: simonmar <unknown> Date: Tue, 8 Jun 1999 15:56:48 +0000 Subject: [PATCH] [project @ 1999-06-08 15:56:44 by simonmar] Allow reserving of stack slots for non-pointer data (eg. cost centres). This means the previous hacks to keep the stack bitmaps correct in the presence of cost centres are now unnecessary, and case-of-case expressions will be compiled properly with profiling on. --- ghc/compiler/codeGen/CgBindery.lhs | 15 ++- ghc/compiler/codeGen/CgCase.lhs | 24 +++-- ghc/compiler/codeGen/CgClosure.lhs | 11 ++- ghc/compiler/codeGen/CgExpr.lhs | 5 +- ghc/compiler/codeGen/CgMonad.lhs | 15 ++- ghc/compiler/codeGen/CgStackery.lhs | 137 +++++++++++----------------- ghc/compiler/codeGen/CgTailCall.lhs | 18 ++-- ghc/compiler/codeGen/CgUpdate.lhs | 15 ++- ghc/compiler/codeGen/CgUsages.lhs | 44 ++++++++- 9 files changed, 151 insertions(+), 133 deletions(-) diff --git a/ghc/compiler/codeGen/CgBindery.lhs b/ghc/compiler/codeGen/CgBindery.lhs index 49b907e2e29b..1d2ff671d30f 100644 --- a/ghc/compiler/codeGen/CgBindery.lhs +++ b/ghc/compiler/codeGen/CgBindery.lhs @@ -422,7 +422,7 @@ problems. 1) Find all the pointer words by searching through the binding list. Invert this to find the non-pointer words and build the bitmap. - 2) Find all the non-pointer words by search through the binding list. + 2) Find all the non-pointer words by searching through the binding list. Merge this with the list of currently free slots. Build the bitmap. @@ -473,7 +473,7 @@ buildLivenessMask uniq sp info_down unboxed_slots) -- merge in the free slots - all_slots = addFreeSlots flatten_slots free ++ + all_slots = mergeSlots flatten_slots (map fst free) ++ if vsp < sp then [vsp+1 .. sp] else [] -- recalibrate the list to be sp-relative @@ -482,6 +482,17 @@ buildLivenessMask uniq sp info_down -- build the bitmap liveness_mask = listToLivenessMask rel_slots +mergeSlots :: [Int] -> [Int] -> [Int] +mergeSlots cs [] = cs +mergeSlots [] ns = ns +mergeSlots (c:cs) (n:ns) + = if c < n then + c : mergeSlots cs (n:ns) + else if c > n then + n : mergeSlots (c:cs) ns + else + panic ("mergeSlots: equal slots: " ++ show (c:cs) ++ show (n:ns)) + {- ALTERNATE version that doesn't work because update frames aren't recorded in the environment. diff --git a/ghc/compiler/codeGen/CgCase.lhs b/ghc/compiler/codeGen/CgCase.lhs index b02e248c1d9e..2ad8e996174a 100644 --- a/ghc/compiler/codeGen/CgCase.lhs +++ b/ghc/compiler/codeGen/CgCase.lhs @@ -1,7 +1,7 @@ % % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998 % -% $Id: CgCase.lhs,v 1.29 1999/05/18 15:03:46 simonpj Exp $ +% $Id: CgCase.lhs,v 1.30 1999/06/08 15:56:45 simonmar Exp $ % %******************************************************** %* * @@ -10,8 +10,7 @@ %******************************************************** \begin{code} -module CgCase ( cgCase, saveVolatileVarsAndRegs, - restoreCurrentCostCentre, freeCostCentreSlot +module CgCase ( cgCase, saveVolatileVarsAndRegs, restoreCurrentCostCentre ) where #include "HsVersions.h" @@ -39,7 +38,7 @@ import CgRetConv ( dataReturnConvPrim, ctrlReturnConvAlg, CtrlReturnConvention(..) ) import CgStackery ( allocPrimStack, allocStackTop, - deAllocStackTop, freeStackSlots + deAllocStackTop, freeStackSlots, dataStackSlots ) import CgTailCall ( tailCallFun ) import CgUsages ( getSpRelOffset, getRealSp ) @@ -434,9 +433,6 @@ cgEvalAlts cc_slot bndr srt alts = let uniq = getUnique bndr in - -- get the stack liveness for the info table (after the CC slot has - -- been freed - this is important). - freeCostCentreSlot cc_slot `thenC` buildContLivenessMask uniq `thenFC` \ liveness_mask -> case alts of @@ -500,12 +496,14 @@ cgEvalAlts cc_slot bndr srt alts -- primitive alts... (StgPrimAlts ty alts deflt) -> + -- Restore the cost centre + restoreCurrentCostCentre cc_slot `thenFC` \ cc_restore -> + -- Generate the switch getAbsC (cgPrimEvalAlts bndr ty alts deflt) `thenFC` \ abs_c -> -- Generate the labelled block, starting with restore-cost-centre getSRTLabel `thenFC` \srt_label -> - restoreCurrentCostCentre cc_slot `thenFC` \ cc_restore -> absC (CRetDirect uniq (cc_restore `mkAbsCStmts` abs_c) (srt_label,srt) liveness_mask) `thenC` @@ -855,19 +853,19 @@ saveCurrentCostCentre = if not opt_SccProfilingOn then returnFC (Nothing, AbsCNop) else - allocPrimStack (getPrimRepSize CostCentreRep) `thenFC` \ slot -> + allocPrimStack (getPrimRepSize CostCentreRep) `thenFC` \ slot -> + dataStackSlots [slot] `thenC` getSpRelOffset slot `thenFC` \ sp_rel -> returnFC (Just slot, CAssign (CVal sp_rel CostCentreRep) (CReg CurCostCentre)) -freeCostCentreSlot :: Maybe VirtualSpOffset -> Code -freeCostCentreSlot Nothing = nopC -freeCostCentreSlot (Just slot) = freeStackSlots [slot] - restoreCurrentCostCentre :: Maybe VirtualSpOffset -> FCode AbstractC restoreCurrentCostCentre Nothing = returnFC AbsCNop restoreCurrentCostCentre (Just slot) = getSpRelOffset slot `thenFC` \ sp_rel -> + freeStackSlots [slot] `thenC` + (\info_down state@(MkCgState abs_c binds ((vsp, free, real, hw), heap_usage)) + -> trace (show slot ++ " " ++ show vsp ++ " " ++ show free) $ state) `thenC` returnFC (CCallProfCCMacro SLIT("RESTORE_CCCS") [CVal sp_rel CostCentreRep]) -- we use the RESTORE_CCCS macro, rather than just -- assigning into CurCostCentre, in case RESTORE_CCC diff --git a/ghc/compiler/codeGen/CgClosure.lhs b/ghc/compiler/codeGen/CgClosure.lhs index 7d532bad1160..8646051f7632 100644 --- a/ghc/compiler/codeGen/CgClosure.lhs +++ b/ghc/compiler/codeGen/CgClosure.lhs @@ -1,7 +1,7 @@ % % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998 % -% $Id: CgClosure.lhs,v 1.31 1999/05/18 15:03:47 simonpj Exp $ +% $Id: CgClosure.lhs,v 1.32 1999/06/08 15:56:46 simonmar Exp $ % \section[CgClosure]{Code generation for closures} @@ -35,8 +35,8 @@ import CgHeapery ( allocDynClosure, fetchAndReschedule, yield, -- HWL fastEntryChecks, thunkChecks ) -import CgStackery ( adjustRealSp, mkTaggedVirtStkOffsets, freeStackSlots ) -import CgUsages ( setRealAndVirtualSp, getVirtSp, +import CgStackery ( mkTaggedVirtStkOffsets, freeStackSlots ) +import CgUsages ( adjustSpAndHp, setRealAndVirtualSp, getVirtSp, getSpRelOffset, getHpRelOffset ) import CLabel ( CLabel, mkClosureLabel, mkFastEntryLabel, @@ -357,8 +357,9 @@ closureCodeBody binder_info closure_info cc all_args body absC (mkAbstractCs (zipWith assign_to_reg arg_regs stk_amodes)) `thenC` - -- Now adjust real stack pointers - adjustRealSp sp_stk_args `thenC` + -- Now adjust real stack pointers (no need to adjust Hp, + -- but call this function for convenience). + adjustSpAndHp sp_stk_args `thenC` absC (CFallThrough (CLbl fast_label CodePtrRep)) diff --git a/ghc/compiler/codeGen/CgExpr.lhs b/ghc/compiler/codeGen/CgExpr.lhs index 4490a8174837..a57ee94f4262 100644 --- a/ghc/compiler/codeGen/CgExpr.lhs +++ b/ghc/compiler/codeGen/CgExpr.lhs @@ -1,7 +1,7 @@ % % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998 % -% $Id: CgExpr.lhs,v 1.25 1999/05/18 15:03:49 simonpj Exp $ +% $Id: CgExpr.lhs,v 1.26 1999/06/08 15:56:47 simonmar Exp $ % %******************************************************** %* * @@ -24,7 +24,7 @@ import CLabel ( mkClosureTblLabel ) import SMRep ( fixedHdrSize ) import CgBindery ( getArgAmodes, getArgAmode, CgIdInfo, nukeDeadBindings) import CgCase ( cgCase, saveVolatileVarsAndRegs, - restoreCurrentCostCentre, freeCostCentreSlot ) + restoreCurrentCostCentre ) import CgClosure ( cgRhsClosure, cgStdRhsClosure ) import CgCon ( buildDynCon, cgReturnDataCon ) import CgLetNoEscape ( cgLetNoEscapeClosure ) @@ -225,7 +225,6 @@ cgExpr (StgLetNoEscape live_in_whole_let live_in_rhss bindings body) saveVolatileVarsAndRegs live_in_rhss `thenFC` \ (save_assts, rhs_eob_info, maybe_cc_slot) -> -- ToDo: cost centre??? - freeCostCentreSlot maybe_cc_slot `thenC` restoreCurrentCostCentre maybe_cc_slot `thenFC` \ restore_cc -> -- Save those variables right now! diff --git a/ghc/compiler/codeGen/CgMonad.lhs b/ghc/compiler/codeGen/CgMonad.lhs index 06a9a52b7df4..df41f44dba8b 100644 --- a/ghc/compiler/codeGen/CgMonad.lhs +++ b/ghc/compiler/codeGen/CgMonad.lhs @@ -1,7 +1,7 @@ % % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998 % -% $Id: CgMonad.lhs,v 1.20 1999/05/18 15:03:49 simonpj Exp $ +% $Id: CgMonad.lhs,v 1.21 1999/06/08 15:56:47 simonmar Exp $ % \section[CgMonad]{The code generation monad} @@ -27,7 +27,7 @@ module CgMonad ( setSRTLabel, getSRTLabel, - StackUsage, HeapUsage, + StackUsage, Slot(..), HeapUsage, profCtrC, cgPanic, @@ -182,9 +182,11 @@ sequelToAmode (SeqFrame _ _) = cgPanic (text "sequelToAmode: SeqFrame") type CgStksAndHeapUsage -- stacks and heap usage information = (StackUsage, HeapUsage) +data Slot = Free | NonPointer deriving (Eq,Show) + type StackUsage = (Int, -- virtSp: Virtual offset of topmost allocated slot - [Int], -- free: List of free slots, in increasing order + [(Int,Slot)], -- free: List of free slots, in increasing order Int, -- realSp: Virtual offset of real stack pointer Int) -- hwSp: Highest value ever taken by virtSp @@ -203,9 +205,7 @@ Initialisation. initialStateC = MkCgState AbsCNop emptyVarEnv initUsage initUsage :: CgStksAndHeapUsage -initUsage = ((0,[],0,0), (initVirtHp, initRealHp)) -initVirtHp = panic "Uninitialised virtual Hp" -initRealHp = panic "Uninitialised real Hp" +initUsage = ((0,[],0,0), (0,0)) \end{code} "envInitForAlternatives" initialises the environment for a case alternative, @@ -462,8 +462,7 @@ forkEvalHelp body_eob_info env_code body_code state_for_body = MkCgState AbsCNop (nukeVolatileBinds binds) - ((v,f,v,v), - (initVirtHp, initRealHp)) + ((v,f,v,v), (0,0)) stateIncUsageEval :: CgState -> CgState -> CgState diff --git a/ghc/compiler/codeGen/CgStackery.lhs b/ghc/compiler/codeGen/CgStackery.lhs index 41ec06a885ef..a5479fe3c9e4 100644 --- a/ghc/compiler/codeGen/CgStackery.lhs +++ b/ghc/compiler/codeGen/CgStackery.lhs @@ -1,7 +1,7 @@ % % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998 % -% $Id: CgStackery.lhs,v 1.10 1998/12/18 17:40:53 simonpj Exp $ +% $Id: CgStackery.lhs,v 1.11 1999/06/08 15:56:47 simonmar Exp $ % \section[CgStackery]{Stack management functions} @@ -11,10 +11,9 @@ Stack-twiddling operations, which are pretty low-down and grimy. \begin{code} module CgStackery ( allocStack, allocPrimStack, allocStackTop, deAllocStackTop, - allocUpdateFrame, - adjustRealSp, adjustStackHW, getFinalStackHW, + adjustStackHW, getFinalStackHW, mkTaggedVirtStkOffsets, mkTaggedStkAmodes, mkTagAssts, - freeStackSlots, addFreeSlots + freeStackSlots, dataStackSlots, addFreeSlots ) where #include "HsVersions.h" @@ -26,6 +25,7 @@ import CgUsages ( getRealSp ) import AbsCUtils ( mkAbstractCs, mkAbsCStmts, getAmodeRep ) import PrimRep ( getPrimRepSize, PrimRep(..), isFollowableRep ) import Panic ( panic ) +import IOExts ( trace ) \end{code} %************************************************************************ @@ -152,21 +152,29 @@ allocPrimStack size info_down (MkCgState absC binds delete_block free_stk slot, real_sp, hw_sp)) -- find_block looks for a contiguous chunk of free slots - find_block :: [VirtualSpOffset] -> Maybe VirtualSpOffset + find_block :: [(VirtualSpOffset,Slot)] -> Maybe VirtualSpOffset find_block [] = Nothing - find_block (slot:slots) - | take size (slot:slots) == [slot..top_slot] = Just top_slot + find_block ((off,free):slots) + | take size ((off,free):slots) == + zip [off..top_slot] (repeat Free) = Just top_slot | otherwise = find_block slots -- The stack grows downwards, with increasing virtual offsets. -- Therefore, the address of a multi-word object is the *highest* -- virtual offset it occupies (top_slot below). - where top_slot = slot+size-1 + where top_slot = off+size-1 - delete_block free_stk slot = [s | s <- free_stk, (s<=slot-size) || (s>slot)] + delete_block free_stk slot = [ (s,f) | (s,f) <- free_stk, + (s<=slot-size) || (s>slot) ] -- Retain slots which are not in the range -- slot-size+1..slot +\end{code} + +Allocate a chunk ON TOP OF the stack. --- Allocate a chunk ON TOP OF the stack +ToDo: should really register this memory as NonPointer stuff in the +free list. + +\begin{code} allocStackTop :: Int -> FCode VirtualSpOffset allocStackTop size info_down (MkCgState absC binds ((virt_sp, free_stk, real_sp, hw_sp), h_usage)) @@ -190,33 +198,6 @@ deAllocStackTop size info_down (MkCgState absC binds new_stk_usage = (pop_virt_sp, free_stk, real_sp, hw_sp) \end{code} -@allocUpdateFrame@ allocates enough space for an update frame on the -stack, records the fact in the end-of-block info (in the ``args'' -fields), and passes on the old ``args'' fields to the enclosed code. - -This is all a bit disgusting. - -\begin{code} -allocUpdateFrame :: Int -- Size of frame - -> Code -- Scope of update - -> Code - -allocUpdateFrame size code - (MkCgInfoDown c_info statics srt (EndOfBlockInfo args_Sp sequel)) - (MkCgState absc binds ((vSp,rr,qq,hwSp),h_usage)) - = case sequel of - - OnStack _ -> code (MkCgInfoDown c_info statics srt new_eob_info) - (MkCgState absc binds new_usage) - - other -> panic "allocUpdateFrame" - - where - new_vSp = vSp + size - new_eob_info = EndOfBlockInfo new_vSp UpdateCode - new_usage = ((new_vSp,rr,qq,hwSp `max` new_vSp), h_usage) -\end{code} - \begin{code} adjustStackHW :: VirtualSpOffset -> Code adjustStackHW offset info_down (MkCgState absC binds usage) @@ -239,34 +220,6 @@ getFinalStackHW fcode info_down (MkCgState absC binds usages) = state1 \end{code} -%************************************************************************ -%* * -\subsection[CgStackery-adjust]{Adjusting the stack pointers} -%* * -%************************************************************************ - -@adjustRealSpX@ generates code to alter the actual stack pointer, and -adjusts the environment accordingly. We are careful to push the -conditional inside the abstract C code to avoid black holes. -ToDo: combine together? - -These functions {\em do not} deal with high-water-mark adjustment. -That's done by functions which allocate stack space. - -\begin{code} -adjustRealSp :: VirtualSpOffset -- New offset for Arg stack ptr - -> Code -adjustRealSp newRealSp info_down (MkCgState absC binds - ((vSp,fSp,realSp,hwSp), h_usage)) - = MkCgState (mkAbsCStmts absC move_instr) binds new_usage - where - move_instr = if (newRealSp == realSp) then AbsCNop - else (CAssign - (CReg Sp) - (CAddr (spRel realSp newRealSp))) - new_usage = ((vSp, fSp, newRealSp, hwSp), h_usage) -\end{code} - %************************************************************************ %* * \subsection[CgStackery-free]{Free stack slots} @@ -276,37 +229,51 @@ adjustRealSp newRealSp info_down (MkCgState absC binds Explicitly free some stack space. \begin{code} -freeStackSlots :: [VirtualSpOffset] -> Code -freeStackSlots extra_free info_down +addFreeStackSlots :: [VirtualSpOffset] -> Slot -> Code +addFreeStackSlots extra_free slot info_down state@(MkCgState abs_c binds ((vsp, free, real, hw), heap_usage)) = MkCgState abs_c binds new_usage where new_usage = ((new_vsp, new_free, real, hw), heap_usage) - (new_vsp, new_free) = trim vsp (addFreeSlots free extra_free) + (new_vsp, new_free) = trim vsp all_free + all_free = addFreeSlots free (zip extra_free (repeat slot)) + +freeStackSlots :: [VirtualSpOffset] -> Code +freeStackSlots slots = addFreeStackSlots slots Free -addFreeSlots :: [Int] -> [Int] -> [Int] +dataStackSlots :: [VirtualSpOffset] -> Code +dataStackSlots slots = addFreeStackSlots slots NonPointer + +addFreeSlots :: [(Int,Slot)] -> [(Int,Slot)] -> [(Int,Slot)] addFreeSlots cs [] = cs addFreeSlots [] ns = ns -addFreeSlots (c:cs) (n:ns) +addFreeSlots ((c,s):cs) ((n,s'):ns) = if c < n then - c : addFreeSlots cs (n:ns) + (c,s) : addFreeSlots cs ((n,s'):ns) else if c > n then - n : addFreeSlots (c:cs) ns + (n,s') : addFreeSlots ((c,s):cs) ns + else if s /= s' then -- c == n + (c,s') : addFreeSlots cs ns else - panic ("addFreeSlots: equal slots: " ++ show (c:cs) ++ show (n:ns)) + panic ("addFreeSlots: equal slots: " ++ show (c:map fst cs) + ++ show (n:map fst ns)) -trim :: Int{-offset-} -> [Int] -> (Int{-offset-}, [Int]) +trim :: Int{-offset-} -> [(Int,Slot)] -> (Int{-offset-}, [(Int,Slot)]) trim current_sp free_slots - = try current_sp (reverse free_slots) + = try current_sp free_slots where - try csp [] = (csp, []) - try csp (slot:slots) - = if csp < slot then - try csp slots -- Free slot off top of stk; ignore - - else if csp == slot then - try (csp-1) slots -- Free slot at top of stk; trim - - else - (csp, reverse (slot:slots)) -- Otherwise gap; give up + try csp [] = (csp,[]) + + try csp (slot@(off,state):slots) = + if state == Free && null slots' then + if csp' < off then + (csp', []) + else if csp' == off then + (csp'-1, []) + else + (csp',[slot]) + else + (csp', slot:slots') + where + (csp',slots') = try csp slots \end{code} diff --git a/ghc/compiler/codeGen/CgTailCall.lhs b/ghc/compiler/codeGen/CgTailCall.lhs index 96ceff561b5c..e98f66b39a41 100644 --- a/ghc/compiler/codeGen/CgTailCall.lhs +++ b/ghc/compiler/codeGen/CgTailCall.lhs @@ -1,7 +1,7 @@ % % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998 % -% $Id: CgTailCall.lhs,v 1.20 1999/05/28 19:24:28 simonpj Exp $ +% $Id: CgTailCall.lhs,v 1.21 1999/06/08 15:56:48 simonmar Exp $ % %******************************************************** %* * @@ -35,8 +35,8 @@ import CgRetConv ( dataReturnConvPrim, ctrlReturnConvAlg, CtrlReturnConvention(..), assignAllRegs, assignRegs ) -import CgStackery ( adjustRealSp, mkTaggedStkAmodes, adjustStackHW ) -import CgUsages ( getSpRelOffset ) +import CgStackery ( mkTaggedStkAmodes, adjustStackHW ) +import CgUsages ( getSpRelOffset, adjustSpAndHp ) import CgUpdate ( pushSeqFrame ) import CLabel ( mkUpdInfoLabel, mkRtsPrimOpLabel ) import ClosureInfo ( nodeMustPointToIt, @@ -266,8 +266,8 @@ performReturn sim_assts finish_code -- stack location) pushReturnAddress eob `thenC` - -- Adjust stack pointer - adjustRealSp args_sp `thenC` + -- Adjust Sp/Hp + adjustSpAndHp args_sp `thenC` -- Do the return finish_code sequel -- "sequel" is `robust' in that it doesn't @@ -299,8 +299,8 @@ returnUnboxedTuple amodes before_jump pushReturnAddress eob `thenC` setEndOfBlockInfo (EndOfBlockInfo args_sp (OnStack args_sp)) ( - -- Adjust stack pointer - adjustRealSp args_sp `thenC` + -- Adjust Sp/Hp + adjustSpAndHp args_sp `thenC` before_jump `thenC` @@ -458,8 +458,8 @@ doTailCall arg_amodes arg_regs finish_code arity pending_assts then nopC else pushReturnAddress eob) `thenC` - -- Final adjustment of stack pointer - adjustRealSp final_sp `thenC` + -- Final adjustment of Sp/Hp + adjustSpAndHp final_sp `thenC` -- Now decide about semi-tagging let diff --git a/ghc/compiler/codeGen/CgUpdate.lhs b/ghc/compiler/codeGen/CgUpdate.lhs index 1eec8f6be916..621e480ffa25 100644 --- a/ghc/compiler/codeGen/CgUpdate.lhs +++ b/ghc/compiler/codeGen/CgUpdate.lhs @@ -13,8 +13,8 @@ import AbsCSyn import Constants ( uF_SIZE, sCC_UF_SIZE, sEQ_FRAME_SIZE, sCC_SEQ_FRAME_SIZE ) import PrimRep ( PrimRep(..) ) -import CgStackery ( allocUpdateFrame ) -import CgUsages ( getSpRelOffset ) +import CgStackery ( allocStackTop ) +import CgUsages ( getVirtSp, getSpRelOffset ) import CmdLineOpts ( opt_SccProfilingOn ) import Panic ( assertPanic ) \end{code} @@ -44,21 +44,26 @@ pushUpdateFrame updatee code then sCC_UF_SIZE else uF_SIZE in +#ifdef DEBUG getEndOfBlockInfo `thenFC` \ eob_info -> ASSERT(case eob_info of { EndOfBlockInfo _ (OnStack _) -> True; _ -> False}) - allocUpdateFrame frame_size ( +#endif + + allocStackTop frame_size `thenFC` \ _ -> + getVirtSp `thenFC` \ vsp -> + + setEndOfBlockInfo (EndOfBlockInfo vsp UpdateCode) ( -- Emit the push macro absC (CMacroStmt PUSH_UPD_FRAME [ updatee, - int_CLit0 -- Known to be zero because we have just + int_CLit0 -- we just entered a closure, so must be zero ]) `thenC` code ) int_CLit0 = mkIntCLit 0 -- out here to avoid pushUpdateFrame CAF (sigh) - \end{code} We push a SEQ frame just before evaluating the scrutinee of a case, if diff --git a/ghc/compiler/codeGen/CgUsages.lhs b/ghc/compiler/codeGen/CgUsages.lhs index a3fd37a0742d..ce20791ee7d4 100644 --- a/ghc/compiler/codeGen/CgUsages.lhs +++ b/ghc/compiler/codeGen/CgUsages.lhs @@ -13,13 +13,15 @@ module CgUsages ( getVirtSp, getRealSp, - getHpRelOffset, getSpRelOffset + getHpRelOffset, getSpRelOffset, + + adjustSpAndHp ) where #include "HsVersions.h" -import AbsCSyn ( RegRelative(..), VirtualHeapOffset, VirtualSpOffset, - hpRel, spRel ) +import AbsCSyn +import AbsCUtils ( mkAbstractCs ) import CgMonad \end{code} @@ -121,3 +123,39 @@ getSpRelOffset :: VirtualSpOffset -> FCode RegRelative getSpRelOffset virtual_offset info_down state@(MkCgState _ _ ((_,_,realSp,_),_)) = (spRel realSp virtual_offset, state) \end{code} + +%************************************************************************ +%* * +\subsection[CgStackery-adjust]{Adjusting the stack pointers} +%* * +%************************************************************************ + +This function adjusts the stack and heap pointers just before a tail +call or return. The stack pointer is adjusted to its final position +(i.e. to point to the last argument for a tail call, or the activation +record for a return). The heap pointer may be moved backwards, in +cases where we overallocated at the beginning of the basic block (see +CgCase.lhs for discussion). + +These functions {\em do not} deal with high-water-mark adjustment. +That's done by functions which allocate stack space. + +\begin{code} +adjustSpAndHp :: VirtualSpOffset -- New offset for Arg stack ptr + -> Code +adjustSpAndHp newRealSp info_down (MkCgState absC binds + ((vSp,fSp,realSp,hwSp), + (vHp, rHp))) + = MkCgState (mkAbstractCs [absC,move_sp,move_hp]) binds new_usage + where + + move_sp = if (newRealSp == realSp) then AbsCNop + else (CAssign (CReg Sp) + (CAddr (spRel realSp newRealSp))) + + move_hp = if (rHp == vHp) then AbsCNop + else (CAssign (CReg Hp) + (CAddr (hpRel rHp vHp))) + + new_usage = ((vSp, fSp, newRealSp, hwSp), (vHp,vHp)) +\end{code} -- GitLab