CmmInfo.hs 20.4 KB
Newer Older
Ian Lynagh's avatar
Ian Lynagh committed
1 2 3 4
{-# OPTIONS -fno-warn-tabs #-}
-- The above warning supression flag is a temporary kludge.
-- While working on this module you are encouraged to remove it and
-- detab the module (please do the detabbing in a separate patch). See
5
--     http://ghc.haskell.org/trac/ghc/wiki/Commentary/CodingStyle#TabsvsSpaces
Ian Lynagh's avatar
Ian Lynagh committed
6 7
-- for details

8
module CmmInfo (
9
  mkEmptyContInfoTable,
10
  cmmToRawCmm,
11
  mkInfoTable,
12 13 14 15 16 17 18 19 20 21 22 23 24 25
  srtEscape,

  -- info table accessors
  closureInfoPtr,
  entryCode,
  getConstrTag,
  cmmGetClosureType,
  infoTable,
  infoTableConstrTag,
  infoTableSrtBitmap,
  infoTableClosureType,
  infoTablePtrs,
  infoTableNonPtrs,
  funInfoTable,
26
  funInfoArity,
27 28 29 30 31 32 33 34 35 36 37

  -- info table sizes and offsets
  stdInfoTableSizeW,
  fixedInfoTableSizeW,
  profInfoTableSizeW,
  maxStdInfoTableSizeW,
  maxRetInfoTableSizeW,
  stdInfoTableSizeB,
  stdSrtBitmapOffset,
  stdClosureTypeOffset,
  stdPtrsOffset, stdNonPtrsOffset,
38 39 40 41
) where

#include "HsVersions.h"

42
import Cmm
43
import CmmUtils
44
import CLabel
45
import SMRep
46
import Bitmap
47 48
import Stream (Stream)
import qualified Stream
49
import Hoopl
50

51
import Maybes
52
import DynFlags
53
import Panic
54
import UniqSupply
55
import MonadUtils
56
import Util
57
import Outputable
58

59
import Data.Bits
60
import Data.Word
61

62
-- When we split at proc points, we need an empty info table.
63
mkEmptyContInfoTable :: CLabel -> CmmInfoTable
64 65 66 67 68 69
mkEmptyContInfoTable info_lbl 
  = CmmInfoTable { cit_lbl  = info_lbl
                 , cit_rep  = mkStackRep []
                 , cit_prof = NoProfilingInfo
                 , cit_srt  = NoC_SRT }

70 71
cmmToRawCmm :: DynFlags -> Stream IO CmmGroup ()
            -> IO (Stream IO RawCmmGroup ())
72
cmmToRawCmm dflags cmms
73
  = do { uniqs <- mkSplitUniqSupply 'i'
74
       ; let do_one uniqs cmm = do
75
                case initUs uniqs $ concatMapM (mkInfoTable dflags) cmm of
76 77 78 79
                  (b,uniqs') -> return (uniqs',b)
                  -- NB. strictness fixes a space leak.  DO NOT REMOVE.
       ; return (Stream.mapAccumL do_one uniqs cmms >> return ())
       }
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95

-- 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
--	<reversed variable part>
--	<normal forward StgInfoTable, but without 
--		an entry point at the front>
--	<code>
--
-- Without tablesNextToCode, the layout of an info table is
--	<entry label>
--	<normal forward rest of StgInfoTable>
--	<forward variable part>
--
Simon Marlow's avatar
Simon Marlow committed
96
--	See includes/rts/storage/InfoTables.h
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
--
-- For return-points these are as follows
--
-- Tables next to code:
--
--			<srt slot>
--			<standard info table>
--  	ret-addr -->	<entry code (if any)>
--
-- Not tables-next-to-code:
--
--	ret-addr -->	<ptr to entry code>
--			<standard info table>
--			<srt slot>
--
--  * The SRT slot is only there if there is SRT info to record

114
mkInfoTable :: DynFlags -> CmmDecl -> UniqSM [RawCmmDecl]
115
mkInfoTable _ (CmmData sec dat)
116 117
  = return [CmmData sec dat]

118
mkInfoTable dflags proc@(CmmProc infos entry_lbl live blocks)
119 120 121 122
  --
  -- 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.
  --
123
  | not (tablesNextToCode dflags)
124 125 126
  = case topInfoTable proc of   --  must be at most one
      -- no info table
      Nothing ->
127
         return [CmmProc mapEmpty entry_lbl live blocks]
128 129 130 131 132

      Just info@CmmInfoTable { cit_lbl = info_lbl } -> do
        (top_decls, (std_info, extra_bits)) <-
             mkInfoTableContents dflags info Nothing
        let
133 134
          rel_std_info   = map (makeRelativeRefTo dflags info_lbl) std_info
          rel_extra_bits = map (makeRelativeRefTo dflags info_lbl) extra_bits
135
        --
136 137 138 139 140 141 142
        -- 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,
                 mkDataLits Data info_lbl
                    (CmmLabel entry_lbl : rel_std_info ++ rel_extra_bits)])
143 144 145 146 147 148 149 150 151

  --
  -- 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
