2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1995
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"
18 HeapOffset(..), -- DPH needs to do a little peaking inside this thing.
19 #endif {- Data Parallel Haskell -}
21 zeroOff, intOff, fixedHdrSize, totHdrSize, varHdrSize,
22 maxOff, addOff, subOff,
23 isZeroOff, possiblyEqualHeapOffset,
29 #if ! OMIT_NATIVE_CODEGEN
33 VirtualHeapOffset(..), HpRelOffset(..),
34 VirtualSpAOffset(..), VirtualSpBOffset(..),
35 SpARelOffset(..), SpBRelOffset(..)
38 import ClosureInfo -- esp. about SMReps
40 #if ! OMIT_NATIVE_CODEGEN
43 import Maybes ( catMaybes, Maybe(..) )
45 import Unpretty -- ********** NOTE **********
49 %************************************************************************
51 \subsection[Offsets-Heap-and-others]{Offsets, Heap and otherwise}
53 %************************************************************************
57 < fixed-hdr-size> < var-hdr-size >
58 ---------------------------------------------------------------------
59 |info| | | | | | | | ptrs... | nonptrs ... | slop.... |
60 ---------------------------------------------------------------------
61 <------------- header ------------>
63 * Node, the ptr to the closure, pts at its info-ptr field
68 FAST_INT -- this many words...
70 FAST_INT -- PLUS: this many FixedHdrSizes
72 [SMRep__Int] -- PLUS: for each elem in this list:
73 -- "Int" VarHdrSizes for rep "SMRep"
75 -- We never have any SpecReps in here, because their
78 [SMRep__Int] -- PLUS: for each elem in this list:
79 -- "Int" TotHdrSizes for rep "SMRep"
81 -- We never have any SpecReps in here, because
82 -- their TotHdrSize is just FixedHdrSize
84 | MaxHeapOffset HeapOffset HeapOffset
85 | SubHeapOffset HeapOffset HeapOffset
86 | AddHeapOffset HeapOffset HeapOffset
89 deriving () -- but: see `eqOff` below
91 #if defined(__GLASGOW_HASKELL__)
92 data SMRep__Int = SMRI_ SMRep Int#
93 #define SMRI(a,b) (SMRI_ a b)
95 type SMRep__Int = (SMRep, Int)
96 #define SMRI(a,b) (a, b)
99 type VirtualHeapOffset = HeapOffset
100 type VirtualSpAOffset = Int
101 type VirtualSpBOffset = Int
103 type HpRelOffset = HeapOffset
104 type SpARelOffset = Int
105 type SpBRelOffset = Int
108 Interface fns for HeapOffsets:
110 zeroOff = ZeroHeapOffset
112 intOff IBOX(n) = MkHeapOffset n ILIT(0) [] []
114 fixedHdrSize = MkHeapOffset ILIT(0) ILIT(1) [] []
117 = if isSpecRep sm_rep -- Tot hdr size for a spec rep is just FixedHdrSize
118 then MkHeapOffset ILIT(0) ILIT(1) [] []
119 else MkHeapOffset ILIT(0) ILIT(0) [] [SMRI(sm_rep, ILIT(1))]
122 = if isSpecRep sm_rep
124 else MkHeapOffset ILIT(0) ILIT(0) [SMRI(sm_rep, ILIT(1))] []
127 %************************************************************************
129 \subsubsection[Heap-offset-arithmetic]{Heap offset arithmetic}
131 %************************************************************************
134 -- For maxOff we do our best when we have something simple to deal with
135 maxOff ZeroHeapOffset off2 = off2
136 maxOff off1 ZeroHeapOffset = off1
137 maxOff off1@(MkHeapOffset int_offs1 fixhdr_offs1 varhdr_offs1 tothdr_offs1)
138 off2@(MkHeapOffset int_offs2 fixhdr_offs2 varhdr_offs2 tothdr_offs2)
139 = if (int_offs1 _LE_ int_offs2) &&
140 (real_fixed1 _LE_ real_fixed2) &&
141 (all negative_or_zero difference_of_real_varhdrs)
145 if (int_offs2 _LE_ int_offs1) &&
146 (real_fixed2 _LE_ real_fixed1) &&
147 (all positive_or_zero difference_of_real_varhdrs)
151 MaxHeapOffset off1 off2
153 -- Normalise, by realising that each tot-hdr is really a
154 -- var-hdr plus a fixed-hdr
155 n_tothdr1 = total_of tothdr_offs1
156 real_fixed1 = fixhdr_offs1 _ADD_ n_tothdr1
157 real_varhdr1 = add_HdrSizes varhdr_offs1 tothdr_offs1
159 n_tothdr2 = total_of tothdr_offs2
160 real_fixed2 = fixhdr_offs2 _ADD_ n_tothdr2
161 real_varhdr2 = add_HdrSizes varhdr_offs2 tothdr_offs2
163 -- Take the difference of the normalised var-hdrs
164 difference_of_real_varhdrs
165 = add_HdrSizes real_varhdr1 (map negate_HdrSize real_varhdr2)
167 negate_HdrSize :: SMRep__Int -> SMRep__Int
168 negate_HdrSize SMRI(rep,n) = SMRI(rep, (_NEG_ n))
170 positive_or_zero SMRI(rep,n) = n _GE_ ILIT(0)
171 negative_or_zero SMRI(rep,n) = n _LE_ ILIT(0)
173 total_of [] = ILIT(0)
174 total_of (SMRI(rep,n):offs) = n _ADD_ total_of offs
176 maxOff other_off1 other_off2 = MaxHeapOffset other_off1 other_off2
178 ------------------------------------------------------------------
180 subOff off1 ZeroHeapOffset = off1
182 (MkHeapOffset int_offs2 fxdhdr_offs2 varhdr_offs2 tothdr_offs2)
184 (MkHeapOffset (_NEG_ int_offs2)
186 (map negate_HdrSize varhdr_offs2)
187 (map negate_HdrSize tothdr_offs2))
189 negate_HdrSize :: SMRep__Int -> SMRep__Int
190 negate_HdrSize SMRI(rep,n) = SMRI(rep,(_NEG_ n))
192 subOff other_off1 other_off2 = SubHeapOffset other_off1 other_off2
194 ------------------------------------------------------------------
196 addOff ZeroHeapOffset off2 = off2
197 addOff off1 ZeroHeapOffset = off1
198 addOff (MkHeapOffset int_offs1 fxdhdr_offs1 varhdr_offs1 tothdr_offs1)
199 (MkHeapOffset int_offs2 fxdhdr_offs2 varhdr_offs2 tothdr_offs2)
201 (int_offs1 _ADD_ int_offs2)
202 (fxdhdr_offs1 _ADD_ fxdhdr_offs2)
203 (add_HdrSizes varhdr_offs1 varhdr_offs2)
204 (add_HdrSizes tothdr_offs1 tothdr_offs2)
206 addOff other_off1 other_off2 = AddHeapOffset other_off1 other_off2
208 ------------------------------------------------------------------
211 add_HdrSizes :: [SMRep__Int] -> [SMRep__Int] -> [SMRep__Int]
213 add_HdrSizes [] offs2 = offs2
214 add_HdrSizes offs1 [] = offs1
215 add_HdrSizes as@(off1@(SMRI(rep1,n1)) : offs1) bs@(off2@(SMRI(rep2,n2)) : offs2)
216 = if rep1 `ltSMRepHdr` rep2 then
217 off1 : (add_HdrSizes offs1 bs)
219 if rep2 `ltSMRepHdr` rep1 then
220 off2 : (add_HdrSizes as offs2)
223 n1_plus_n2 = n1 _ADD_ n2
225 -- So they are the same rep
226 if n1_plus_n2 _EQ_ ILIT(0) then
227 add_HdrSizes offs1 offs2
229 (SMRI(rep1, n1_plus_n2)) : (add_HdrSizes offs1 offs2)
233 isZeroOff :: HeapOffset -> Bool
234 isZeroOff ZeroHeapOffset = True
235 isZeroOff (MaxHeapOffset off1 off2) = isZeroOff off1 && isZeroOff off2
237 isZeroOff (AddHeapOffset off1 off2) = isZeroOff off1 && isZeroOff off2
238 -- This assumes that AddHeapOffset only has positive arguments
240 isZeroOff (MkHeapOffset int_offs fxdhdr_offs varhdr_offs tothdr_offs)
241 = int_offs _EQ_ ILIT(0) && fxdhdr_offs _EQ_ ILIT(0) &&
242 null varhdr_offs && null tothdr_offs
244 isZeroOff (SubHeapOffset off1 off2) = panic "Can't say if a SubHeapOffset is zero"
247 @possiblyEqualHeapOffset@ tells if two heap offsets might be equal.
248 It has to be conservative, but the situation in which it is used
249 (@doSimultaneously@) makes it likely to give a good answer.
252 possiblyEqualHeapOffset :: HeapOffset -> HeapOffset -> Bool
253 possiblyEqualHeapOffset o1 o2
254 = case (o1 `subOff` o2) of
256 SubHeapOffset _ _ -> True -- Very conservative
258 diff -> not (isZeroOff diff) -- Won't be any SubHeapOffsets in diff
259 -- NB: this claim depends on the use of
260 -- heap offsets, so this defn might need
265 %************************************************************************
267 \subsection[HeapOffs-printing]{Printing heap offsets}
269 %************************************************************************
271 IMPORTANT: @pprHeapOffset@ and @pprHeapOffsetPieces@ guarantee to
272 print either a single value, or a parenthesised value. No need for
273 the caller to parenthesise.
276 pprHeapOffset :: PprStyle -> HeapOffset -> Unpretty
278 pprHeapOffset sty ZeroHeapOffset = uppChar '0'
280 pprHeapOffset sty (MaxHeapOffset off1 off2)
281 = uppBesides [uppPStr SLIT("STG_MAX"), uppLparen,
282 pprHeapOffset sty off1, uppComma, pprHeapOffset sty off2,
284 pprHeapOffset sty (AddHeapOffset off1 off2)
285 = uppBesides [uppLparen, pprHeapOffset sty off1, uppChar '+',
286 pprHeapOffset sty off2, uppRparen]
287 pprHeapOffset sty (SubHeapOffset off1 off2)
288 = uppBesides [uppLparen, pprHeapOffset sty off1, uppChar '-',
289 pprHeapOffset sty off2, uppRparen]
291 pprHeapOffset sty (MkHeapOffset int_offs fxdhdr_offs varhdr_offs tothdr_offs)
292 = pprHeapOffsetPieces sty int_offs fxdhdr_offs varhdr_offs tothdr_offs
296 pprHeapOffsetPieces :: PprStyle
298 -> FAST_INT -- Fixed hdrs
299 -> [SMRep__Int] -- Var hdrs
300 -> [SMRep__Int] -- Tot hdrs
303 pprHeapOffsetPieces sty n ILIT(0) [] [] = uppInt IBOX(n) -- Deals with zero case too
305 pprHeapOffsetPieces sty int_offs fxdhdr_offs varhdr_offs tothdr_offs
307 if int_offs _EQ_ ILIT(0)
309 else Just (uppInt IBOX(int_offs))
312 if fxdhdr_offs _EQ_ ILIT(0) then
314 else if fxdhdr_offs _EQ_ ILIT(1) then
315 Just (uppPStr SLIT("_FHS"))
317 Just (uppBesides [uppStr "(_FHS*", uppInt IBOX(fxdhdr_offs), uppChar ')'])
319 pp_varhdr_offs = pp_hdrs (uppPStr SLIT("_VHS")) varhdr_offs
321 pp_tothdr_offs = pp_hdrs (uppPStr SLIT("_HS")) tothdr_offs
323 case (catMaybes [pp_tothdr_offs, pp_varhdr_offs, pp_fxdhdr_offs, pp_int_offs]) of
325 [pp] -> pp -- Each blob is parenthesised if necessary
326 pps -> uppBesides [ uppLparen, uppIntersperse (uppChar '+') pps, uppRparen ]
328 pp_hdrs hdr_pp [] = Nothing
329 pp_hdrs hdr_pp [SMRI(rep, n)] | n _EQ_ ILIT(1) = Just (uppBeside (uppStr (show rep)) hdr_pp)
330 pp_hdrs hdr_pp hdrs = Just (uppBesides [ uppLparen,
331 uppInterleave (uppChar '+')
332 (map (pp_hdr hdr_pp) hdrs),
335 pp_hdr :: Unpretty -> SMRep__Int -> Unpretty
336 pp_hdr pp_str (SMRI(rep, n))
337 = if n _EQ_ ILIT(1) then
338 uppBeside (uppStr (show rep)) pp_str
340 uppBesides [uppInt IBOX(n), uppChar '*', uppStr (show rep), pp_str]
343 %************************************************************************
345 \subsection[HeapOffs-conversion]{Converting heap offsets to words}
347 %************************************************************************
349 @intOffsetIntoGoods@ and @hpRelToInt@ convert HeapOffsets into Ints.
351 @intOffsetIntoGoods@ {\em tries} to convert a HeapOffset in a SPEC
352 closure into an Int, returning the (0-origin) index from the beginning
353 of the ``goods'' in the closure. [SPECs don't have VHSs, by
354 definition, so the index is merely ignoring the FHS].
356 @hpRelToInt@ is for the native code-generator(s); it is courtesy of
357 Jon Hill and the DAP code generator. We've just abstracted away some
358 of the implementation-dependent bits.
361 intOffsetIntoGoods :: HeapOffset -> Maybe Int
363 intOffsetIntoGoods (MkHeapOffset n ILIT(1){-FHS-} [{-no VHSs-}] [{-no totHSs-}])
365 intOffsetIntoGoods anything_else = Nothing
369 #if ! OMIT_NATIVE_CODEGEN
371 hpRelToInt :: Target -> HeapOffset -> Int
373 hpRelToInt target (MaxHeapOffset left right)
374 = (hpRelToInt target left) `max` (hpRelToInt target right)
376 hpRelToInt target (SubHeapOffset left right)
377 = (hpRelToInt target left) - (hpRelToInt target right)
379 hpRelToInt target (AddHeapOffset left right)
380 = (hpRelToInt target left) + (hpRelToInt target right)
382 hpRelToInt target ZeroHeapOffset = 0
384 hpRelToInt target (MkHeapOffset base fhs vhs ths)
386 vhs_pieces, ths_pieces :: [Int]
387 fhs_off, vhs_off, ths_off :: Int
389 vhs_pieces = map (\ (SMRI(r, n)) -> vhs_size r * IBOX(n)) vhs
390 ths_pieces = map (\ (SMRI(r, n)) -> (fhs_size + vhs_size r) * IBOX(n)) ths
392 fhs_off = fhs_size * IBOX(fhs)
393 vhs_off = sum vhs_pieces
394 ths_off = sum ths_pieces
396 IBOX(base) + fhs_off + vhs_off + ths_off
398 fhs_size = (fixedHeaderSize target) :: Int
399 vhs_size r = (varHeaderSize target r) :: Int