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@.
15 zeroOff, intOff, fixedHdrSize, totHdrSize, varHdrSize,
16 maxOff, addOff, subOff,
17 isZeroOff, possiblyEqualHeapOffset,
23 #if ! OMIT_NATIVE_CODEGEN
27 VirtualHeapOffset, HpRelOffset,
28 VirtualSpAOffset, VirtualSpBOffset,
29 SpARelOffset, SpBRelOffset
32 #include "HsVersions.h"
34 #if ! OMIT_NATIVE_CODEGEN
35 import {-# SOURCE #-} MachMisc
38 import Maybes ( catMaybes )
42 import GlaExts ( Int(..), Int#, (+#), negateInt#, (<=#), (>=#), (==#) )
45 %************************************************************************
47 \subsection[Offsets-Heap-and-others]{Offsets, Heap and otherwise}
49 %************************************************************************
53 < fixed-hdr-size> < var-hdr-size >
54 ---------------------------------------------------------------------
55 |info| | | | | | | | ptrs... | nonptrs ... | slop.... |
56 ---------------------------------------------------------------------
57 <------------- header ------------>
59 * Node, the ptr to the closure, pts at its info-ptr field
64 FAST_INT -- this many words...
66 FAST_INT -- PLUS: this many FixedHdrSizes
68 [SMRep__Int] -- PLUS: for each elem in this list:
69 -- "Int" VarHdrSizes for rep "SMRep"
71 -- We never have any SpecReps in here, because their
74 [SMRep__Int] -- PLUS: for each elem in this list:
75 -- "Int" TotHdrSizes for rep "SMRep"
77 -- We never have any SpecReps in here, because
78 -- their TotHdrSize is just FixedHdrSize
80 | MaxHeapOffset HeapOffset HeapOffset
81 | SubHeapOffset HeapOffset HeapOffset
82 | AddHeapOffset HeapOffset HeapOffset
85 deriving () -- but: see `eqOff` below
87 data SMRep__Int = SMRI_ SMRep Int#
88 #define SMRI(a,b) (SMRI_ a b)
90 type VirtualHeapOffset = HeapOffset
91 type VirtualSpAOffset = Int
92 type VirtualSpBOffset = Int
94 type HpRelOffset = HeapOffset
95 type SpARelOffset = Int
96 type SpBRelOffset = Int
99 Interface fns for HeapOffsets:
101 zeroOff = ZeroHeapOffset
103 intOff IBOX(n) = MkHeapOffset n ILIT(0) [] []
105 fixedHdrSize = MkHeapOffset ILIT(0) ILIT(1) [] []
108 = if isSpecRep sm_rep -- Tot hdr size for a spec rep is just FixedHdrSize
109 then MkHeapOffset ILIT(0) ILIT(1) [] []
110 else MkHeapOffset ILIT(0) ILIT(0) [] [SMRI(sm_rep, ILIT(1))]
113 = if isSpecRep sm_rep
115 else MkHeapOffset ILIT(0) ILIT(0) [SMRI(sm_rep, ILIT(1))] []
118 %************************************************************************
120 \subsubsection[Heap-offset-arithmetic]{Heap offset arithmetic}
122 %************************************************************************
125 -- For maxOff we do our best when we have something simple to deal with
126 maxOff ZeroHeapOffset off2 = off2
127 maxOff off1 ZeroHeapOffset = off1
128 maxOff off1@(MkHeapOffset int_offs1 fixhdr_offs1 varhdr_offs1 tothdr_offs1)
129 off2@(MkHeapOffset int_offs2 fixhdr_offs2 varhdr_offs2 tothdr_offs2)
130 = if (int_offs1 _LE_ int_offs2) &&
131 (real_fixed1 _LE_ real_fixed2) &&
132 (all negative_or_zero difference_of_real_varhdrs)
136 if (int_offs2 _LE_ int_offs1) &&
137 (real_fixed2 _LE_ real_fixed1) &&
138 (all positive_or_zero difference_of_real_varhdrs)
142 MaxHeapOffset off1 off2
144 -- Normalise, by realising that each tot-hdr is really a
145 -- var-hdr plus a fixed-hdr
146 n_tothdr1 = total_of tothdr_offs1
147 real_fixed1 = fixhdr_offs1 _ADD_ n_tothdr1
148 real_varhdr1 = add_HdrSizes varhdr_offs1 tothdr_offs1
150 n_tothdr2 = total_of tothdr_offs2
151 real_fixed2 = fixhdr_offs2 _ADD_ n_tothdr2
152 real_varhdr2 = add_HdrSizes varhdr_offs2 tothdr_offs2
154 -- Take the difference of the normalised var-hdrs
155 difference_of_real_varhdrs
156 = add_HdrSizes real_varhdr1 (map negate_HdrSize real_varhdr2)
158 negate_HdrSize :: SMRep__Int -> SMRep__Int
159 negate_HdrSize SMRI(rep,n) = SMRI(rep, (_NEG_ n))
161 positive_or_zero SMRI(rep,n) = n _GE_ ILIT(0)
162 negative_or_zero SMRI(rep,n) = n _LE_ ILIT(0)
164 total_of [] = ILIT(0)
165 total_of (SMRI(rep,n):offs) = n _ADD_ total_of offs
167 maxOff other_off1 other_off2 = MaxHeapOffset other_off1 other_off2
169 ------------------------------------------------------------------
171 subOff off1 ZeroHeapOffset = off1
173 (MkHeapOffset int_offs2 fxdhdr_offs2 varhdr_offs2 tothdr_offs2)
175 (MkHeapOffset (_NEG_ int_offs2)
177 (map negate_HdrSize varhdr_offs2)
178 (map negate_HdrSize tothdr_offs2))
180 negate_HdrSize :: SMRep__Int -> SMRep__Int
181 negate_HdrSize SMRI(rep,n) = SMRI(rep,(_NEG_ n))
183 subOff other_off1 other_off2 = SubHeapOffset other_off1 other_off2
185 ------------------------------------------------------------------
187 addOff ZeroHeapOffset off2 = off2
188 addOff off1 ZeroHeapOffset = off1
189 addOff (MkHeapOffset int_offs1 fxdhdr_offs1 varhdr_offs1 tothdr_offs1)
190 (MkHeapOffset int_offs2 fxdhdr_offs2 varhdr_offs2 tothdr_offs2)
192 (int_offs1 _ADD_ int_offs2)
193 (fxdhdr_offs1 _ADD_ fxdhdr_offs2)
194 (add_HdrSizes varhdr_offs1 varhdr_offs2)
195 (add_HdrSizes tothdr_offs1 tothdr_offs2)
197 addOff other_off1 other_off2 = AddHeapOffset other_off1 other_off2
199 ------------------------------------------------------------------
202 add_HdrSizes :: [SMRep__Int] -> [SMRep__Int] -> [SMRep__Int]
204 add_HdrSizes [] offs2 = offs2
205 add_HdrSizes offs1 [] = offs1
206 add_HdrSizes as@(off1@(SMRI(rep1,n1)) : offs1) bs@(off2@(SMRI(rep2,n2)) : offs2)
207 = if rep1 `ltSMRepHdr` rep2 then
208 off1 : (add_HdrSizes offs1 bs)
210 if rep2 `ltSMRepHdr` rep1 then
211 off2 : (add_HdrSizes as offs2)
214 n1_plus_n2 = n1 _ADD_ n2
216 -- So they are the same rep
217 if n1_plus_n2 _EQ_ ILIT(0) then
218 add_HdrSizes offs1 offs2
220 (SMRI(rep1, n1_plus_n2)) : (add_HdrSizes offs1 offs2)
224 isZeroOff :: HeapOffset -> Bool
225 isZeroOff ZeroHeapOffset = True
226 isZeroOff (MaxHeapOffset off1 off2) = isZeroOff off1 && isZeroOff off2
228 isZeroOff (AddHeapOffset off1 off2) = isZeroOff off1 && isZeroOff off2
229 -- This assumes that AddHeapOffset only has positive arguments
231 isZeroOff (MkHeapOffset int_offs fxdhdr_offs varhdr_offs tothdr_offs)
232 = int_offs _EQ_ ILIT(0) && fxdhdr_offs _EQ_ ILIT(0) &&
233 null varhdr_offs && null tothdr_offs
235 isZeroOff (SubHeapOffset off1 off2) = panic "Can't say if a SubHeapOffset is zero"
238 @possiblyEqualHeapOffset@ tells if two heap offsets might be equal.
239 It has to be conservative, but the situation in which it is used
240 (@doSimultaneously@) makes it likely to give a good answer.
243 possiblyEqualHeapOffset :: HeapOffset -> HeapOffset -> Bool
244 possiblyEqualHeapOffset o1 o2
245 = case (o1 `subOff` o2) of
247 SubHeapOffset _ _ -> True -- Very conservative
249 diff -> not (isZeroOff diff) -- Won't be any SubHeapOffsets in diff
250 -- NB: this claim depends on the use of
251 -- heap offsets, so this defn might need
256 %************************************************************************
258 \subsection[HeapOffs-printing]{Printing heap offsets}
260 %************************************************************************
262 IMPORTANT: @pprHeapOffset@ and @pprHeapOffsetPieces@ guarantee to
263 print either a single value, or a parenthesised value. No need for
264 the caller to parenthesise.
267 pprHeapOffset :: HeapOffset -> SDoc
269 pprHeapOffset ZeroHeapOffset = char '0'
271 pprHeapOffset (MaxHeapOffset off1 off2)
272 = (<>) (ptext SLIT("STG_MAX"))
273 (parens (hcat [pprHeapOffset off1, comma, pprHeapOffset off2]))
275 pprHeapOffset (AddHeapOffset off1 off2)
276 = parens (hcat [pprHeapOffset off1, char '+',
278 pprHeapOffset (SubHeapOffset off1 off2)
279 = parens (hcat [pprHeapOffset off1, char '-',
282 pprHeapOffset (MkHeapOffset int_offs fxdhdr_offs varhdr_offs tothdr_offs)
283 = pprHeapOffsetPieces int_offs fxdhdr_offs varhdr_offs tothdr_offs
287 pprHeapOffsetPieces :: FAST_INT -- Words
288 -> FAST_INT -- Fixed hdrs
289 -> [SMRep__Int] -- Var hdrs
290 -> [SMRep__Int] -- Tot hdrs
293 pprHeapOffsetPieces n ILIT(0) [] [] = int IBOX(n) -- Deals with zero case too
295 pprHeapOffsetPieces int_offs fxdhdr_offs varhdr_offs tothdr_offs
297 if int_offs _EQ_ ILIT(0)
299 else Just (int IBOX(int_offs))
302 if fxdhdr_offs _EQ_ ILIT(0) then
304 else if fxdhdr_offs _EQ_ ILIT(1) then
305 Just (ptext SLIT("_FHS"))
307 Just (hcat [char '(', ptext SLIT("_FHS*"), int IBOX(fxdhdr_offs), char ')'])
309 pp_varhdr_offs = pp_hdrs (ptext SLIT("_VHS")) varhdr_offs
311 pp_tothdr_offs = pp_hdrs (ptext SLIT("_HS")) tothdr_offs
313 case (catMaybes [pp_tothdr_offs, pp_varhdr_offs, pp_fxdhdr_offs, pp_int_offs]) of
315 [pp] -> pp -- Each blob is parenthesised if necessary
316 pps -> parens (hcat (punctuate (char '+') pps))
318 pp_hdrs hdr_pp [] = Nothing
319 pp_hdrs hdr_pp [SMRI(rep, n)] | n _EQ_ ILIT(1) = Just ((<>) (text (show rep)) hdr_pp)
320 pp_hdrs hdr_pp hdrs = Just (parens (hsep (punctuate (char '+')
321 (map (pp_hdr hdr_pp) hdrs))))
323 pp_hdr :: SDoc -> SMRep__Int -> SDoc
324 pp_hdr pp_str (SMRI(rep, n))
325 = if n _EQ_ ILIT(1) then
326 (<>) (text (show rep)) pp_str
328 hcat [int IBOX(n), char '*', text (show rep), pp_str]
331 %************************************************************************
333 \subsection[HeapOffs-conversion]{Converting heap offsets to words}
335 %************************************************************************
337 @intOffsetIntoGoods@ and @hpRelToInt@ convert HeapOffsets into Ints.
339 @intOffsetIntoGoods@ {\em tries} to convert a HeapOffset in a SPEC
340 closure into an Int, returning the (0-origin) index from the beginning
341 of the ``goods'' in the closure. [SPECs don't have VHSs, by
342 definition, so the index is merely ignoring the FHS].
344 @hpRelToInt@ is for the native code-generator(s); it is courtesy of
345 Jon Hill and the DAP code generator. We've just abstracted away some
346 of the implementation-dependent bits.
349 intOffsetIntoGoods :: HeapOffset -> Maybe Int
351 intOffsetIntoGoods (MkHeapOffset n ILIT(1){-FHS-} [{-no VHSs-}] [{-no totHSs-}])
353 intOffsetIntoGoods anything_else = Nothing
357 #if ! OMIT_NATIVE_CODEGEN
359 hpRelToInt :: HeapOffset -> Int
361 hpRelToInt ZeroHeapOffset = 0
363 hpRelToInt (MaxHeapOffset left right)
364 = hpRelToInt left `max` hpRelToInt right
366 hpRelToInt (SubHeapOffset left right)
367 = hpRelToInt left - hpRelToInt right
369 hpRelToInt (AddHeapOffset left right)
370 = hpRelToInt left + hpRelToInt right
372 hpRelToInt (MkHeapOffset base fhs vhs ths)
374 vhs_pieces, ths_pieces :: [Int]
375 fhs_off, vhs_off, ths_off :: Int
377 vhs_pieces = map (\ (SMRI(r, n)) -> vhs_size r * IBOX(n)) vhs
378 ths_pieces = map (\ (SMRI(r, n)) -> (fhs_size + vhs_size r) * IBOX(n)) ths
380 fhs_off = fhs_size * IBOX(fhs)
381 vhs_off = sum vhs_pieces
382 ths_off = sum ths_pieces
384 IBOX(base) + fhs_off + vhs_off + ths_off
386 fhs_size = fixedHdrSizeInWords
387 vhs_size r = varHdrSizeInWords r