CmmInfo.hs 20.5 KB
Newer Older
1
{-# LANGUAGE CPP #-}
2
module CmmInfo (
3
  mkEmptyContInfoTable,
4
  cmmToRawCmm,
5
  mkInfoTable,
6 7 8 9 10 11 12 13 14 15 16 17 18 19
  srtEscape,

  -- info table accessors
  closureInfoPtr,
  entryCode,
  getConstrTag,
  cmmGetClosureType,
  infoTable,
  infoTableConstrTag,
  infoTableSrtBitmap,
  infoTableClosureType,
  infoTablePtrs,
  infoTableNonPtrs,
  funInfoTable,
20
  funInfoArity,
21 22 23 24 25 26 27 28

  -- info table sizes and offsets
  stdInfoTableSizeW,
  fixedInfoTableSizeW,
  profInfoTableSizeW,
  maxStdInfoTableSizeW,
  maxRetInfoTableSizeW,
  stdInfoTableSizeB,
29
  conInfoTableSizeB,
30 31 32
  stdSrtBitmapOffset,
  stdClosureTypeOffset,
  stdPtrsOffset, stdNonPtrsOffset,
33 34 35 36
) where

#include "HsVersions.h"

37
import Cmm
38
import CmmUtils
39
import CLabel
40
import SMRep
41
import Bitmap
42 43
import Stream (Stream)
import qualified Stream
44
import Hoopl.Collections
45

46
import Maybes
47
import DynFlags
48
import Panic
49
import UniqSupply
50
import MonadUtils
51
import Util
52
import Outputable
53

54
import Data.Bits
55
import Data.Word
56

57
-- When we split at proc points, we need an empty info table.
58
mkEmptyContInfoTable :: CLabel -> CmmInfoTable
59
mkEmptyContInfoTable info_lbl
60 61 62 63 64
  = CmmInfoTable { cit_lbl  = info_lbl
                 , cit_rep  = mkStackRep []
                 , cit_prof = NoProfilingInfo
                 , cit_srt  = NoC_SRT }

65 66
cmmToRawCmm :: DynFlags -> Stream IO CmmGroup ()
            -> IO (Stream IO RawCmmGroup ())
67
cmmToRawCmm dflags cmms
68
  = do { uniqs <- mkSplitUniqSupply 'i'
69
       ; let do_one uniqs cmm = do
70
                case initUs uniqs $ concatMapM (mkInfoTable dflags) cmm of
71 72 73 74
                  (b,uniqs') -> return (uniqs',b)
                  -- NB. strictness fixes a space leak.  DO NOT REMOVE.
       ; return (Stream.mapAccumL do_one uniqs cmms >> return ())
       }
75 76 77 78 79 80

-- Make a concrete info table, represented as a list of CmmStatic
-- (it can't be simply a list of Word, because the SRT field is
-- represented by a label+offset expression).
--
-- With tablesNextToCode, the layout is
81 82 83 84
--      <reversed variable part>
--      <normal forward StgInfoTable, but without
--              an entry point at the front>
--      <code>
85 86
--
-- Without tablesNextToCode, the layout of an info table is
87 88 89
--      <entry label>
--      <normal forward rest of StgInfoTable>
--      <forward variable part>
90
--
91
--      See includes/rts/storage/InfoTables.h
92 93 94 95 96
--
-- For return-points these are as follows
--
-- Tables next to code:
--
97 98 99
--                      <srt slot>
--                      <standard info table>
--      ret-addr -->    <entry code (if any)>
100 101 102
--
-- Not tables-next-to-code:
--
103 104 105
--      ret-addr -->    <ptr to entry code>
--                      <standard info table>
--                      <srt slot>
106 107 108
--
--  * The SRT slot is only there if there is SRT info to record

109
mkInfoTable :: DynFlags -> CmmDecl -> UniqSM [RawCmmDecl]
110
mkInfoTable _ (CmmData sec dat)
111 112
  = return [CmmData sec dat]

113
mkInfoTable dflags proc@(CmmProc infos entry_lbl live blocks)
114 115 116 117
  --
  -- in the non-tables-next-to-code case, procs can have at most a
  -- single info table associated with the entry label of the proc.
  --
118
  | not (tablesNextToCode dflags)
119 120 121
  = case topInfoTable proc of   --  must be at most one
      -- no info table
      Nothing ->
122
         return [CmmProc mapEmpty entry_lbl live blocks]
123 124 125 126 127

      Just info@CmmInfoTable { cit_lbl = info_lbl } -> do
        (top_decls, (std_info, extra_bits)) <-
             mkInfoTableContents dflags info Nothing
        let
128 129
          rel_std_info   = map (makeRelativeRefTo dflags info_lbl) std_info
          rel_extra_bits = map (makeRelativeRefTo dflags info_lbl) extra_bits
130
        --
131 132 133 134 135
        -- Separately emit info table (with the function entry
        -- point as first entry) and the entry code
        --
        return (top_decls ++
                [CmmProc mapEmpty entry_lbl live blocks,
136
                 mkRODataLits info_lbl
137
                    (CmmLabel entry_lbl : rel_std_info ++ rel_extra_bits)])
138 139 140 141 142 143 144 145 146

  --
  -- With tables-next-to-code, we can have many info tables,
  -- associated with some of the BlockIds of the proc.  For each info
  -- table we need to turn it into CmmStatics, and collect any new
  -- CmmDecls that arise from doing so.
  --
  | otherwise
  = do
147 148
    (top_declss, raw_infos) <-
       unzip `fmap` mapM do_one_info (mapToList (info_tbls infos))
149
    return (concat top_declss ++
150
            [CmmProc (mapFromList raw_infos) entry_lbl live blocks])
151 152 153 154 155 156 157

  where
   do_one_info (lbl,itbl) = do
     (top_decls, (std_info, extra_bits)) <-
         mkInfoTableContents dflags itbl Nothing
     let
        info_lbl = cit_lbl itbl
158 159
        rel_std_info   = map (makeRelativeRefTo dflags info_lbl) std_info
        rel_extra_bits = map (makeRelativeRefTo dflags info_lbl) extra_bits
160 161 162
     --
     return (top_decls, (lbl, Statics info_lbl $ map CmmStaticLit $
                              reverse rel_extra_bits ++ rel_std_info))
163 164

-----------------------------------------------------
165 166
type InfoTableContents = ( [CmmLit]          -- The standard part
                         , [CmmLit] )        -- The "extra bits"
167 168
-- These Lits have *not* had mkRelativeTo applied to them

169
mkInfoTableContents :: DynFlags
170
                    -> CmmInfoTable
171
                    -> Maybe Int               -- Override default RTS type tag?
Simon Peyton Jones's avatar
Simon Peyton Jones committed
172
                    -> UniqSM ([RawCmmDecl],             -- Auxiliary top decls
173
                               InfoTableContents)       -- Info tbl + extra bits
174

175
mkInfoTableContents dflags
176
                    info@(CmmInfoTable { cit_lbl  = info_lbl
Simon Peyton Jones's avatar
Simon Peyton Jones committed
177 178
                                       , cit_rep  = smrep
                                       , cit_prof = prof
179
                                       , cit_srt = srt })
Simon Peyton Jones's avatar
Simon Peyton Jones committed
180 181
                    mb_rts_tag
  | RTSRep rts_tag rep <- smrep
182
  = mkInfoTableContents dflags info{cit_rep = rep} (Just rts_tag)
Simon Peyton Jones's avatar
Simon Peyton Jones committed
183 184 185
    -- Completely override the rts_tag that mkInfoTableContents would
    -- otherwise compute, with the rts_tag stored in the RTSRep
    -- (which in turn came from a handwritten .cmm file)
186

187
  | StackRep frame <- smrep
188
  = do { (prof_lits, prof_data) <- mkProfLits dflags prof
189
       ; let (srt_label, srt_bitmap) = mkSRTLit dflags srt
190
       ; (liveness_lit, liveness_data) <- mkLivenessBits dflags frame
191
       ; let
192
             std_info = mkStdInfoTable dflags prof_lits rts_tag srt_bitmap liveness_lit
193
             rts_tag | Just tag <- mb_rts_tag = tag
194 195 196
                     | null liveness_data     = rET_SMALL -- Fits in extra_bits
                     | otherwise              = rET_BIG   -- Does not; extra_bits is
                                                          -- a label
197
       ; return (prof_data ++ liveness_data, (std_info, srt_label)) }
198 199

  | HeapRep _ ptrs nonptrs closure_type <- smrep
200
  = do { let layout  = packIntsCLit dflags ptrs nonptrs
201
       ; (prof_lits, prof_data) <- mkProfLits dflags prof
202
       ; let (srt_label, srt_bitmap) = mkSRTLit dflags srt
203
       ; (mb_srt_field, mb_layout, extra_bits, ct_data)
204
                                <- mk_pieces closure_type srt_label
205
       ; let std_info = mkStdInfoTable dflags prof_lits
206
                                       (mb_rts_tag   `orElse` rtsClosureType smrep)
207 208 209 210 211 212
                                       (mb_srt_field `orElse` srt_bitmap)
                                       (mb_layout    `orElse` layout)
       ; return (prof_data ++ ct_data, (std_info, extra_bits)) }
  where
    mk_pieces :: ClosureTypeInfo -> [CmmLit]
              -> UniqSM ( Maybe StgHalfWord  -- Override the SRT field with this
213 214 215
                        , Maybe CmmLit       -- Override the layout field with this
                        , [CmmLit]           -- "Extra bits" for info table
                        , [RawCmmDecl])      -- Auxiliary data decls
216 217
    mk_pieces (Constr con_tag con_descr) _no_srt    -- A data constructor
      = do { (descr_lit, decl) <- newStringLit con_descr
218 219
           ; return ( Just (toStgHalfWord dflags (fromIntegral con_tag))
                    , Nothing, [descr_lit], [decl]) }
220 221 222 223 224

    mk_pieces Thunk srt_label
      = return (Nothing, Nothing, srt_label, [])

    mk_pieces (ThunkSelector offset) _no_srt
225
      = return (Just (toStgHalfWord dflags 0), Just (mkWordCLit dflags (fromIntegral offset)), [], [])
226 227
         -- Layout known (one free var); we use the layout field for offset

228
    mk_pieces (Fun arity (ArgSpec fun_type)) srt_label
229
      = do { let extra_bits = packIntsCLit dflags fun_type arity : srt_label
230 231 232
           ; return (Nothing, Nothing,  extra_bits, []) }

    mk_pieces (Fun arity (ArgGen arg_bits)) srt_label
233
      = do { (liveness_lit, liveness_data) <- mkLivenessBits dflags arg_bits
234 235 236
           ; let fun_type | null liveness_data = aRG_GEN
                          | otherwise          = aRG_GEN_BIG
                 extra_bits = [ packIntsCLit dflags fun_type arity
237 238 239
                              , srt_lit, liveness_lit, slow_entry ]
           ; return (Nothing, Nothing, extra_bits, liveness_data) }
      where
240
        slow_entry = CmmLabel (toSlowEntryLbl info_lbl)
241
        srt_lit = case srt_label of
242
                    []          -> mkIntCLit dflags 0
243 244
                    (lit:_rest) -> ASSERT( null _rest ) lit

245
    mk_pieces other _ = pprPanic "mk_pieces" (ppr other)
246

247
mkInfoTableContents _ _ _ = panic "mkInfoTableContents"   -- NonInfoTable dealt with earlier
248

249 250 251 252 253 254
packIntsCLit :: DynFlags -> Int -> Int -> CmmLit
packIntsCLit dflags a b = packHalfWordsCLit dflags
                           (toStgHalfWord dflags (fromIntegral a))
                           (toStgHalfWord dflags (fromIntegral b))


255 256
mkSRTLit :: DynFlags
         -> C_SRT
257 258
         -> ([CmmLit],    -- srt_label, if any
             StgHalfWord) -- srt_bitmap
259
mkSRTLit dflags NoC_SRT                = ([], toStgHalfWord dflags 0)
260
mkSRTLit dflags (C_SRT lbl off bitmap) = ([cmmLabelOffW dflags lbl off], bitmap)
261 262 263 264 265 266 267 268 269 270 271 272 273


-------------------------------------------------------------------------
--
--      Lay out the info table and handle relative offsets
--
-------------------------------------------------------------------------

-- This function takes
--   * the standard info table portion (StgInfoTable)
--   * the "extra bits" (StgFunInfoExtraRev etc.)
--   * the entry label
--   * the code
Simon Peyton Jones's avatar
Simon Peyton Jones committed
274
-- and lays them out in memory, producing a list of RawCmmDecl
275 276 277

-------------------------------------------------------------------------
--
278
--      Position independent code
279 280 281 282 283 284 285 286 287 288
--
-------------------------------------------------------------------------
-- In order to support position independent code, we mustn't put absolute
-- references into read-only space. Info tables in the tablesNextToCode
-- case must be in .text, which is read-only, so we doctor the CmmLits
-- to use relative offsets instead.

-- Note that this is done even when the -fPIC flag is not specified,
-- as we want to keep binary compatibility between PIC and non-PIC.

289
makeRelativeRefTo :: DynFlags -> CLabel -> CmmLit -> CmmLit
290

291 292
makeRelativeRefTo dflags info_lbl (CmmLabel lbl)
  | tablesNextToCode dflags
293
  = CmmLabelDiffOff lbl info_lbl 0
294 295
makeRelativeRefTo dflags info_lbl (CmmLabelOff lbl off)
  | tablesNextToCode dflags
296
  = CmmLabelDiffOff lbl info_lbl off
297
makeRelativeRefTo _ _ lit = lit
298

299 300 301

-------------------------------------------------------------------------
--
302
--              Build a liveness mask for the stack layout
303 304 305 306 307
--
-------------------------------------------------------------------------

-- There are four kinds of things on the stack:
--
308 309 310 311
--      - pointer variables (bound in the environment)
--      - non-pointer variables (bound in the environment)
--      - free slots (recorded in the stack free list)
--      - non-pointer data slots (recorded in the stack free list)
312 313 314 315 316 317 318 319
--
-- The first two are represented with a 'Just' of a 'LocalReg'.
-- The last two with one or more 'Nothing' constructors.
-- Each 'Nothing' represents one used word.
--
-- The head of the stack layout is the top of the stack and
-- the least-significant bit.

320
mkLivenessBits :: DynFlags -> Liveness -> UniqSM (CmmLit, [RawCmmDecl])
Thomas Schilling's avatar
Thomas Schilling committed
321 322 323
              -- ^ Returns:
              --   1. The bitmap (literal value or label)
              --   2. Large bitmap CmmData if needed
324

325
mkLivenessBits dflags liveness
326
  | n_bits > mAX_SMALL_BITMAP_SIZE dflags -- does not fit in one word
327
  = do { uniq <- getUniqueM
328
       ; let bitmap_lbl = mkBitmapLabel uniq
329
       ; return (CmmLabel bitmap_lbl,
330
                 [mkRODataLits bitmap_lbl lits]) }
331

332
  | otherwise -- Fits in one word
333
  = return (mkStgWordCLit dflags bitmap_word, [])
334 335
  where
    n_bits = length liveness
336 337

    bitmap :: Bitmap
338
    bitmap = mkBitmap dflags liveness
339

340
    small_bitmap = case bitmap of
341
                     []  -> toStgWord dflags 0
342
                     [b] -> b
343
                     _   -> panic "mkLiveness"
344
    bitmap_word = toStgWord dflags (fromIntegral n_bits)
345
              .|. (small_bitmap `shiftL` bITMAP_BITS_SHIFT dflags)
346

347 348
    lits = mkWordCLit dflags (fromIntegral n_bits)
         : map (mkStgWordCLit dflags) bitmap
349 350
      -- The first word is the size.  The structure must match
      -- StgLargeBitmap in includes/rts/storage/InfoTable.h
351 352 353

-------------------------------------------------------------------------
--
354
--      Generating a standard info table
355 356 357 358
--
-------------------------------------------------------------------------

-- The standard bits of an info table.  This part of the info table
359 360
-- corresponds to the StgInfoTable type defined in
-- includes/rts/storage/InfoTables.h.
361 362 363 364 365
--
-- Its shape varies with ticky/profiling/tables next to code etc
-- so we can't use constant offsets from Constants

mkStdInfoTable
366
   :: DynFlags
367
   -> (CmmLit,CmmLit)   -- Closure type descr and closure descr  (profiling)
368 369
   -> Int               -- Closure RTS tag
   -> StgHalfWord       -- SRT length
370
   -> CmmLit            -- layout field
371 372
   -> [CmmLit]

373
mkStdInfoTable dflags (type_descr, closure_descr) cl_type srt_len layout_lit
374
 =      -- Parallel revertible-black hole field
375
    prof_info
376 377
        -- Ticky info (none at present)
        -- Debug info (none at present)
378 379
 ++ [layout_lit, type_lit]

380 381 382 383
 where
    prof_info
        | gopt Opt_SccProfilingOn dflags = [type_descr, closure_descr]
        | otherwise = []
384

385
    type_lit = packHalfWordsCLit dflags (toStgHalfWord dflags (fromIntegral cl_type)) srt_len
386

387 388 389 390 391 392
-------------------------------------------------------------------------
--
--      Making string literals
--
-------------------------------------------------------------------------

393 394 395
mkProfLits :: DynFlags -> ProfilingInfo -> UniqSM ((CmmLit,CmmLit), [RawCmmDecl])
mkProfLits dflags NoProfilingInfo       = return ((zeroCLit dflags, zeroCLit dflags), [])
mkProfLits _ (ProfilingInfo td cd)
396 397 398 399
  = do { (td_lit, td_decl) <- newStringLit td
       ; (cd_lit, cd_decl) <- newStringLit cd
       ; return ((td_lit,cd_lit), [td_decl,cd_decl]) }

Simon Peyton Jones's avatar
Simon Peyton Jones committed
400
newStringLit :: [Word8] -> UniqSM (CmmLit, GenCmmDecl CmmStatics info stmt)
401
newStringLit bytes
402
  = do { uniq <- getUniqueM
403
       ; return (mkByteStringCLit (mkStringLitLabel uniq) bytes) }
404

Simon Marlow's avatar
Simon Marlow committed
405 406 407 408 409 410

-- Misc utils

-- | Value of the srt field of an info table when using an StgLargeSRT
srtEscape :: DynFlags -> StgHalfWord
srtEscape dflags = toStgHalfWord dflags (-1)
411 412 413

-------------------------------------------------------------------------
--
414
--      Accessing fields of an info table
415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488
--
-------------------------------------------------------------------------

closureInfoPtr :: DynFlags -> CmmExpr -> CmmExpr
-- Takes a closure pointer and returns the info table pointer
closureInfoPtr dflags e = CmmLoad e (bWord dflags)

entryCode :: DynFlags -> CmmExpr -> CmmExpr
-- Takes an info pointer (the first word of a closure)
-- and returns its entry code
entryCode dflags e
 | tablesNextToCode dflags = e
 | otherwise               = CmmLoad e (bWord dflags)

getConstrTag :: DynFlags -> CmmExpr -> CmmExpr
-- Takes a closure pointer, and return the *zero-indexed*
-- constructor tag obtained from the info table
-- This lives in the SRT field of the info table
-- (constructors don't need SRTs).
getConstrTag dflags closure_ptr
  = CmmMachOp (MO_UU_Conv (halfWordWidth dflags) (wordWidth dflags)) [infoTableConstrTag dflags info_table]
  where
    info_table = infoTable dflags (closureInfoPtr dflags closure_ptr)

cmmGetClosureType :: DynFlags -> CmmExpr -> CmmExpr
-- Takes a closure pointer, and return the closure type
-- obtained from the info table
cmmGetClosureType dflags closure_ptr
  = CmmMachOp (MO_UU_Conv (halfWordWidth dflags) (wordWidth dflags)) [infoTableClosureType dflags info_table]
  where
    info_table = infoTable dflags (closureInfoPtr dflags closure_ptr)

infoTable :: DynFlags -> CmmExpr -> CmmExpr
-- Takes an info pointer (the first word of a closure)
-- and returns a pointer to the first word of the standard-form
-- info table, excluding the entry-code word (if present)
infoTable dflags info_ptr
  | tablesNextToCode dflags = cmmOffsetB dflags info_ptr (- stdInfoTableSizeB dflags)
  | otherwise               = cmmOffsetW dflags info_ptr 1 -- Past the entry code pointer

infoTableConstrTag :: DynFlags -> CmmExpr -> CmmExpr
-- Takes an info table pointer (from infoTable) and returns the constr tag
-- field of the info table (same as the srt_bitmap field)
infoTableConstrTag = infoTableSrtBitmap

infoTableSrtBitmap :: DynFlags -> CmmExpr -> CmmExpr
-- Takes an info table pointer (from infoTable) and returns the srt_bitmap
-- field of the info table
infoTableSrtBitmap dflags info_tbl
  = CmmLoad (cmmOffsetB dflags info_tbl (stdSrtBitmapOffset dflags)) (bHalfWord dflags)

infoTableClosureType :: DynFlags -> CmmExpr -> CmmExpr
-- Takes an info table pointer (from infoTable) and returns the closure type
-- field of the info table.
infoTableClosureType dflags info_tbl
  = CmmLoad (cmmOffsetB dflags info_tbl (stdClosureTypeOffset dflags)) (bHalfWord dflags)

infoTablePtrs :: DynFlags -> CmmExpr -> CmmExpr
infoTablePtrs dflags info_tbl
  = CmmLoad (cmmOffsetB dflags info_tbl (stdPtrsOffset dflags)) (bHalfWord dflags)

infoTableNonPtrs :: DynFlags -> CmmExpr -> CmmExpr
infoTableNonPtrs dflags info_tbl
  = CmmLoad (cmmOffsetB dflags info_tbl (stdNonPtrsOffset dflags)) (bHalfWord dflags)

funInfoTable :: DynFlags -> CmmExpr -> CmmExpr
-- Takes the info pointer of a function,
-- and returns a pointer to the first word of the StgFunInfoExtra struct
-- in the info table.
funInfoTable dflags info_ptr
  | tablesNextToCode dflags
  = cmmOffsetB dflags info_ptr (- stdInfoTableSizeB dflags - sIZEOF_StgFunInfoExtraRev dflags)
  | otherwise
  = cmmOffsetW dflags info_ptr (1 + stdInfoTableSizeW dflags)
489
                                -- Past the entry code pointer
490

491 492 493
-- Takes the info pointer of a function, returns the function's arity
funInfoArity :: DynFlags -> CmmExpr -> CmmExpr
funInfoArity dflags iptr
parcs's avatar
parcs committed
494
  = cmmToWord dflags (cmmLoadIndex dflags rep fun_info (offset `div` rep_bytes))
495 496 497 498 499
  where
   fun_info = funInfoTable dflags iptr
   rep = cmmBits (widthFromBytes rep_bytes)

   (rep_bytes, offset)
parcs's avatar
parcs committed
500
    | tablesNextToCode dflags = ( pc_REP_StgFunInfoExtraRev_arity pc
501
                                , oFFSET_StgFunInfoExtraRev_arity dflags )
parcs's avatar
parcs committed
502 503
    | otherwise               = ( pc_REP_StgFunInfoExtraFwd_arity pc
                                , oFFSET_StgFunInfoExtraFwd_arity dflags )
504 505 506

   pc = sPlatformConstants (settings dflags)

507 508 509 510 511
-----------------------------------------------------------------------------
--
--      Info table sizes & offsets
--
-----------------------------------------------------------------------------
512

513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543
stdInfoTableSizeW :: DynFlags -> WordOff
-- The size of a standard info table varies with profiling/ticky etc,
-- so we can't get it from Constants
-- It must vary in sync with mkStdInfoTable
stdInfoTableSizeW dflags
  = fixedInfoTableSizeW
  + if gopt Opt_SccProfilingOn dflags
       then profInfoTableSizeW
       else 0

fixedInfoTableSizeW :: WordOff
fixedInfoTableSizeW = 2 -- layout, type

profInfoTableSizeW :: WordOff
profInfoTableSizeW = 2

maxStdInfoTableSizeW :: WordOff
maxStdInfoTableSizeW =
  1 {- entry, when !tablesNextToCode -}
  + fixedInfoTableSizeW
  + profInfoTableSizeW

maxRetInfoTableSizeW :: WordOff
maxRetInfoTableSizeW =
  maxStdInfoTableSizeW
  + 1 {- srt label -}

stdInfoTableSizeB  :: DynFlags -> ByteOff
stdInfoTableSizeB dflags = stdInfoTableSizeW dflags * wORD_SIZE dflags

stdSrtBitmapOffset :: DynFlags -> ByteOff
544
-- Byte offset of the SRT bitmap half-word which is
545 546 547 548
-- in the *higher-addressed* part of the type_lit
stdSrtBitmapOffset dflags = stdInfoTableSizeB dflags - hALF_WORD_SIZE dflags

stdClosureTypeOffset :: DynFlags -> ByteOff
549
-- Byte offset of the closure type half-word
550 551 552 553 554
stdClosureTypeOffset dflags = stdInfoTableSizeB dflags - wORD_SIZE dflags

stdPtrsOffset, stdNonPtrsOffset :: DynFlags -> ByteOff
stdPtrsOffset    dflags = stdInfoTableSizeB dflags - 2 * wORD_SIZE dflags
stdNonPtrsOffset dflags = stdInfoTableSizeB dflags - 2 * wORD_SIZE dflags + hALF_WORD_SIZE dflags
555 556 557

conInfoTableSizeB :: DynFlags -> Int
conInfoTableSizeB dflags = stdInfoTableSizeB dflags + wORD_SIZE dflags