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