1 -----------------------------------------------------------------------------
3 -- Building info tables.
5 -- (c) The University of Glasgow 2004-2006
7 -----------------------------------------------------------------------------
10 emitClosureCodeAndInfoTable,
14 emitReturnTarget, emitAlgReturnTarget,
19 mkFunGenInfoExtraBits,
20 entryCode, closureInfoPtr,
22 infoTable, infoTableClosureType,
23 infoTablePtrs, infoTableNonPtrs,
24 funInfoTable, makeRelativeRefTo
28 #include "HsVersions.h"
52 -------------------------------------------------------------------------
54 -- Generating the info table and code for a closure
56 -------------------------------------------------------------------------
58 -- Here we make a concrete info table, represented as a list of CmmAddr
59 -- (it can't be simply a list of Word, because the SRT field is
60 -- represented by a label+offset expression).
62 -- With tablesNextToCode, the layout is
63 -- <reversed variable part>
64 -- <normal forward StgInfoTable, but without
65 -- an entry point at the front>
68 -- Without tablesNextToCode, the layout of an info table is
70 -- <normal forward rest of StgInfoTable>
71 -- <forward variable part>
73 -- See includes/InfoTables.h
75 emitClosureCodeAndInfoTable :: ClosureInfo -> [LocalReg] -> CgStmts -> Code
76 emitClosureCodeAndInfoTable cl_info args body
77 = do { ty_descr_lit <-
79 then mkStringCLit (closureTypeDescr cl_info)
80 else return (mkIntCLit 0)
83 then mkStringCLit cl_descr_string
84 else return (mkIntCLit 0)
85 ; let std_info = mkStdInfoTable ty_descr_lit cl_descr_lit
86 cl_type srt_len layout_lit
88 ; blks <- cgStmtsToBlocks body
92 then do cstr <- mkStringCLit $ fromJust conIdentity
93 return (makeRelativeRefTo info_lbl cstr)
94 else return (mkIntCLit 0)
96 ; emitInfoTableAndCode info_lbl std_info (extra_bits conName) args blks }
98 info_lbl = infoTableLabelFromCI cl_info
100 cl_descr_string = closureValDescr cl_info
101 cl_type = smRepClosureTypeInt (closureSMRep cl_info)
103 srt = closureSRT cl_info
104 needs_srt = needsSRT srt
106 mb_con = isConstrClosure_maybe cl_info
107 is_con = isJust mb_con
109 (srt_label,srt_len,conIdentity)
111 Just con -> -- Constructors don't have an SRT
112 -- We keep the *zero-indexed* tag in the srt_len
113 -- field of the info table.
114 (mkIntCLit 0, fromIntegral (dataConTagZ con), Just $ dataConIdentity con)
116 Nothing -> -- Not a constructor
117 let (label, len) = srtLabelAndLength srt info_lbl
118 in (label, len, Nothing)
120 ptrs = closurePtrsSize cl_info
122 size = closureNonHdrSize cl_info
123 layout_lit = packHalfWordsCLit ptrs nptrs
126 | is_fun = fun_extra_bits
128 | needs_srt = [srt_label]
131 maybe_fun_stuff = closureFunInfo cl_info
132 is_fun = isJust maybe_fun_stuff
133 (Just (arity, arg_descr)) = maybe_fun_stuff
136 | ArgGen liveness <- arg_descr
139 makeRelativeRefTo info_lbl $ mkLivenessCLit liveness,
141 | needs_srt = [fun_amode, srt_label]
142 | otherwise = [fun_amode]
144 slow_entry = makeRelativeRefTo info_lbl (CmmLabel slow_entry_label)
145 slow_entry_label = mkSlowEntryLabel (closureName cl_info)
147 fun_amode = packHalfWordsCLit fun_type arity
148 fun_type = argDescrType arg_descr
150 -- We keep the *zero-indexed* tag in the srt_len field of the info
151 -- table of a data constructor.
152 dataConTagZ :: DataCon -> ConTagZ
153 dataConTagZ con = dataConTag con - fIRST_TAG
155 -- A low-level way to generate the variable part of a fun-style info table.
156 -- (must match fun_extra_bits above). Used by the C-- parser.
157 mkFunGenInfoExtraBits :: Int -> Int -> CmmLit -> CmmLit -> CmmLit -> [CmmLit]
158 mkFunGenInfoExtraBits fun_type arity srt_label liveness slow_entry
159 = [ packHalfWordsCLit fun_type arity,
164 -------------------------------------------------------------------------
166 -- Generating the info table and code for a return point
168 -------------------------------------------------------------------------
170 -- Here's the layout of a return-point info table
172 -- Tables next to code:
175 -- <standard info table>
176 -- ret-addr --> <entry code (if any)>
178 -- Not tables-next-to-code:
180 -- ret-addr --> <ptr to entry code>
181 -- <standard info table>
184 -- * The SRT slot is only there is SRT info to record
188 -> CgStmts -- The direct-return code (if any)
191 emitReturnTarget name stmts srt
192 = do { live_slots <- getLiveStackSlots
193 ; liveness <- buildContLiveness name live_slots
194 ; srt_info <- getSRTInfo name srt
197 cl_type | isBigLiveness liveness = rET_BIG
198 | otherwise = rET_SMALL
200 (std_info, extra_bits) =
201 mkRetInfoTable info_lbl liveness srt_info cl_type
203 ; blks <- cgStmtsToBlocks stmts
204 ; emitInfoTableAndCode info_lbl std_info extra_bits args blks
207 args = {- trace "emitReturnTarget: missing args" -} []
208 uniq = getUnique name
209 info_lbl = mkReturnInfoLabel uniq
213 :: CLabel -- info label
214 -> Liveness -- liveness
216 -> Int -- type (eg. rET_SMALL)
217 -> ([CmmLit],[CmmLit])
218 mkRetInfoTable info_lbl liveness srt_info cl_type
219 = (std_info, srt_slot)
221 (srt_label, srt_len) = srtLabelAndLength srt_info info_lbl
223 srt_slot | needsSRT srt_info = [srt_label]
226 liveness_lit = makeRelativeRefTo info_lbl $ mkLivenessCLit liveness
227 std_info = mkStdInfoTable zeroCLit zeroCLit cl_type srt_len liveness_lit
230 :: Name -- Just for its unique
231 -> [(ConTagZ, CgStmts)] -- Tagged branches
232 -> Maybe CgStmts -- Default branch (if any)
233 -> SRT -- Continuation's SRT
234 -> Int -- family size
235 -> FCode (CLabel, SemiTaggingStuff)
237 emitAlgReturnTarget name branches mb_deflt srt fam_sz
238 = do { blks <- getCgStmts $
239 emitSwitch tag_expr branches mb_deflt 0 (fam_sz - 1)
240 -- NB: tag_expr is zero-based
241 ; lbl <- emitReturnTarget name blks srt
242 ; return (lbl, Nothing) }
243 -- Nothing: the internal branches in the switch don't have
244 -- global labels, so we can't use them at the 'call site'
246 tag_expr = getConstrTag (CmmReg nodeReg)
248 --------------------------------
249 emitReturnInstr :: Code
251 = do { info_amode <- getSequelAmode
252 ; stmtC (CmmJump (entryCode info_amode) []) }
254 -------------------------------------------------------------------------
256 -- Generating a standard info table
258 -------------------------------------------------------------------------
260 -- The standard bits of an info table. This part of the info table
261 -- corresponds to the StgInfoTable type defined in InfoTables.h.
263 -- Its shape varies with ticky/profiling/tables next to code etc
264 -- so we can't use constant offsets from Constants
267 :: CmmLit -- closure type descr (profiling)
268 -> CmmLit -- closure descr (profiling)
269 -> Int -- closure type
270 -> StgHalfWord -- SRT length
271 -> CmmLit -- layout field
274 mkStdInfoTable type_descr closure_descr cl_type srt_len layout_lit
275 = -- Parallel revertible-black hole field
277 -- Ticky info (none at present)
278 -- Debug info (none at present)
279 ++ [layout_lit, type_lit]
283 | opt_SccProfilingOn = [type_descr, closure_descr]
286 type_lit = packHalfWordsCLit cl_type srt_len
288 stdInfoTableSizeW :: WordOff
289 -- The size of a standard info table varies with profiling/ticky etc,
290 -- so we can't get it from Constants
291 -- It must vary in sync with mkStdInfoTable
293 = size_fixed + size_prof
295 size_fixed = 2 -- layout, type
296 size_prof | opt_SccProfilingOn = 2
299 stdInfoTableSizeB = stdInfoTableSizeW * wORD_SIZE :: ByteOff
301 stdSrtBitmapOffset :: ByteOff
302 -- Byte offset of the SRT bitmap half-word which is
303 -- in the *higher-addressed* part of the type_lit
304 stdSrtBitmapOffset = stdInfoTableSizeB - hALF_WORD_SIZE
306 stdClosureTypeOffset :: ByteOff
307 -- Byte offset of the closure type half-word
308 stdClosureTypeOffset = stdInfoTableSizeB - wORD_SIZE
310 stdPtrsOffset, stdNonPtrsOffset :: ByteOff
311 stdPtrsOffset = stdInfoTableSizeB - 2*wORD_SIZE
312 stdNonPtrsOffset = stdInfoTableSizeB - 2*wORD_SIZE + hALF_WORD_SIZE
314 -------------------------------------------------------------------------
316 -- Accessing fields of an info table
318 -------------------------------------------------------------------------
320 closureInfoPtr :: CmmExpr -> CmmExpr
321 -- Takes a closure pointer and returns the info table pointer
322 closureInfoPtr e = CmmLoad e wordRep
324 entryCode :: CmmExpr -> CmmExpr
325 -- Takes an info pointer (the first word of a closure)
326 -- and returns its entry code
327 entryCode e | tablesNextToCode = e
328 | otherwise = CmmLoad e wordRep
330 getConstrTag :: CmmExpr -> CmmExpr
331 -- Takes a closure pointer, and return the *zero-indexed*
332 -- constructor tag obtained from the info table
333 -- This lives in the SRT field of the info table
334 -- (constructors don't need SRTs).
335 getConstrTag closure_ptr
336 = CmmMachOp (MO_U_Conv halfWordRep wordRep) [infoTableConstrTag info_table]
338 info_table = infoTable (closureInfoPtr closure_ptr)
340 infoTable :: CmmExpr -> CmmExpr
341 -- Takes an info pointer (the first word of a closure)
342 -- and returns a pointer to the first word of the standard-form
343 -- info table, excluding the entry-code word (if present)
345 | tablesNextToCode = cmmOffsetB info_ptr (- stdInfoTableSizeB)
346 | otherwise = cmmOffsetW info_ptr 1 -- Past the entry code pointer
348 infoTableConstrTag :: CmmExpr -> CmmExpr
349 -- Takes an info table pointer (from infoTable) and returns the constr tag
350 -- field of the info table (same as the srt_bitmap field)
351 infoTableConstrTag = infoTableSrtBitmap
353 infoTableSrtBitmap :: CmmExpr -> CmmExpr
354 -- Takes an info table pointer (from infoTable) and returns the srt_bitmap
355 -- field of the info table
356 infoTableSrtBitmap info_tbl
357 = CmmLoad (cmmOffsetB info_tbl stdSrtBitmapOffset) halfWordRep
359 infoTableClosureType :: CmmExpr -> CmmExpr
360 -- Takes an info table pointer (from infoTable) and returns the closure type
361 -- field of the info table.
362 infoTableClosureType info_tbl
363 = CmmLoad (cmmOffsetB info_tbl stdClosureTypeOffset) halfWordRep
365 infoTablePtrs :: CmmExpr -> CmmExpr
366 infoTablePtrs info_tbl
367 = CmmLoad (cmmOffsetB info_tbl stdPtrsOffset) halfWordRep
369 infoTableNonPtrs :: CmmExpr -> CmmExpr
370 infoTableNonPtrs info_tbl
371 = CmmLoad (cmmOffsetB info_tbl stdNonPtrsOffset) halfWordRep
373 funInfoTable :: CmmExpr -> CmmExpr
374 -- Takes the info pointer of a function,
375 -- and returns a pointer to the first word of the StgFunInfoExtra struct
376 -- in the info table.
377 funInfoTable info_ptr
379 = cmmOffsetB info_ptr (- stdInfoTableSizeB - sIZEOF_StgFunInfoExtraRev)
381 = cmmOffsetW info_ptr (1 + stdInfoTableSizeW)
382 -- Past the entry code pointer
384 -------------------------------------------------------------------------
386 -- Emit the code for a closure (or return address)
387 -- and its associated info table
389 -------------------------------------------------------------------------
391 -- The complication here concerns whether or not we can
392 -- put the info table next to the code
395 :: CLabel -- Label of info table
396 -> [CmmLit] -- ...its invariant part
397 -> [CmmLit] -- ...and its variant part
398 -> [LocalReg] -- ...args
399 -> [CmmBasicBlock] -- ...and body
402 emitInfoTableAndCode info_lbl std_info extra_bits args blocks
403 | tablesNextToCode -- Reverse the extra_bits; and emit the top-level proc
404 = emitProc (reverse extra_bits ++ std_info)
405 entry_lbl args blocks
406 -- NB: the info_lbl is discarded
408 | null blocks -- No actual code; only the info table is significant
409 = -- Use a zero place-holder in place of the
410 -- entry-label in the info table
411 emitRODataLits info_lbl (zeroCLit : std_info ++ extra_bits)
413 | otherwise -- Separately emit info table (with the function entry
414 = -- point as first entry) and the entry code
415 do { emitDataLits info_lbl (CmmLabel entry_lbl : std_info ++ extra_bits)
416 ; emitProc [] entry_lbl args blocks }
419 entry_lbl = infoLblToEntryLbl info_lbl
421 -------------------------------------------------------------------------
423 -- Static reference tables
425 -------------------------------------------------------------------------
427 -- There is just one SRT for each top level binding; all the nested
428 -- bindings use sub-sections of this SRT. The label is passed down to
429 -- the nested bindings via the monad.
431 getSRTInfo :: Name -> SRT -> FCode C_SRT
432 getSRTInfo id NoSRT = return NoC_SRT
433 getSRTInfo id (SRT off len bmp)
434 | len > hALF_WORD_SIZE_IN_BITS || bmp == [fromIntegral srt_escape]
435 = do { srt_lbl <- getSRTLabel
436 ; let srt_desc_lbl = mkSRTDescLabel id
437 ; emitRODataLits srt_desc_lbl
438 ( cmmLabelOffW srt_lbl off
439 : mkWordCLit (fromIntegral len)
440 : map mkWordCLit bmp)
441 ; return (C_SRT srt_desc_lbl 0 srt_escape) }
444 = do { srt_lbl <- getSRTLabel
445 ; return (C_SRT srt_lbl off (fromIntegral (head bmp))) }
446 -- The fromIntegral converts to StgHalfWord
448 srt_escape = (-1) :: StgHalfWord
450 srtLabelAndLength :: C_SRT -> CLabel -> (CmmLit, StgHalfWord)
451 srtLabelAndLength NoC_SRT _
453 srtLabelAndLength (C_SRT lbl off bitmap) info_lbl
454 = (makeRelativeRefTo info_lbl $ cmmLabelOffW lbl off, bitmap)
456 -------------------------------------------------------------------------
458 -- Position independent code
460 -------------------------------------------------------------------------
461 -- In order to support position independent code, we mustn't put absolute
462 -- references into read-only space. Info tables in the tablesNextToCode
463 -- case must be in .text, which is read-only, so we doctor the CmmLits
464 -- to use relative offsets instead.
466 -- Note that this is done even when the -fPIC flag is not specified,
467 -- as we want to keep binary compatibility between PIC and non-PIC.
469 makeRelativeRefTo :: CLabel -> CmmLit -> CmmLit
471 makeRelativeRefTo info_lbl (CmmLabel lbl)
473 = CmmLabelDiffOff lbl info_lbl 0
474 makeRelativeRefTo info_lbl (CmmLabelOff lbl off)
476 = CmmLabelDiffOff lbl info_lbl off
477 makeRelativeRefTo _ lit = lit