152 153
    (top_declss, raw_infos) <-
       unzip `fmap` mapM do_one_info (mapToList (info_tbls infos))
154
    return (concat top_declss ++
155
            [CmmProc (mapFromList raw_infos) entry_lbl live blocks])
156 157 158 159 160 161 162

  where
   do_one_info (lbl,itbl) = do
     (top_decls, (std_info, extra_bits)) <-
         mkInfoTableContents dflags itbl Nothing
     let
        info_lbl = cit_lbl itbl
163 164
        rel_std_info   = map (makeRelativeRefTo dflags info_lbl) std_info
        rel_extra_bits = map (makeRelativeRefTo dflags info_lbl) extra_bits
165 166 167
     --
     return (top_decls, (lbl, Statics info_lbl $ map CmmStaticLit $
                              reverse rel_extra_bits ++ rel_std_info))
168 169 170 171 172 173

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

174
mkInfoTableContents :: DynFlags
175
                    -> CmmInfoTable
176
                    -> Maybe Int               -- Override default RTS type tag?
Simon Peyton Jones's avatar
Simon Peyton Jones committed
177
                    -> UniqSM ([RawCmmDecl],             -- Auxiliary top decls
178
                               InfoTableContents)	-- Info tbl + extra bits
179

180
mkInfoTableContents dflags
181
                    info@(CmmInfoTable { cit_lbl  = info_lbl
Simon Peyton Jones's avatar
Simon Peyton Jones committed
182 183 184 185 186
                                       , cit_rep  = smrep
                                       , cit_prof = prof
                                       , cit_srt = srt }) 
                    mb_rts_tag
  | RTSRep rts_tag rep <- smrep
187
  = mkInfoTableContents dflags info{cit_rep = rep} (Just rts_tag)
Simon Peyton Jones's avatar
Simon Peyton Jones committed
188 189 190
    -- 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)
191

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

  | HeapRep _ ptrs nonptrs closure_type <- smrep
205
  = do { let layout  = packIntsCLit dflags ptrs nonptrs
206
       ; (prof_lits, prof_data) <- mkProfLits dflags prof
207
       ; let (srt_label, srt_bitmap) = mkSRTLit dflags srt
208
       ; (mb_srt_field, mb_layout, extra_bits, ct_data)
209
                                <- mk_pieces closure_type srt_label
210
       ; let std_info = mkStdInfoTable dflags prof_lits
211
                                       (mb_rts_tag   `orElse` rtsClosureType smrep)
212 213 214 215 216 217 218 219
                                       (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
                 	, Maybe CmmLit       -- Override the layout field with this
                 	, [CmmLit]           -- "Extra bits" for info table
Simon Peyton Jones's avatar
Simon Peyton Jones committed
220
                 	, [RawCmmDecl])	     -- Auxiliary data decls 
221 222
    mk_pieces (Constr con_tag con_descr) _no_srt    -- A data constructor
      = do { (descr_lit, decl) <- newStringLit con_descr
223 224
           ; return ( Just (toStgHalfWord dflags (fromIntegral con_tag))
                    , Nothing, [descr_lit], [decl]) }
225 226 227 228 229

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

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

    mk_pieces (Fun arity (ArgSpec fun_type)) srt_label 
234
      = do { let extra_bits = packIntsCLit dflags fun_type arity : srt_label
235 236 237
           ; return (Nothing, Nothing,  extra_bits, []) }

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

250
    mk_pieces other _ = pprPanic "mk_pieces" (ppr other)
251

252
mkInfoTableContents _ _ _ = panic "mkInfoTableContents"   -- NonInfoTable dealt with earlier
253

254 255 256 257 258 259
packIntsCLit :: DynFlags -> Int -> Int -> CmmLit
packIntsCLit dflags a b = packHalfWordsCLit dflags
                           (toStgHalfWord dflags (fromIntegral a))
                           (toStgHalfWord dflags (fromIntegral b))


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


-------------------------------------------------------------------------
--
--      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
279
-- and lays them out in memory, producing a list of RawCmmDecl
280 281 282 283 284 285 286 287 288 289 290 291 292 293

-------------------------------------------------------------------------
--
--	Position independent code
--
-------------------------------------------------------------------------
-- 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.

294
makeRelativeRefTo :: DynFlags -> CLabel -> CmmLit -> CmmLit
295
        
296 297
makeRelativeRefTo dflags info_lbl (CmmLabel lbl)
  | tablesNextToCode dflags
298
  = CmmLabelDiffOff lbl info_lbl 0
299 300
makeRelativeRefTo dflags info_lbl (CmmLabelOff lbl off)
  | tablesNextToCode dflags
301
  = CmmLabelDiffOff lbl info_lbl off
302
makeRelativeRefTo _ _ lit = lit
303

304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324

-------------------------------------------------------------------------
--
--		Build a liveness mask for the stack layout
--
-------------------------------------------------------------------------

-- There are four kinds of things on the stack:
--
--	- 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)
--
-- 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.

