8 -- info table accessors
22 -- info table sizes and offsets
32 stdPtrsOffset
, stdNonPtrsOffset
,
35 #include
"HsVersions.h"
44 import Stream
(Stream
)
45 import qualified Stream
46 import Hoopl
.Collections
59 -- When we split at proc points, we need an empty info table.
60 mkEmptyContInfoTable
:: CLabel
-> CmmInfoTable
61 mkEmptyContInfoTable info_lbl
62 = CmmInfoTable
{ cit_lbl
= info_lbl
63 , cit_rep
= mkStackRep
[]
64 , cit_prof
= NoProfilingInfo
67 cmmToRawCmm
:: DynFlags
-> Stream
IO CmmGroup
()
68 -> IO (Stream
IO RawCmmGroup
())
69 cmmToRawCmm dflags cmms
70 = do { uniqs
<- mkSplitUniqSupply
'i
'
71 ; let do_one uniqs cmm
= do
72 case initUs uniqs
$ concatMapM
(mkInfoTable dflags
) cmm
of
73 (b
,uniqs
') -> return (uniqs
',b
)
74 -- NB. strictness fixes a space leak. DO NOT REMOVE.
75 ; return (Stream
.mapAccumL do_one uniqs cmms
>> return ())
78 -- Make a concrete info table, represented as a list of CmmStatic
79 -- (it can't be simply a list of Word, because the SRT field is
80 -- represented by a label+offset expression).
82 -- With tablesNextToCode, the layout is
83 -- <reversed variable part>
84 -- <normal forward StgInfoTable, but without
85 -- an entry point at the front>
88 -- Without tablesNextToCode, the layout of an info table is
90 -- <normal forward rest of StgInfoTable>
91 -- <forward variable part>
93 -- See includes/rts/storage/InfoTables.h
95 -- For return-points these are as follows
97 -- Tables next to code:
100 -- <standard info table>
101 -- ret-addr --> <entry code (if any)>
103 -- Not tables-next-to-code:
105 -- ret-addr --> <ptr to entry code>
106 -- <standard info table>
109 -- * The SRT slot is only there if there is SRT info to record
111 mkInfoTable
:: DynFlags
-> CmmDecl
-> UniqSM
[RawCmmDecl
]
112 mkInfoTable _
(CmmData sec dat
)
113 = return [CmmData sec dat
]
115 mkInfoTable dflags proc
@(CmmProc infos entry_lbl live blocks
)
117 -- in the non-tables-next-to-code case, procs can have at most a
118 -- single info table associated with the entry label of the proc.
120 |
not (tablesNextToCode dflags
)
121 = case topInfoTable proc
of -- must be at most one
124 return [CmmProc mapEmpty entry_lbl live blocks
]
126 Just info
@CmmInfoTable
{ cit_lbl
= info_lbl
} -> do
127 (top_decls
, (std_info
, extra_bits
)) <-
128 mkInfoTableContents dflags info Nothing
130 rel_std_info
= map (makeRelativeRefTo dflags info_lbl
) std_info
131 rel_extra_bits
= map (makeRelativeRefTo dflags info_lbl
) extra_bits
133 -- Separately emit info table (with the function entry
134 -- point as first entry) and the entry code
137 [CmmProc mapEmpty entry_lbl live blocks
,
138 mkRODataLits info_lbl
139 (CmmLabel entry_lbl
: rel_std_info
++ rel_extra_bits
)])
142 -- With tables-next-to-code, we can have many info tables,
143 -- associated with some of the BlockIds of the proc. For each info
144 -- table we need to turn it into CmmStatics, and collect any new
145 -- CmmDecls that arise from doing so.
149 (top_declss
, raw_infos
) <-
150 unzip `
fmap`
mapM do_one_info
(mapToList
(info_tbls infos
))
151 return (concat top_declss
++
152 [CmmProc
(mapFromList raw_infos
) entry_lbl live blocks
])
155 do_one_info
(lbl
,itbl
) = do
156 (top_decls
, (std_info
, extra_bits
)) <-
157 mkInfoTableContents dflags itbl Nothing
159 info_lbl
= cit_lbl itbl
160 rel_std_info
= map (makeRelativeRefTo dflags info_lbl
) std_info
161 rel_extra_bits
= map (makeRelativeRefTo dflags info_lbl
) extra_bits
163 return (top_decls
, (lbl
, Statics info_lbl
$ map CmmStaticLit
$
164 reverse rel_extra_bits
++ rel_std_info
))
166 -----------------------------------------------------
167 type InfoTableContents
= ( [CmmLit
] -- The standard part
168 , [CmmLit
] ) -- The "extra bits"
169 -- These Lits have *not* had mkRelativeTo applied to them
171 mkInfoTableContents
:: DynFlags
173 -> Maybe Int -- Override default RTS type tag?
174 -> UniqSM
([RawCmmDecl
], -- Auxiliary top decls
175 InfoTableContents
) -- Info tbl + extra bits
177 mkInfoTableContents dflags
178 info
@(CmmInfoTable
{ cit_lbl
= info_lbl
183 | RTSRep rts_tag rep
<- smrep
184 = mkInfoTableContents dflags info
{cit_rep
= rep
} (Just rts_tag
)
185 -- Completely override the rts_tag that mkInfoTableContents would
186 -- otherwise compute, with the rts_tag stored in the RTSRep
187 -- (which in turn came from a handwritten .cmm file)
189 | StackRep frame
<- smrep
190 = do { (prof_lits
, prof_data
) <- mkProfLits dflags prof
191 ; let (srt_label
, srt_bitmap
) = mkSRTLit dflags srt
192 ; (liveness_lit
, liveness_data
) <- mkLivenessBits dflags frame
194 std_info
= mkStdInfoTable dflags prof_lits rts_tag srt_bitmap liveness_lit
195 rts_tag | Just tag
<- mb_rts_tag
= tag
196 |
null liveness_data
= rET_SMALL
-- Fits in extra_bits
197 |
otherwise = rET_BIG
-- Does not; extra_bits is
199 ; return (prof_data
++ liveness_data
, (std_info
, srt_label
)) }
201 | HeapRep _ ptrs nonptrs closure_type
<- smrep
202 = do { let layout
= packIntsCLit dflags ptrs nonptrs
203 ; (prof_lits
, prof_data
) <- mkProfLits dflags prof
204 ; let (srt_label
, srt_bitmap
) = mkSRTLit dflags srt
205 ; (mb_srt_field
, mb_layout
, extra_bits
, ct_data
)
206 <- mk_pieces closure_type srt_label
207 ; let std_info
= mkStdInfoTable dflags prof_lits
208 (mb_rts_tag `orElse` rtsClosureType smrep
)
209 (mb_srt_field `orElse` srt_bitmap
)
210 (mb_layout `orElse` layout
)
211 ; return (prof_data
++ ct_data
, (std_info
, extra_bits
)) }
213 mk_pieces
:: ClosureTypeInfo
-> [CmmLit
]
214 -> UniqSM
( Maybe StgHalfWord
-- Override the SRT field with this
215 , Maybe CmmLit
-- Override the layout field with this
216 , [CmmLit
] -- "Extra bits" for info table
217 , [RawCmmDecl
]) -- Auxiliary data decls
218 mk_pieces
(Constr con_tag con_descr
) _no_srt
-- A data constructor
219 = do { (descr_lit
, decl
) <- newStringLit con_descr
220 ; return ( Just
(toStgHalfWord dflags
(fromIntegral con_tag
))
221 , Nothing
, [descr_lit
], [decl
]) }
223 mk_pieces Thunk srt_label
224 = return (Nothing
, Nothing
, srt_label
, [])
226 mk_pieces
(ThunkSelector offset
) _no_srt
227 = return (Just
(toStgHalfWord dflags
0), Just
(mkWordCLit dflags
(fromIntegral offset
)), [], [])
228 -- Layout known (one free var); we use the layout field for offset
230 mk_pieces
(Fun arity
(ArgSpec fun_type
)) srt_label
231 = do { let extra_bits
= packIntsCLit dflags fun_type arity
: srt_label
232 ; return (Nothing
, Nothing
, extra_bits
, []) }
234 mk_pieces
(Fun arity
(ArgGen arg_bits
)) srt_label
235 = do { (liveness_lit
, liveness_data
) <- mkLivenessBits dflags arg_bits
236 ; let fun_type |
null liveness_data
= aRG_GEN
237 |
otherwise = aRG_GEN_BIG
238 extra_bits
= [ packIntsCLit dflags fun_type arity
239 , srt_lit
, liveness_lit
, slow_entry
]
240 ; return (Nothing
, Nothing
, extra_bits
, liveness_data
) }
242 slow_entry
= CmmLabel
(toSlowEntryLbl info_lbl
)
243 srt_lit
= case srt_label
of
244 [] -> mkIntCLit dflags
0
245 (lit
:_rest
) -> ASSERT
( null _rest
) lit
247 mk_pieces other _
= pprPanic
"mk_pieces" (ppr other
)
249 mkInfoTableContents _ _ _
= panic
"mkInfoTableContents" -- NonInfoTable dealt with earlier
251 packIntsCLit
:: DynFlags
-> Int -> Int -> CmmLit
252 packIntsCLit dflags a b
= packHalfWordsCLit dflags
253 (toStgHalfWord dflags
(fromIntegral a
))
254 (toStgHalfWord dflags
(fromIntegral b
))
259 -> ([CmmLit
], -- srt_label, if any
260 StgHalfWord
) -- srt_bitmap
261 mkSRTLit dflags NoC_SRT
= ([], toStgHalfWord dflags
0)
262 mkSRTLit dflags
(C_SRT lbl off bitmap
) = ([cmmLabelOffW dflags lbl off
], bitmap
)
265 -------------------------------------------------------------------------
267 -- Lay out the info table and handle relative offsets
269 -------------------------------------------------------------------------
271 -- This function takes
272 -- * the standard info table portion (StgInfoTable)
273 -- * the "extra bits" (StgFunInfoExtraRev etc.)
276 -- and lays them out in memory, producing a list of RawCmmDecl
278 -------------------------------------------------------------------------
280 -- Position independent code
282 -------------------------------------------------------------------------
283 -- In order to support position independent code, we mustn't put absolute
284 -- references into read-only space. Info tables in the tablesNextToCode
285 -- case must be in .text, which is read-only, so we doctor the CmmLits
286 -- to use relative offsets instead.
288 -- Note that this is done even when the -fPIC flag is not specified,
289 -- as we want to keep binary compatibility between PIC and non-PIC.
291 makeRelativeRefTo
:: DynFlags
-> CLabel
-> CmmLit
-> CmmLit
293 makeRelativeRefTo dflags info_lbl
(CmmLabel lbl
)
294 | tablesNextToCode dflags
295 = CmmLabelDiffOff lbl info_lbl
0
296 makeRelativeRefTo dflags info_lbl
(CmmLabelOff lbl off
)
297 | tablesNextToCode dflags
298 = CmmLabelDiffOff lbl info_lbl off
299 makeRelativeRefTo _ _ lit
= lit
302 -------------------------------------------------------------------------
304 -- Build a liveness mask for the stack layout
306 -------------------------------------------------------------------------
308 -- There are four kinds of things on the stack:
310 -- - pointer variables (bound in the environment)
311 -- - non-pointer variables (bound in the environment)
312 -- - free slots (recorded in the stack free list)
313 -- - non-pointer data slots (recorded in the stack free list)
315 -- The first two are represented with a 'Just' of a 'LocalReg'.
316 -- The last two with one or more 'Nothing' constructors.
317 -- Each 'Nothing' represents one used word.
319 -- The head of the stack layout is the top of the stack and
320 -- the least-significant bit.
322 mkLivenessBits
:: DynFlags
-> Liveness
-> UniqSM
(CmmLit
, [RawCmmDecl
])
324 -- 1. The bitmap (literal value or label)
325 -- 2. Large bitmap CmmData if needed
327 mkLivenessBits dflags liveness
328 | n_bits
> mAX_SMALL_BITMAP_SIZE dflags
-- does not fit in one word
329 = do { uniq
<- getUniqueM
330 ; let bitmap_lbl
= mkBitmapLabel uniq
331 ; return (CmmLabel bitmap_lbl
,
332 [mkRODataLits bitmap_lbl lits
]) }
334 |
otherwise -- Fits in one word
335 = return (mkStgWordCLit dflags bitmap_word
, [])
337 n_bits
= length liveness
340 bitmap
= mkBitmap dflags liveness
342 small_bitmap
= case bitmap
of
343 [] -> toStgWord dflags
0
345 _
-> panic
"mkLiveness"
346 bitmap_word
= toStgWord dflags
(fromIntegral n_bits
)
347 .|
. (small_bitmap `shiftL` bITMAP_BITS_SHIFT dflags
)
349 lits
= mkWordCLit dflags
(fromIntegral n_bits
)
350 : map (mkStgWordCLit dflags
) bitmap
351 -- The first word is the size. The structure must match
352 -- StgLargeBitmap in includes/rts/storage/InfoTable.h
354 -------------------------------------------------------------------------
356 -- Generating a standard info table
358 -------------------------------------------------------------------------
360 -- The standard bits of an info table. This part of the info table
361 -- corresponds to the StgInfoTable type defined in
362 -- includes/rts/storage/InfoTables.h.
364 -- Its shape varies with ticky/profiling/tables next to code etc
365 -- so we can't use constant offsets from Constants
369 -> (CmmLit
,CmmLit
) -- Closure type descr and closure descr (profiling)
370 -> Int -- Closure RTS tag
371 -> StgHalfWord
-- SRT length
372 -> CmmLit
-- layout field
375 mkStdInfoTable dflags
(type_descr
, closure_descr
) cl_type srt_len layout_lit
376 = -- Parallel revertible-black hole field
378 -- Ticky info (none at present)
379 -- Debug info (none at present)
380 ++ [layout_lit
, type_lit
]
384 | gopt Opt_SccProfilingOn dflags
= [type_descr
, closure_descr
]
387 type_lit
= packHalfWordsCLit dflags
(toStgHalfWord dflags
(fromIntegral cl_type
)) srt_len
389 -------------------------------------------------------------------------
391 -- Making string literals
393 -------------------------------------------------------------------------
395 mkProfLits
:: DynFlags
-> ProfilingInfo
-> UniqSM
((CmmLit
,CmmLit
), [RawCmmDecl
])
396 mkProfLits dflags NoProfilingInfo
= return ((zeroCLit dflags
, zeroCLit dflags
), [])
397 mkProfLits _
(ProfilingInfo td cd
)
398 = do { (td_lit
, td_decl
) <- newStringLit td
399 ; (cd_lit
, cd_decl
) <- newStringLit cd
400 ; return ((td_lit
,cd_lit
), [td_decl
,cd_decl
]) }
402 newStringLit
:: [Word8
] -> UniqSM
(CmmLit
, GenCmmDecl CmmStatics info stmt
)
404 = do { uniq
<- getUniqueM
405 ; return (mkByteStringCLit
(mkStringLitLabel uniq
) bytes
) }
410 -- | Value of the srt field of an info table when using an StgLargeSRT
411 srtEscape
:: DynFlags
-> StgHalfWord
412 srtEscape dflags
= toStgHalfWord dflags
(-1)
414 -------------------------------------------------------------------------
416 -- Accessing fields of an info table
418 -------------------------------------------------------------------------
420 -- | Wrap a 'CmmExpr' in an alignment check when @-falignment-sanitisation@ is
422 wordAligned
:: DynFlags
-> CmmExpr
-> CmmExpr
424 | gopt Opt_AlignmentSanitisation dflags
425 = CmmMachOp
(MO_AlignmentCheck
(wORD_SIZE dflags
) (wordWidth dflags
)) [e
]
429 closureInfoPtr
:: DynFlags
-> CmmExpr
-> CmmExpr
430 -- Takes a closure pointer and returns the info table pointer
431 closureInfoPtr dflags e
=
432 CmmLoad
(wordAligned dflags e
) (bWord dflags
)
434 entryCode
:: DynFlags
-> CmmExpr
-> CmmExpr
435 -- Takes an info pointer (the first word of a closure)
436 -- and returns its entry code
438 | tablesNextToCode dflags
= e
439 |
otherwise = CmmLoad e
(bWord dflags
)
441 getConstrTag
:: DynFlags
-> CmmExpr
-> CmmExpr
442 -- Takes a closure pointer, and return the *zero-indexed*
443 -- constructor tag obtained from the info table
444 -- This lives in the SRT field of the info table
445 -- (constructors don't need SRTs).
446 getConstrTag dflags closure_ptr
447 = CmmMachOp
(MO_UU_Conv
(halfWordWidth dflags
) (wordWidth dflags
)) [infoTableConstrTag dflags info_table
]
449 info_table
= infoTable dflags
(closureInfoPtr dflags closure_ptr
)
451 cmmGetClosureType
:: DynFlags
-> CmmExpr
-> CmmExpr
452 -- Takes a closure pointer, and return the closure type
453 -- obtained from the info table
454 cmmGetClosureType dflags closure_ptr
455 = CmmMachOp
(MO_UU_Conv
(halfWordWidth dflags
) (wordWidth dflags
)) [infoTableClosureType dflags info_table
]
457 info_table
= infoTable dflags
(closureInfoPtr dflags closure_ptr
)
459 infoTable
:: DynFlags
-> CmmExpr
-> CmmExpr
460 -- Takes an info pointer (the first word of a closure)
461 -- and returns a pointer to the first word of the standard-form
462 -- info table, excluding the entry-code word (if present)
463 infoTable dflags info_ptr
464 | tablesNextToCode dflags
= cmmOffsetB dflags info_ptr
(- stdInfoTableSizeB dflags
)
465 |
otherwise = cmmOffsetW dflags info_ptr
1 -- Past the entry code pointer
467 infoTableConstrTag
:: DynFlags
-> CmmExpr
-> CmmExpr
468 -- Takes an info table pointer (from infoTable) and returns the constr tag
469 -- field of the info table (same as the srt_bitmap field)
470 infoTableConstrTag
= infoTableSrtBitmap
472 infoTableSrtBitmap
:: DynFlags
-> CmmExpr
-> CmmExpr
473 -- Takes an info table pointer (from infoTable) and returns the srt_bitmap
474 -- field of the info table
475 infoTableSrtBitmap dflags info_tbl
476 = CmmLoad
(cmmOffsetB dflags info_tbl
(stdSrtBitmapOffset dflags
)) (bHalfWord dflags
)
478 infoTableClosureType
:: DynFlags
-> CmmExpr
-> CmmExpr
479 -- Takes an info table pointer (from infoTable) and returns the closure type
480 -- field of the info table.
481 infoTableClosureType dflags info_tbl
482 = CmmLoad
(cmmOffsetB dflags info_tbl
(stdClosureTypeOffset dflags
)) (bHalfWord dflags
)
484 infoTablePtrs
:: DynFlags
-> CmmExpr
-> CmmExpr
485 infoTablePtrs dflags info_tbl
486 = CmmLoad
(cmmOffsetB dflags info_tbl
(stdPtrsOffset dflags
)) (bHalfWord dflags
)
488 infoTableNonPtrs
:: DynFlags
-> CmmExpr
-> CmmExpr
489 infoTableNonPtrs dflags info_tbl
490 = CmmLoad
(cmmOffsetB dflags info_tbl
(stdNonPtrsOffset dflags
)) (bHalfWord dflags
)
492 funInfoTable
:: DynFlags
-> CmmExpr
-> CmmExpr
493 -- Takes the info pointer of a function,
494 -- and returns a pointer to the first word of the StgFunInfoExtra struct
495 -- in the info table.
496 funInfoTable dflags info_ptr
497 | tablesNextToCode dflags
498 = cmmOffsetB dflags info_ptr
(- stdInfoTableSizeB dflags
- sIZEOF_StgFunInfoExtraRev dflags
)
500 = cmmOffsetW dflags info_ptr
(1 + stdInfoTableSizeW dflags
)
501 -- Past the entry code pointer
503 -- Takes the info pointer of a function, returns the function's arity
504 funInfoArity
:: DynFlags
-> CmmExpr
-> CmmExpr
505 funInfoArity dflags iptr
506 = cmmToWord dflags
(cmmLoadIndex dflags rep fun_info
(offset `
div` rep_bytes
))
508 fun_info
= funInfoTable dflags iptr
509 rep
= cmmBits
(widthFromBytes rep_bytes
)
512 | tablesNextToCode dflags
= ( pc_REP_StgFunInfoExtraRev_arity pc
513 , oFFSET_StgFunInfoExtraRev_arity dflags
)
514 |
otherwise = ( pc_REP_StgFunInfoExtraFwd_arity pc
515 , oFFSET_StgFunInfoExtraFwd_arity dflags
)
517 pc
= sPlatformConstants
(settings dflags
)
519 -----------------------------------------------------------------------------
521 -- Info table sizes & offsets
523 -----------------------------------------------------------------------------
525 stdInfoTableSizeW
:: DynFlags
-> WordOff
526 -- The size of a standard info table varies with profiling/ticky etc,
527 -- so we can't get it from Constants
528 -- It must vary in sync with mkStdInfoTable
529 stdInfoTableSizeW dflags
530 = fixedInfoTableSizeW
531 + if gopt Opt_SccProfilingOn dflags
532 then profInfoTableSizeW
535 fixedInfoTableSizeW
:: WordOff
536 fixedInfoTableSizeW
= 2 -- layout, type
538 profInfoTableSizeW
:: WordOff
539 profInfoTableSizeW
= 2
541 maxStdInfoTableSizeW
:: WordOff
542 maxStdInfoTableSizeW
=
543 1 {- entry, when !tablesNextToCode -}
544 + fixedInfoTableSizeW
547 maxRetInfoTableSizeW
:: WordOff
548 maxRetInfoTableSizeW
=
552 stdInfoTableSizeB
:: DynFlags
-> ByteOff
553 stdInfoTableSizeB dflags
= stdInfoTableSizeW dflags
* wORD_SIZE dflags
555 stdSrtBitmapOffset
:: DynFlags
-> ByteOff
556 -- Byte offset of the SRT bitmap half-word which is
557 -- in the *higher-addressed* part of the type_lit
558 stdSrtBitmapOffset dflags
= stdInfoTableSizeB dflags
- hALF_WORD_SIZE dflags
560 stdClosureTypeOffset
:: DynFlags
-> ByteOff
561 -- Byte offset of the closure type half-word
562 stdClosureTypeOffset dflags
= stdInfoTableSizeB dflags
- wORD_SIZE dflags
564 stdPtrsOffset
, stdNonPtrsOffset
:: DynFlags
-> ByteOff
565 stdPtrsOffset dflags
= stdInfoTableSizeB dflags
- 2 * wORD_SIZE dflags
566 stdNonPtrsOffset dflags
= stdInfoTableSizeB dflags
- 2 * wORD_SIZE dflags
+ hALF_WORD_SIZE dflags
568 conInfoTableSizeB
:: DynFlags
-> Int
569 conInfoTableSizeB dflags
= stdInfoTableSizeB dflags
+ wORD_SIZE dflags