2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1996
4 \section[HeapOffs]{Abstract C: heap offsets}
6 Part of ``Abstract C.'' Heap offsets---main point: they are {\em
7 symbolic}---are sufficiently turgid that they get their own module.
9 INTERNAL MODULE: should be accessed via @AbsCSyn.hi@.
12 #include "HsVersions.h"
17 zeroOff, intOff, fixedHdrSize, totHdrSize, varHdrSize,
18 maxOff, addOff, subOff,
19 isZeroOff, possiblyEqualHeapOffset,
26 #if ! OMIT_NATIVE_CODEGEN
31 VirtualHeapOffset(..), HpRelOffset(..),
32 VirtualSpAOffset(..), VirtualSpBOffset(..),
33 SpARelOffset(..), SpBRelOffset(..)
38 import ClosureInfo ( isSpecRep )
39 import Maybes ( catMaybes )
41 import Unpretty -- ********** NOTE **********
43 #if ! OMIT_NATIVE_CODEGEN
44 --import MachDesc ( Target )
48 %************************************************************************
50 \subsection[Offsets-Heap-and-others]{Offsets, Heap and otherwise}
52 %************************************************************************
56 < fixed-hdr-size> < var-hdr-size >
57 ---------------------------------------------------------------------
58 |info| | | | | | | | ptrs... | nonptrs ... | slop.... |
59 ---------------------------------------------------------------------
60 <------------- header ------------>
62 * Node, the ptr to the closure, pts at its info-ptr field
67 FAST_INT -- this many words...
69 FAST_INT -- PLUS: this many FixedHdrSizes
71 [SMRep__Int] -- PLUS: for each elem in this list:
72 -- "Int" VarHdrSizes for rep "SMRep"
74 -- We never have any SpecReps in here, because their
77 [SMRep__Int] -- PLUS: for each elem in this list:
78 -- "Int" TotHdrSizes for rep "SMRep"
80 -- We never have any SpecReps in here, because
81 -- their TotHdrSize is just FixedHdrSize
83 | MaxHeapOffset HeapOffset HeapOffset
84 | SubHeapOffset HeapOffset HeapOffset
85 | AddHeapOffset HeapOffset HeapOffset
88 deriving () -- but: see `eqOff` below
90 data SMRep__Int = SMRI_ SMRep Int#
91 #define SMRI(a,b) (SMRI_ a b)
93 type VirtualHeapOffset = HeapOffset
94 type VirtualSpAOffset = Int
95 type VirtualSpBOffset = Int
97 type HpRelOffset = HeapOffset
98 type SpARelOffset = Int
99 type SpBRelOffset = Int
102 Interface fns for HeapOffsets:
104 zeroOff = ZeroHeapOffset
106 intOff IBOX(n) = MkHeapOffset n ILIT(0) [] []
108 fixedHdrSize = MkHeapOffset ILIT(0) ILIT(1) [] []
111 = if isSpecRep sm_rep -- Tot hdr size for a spec rep is just FixedHdrSize
112 then MkHeapOffset ILIT(0) ILIT(1) [] []
113 else MkHeapOffset ILIT(0) ILIT(0) [] [SMRI(sm_rep, ILIT(1))]
116 = if isSpecRep sm_rep
118 else MkHeapOffset ILIT(0) ILIT(0) [SMRI(sm_rep, ILIT(1))] []
121 %************************************************************************
123 \subsubsection[Heap-offset-arithmetic]{Heap offset arithmetic}
125 %************************************************************************
128 -- For maxOff we do our best when we have something simple to deal with
129 maxOff ZeroHeapOffset off2 = off2
130 maxOff off1 ZeroHeapOffset = off1
131 maxOff off1@(MkHeapOffset int_offs1 fixhdr_offs1 varhdr_offs1 tothdr_offs1)
132 off2@(MkHeapOffset int_offs2 fixhdr_offs2 varhdr_offs2 tothdr_offs2)
133 = if (int_offs1 _LE_ int_offs2) &&
134 (real_fixed1 _LE_ real_fixed2) &&
135 (all negative_or_zero difference_of_real_varhdrs)
139 if (int_offs2 _LE_ int_offs1) &&
140 (real_fixed2 _LE_ real_fixed1) &&
141 (all positive_or_zero difference_of_real_varhdrs)
145 MaxHeapOffset off1 off2
147 -- Normalise, by realising that each tot-hdr is really a
148 -- var-hdr plus a fixed-hdr
149 n_tothdr1 = total_of tothdr_offs1
150 real_fixed1 = fixhdr_offs1 _ADD_ n_tothdr1
151 real_varhdr1 = add_HdrSizes varhdr_offs1 tothdr_offs1
153 n_tothdr2 = total_of tothdr_offs2
154 real_fixed2 = fixhdr_offs2 _ADD_ n_tothdr2
155 real_varhdr2 = add_HdrSizes varhdr_offs2 tothdr_offs2
157 -- Take the difference of the normalised var-hdrs
158 difference_of_real_varhdrs
159 = add_HdrSizes real_varhdr1 (map negate_HdrSize real_varhdr2)
161 negate_HdrSize :: SMRep__Int -> SMRep__Int
162 negate_HdrSize SMRI(rep,n) = SMRI(rep, (_NEG_ n))
164 positive_or_zero SMRI(rep,n) = n _GE_ ILIT(0)
165 negative_or_zero SMRI(rep,n) = n _LE_ ILIT(0)
167 total_of [] = ILIT(0)
168 total_of (SMRI(rep,n):offs) = n _ADD_ total_of offs
170 maxOff other_off1 other_off2 = MaxHeapOffset other_off1 other_off2
172 ------------------------------------------------------------------
174 subOff off1 ZeroHeapOffset = off1
176 (MkHeapOffset int_offs2 fxdhdr_offs2 varhdr_offs2 tothdr_offs2)
178 (MkHeapOffset (_NEG_ int_offs2)
180 (map negate_HdrSize varhdr_offs2)
181 (map negate_HdrSize tothdr_offs2))
183 negate_HdrSize :: SMRep__Int -> SMRep__Int
184 negate_HdrSize SMRI(rep,n) = SMRI(rep,(_NEG_ n))
186 subOff other_off1 other_off2 = SubHeapOffset other_off1 other_off2
188 ------------------------------------------------------------------
190 addOff ZeroHeapOffset off2 = off2
191 addOff off1 ZeroHeapOffset = off1
192 addOff (MkHeapOffset int_offs1 fxdhdr_offs1 varhdr_offs1 tothdr_offs1)
193 (MkHeapOffset int_offs2 fxdhdr_offs2 varhdr_offs2 tothdr_offs2)
195 (int_offs1 _ADD_ int_offs2)
196 (fxdhdr_offs1 _ADD_ fxdhdr_offs2)
197 (add_HdrSizes varhdr_offs1 varhdr_offs2)
198 (add_HdrSizes tothdr_offs1 tothdr_offs2)
200 addOff other_off1 other_off2 = AddHeapOffset other_off1 other_off2
202 ------------------------------------------------------------------
205 add_HdrSizes :: [SMRep__Int] -> [SMRep__Int] -> [SMRep__Int]
207 add_HdrSizes [] offs2 = offs2
208 add_HdrSizes offs1 [] = offs1
209 add_HdrSizes as@(off1@(SMRI(rep1,n1)) : offs1) bs@(off2@(SMRI(rep2,n2)) : offs2)
210 = if rep1 `ltSMRepHdr` rep2 then
211 off1 : (add_HdrSizes offs1 bs)
213 if rep2 `ltSMRepHdr` rep1 then
214 off2 : (add_HdrSizes as offs2)
217 n1_plus_n2 = n1 _ADD_ n2
219 -- So they are the same rep
220 if n1_plus_n2 _EQ_ ILIT(0) then
221 add_HdrSizes offs1 offs2
223 (SMRI(rep1, n1_plus_n2)) : (add_HdrSizes offs1 offs2)
227 isZeroOff :: HeapOffset -> Bool
228 isZeroOff ZeroHeapOffset = True
229 isZeroOff (MaxHeapOffset off1 off2) = isZeroOff off1 && isZeroOff off2
231 isZeroOff (AddHeapOffset off1 off2) = isZeroOff off1 && isZeroOff off2
232 -- This assumes that AddHeapOffset only has positive arguments
234 isZeroOff (MkHeapOffset int_offs fxdhdr_offs varhdr_offs tothdr_offs)
235 = int_offs _EQ_ ILIT(0) && fxdhdr_offs _EQ_ ILIT(0) &&
236 null varhdr_offs && null tothdr_offs
238 isZeroOff (SubHeapOffset off1 off2) = panic "Can't say if a SubHeapOffset is zero"
241 @possiblyEqualHeapOffset@ tells if two heap offsets might be equal.
242 It has to be conservative, but the situation in which it is used
243 (@doSimultaneously@) makes it likely to give a good answer.
246 possiblyEqualHeapOffset :: HeapOffset -> HeapOffset -> Bool
247 possiblyEqualHeapOffset o1 o2
248 = case (o1 `subOff` o2) of
250 SubHeapOffset _ _ -> True -- Very conservative
252 diff -> not (isZeroOff diff) -- Won't be any SubHeapOffsets in diff
253 -- NB: this claim depends on the use of
254 -- heap offsets, so this defn might need
259 %************************************************************************
261 \subsection[HeapOffs-printing]{Printing heap offsets}
263 %************************************************************************
265 IMPORTANT: @pprHeapOffset@ and @pprHeapOffsetPieces@ guarantee to
266 print either a single value, or a parenthesised value. No need for
267 the caller to parenthesise.
270 pprHeapOffset :: PprStyle -> HeapOffset -> Unpretty
272 pprHeapOffset sty ZeroHeapOffset = uppChar '0'
274 pprHeapOffset sty (MaxHeapOffset off1 off2)
275 = uppBesides [uppPStr SLIT("STG_MAX"), uppLparen,
276 pprHeapOffset sty off1, uppComma, pprHeapOffset sty off2,
278 pprHeapOffset sty (AddHeapOffset off1 off2)
279 = uppBesides [uppLparen, pprHeapOffset sty off1, uppChar '+',
280 pprHeapOffset sty off2, uppRparen]
281 pprHeapOffset sty (SubHeapOffset off1 off2)
282 = uppBesides [uppLparen, pprHeapOffset sty off1, uppChar '-',
283 pprHeapOffset sty off2, uppRparen]
285 pprHeapOffset sty (MkHeapOffset int_offs fxdhdr_offs varhdr_offs tothdr_offs)
286 = pprHeapOffsetPieces sty int_offs fxdhdr_offs varhdr_offs tothdr_offs
290 pprHeapOffsetPieces :: PprStyle
292 -> FAST_INT -- Fixed hdrs
293 -> [SMRep__Int] -- Var hdrs
294 -> [SMRep__Int] -- Tot hdrs
297 pprHeapOffsetPieces sty n ILIT(0) [] [] = uppInt IBOX(n) -- Deals with zero case too
299 pprHeapOffsetPieces sty int_offs fxdhdr_offs varhdr_offs tothdr_offs
301 if int_offs _EQ_ ILIT(0)
303 else Just (uppInt IBOX(int_offs))
306 if fxdhdr_offs _EQ_ ILIT(0) then
308 else if fxdhdr_offs _EQ_ ILIT(1) then
309 Just (uppPStr SLIT("_FHS"))
311 Just (uppBesides [uppStr "(_FHS*", uppInt IBOX(fxdhdr_offs), uppChar ')'])
313 pp_varhdr_offs = pp_hdrs (uppPStr SLIT("_VHS")) varhdr_offs
315 pp_tothdr_offs = pp_hdrs (uppPStr SLIT("_HS")) tothdr_offs
317 case (catMaybes [pp_tothdr_offs, pp_varhdr_offs, pp_fxdhdr_offs, pp_int_offs]) of
319 [pp] -> pp -- Each blob is parenthesised if necessary
320 pps -> uppBesides [ uppLparen, uppIntersperse (uppChar '+') pps, uppRparen ]
322 pp_hdrs hdr_pp [] = Nothing
323 pp_hdrs hdr_pp [SMRI(rep, n)] | n _EQ_ ILIT(1) = Just (uppBeside (uppStr (show rep)) hdr_pp)
324 pp_hdrs hdr_pp hdrs = Just (uppBesides [ uppLparen,
325 uppInterleave (uppChar '+')
326 (map (pp_hdr hdr_pp) hdrs),
329 pp_hdr :: Unpretty -> SMRep__Int -> Unpretty
330 pp_hdr pp_str (SMRI(rep, n))
331 = if n _EQ_ ILIT(1) then
332 uppBeside (uppStr (show rep)) pp_str
334 uppBesides [uppInt IBOX(n), uppChar '*', uppStr (show rep), pp_str]
337 %************************************************************************
339 \subsection[HeapOffs-conversion]{Converting heap offsets to words}
341 %************************************************************************
343 @intOffsetIntoGoods@ and @hpRelToInt@ convert HeapOffsets into Ints.
345 @intOffsetIntoGoods@ {\em tries} to convert a HeapOffset in a SPEC
346 closure into an Int, returning the (0-origin) index from the beginning
347 of the ``goods'' in the closure. [SPECs don't have VHSs, by
348 definition, so the index is merely ignoring the FHS].
350 @hpRelToInt@ is for the native code-generator(s); it is courtesy of
351 Jon Hill and the DAP code generator. We've just abstracted away some
352 of the implementation-dependent bits.
355 intOffsetIntoGoods :: HeapOffset -> Maybe Int
357 intOffsetIntoGoods (MkHeapOffset n ILIT(1){-FHS-} [{-no VHSs-}] [{-no totHSs-}])
359 intOffsetIntoGoods anything_else = Nothing
364 #if ! OMIT_NATIVE_CODEGEN
366 hpRelToInt :: Target -> HeapOffset -> Int
368 hpRelToInt target (MaxHeapOffset left right)
369 = (hpRelToInt target left) `max` (hpRelToInt target right)
371 hpRelToInt target (SubHeapOffset left right)
372 = (hpRelToInt target left) - (hpRelToInt target right)
374 hpRelToInt target (AddHeapOffset left right)
375 = (hpRelToInt target left) + (hpRelToInt target right)
377 hpRelToInt target ZeroHeapOffset = 0
379 hpRelToInt target (MkHeapOffset base fhs vhs ths)
381 vhs_pieces, ths_pieces :: [Int]
382 fhs_off, vhs_off, ths_off :: Int
384 vhs_pieces = map (\ (SMRI(r, n)) -> vhs_size r * IBOX(n)) vhs
385 ths_pieces = map (\ (SMRI(r, n)) -> (fhs_size + vhs_size r) * IBOX(n)) ths
387 fhs_off = fhs_size * IBOX(fhs)
388 vhs_off = sum vhs_pieces
389 ths_off = sum ths_pieces
391 IBOX(base) + fhs_off + vhs_off + ths_off
393 fhs_size = (fixedHeaderSize target) :: Int
394 vhs_size r = (varHeaderSize target r) :: Int