325
mkLivenessBits :: DynFlags -> Liveness -> UniqSM (CmmLit, [RawCmmDecl])
Thomas Schilling's avatar
Thomas Schilling committed
326 327 328
              -- ^ Returns:
              --   1. The bitmap (literal value or label)
              --   2. Large bitmap CmmData if needed
329

330
mkLivenessBits dflags liveness
331
  | n_bits > mAX_SMALL_BITMAP_SIZE dflags -- does not fit in one word
332 333 334 335
  = do { uniq <- getUniqueUs
       ; let bitmap_lbl = mkBitmapLabel uniq
       ; return (CmmLabel bitmap_lbl, 
                 [mkRODataLits bitmap_lbl lits]) }
336

337
  | otherwise -- Fits in one word
338
  = return (mkStgWordCLit dflags bitmap_word, [])
339 340
  where
    n_bits = length liveness
341 342

    bitmap :: Bitmap
343
    bitmap = mkBitmap dflags liveness
344 345

    small_bitmap = case bitmap of 
346
                     []  -> toStgWord dflags 0
347 348
                     [b] -> b
		     _   -> panic "mkLiveness"
349
    bitmap_word = toStgWord dflags (fromIntegral n_bits)
350
              .|. (small_bitmap `shiftL` bITMAP_BITS_SHIFT dflags)
351

352 353
    lits = mkWordCLit dflags (fromIntegral n_bits)
         : map (mkStgWordCLit dflags) bitmap
354 355
      -- The first word is the size.  The structure must match
      -- StgLargeBitmap in includes/rts/storage/InfoTable.h
356 357 358 359 360 361 362 363

-------------------------------------------------------------------------
--
--	Generating a standard info table
--
-------------------------------------------------------------------------

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

mkStdInfoTable
371 372
   :: DynFlags
   -> (CmmLit,CmmLit)	-- Closure type descr and closure descr  (profiling)
373 374
   -> Int               -- Closure RTS tag
   -> StgHalfWord       -- SRT length
375 376 377
   -> CmmLit		-- layout field
   -> [CmmLit]

378
mkStdInfoTable dflags (type_descr, closure_descr) cl_type srt_len layout_lit
379 380 381 382 383 384 385 386
 = 	-- Parallel revertible-black hole field
    prof_info
	-- Ticky info (none at present)
	-- Debug info (none at present)
 ++ [layout_lit, type_lit]

 where  
    prof_info 
ian@well-typed.com's avatar
ian@well-typed.com committed
387
	| gopt Opt_SccProfilingOn dflags = [type_descr, closure_descr]
388
	| otherwise = []
389

390
    type_lit = packHalfWordsCLit dflags (toStgHalfWord dflags (fromIntegral cl_type)) srt_len
391

392 393 394 395 396 397
-------------------------------------------------------------------------
--
--      Making string literals
--
-------------------------------------------------------------------------

398 399 400
mkProfLits :: DynFlags -> ProfilingInfo -> UniqSM ((CmmLit,CmmLit), [RawCmmDecl])
mkProfLits dflags NoProfilingInfo       = return ((zeroCLit dflags, zeroCLit dflags), [])
mkProfLits _ (ProfilingInfo td cd)
401 402 403 404
  = 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
405
newStringLit :: [Word8] -> UniqSM (CmmLit, GenCmmDecl CmmStatics info stmt)
406 407 408 409
newStringLit bytes
  = do { uniq <- getUniqueUs
       ; return (mkByteStringCLit uniq bytes) }

Simon Marlow's avatar
Simon Marlow committed
410 411 412 413 414 415

-- Misc utils

-- | Value of the srt field of an info table when using an StgLargeSRT
srtEscape :: DynFlags -> StgHalfWord
srtEscape dflags = toStgHalfWord dflags (-1)
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 489 490 491 492 493 494 495

-------------------------------------------------------------------------
--
--	Accessing fields of an info table
--
-------------------------------------------------------------------------

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)
				-- Past the entry code pointer

496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511
-- Takes the info pointer of a function, returns the function's arity
funInfoArity :: DynFlags -> CmmExpr -> CmmExpr
funInfoArity dflags iptr
  = cmmToWord dflags (cmmLoadIndex dflags rep fun_info offset)
  where
   fun_info = funInfoTable dflags iptr
   rep = cmmBits (widthFromBytes rep_bytes)

   (rep_bytes, offset)
    | tablesNextToCode dflags = ( pc_REP_StgFunInfoExtraFwd_arity pc
                                , oFFSET_StgFunInfoExtraFwd_arity dflags )
    | otherwise               = ( pc_REP_StgFunInfoExtraRev_arity pc
                                , oFFSET_StgFunInfoExtraRev_arity dflags )

   pc = sPlatformConstants (settings dflags)

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 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560
-----------------------------------------------------------------------------
--
--      Info table sizes & offsets
--
-----------------------------------------------------------------------------
	
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
-- Byte offset of the SRT bitmap half-word which is 
-- in the *higher-addressed* part of the type_lit
stdSrtBitmapOffset dflags = stdInfoTableSizeB dflags - hALF_WORD_SIZE dflags

stdClosureTypeOffset :: DynFlags -> ByteOff
-- Byte offset of the closure type half-word 
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