[project @ 1999-06-08 15:56:44 by simonmar]
[ghc-hetmet.git] / ghc / compiler / codeGen / CgUsages.lhs
1 %
2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
3 %
4 \section[CgUsages]{Accessing and modifying stacks and heap usage info}
5
6 This module provides the functions to access (\tr{get*} functions) and
7 modify (\tr{set*} functions) the stacks and heap usage information.
8
9 \begin{code}
10 module CgUsages (
11         initHeapUsage, setVirtHp, getVirtAndRealHp, setRealHp,
12         setRealAndVirtualSp,
13
14         getVirtSp, getRealSp,
15
16         getHpRelOffset, getSpRelOffset,
17
18         adjustSpAndHp
19     ) where
20
21 #include "HsVersions.h"
22
23 import AbsCSyn
24 import AbsCUtils        ( mkAbstractCs )
25 import CgMonad
26 \end{code}
27
28 %************************************************************************
29 %*                                                                      *
30 \subsection[CgUsages-heapery]{Monad things for fiddling with heap usage}
31 %*                                                                      *
32 %************************************************************************
33
34 @initHeapUsage@ applies a function to the amount of heap that it uses.
35 It initialises the heap usage to zeros, and passes on an unchanged
36 heap usage.
37
38 It is usually a prelude to performing a GC check, so everything must
39 be in a tidy and consistent state.
40
41 \begin{code}
42 initHeapUsage :: (VirtualHeapOffset -> Code) -> Code
43
44 initHeapUsage fcode info_down (MkCgState absC binds (stk_usage, heap_usage))
45   = state3
46   where
47     state1 = MkCgState absC binds (stk_usage, (0, 0))
48     state2 = fcode (heapHWM heap_usage2) info_down state1
49     (MkCgState absC2 binds2 (stk_usage2, heap_usage2)) = state2
50     state3 = MkCgState  absC2
51                         binds2
52                         (stk_usage2, heap_usage {- unchanged -})
53 \end{code}
54
55 \begin{code}
56 setVirtHp :: VirtualHeapOffset -> Code
57 setVirtHp new_virtHp info_down
58           state@(MkCgState absC binds (stk, (virtHp, realHp)))
59   = MkCgState absC binds (stk, (new_virtHp, realHp))
60 \end{code}
61
62 \begin{code}
63 getVirtAndRealHp :: FCode (VirtualHeapOffset, VirtualHeapOffset)
64 getVirtAndRealHp info_down state@(MkCgState _ _ (_, (virtHp, realHp)))
65   = ((virtHp, realHp), state)
66 \end{code}
67
68 \begin{code}
69 setRealHp ::  VirtualHeapOffset -> Code
70 setRealHp realHp info_down (MkCgState absC binds (stk_usage, (vHp, _)))
71   = MkCgState absC binds (stk_usage, (vHp, realHp))
72 \end{code}
73
74 \begin{code}
75 getHpRelOffset :: VirtualHeapOffset -> FCode RegRelative
76 getHpRelOffset virtual_offset info_down state@(MkCgState _ _ (_,(_,realHp)))
77   = (hpRel realHp virtual_offset, state)
78 \end{code}
79
80 The heap high water mark is the larger of virtHp and hwHp.  The latter is
81 only records the high water marks of forked-off branches, so to find the
82 heap high water mark you have to take the max of virtHp and hwHp.  Remember,
83 virtHp never retreats!
84
85 \begin{code}
86 heapHWM (virtHp, realHp) = virtHp
87 \end{code}
88
89 %************************************************************************
90 %*                                                                      *
91 \subsection[CgUsages-stackery]{Monad things for fiddling with stack usage}
92 %*                                                                      *
93 %************************************************************************
94
95 @setRealAndVirtualSp@ sets into the environment the offsets of the
96 current position of the real and virtual stack pointers in the current
97 stack frame.  The high-water mark is set too.  It generates no code.
98 It is used to initialise things at the beginning of a closure body.
99
100 \begin{code}
101 setRealAndVirtualSp :: VirtualSpOffset  -- New real Sp
102                      -> Code
103
104 setRealAndVirtualSp sp info_down (MkCgState absC binds
105                                         ((vsp,f,realSp,hwsp), h_usage))
106   = MkCgState absC binds new_usage
107   where
108     new_usage = ((sp, f, sp, sp), h_usage)
109 \end{code}
110
111 \begin{code}
112 getVirtSp :: FCode VirtualSpOffset
113 getVirtSp info_down state@(MkCgState absC binds ((virtSp,_,_,_), _))
114   = (virtSp, state)
115
116 getRealSp :: FCode VirtualSpOffset
117 getRealSp info_down state@(MkCgState absC binds ((_,_,realSp,_),_)) 
118   = (realSp,state)
119 \end{code}
120
121 \begin{code}
122 getSpRelOffset :: VirtualSpOffset -> FCode RegRelative
123 getSpRelOffset virtual_offset info_down state@(MkCgState _ _ ((_,_,realSp,_),_))
124   = (spRel realSp virtual_offset, state)
125 \end{code}
126
127 %************************************************************************
128 %*                                                                      *
129 \subsection[CgStackery-adjust]{Adjusting the stack pointers}
130 %*                                                                      *
131 %************************************************************************
132
133 This function adjusts the stack and heap pointers just before a tail
134 call or return.  The stack pointer is adjusted to its final position
135 (i.e. to point to the last argument for a tail call, or the activation
136 record for a return).  The heap pointer may be moved backwards, in
137 cases where we overallocated at the beginning of the basic block (see
138 CgCase.lhs for discussion).
139
140 These functions {\em do not} deal with high-water-mark adjustment.
141 That's done by functions which allocate stack space.
142
143 \begin{code}
144 adjustSpAndHp :: VirtualSpOffset        -- New offset for Arg stack ptr
145               -> Code
146 adjustSpAndHp newRealSp info_down (MkCgState absC binds
147                                         ((vSp,fSp,realSp,hwSp), 
148                                          (vHp, rHp)))
149   = MkCgState (mkAbstractCs [absC,move_sp,move_hp]) binds new_usage
150     where
151
152     move_sp = if (newRealSp == realSp) then AbsCNop
153               else (CAssign (CReg Sp)
154                             (CAddr (spRel realSp newRealSp)))
155
156     move_hp = if (rHp == vHp) then AbsCNop
157               else (CAssign (CReg Hp)
158                             (CAddr (hpRel rHp vHp)))
159
160     new_usage = ((vSp, fSp, newRealSp, hwSp), (vHp,vHp))
161 \end{code}