Be more selective in which conditionals we invert
[ghc.git] / compiler / cmm / SMRep.hs
1 -- (c) The University of Glasgow 2006
2 -- (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
3 --
4 -- Storage manager representation of closures
5
6 {-# LANGUAGE CPP,GeneralizedNewtypeDeriving #-}
7
8 module SMRep (
9 -- * Words and bytes
10 WordOff, ByteOff,
11 wordsToBytes, bytesToWordsRoundUp,
12 roundUpToWords, roundUpTo,
13
14 StgWord, fromStgWord, toStgWord,
15 StgHalfWord, fromStgHalfWord, toStgHalfWord,
16 hALF_WORD_SIZE, hALF_WORD_SIZE_IN_BITS,
17
18 -- * Closure repesentation
19 SMRep(..), -- CmmInfo sees the rep; no one else does
20 IsStatic,
21 ClosureTypeInfo(..), ArgDescr(..), Liveness,
22 ConstrDescription,
23
24 -- ** Construction
25 mkHeapRep, blackHoleRep, indStaticRep, mkStackRep, mkRTSRep, arrPtrsRep,
26 smallArrPtrsRep, arrWordsRep,
27
28 -- ** Predicates
29 isStaticRep, isConRep, isThunkRep, isFunRep, isStaticNoCafCon,
30 isStackRep,
31
32 -- ** Size-related things
33 heapClosureSizeW,
34 fixedHdrSizeW, arrWordsHdrSize, arrWordsHdrSizeW, arrPtrsHdrSize,
35 arrPtrsHdrSizeW, profHdrSize, thunkHdrSize, nonHdrSize, nonHdrSizeW,
36 smallArrPtrsHdrSize, smallArrPtrsHdrSizeW, hdrSize, hdrSizeW,
37 fixedHdrSize,
38
39 -- ** RTS closure types
40 rtsClosureType, rET_SMALL, rET_BIG,
41 aRG_GEN, aRG_GEN_BIG,
42
43 -- ** Arrays
44 card, cardRoundUp, cardTableSizeB, cardTableSizeW,
45
46 -- * Operations over [Word8] strings that don't belong here
47 pprWord8String, stringToWord8s
48 ) where
49
50 import GhcPrelude
51
52 import BasicTypes( ConTagZ )
53 import DynFlags
54 import Outputable
55 import Platform
56 import FastString
57
58 import Data.Char( ord )
59 import Data.Word
60 import Data.Bits
61
62 {-
63 ************************************************************************
64 * *
65 Words and bytes
66 * *
67 ************************************************************************
68 -}
69
70 -- | Word offset, or word count
71 type WordOff = Int
72
73 -- | Byte offset, or byte count
74 type ByteOff = Int
75
76 -- | Round up the given byte count to the next byte count that's a
77 -- multiple of the machine's word size.
78 roundUpToWords :: DynFlags -> ByteOff -> ByteOff
79 roundUpToWords dflags n = roundUpTo n (wORD_SIZE dflags)
80
81 -- | Round up @base@ to a multiple of @size@.
82 roundUpTo :: ByteOff -> ByteOff -> ByteOff
83 roundUpTo base size = (base + (size - 1)) .&. (complement (size - 1))
84
85 -- | Convert the given number of words to a number of bytes.
86 --
87 -- This function morally has type @WordOff -> ByteOff@, but uses @Num
88 -- a@ to allow for overloading.
89 wordsToBytes :: Num a => DynFlags -> a -> a
90 wordsToBytes dflags n = fromIntegral (wORD_SIZE dflags) * n
91 {-# SPECIALIZE wordsToBytes :: DynFlags -> Int -> Int #-}
92 {-# SPECIALIZE wordsToBytes :: DynFlags -> Word -> Word #-}
93 {-# SPECIALIZE wordsToBytes :: DynFlags -> Integer -> Integer #-}
94
95 -- | First round the given byte count up to a multiple of the
96 -- machine's word size and then convert the result to words.
97 bytesToWordsRoundUp :: DynFlags -> ByteOff -> WordOff
98 bytesToWordsRoundUp dflags n = (n + word_size - 1) `quot` word_size
99 where word_size = wORD_SIZE dflags
100 -- StgWord is a type representing an StgWord on the target platform.
101 -- A Word64 is large enough to hold a Word for either a 32bit or 64bit platform
102 newtype StgWord = StgWord Word64
103 deriving (Eq, Bits)
104
105 fromStgWord :: StgWord -> Integer
106 fromStgWord (StgWord i) = toInteger i
107
108 toStgWord :: DynFlags -> Integer -> StgWord
109 toStgWord dflags i
110 = case platformWordSize (targetPlatform dflags) of
111 -- These conversions mean that things like toStgWord (-1)
112 -- do the right thing
113 4 -> StgWord (fromIntegral (fromInteger i :: Word32))
114 8 -> StgWord (fromInteger i :: Word64)
115 w -> panic ("toStgWord: Unknown platformWordSize: " ++ show w)
116
117 instance Outputable StgWord where
118 ppr (StgWord i) = integer (toInteger i)
119
120 --
121
122 -- A Word32 is large enough to hold half a Word for either a 32bit or
123 -- 64bit platform
124 newtype StgHalfWord = StgHalfWord Word32
125 deriving Eq
126
127 fromStgHalfWord :: StgHalfWord -> Integer
128 fromStgHalfWord (StgHalfWord w) = toInteger w
129
130 toStgHalfWord :: DynFlags -> Integer -> StgHalfWord
131 toStgHalfWord dflags i
132 = case platformWordSize (targetPlatform dflags) of
133 -- These conversions mean that things like toStgHalfWord (-1)
134 -- do the right thing
135 4 -> StgHalfWord (fromIntegral (fromInteger i :: Word16))
136 8 -> StgHalfWord (fromInteger i :: Word32)
137 w -> panic ("toStgHalfWord: Unknown platformWordSize: " ++ show w)
138
139 instance Outputable StgHalfWord where
140 ppr (StgHalfWord w) = integer (toInteger w)
141
142 hALF_WORD_SIZE :: DynFlags -> ByteOff
143 hALF_WORD_SIZE dflags = platformWordSize (targetPlatform dflags) `shiftR` 1
144 hALF_WORD_SIZE_IN_BITS :: DynFlags -> Int
145 hALF_WORD_SIZE_IN_BITS dflags = platformWordSize (targetPlatform dflags) `shiftL` 2
146
147 {-
148 ************************************************************************
149 * *
150 \subsubsection[SMRep-datatype]{@SMRep@---storage manager representation}
151 * *
152 ************************************************************************
153 -}
154
155 -- | A description of the layout of a closure. Corresponds directly
156 -- to the closure types in includes/rts/storage/ClosureTypes.h.
157 data SMRep
158 = HeapRep -- GC routines consult sizes in info tbl
159 IsStatic
160 !WordOff -- # ptr words
161 !WordOff -- # non-ptr words INCLUDING SLOP (see mkHeapRep below)
162 ClosureTypeInfo -- type-specific info
163
164 | ArrayPtrsRep
165 !WordOff -- # ptr words
166 !WordOff -- # card table words
167
168 | SmallArrayPtrsRep
169 !WordOff -- # ptr words
170
171 | ArrayWordsRep
172 !WordOff -- # bytes expressed in words, rounded up
173
174 | StackRep -- Stack frame (RET_SMALL or RET_BIG)
175 Liveness
176
177 | RTSRep -- The RTS needs to declare info tables with specific
178 Int -- type tags, so this form lets us override the default
179 SMRep -- tag for an SMRep.
180
181 -- | True <=> This is a static closure. Affects how we garbage-collect it.
182 -- Static closure have an extra static link field at the end.
183 -- Constructors do not have a static variant; see Note [static constructors]
184 type IsStatic = Bool
185
186 -- From an SMRep you can get to the closure type defined in
187 -- includes/rts/storage/ClosureTypes.h. Described by the function
188 -- rtsClosureType below.
189
190 data ClosureTypeInfo
191 = Constr ConTagZ ConstrDescription
192 | Fun FunArity ArgDescr
193 | Thunk
194 | ThunkSelector SelectorOffset
195 | BlackHole
196 | IndStatic
197
198 type ConstrDescription = [Word8] -- result of dataConIdentity
199 type FunArity = Int
200 type SelectorOffset = Int
201
202 -------------------------
203 -- We represent liveness bitmaps as a Bitmap (whose internal
204 -- representation really is a bitmap). These are pinned onto case return
205 -- vectors to indicate the state of the stack for the garbage collector.
206 --
207 -- In the compiled program, liveness bitmaps that fit inside a single
208 -- word (StgWord) are stored as a single word, while larger bitmaps are
209 -- stored as a pointer to an array of words.
210
211 type Liveness = [Bool] -- One Bool per word; True <=> non-ptr or dead
212 -- False <=> ptr
213
214 -------------------------
215 -- An ArgDescr describes the argument pattern of a function
216
217 data ArgDescr
218 = ArgSpec -- Fits one of the standard patterns
219 !Int -- RTS type identifier ARG_P, ARG_N, ...
220
221 | ArgGen -- General case
222 Liveness -- Details about the arguments
223
224
225 -----------------------------------------------------------------------------
226 -- Construction
227
228 mkHeapRep :: DynFlags -> IsStatic -> WordOff -> WordOff -> ClosureTypeInfo
229 -> SMRep
230 mkHeapRep dflags is_static ptr_wds nonptr_wds cl_type_info
231 = HeapRep is_static
232 ptr_wds
233 (nonptr_wds + slop_wds)
234 cl_type_info
235 where
236 slop_wds
237 | is_static = 0
238 | otherwise = max 0 (minClosureSize dflags - (hdr_size + payload_size))
239
240 hdr_size = closureTypeHdrSize dflags cl_type_info
241 payload_size = ptr_wds + nonptr_wds
242
243 mkRTSRep :: Int -> SMRep -> SMRep
244 mkRTSRep = RTSRep
245
246 mkStackRep :: [Bool] -> SMRep
247 mkStackRep liveness = StackRep liveness
248
249 blackHoleRep :: SMRep
250 blackHoleRep = HeapRep False 0 0 BlackHole
251
252 indStaticRep :: SMRep
253 indStaticRep = HeapRep True 1 0 IndStatic
254
255 arrPtrsRep :: DynFlags -> WordOff -> SMRep
256 arrPtrsRep dflags elems = ArrayPtrsRep elems (cardTableSizeW dflags elems)
257
258 smallArrPtrsRep :: WordOff -> SMRep
259 smallArrPtrsRep elems = SmallArrayPtrsRep elems
260
261 arrWordsRep :: DynFlags -> ByteOff -> SMRep
262 arrWordsRep dflags bytes = ArrayWordsRep (bytesToWordsRoundUp dflags bytes)
263
264 -----------------------------------------------------------------------------
265 -- Predicates
266
267 isStaticRep :: SMRep -> IsStatic
268 isStaticRep (HeapRep is_static _ _ _) = is_static
269 isStaticRep (RTSRep _ rep) = isStaticRep rep
270 isStaticRep _ = False
271
272 isStackRep :: SMRep -> Bool
273 isStackRep StackRep{} = True
274 isStackRep (RTSRep _ rep) = isStackRep rep
275 isStackRep _ = False
276
277 isConRep :: SMRep -> Bool
278 isConRep (HeapRep _ _ _ Constr{}) = True
279 isConRep _ = False
280
281 isThunkRep :: SMRep -> Bool
282 isThunkRep (HeapRep _ _ _ Thunk{}) = True
283 isThunkRep (HeapRep _ _ _ ThunkSelector{}) = True
284 isThunkRep (HeapRep _ _ _ BlackHole{}) = True
285 isThunkRep (HeapRep _ _ _ IndStatic{}) = True
286 isThunkRep _ = False
287
288 isFunRep :: SMRep -> Bool
289 isFunRep (HeapRep _ _ _ Fun{}) = True
290 isFunRep _ = False
291
292 isStaticNoCafCon :: SMRep -> Bool
293 -- This should line up exactly with CONSTR_NOCAF below
294 -- See Note [Static NoCaf constructors]
295 isStaticNoCafCon (HeapRep _ 0 _ Constr{}) = True
296 isStaticNoCafCon _ = False
297
298
299 -----------------------------------------------------------------------------
300 -- Size-related things
301
302 fixedHdrSize :: DynFlags -> ByteOff
303 fixedHdrSize dflags = wordsToBytes dflags (fixedHdrSizeW dflags)
304
305 -- | Size of a closure header (StgHeader in includes/rts/storage/Closures.h)
306 fixedHdrSizeW :: DynFlags -> WordOff
307 fixedHdrSizeW dflags = sTD_HDR_SIZE dflags + profHdrSize dflags
308
309 -- | Size of the profiling part of a closure header
310 -- (StgProfHeader in includes/rts/storage/Closures.h)
311 profHdrSize :: DynFlags -> WordOff
312 profHdrSize dflags
313 | gopt Opt_SccProfilingOn dflags = pROF_HDR_SIZE dflags
314 | otherwise = 0
315
316 -- | The garbage collector requires that every closure is at least as
317 -- big as this.
318 minClosureSize :: DynFlags -> WordOff
319 minClosureSize dflags = fixedHdrSizeW dflags + mIN_PAYLOAD_SIZE dflags
320
321 arrWordsHdrSize :: DynFlags -> ByteOff
322 arrWordsHdrSize dflags
323 = fixedHdrSize dflags + sIZEOF_StgArrBytes_NoHdr dflags
324
325 arrWordsHdrSizeW :: DynFlags -> WordOff
326 arrWordsHdrSizeW dflags =
327 fixedHdrSizeW dflags +
328 (sIZEOF_StgArrBytes_NoHdr dflags `quot` wORD_SIZE dflags)
329
330 arrPtrsHdrSize :: DynFlags -> ByteOff
331 arrPtrsHdrSize dflags
332 = fixedHdrSize dflags + sIZEOF_StgMutArrPtrs_NoHdr dflags
333
334 arrPtrsHdrSizeW :: DynFlags -> WordOff
335 arrPtrsHdrSizeW dflags =
336 fixedHdrSizeW dflags +
337 (sIZEOF_StgMutArrPtrs_NoHdr dflags `quot` wORD_SIZE dflags)
338
339 smallArrPtrsHdrSize :: DynFlags -> ByteOff
340 smallArrPtrsHdrSize dflags
341 = fixedHdrSize dflags + sIZEOF_StgSmallMutArrPtrs_NoHdr dflags
342
343 smallArrPtrsHdrSizeW :: DynFlags -> WordOff
344 smallArrPtrsHdrSizeW dflags =
345 fixedHdrSizeW dflags +
346 (sIZEOF_StgSmallMutArrPtrs_NoHdr dflags `quot` wORD_SIZE dflags)
347
348 -- Thunks have an extra header word on SMP, so the update doesn't
349 -- splat the payload.
350 thunkHdrSize :: DynFlags -> WordOff
351 thunkHdrSize dflags = fixedHdrSizeW dflags + smp_hdr
352 where smp_hdr = sIZEOF_StgSMPThunkHeader dflags `quot` wORD_SIZE dflags
353
354 hdrSize :: DynFlags -> SMRep -> ByteOff
355 hdrSize dflags rep = wordsToBytes dflags (hdrSizeW dflags rep)
356
357 hdrSizeW :: DynFlags -> SMRep -> WordOff
358 hdrSizeW dflags (HeapRep _ _ _ ty) = closureTypeHdrSize dflags ty
359 hdrSizeW dflags (ArrayPtrsRep _ _) = arrPtrsHdrSizeW dflags
360 hdrSizeW dflags (SmallArrayPtrsRep _) = smallArrPtrsHdrSizeW dflags
361 hdrSizeW dflags (ArrayWordsRep _) = arrWordsHdrSizeW dflags
362 hdrSizeW _ _ = panic "SMRep.hdrSizeW"
363
364 nonHdrSize :: DynFlags -> SMRep -> ByteOff
365 nonHdrSize dflags rep = wordsToBytes dflags (nonHdrSizeW rep)
366
367 nonHdrSizeW :: SMRep -> WordOff
368 nonHdrSizeW (HeapRep _ p np _) = p + np
369 nonHdrSizeW (ArrayPtrsRep elems ct) = elems + ct
370 nonHdrSizeW (SmallArrayPtrsRep elems) = elems
371 nonHdrSizeW (ArrayWordsRep words) = words
372 nonHdrSizeW (StackRep bs) = length bs
373 nonHdrSizeW (RTSRep _ rep) = nonHdrSizeW rep
374
375 -- | The total size of the closure, in words.
376 heapClosureSizeW :: DynFlags -> SMRep -> WordOff
377 heapClosureSizeW dflags (HeapRep _ p np ty)
378 = closureTypeHdrSize dflags ty + p + np
379 heapClosureSizeW dflags (ArrayPtrsRep elems ct)
380 = arrPtrsHdrSizeW dflags + elems + ct
381 heapClosureSizeW dflags (SmallArrayPtrsRep elems)
382 = smallArrPtrsHdrSizeW dflags + elems
383 heapClosureSizeW dflags (ArrayWordsRep words)
384 = arrWordsHdrSizeW dflags + words
385 heapClosureSizeW _ _ = panic "SMRep.heapClosureSize"
386
387 closureTypeHdrSize :: DynFlags -> ClosureTypeInfo -> WordOff
388 closureTypeHdrSize dflags ty = case ty of
389 Thunk{} -> thunkHdrSize dflags
390 ThunkSelector{} -> thunkHdrSize dflags
391 BlackHole{} -> thunkHdrSize dflags
392 IndStatic{} -> thunkHdrSize dflags
393 _ -> fixedHdrSizeW dflags
394 -- All thunks use thunkHdrSize, even if they are non-updatable.
395 -- this is because we don't have separate closure types for
396 -- updatable vs. non-updatable thunks, so the GC can't tell the
397 -- difference. If we ever have significant numbers of non-
398 -- updatable thunks, it might be worth fixing this.
399
400 -- ---------------------------------------------------------------------------
401 -- Arrays
402
403 -- | The byte offset into the card table of the card for a given element
404 card :: DynFlags -> Int -> Int
405 card dflags i = i `shiftR` mUT_ARR_PTRS_CARD_BITS dflags
406
407 -- | Convert a number of elements to a number of cards, rounding up
408 cardRoundUp :: DynFlags -> Int -> Int
409 cardRoundUp dflags i =
410 card dflags (i + ((1 `shiftL` mUT_ARR_PTRS_CARD_BITS dflags) - 1))
411
412 -- | The size of a card table, in bytes
413 cardTableSizeB :: DynFlags -> Int -> ByteOff
414 cardTableSizeB dflags elems = cardRoundUp dflags elems
415
416 -- | The size of a card table, in words
417 cardTableSizeW :: DynFlags -> Int -> WordOff
418 cardTableSizeW dflags elems =
419 bytesToWordsRoundUp dflags (cardTableSizeB dflags elems)
420
421 -----------------------------------------------------------------------------
422 -- deriving the RTS closure type from an SMRep
423
424 #include "../includes/rts/storage/ClosureTypes.h"
425 #include "../includes/rts/storage/FunTypes.h"
426 -- Defines CONSTR, CONSTR_1_0 etc
427
428 -- | Derives the RTS closure type from an 'SMRep'
429 rtsClosureType :: SMRep -> Int
430 rtsClosureType rep
431 = case rep of
432 RTSRep ty _ -> ty
433
434 -- See Note [static constructors]
435 HeapRep _ 1 0 Constr{} -> CONSTR_1_0
436 HeapRep _ 0 1 Constr{} -> CONSTR_0_1
437 HeapRep _ 2 0 Constr{} -> CONSTR_2_0
438 HeapRep _ 1 1 Constr{} -> CONSTR_1_1
439 HeapRep _ 0 2 Constr{} -> CONSTR_0_2
440 HeapRep _ 0 _ Constr{} -> CONSTR_NOCAF
441 -- See Note [Static NoCaf constructors]
442 HeapRep _ _ _ Constr{} -> CONSTR
443
444 HeapRep False 1 0 Fun{} -> FUN_1_0
445 HeapRep False 0 1 Fun{} -> FUN_0_1
446 HeapRep False 2 0 Fun{} -> FUN_2_0
447 HeapRep False 1 1 Fun{} -> FUN_1_1
448 HeapRep False 0 2 Fun{} -> FUN_0_2
449 HeapRep False _ _ Fun{} -> FUN
450
451 HeapRep False 1 0 Thunk{} -> THUNK_1_0
452 HeapRep False 0 1 Thunk{} -> THUNK_0_1
453 HeapRep False 2 0 Thunk{} -> THUNK_2_0
454 HeapRep False 1 1 Thunk{} -> THUNK_1_1
455 HeapRep False 0 2 Thunk{} -> THUNK_0_2
456 HeapRep False _ _ Thunk{} -> THUNK
457
458 HeapRep False _ _ ThunkSelector{} -> THUNK_SELECTOR
459
460 HeapRep True _ _ Fun{} -> FUN_STATIC
461 HeapRep True _ _ Thunk{} -> THUNK_STATIC
462
463 HeapRep False _ _ BlackHole{} -> BLACKHOLE
464
465 HeapRep False _ _ IndStatic{} -> IND_STATIC
466
467 _ -> panic "rtsClosureType"
468
469 -- We export these ones
470 rET_SMALL, rET_BIG, aRG_GEN, aRG_GEN_BIG :: Int
471 rET_SMALL = RET_SMALL
472 rET_BIG = RET_BIG
473 aRG_GEN = ARG_GEN
474 aRG_GEN_BIG = ARG_GEN_BIG
475
476 {-
477 Note [static constructors]
478 ~~~~~~~~~~~~~~~~~~~~~~~~~~
479
480 We used to have a CONSTR_STATIC closure type, and each constructor had
481 two info tables: one with CONSTR (or CONSTR_1_0 etc.), and one with
482 CONSTR_STATIC.
483
484 This distinction was removed, because when copying a data structure
485 into a compact region, we must copy static constructors into the
486 compact region too. If we didn't do this, we would need to track the
487 references from the compact region out to the static constructors,
488 because they might (indirectly) refer to CAFs.
489
490 Since static constructors will be copied to the heap, if we wanted to
491 use different info tables for static and dynamic constructors, we
492 would have to switch the info pointer when copying the constructor
493 into the compact region, which means we would need an extra field of
494 the static info table to point to the dynamic one.
495
496 However, since the distinction between static and dynamic closure
497 types is never actually needed (other than for assertions), we can
498 just drop the distinction and use the same info table for both.
499
500 The GC *does* need to distinguish between static and dynamic closures,
501 but it does this using the HEAP_ALLOCED() macro which checks whether
502 the address of the closure resides within the dynamic heap.
503 HEAP_ALLOCED() doesn't read the closure's info table.
504
505 Note [Static NoCaf constructors]
506 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
507 If we know that a top-level binding 'x' is not Caffy (ie no CAFs are
508 reachable from 'x'), then a statically allocated constructor (Just x)
509 is also not Caffy, and the garbage collector need not follow its
510 argument fields. Exploiting this would require two static info tables
511 for Just, for the two cases where the argument was Caffy or non-Caffy.
512
513 Currently we don't do this; instead we treat nullary constructors
514 as non-Caffy, and the others as potentially Caffy.
515
516
517 ************************************************************************
518 * *
519 Pretty printing of SMRep and friends
520 * *
521 ************************************************************************
522 -}
523
524 instance Outputable ClosureTypeInfo where
525 ppr = pprTypeInfo
526
527 instance Outputable SMRep where
528 ppr (HeapRep static ps nps tyinfo)
529 = hang (header <+> lbrace) 2 (ppr tyinfo <+> rbrace)
530 where
531 header = text "HeapRep"
532 <+> if static then text "static" else empty
533 <+> pp_n "ptrs" ps <+> pp_n "nonptrs" nps
534 pp_n :: String -> Int -> SDoc
535 pp_n _ 0 = empty
536 pp_n s n = int n <+> text s
537
538 ppr (ArrayPtrsRep size _) = text "ArrayPtrsRep" <+> ppr size
539
540 ppr (SmallArrayPtrsRep size) = text "SmallArrayPtrsRep" <+> ppr size
541
542 ppr (ArrayWordsRep words) = text "ArrayWordsRep" <+> ppr words
543
544 ppr (StackRep bs) = text "StackRep" <+> ppr bs
545
546 ppr (RTSRep ty rep) = text "tag:" <> ppr ty <+> ppr rep
547
548 instance Outputable ArgDescr where
549 ppr (ArgSpec n) = text "ArgSpec" <+> ppr n
550 ppr (ArgGen ls) = text "ArgGen" <+> ppr ls
551
552 pprTypeInfo :: ClosureTypeInfo -> SDoc
553 pprTypeInfo (Constr tag descr)
554 = text "Con" <+>
555 braces (sep [ text "tag:" <+> ppr tag
556 , text "descr:" <> text (show descr) ])
557
558 pprTypeInfo (Fun arity args)
559 = text "Fun" <+>
560 braces (sep [ text "arity:" <+> ppr arity
561 , ptext (sLit ("fun_type:")) <+> ppr args ])
562
563 pprTypeInfo (ThunkSelector offset)
564 = text "ThunkSel" <+> ppr offset
565
566 pprTypeInfo Thunk = text "Thunk"
567 pprTypeInfo BlackHole = text "BlackHole"
568 pprTypeInfo IndStatic = text "IndStatic"
569
570 -- XXX Does not belong here!!
571 stringToWord8s :: String -> [Word8]
572 stringToWord8s s = map (fromIntegral . ord) s
573
574 pprWord8String :: [Word8] -> SDoc
575 -- Debug printing. Not very clever right now.
576 pprWord8String ws = text (show ws)