1 -----------------------------------------------------------------------------
3 -- Building info tables.
5 -- (c) The University of Glasgow 2004-2006
7 -----------------------------------------------------------------------------
10 emitClosureCodeAndInfoTable,
13 emitReturnTarget, emitAlgReturnTarget,
18 mkFunGenInfoExtraBits,
19 entryCode, closureInfoPtr,
21 infoTable, infoTableClosureType,
22 infoTablePtrs, infoTableNonPtrs,
23 funInfoTable, makeRelativeRefTo
27 #include "HsVersions.h"
50 -------------------------------------------------------------------------
52 -- Generating the info table and code for a closure
54 -------------------------------------------------------------------------
56 -- Here we make a concrete info table, represented as a list of CmmAddr
57 -- (it can't be simply a list of Word, because the SRT field is
58 -- represented by a label+offset expression).
60 -- With tablesNextToCode, the layout is
61 -- <reversed variable part>
62 -- <normal forward StgInfoTable, but without
63 -- an entry point at the front>
66 -- Without tablesNextToCode, the layout of an info table is
68 -- <normal forward rest of StgInfoTable>
69 -- <forward variable part>
71 -- See includes/InfoTables.h
73 emitClosureCodeAndInfoTable :: ClosureInfo -> CmmFormals -> CgStmts -> Code
74 emitClosureCodeAndInfoTable cl_info args body
75 = do { ty_descr_lit <-
77 then do lit <- mkStringCLit (closureTypeDescr cl_info)
78 return (makeRelativeRefTo info_lbl lit)
79 else return (mkIntCLit 0)
82 then do lit <- mkStringCLit cl_descr_string
83 return (makeRelativeRefTo info_lbl lit)
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 <- mkByteStringCLit $ fromJust conIdentity
93 return (makeRelativeRefTo info_lbl cstr)
94 else return (mkIntCLit 0)
96 ; panic "emitClosureCodeAndInfoTable" } --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),
115 Just $ dataConIdentity con)
117 Nothing -> -- Not a constructor
118 let (label, len) = srtLabelAndLength srt info_lbl
119 in (label, len, Nothing)
121 ptrs = closurePtrsSize cl_info
123 size = closureNonHdrSize cl_info
124 layout_lit = packHalfWordsCLit ptrs nptrs
127 | is_fun = fun_extra_bits
129 | needs_srt = [srt_label]
132 maybe_fun_stuff = closureFunInfo cl_info
133 is_fun = isJust maybe_fun_stuff
134 (Just (arity, arg_descr)) = maybe_fun_stuff
137 | ArgGen liveness <- arg_descr
140 makeRelativeRefTo info_lbl $ mkLivenessCLit liveness,
142 | needs_srt = [fun_amode, srt_label]
143 | otherwise = [fun_amode]
145 slow_entry = makeRelativeRefTo info_lbl (CmmLabel slow_entry_label)
146 slow_entry_label = mkSlowEntryLabel (closureName cl_info)
148 fun_amode = packHalfWordsCLit fun_type arity
149 fun_type = argDescrType arg_descr
151 -- We keep the *zero-indexed* tag in the srt_len field of the info
152 -- table of a data constructor.
153 dataConTagZ :: DataCon -> ConTagZ
154 dataConTagZ con = dataConTag con - fIRST_TAG
156 -- A low-level way to generate the variable part of a fun-style info table.
157 -- (must match fun_extra_bits above). Used by the C-- parser.
158 mkFunGenInfoExtraBits :: Int -> Int -> CmmLit -> CmmLit -> CmmLit -> [CmmLit]
159 mkFunGenInfoExtraBits fun_type arity srt_label liveness slow_entry
160 = [ packHalfWordsCLit fun_type arity,
165 -------------------------------------------------------------------------
167 -- Generating the info table and code for a return point
169 -------------------------------------------------------------------------
171 -- Here's the layout of a return-point info table
173 -- Tables next to code:
176 -- <standard info table>
177 -- ret-addr --> <entry code (if any)>
179 -- Not tables-next-to-code:
181 -- ret-addr --> <ptr to entry code>
182 -- <standard info table>
185 -- * The SRT slot is only there is SRT info to record
189 -> CgStmts -- The direct-return code (if any)
191 emitReturnTarget name stmts
192 = do { live_slots <- getLiveStackSlots
193 ; liveness <- buildContLiveness name live_slots
194 ; srt_info <- getSRTInfo
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 ; panic "emitReturnTarget" --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 -> StgHalfWord -- 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 -> Int -- family size
234 -> FCode (CLabel, SemiTaggingStuff)
236 emitAlgReturnTarget name branches mb_deflt fam_sz
237 = do { blks <- getCgStmts $
238 emitSwitch tag_expr branches mb_deflt 0 (fam_sz - 1)
239 -- NB: tag_expr is zero-based
240 ; lbl <- emitReturnTarget name blks
241 ; return (lbl, Nothing) }
242 -- Nothing: the internal branches in the switch don't have
243 -- global labels, so we can't use them at the 'call site'
245 tag_expr = getConstrTag (CmmReg nodeReg)
247 --------------------------------
248 emitReturnInstr :: Code
250 = do { info_amode <- getSequelAmode
251 ; stmtC (CmmJump (entryCode info_amode) []) }
253 -------------------------------------------------------------------------
255 -- Generating a standard info table
257 -------------------------------------------------------------------------
259 -- The standard bits of an info table. This part of the info table
260 -- corresponds to the StgInfoTable type defined in InfoTables.h.
262 -- Its shape varies with ticky/profiling/tables next to code etc
263 -- so we can't use constant offsets from Constants
266 :: CmmLit -- closure type descr (profiling)
267 -> CmmLit -- closure descr (profiling)
268 -> StgHalfWord -- closure type
269 -> StgHalfWord -- SRT length
270 -> CmmLit -- layout field
273 mkStdInfoTable type_descr closure_descr cl_type srt_len layout_lit
274 = -- Parallel revertible-black hole field
276 -- Ticky info (none at present)
277 -- Debug info (none at present)
278 ++ [layout_lit, type_lit]
282 | opt_SccProfilingOn = [type_descr, closure_descr]
285 type_lit = packHalfWordsCLit cl_type srt_len
287 stdInfoTableSizeW :: WordOff
288 -- The size of a standard info table varies with profiling/ticky etc,
289 -- so we can't get it from Constants
290 -- It must vary in sync with mkStdInfoTable
292 = size_fixed + size_prof
294 size_fixed = 2 -- layout, type
295 size_prof | opt_SccProfilingOn = 2
298 stdInfoTableSizeB = stdInfoTableSizeW * wORD_SIZE :: ByteOff
300 stdSrtBitmapOffset :: ByteOff
301 -- Byte offset of the SRT bitmap half-word which is
302 -- in the *higher-addressed* part of the type_lit
303 stdSrtBitmapOffset = stdInfoTableSizeB - hALF_WORD_SIZE
305 stdClosureTypeOffset :: ByteOff
306 -- Byte offset of the closure type half-word
307 stdClosureTypeOffset = stdInfoTableSizeB - wORD_SIZE
309 stdPtrsOffset, stdNonPtrsOffset :: ByteOff
310 stdPtrsOffset = stdInfoTableSizeB - 2*wORD_SIZE
311 stdNonPtrsOffset = stdInfoTableSizeB - 2*wORD_SIZE + hALF_WORD_SIZE
313 -------------------------------------------------------------------------
315 -- Accessing fields of an info table
317 -------------------------------------------------------------------------
319 closureInfoPtr :: CmmExpr -> CmmExpr
320 -- Takes a closure pointer and returns the info table pointer
321 closureInfoPtr e = CmmLoad e wordRep
323 entryCode :: CmmExpr -> CmmExpr
324 -- Takes an info pointer (the first word of a closure)
325 -- and returns its entry code
326 entryCode e | tablesNextToCode = e
327 | otherwise = CmmLoad e wordRep
329 getConstrTag :: CmmExpr -> CmmExpr
330 -- Takes a closure pointer, and return the *zero-indexed*
331 -- constructor tag obtained from the info table
332 -- This lives in the SRT field of the info table
333 -- (constructors don't need SRTs).
334 getConstrTag closure_ptr
335 = CmmMachOp (MO_U_Conv halfWordRep wordRep) [infoTableConstrTag info_table]
337 info_table = infoTable (closureInfoPtr closure_ptr)
339 infoTable :: CmmExpr -> CmmExpr
340 -- Takes an info pointer (the first word of a closure)
341 -- and returns a pointer to the first word of the standard-form
342 -- info table, excluding the entry-code word (if present)
344 | tablesNextToCode = cmmOffsetB info_ptr (- stdInfoTableSizeB)
345 | otherwise = cmmOffsetW info_ptr 1 -- Past the entry code pointer
347 infoTableConstrTag :: CmmExpr -> CmmExpr
348 -- Takes an info table pointer (from infoTable) and returns the constr tag
349 -- field of the info table (same as the srt_bitmap field)
350 infoTableConstrTag = infoTableSrtBitmap
352 infoTableSrtBitmap :: CmmExpr -> CmmExpr
353 -- Takes an info table pointer (from infoTable) and returns the srt_bitmap
354 -- field of the info table
355 infoTableSrtBitmap info_tbl
356 = CmmLoad (cmmOffsetB info_tbl stdSrtBitmapOffset) halfWordRep
358 infoTableClosureType :: CmmExpr -> CmmExpr
359 -- Takes an info table pointer (from infoTable) and returns the closure type
360 -- field of the info table.
361 infoTableClosureType info_tbl
362 = CmmLoad (cmmOffsetB info_tbl stdClosureTypeOffset) halfWordRep
364 infoTablePtrs :: CmmExpr -> CmmExpr
365 infoTablePtrs info_tbl
366 = CmmLoad (cmmOffsetB info_tbl stdPtrsOffset) halfWordRep
368 infoTableNonPtrs :: CmmExpr -> CmmExpr
369 infoTableNonPtrs info_tbl
370 = CmmLoad (cmmOffsetB info_tbl stdNonPtrsOffset) halfWordRep
372 funInfoTable :: CmmExpr -> CmmExpr
373 -- Takes the info pointer of a function,
374 -- and returns a pointer to the first word of the StgFunInfoExtra struct
375 -- in the info table.
376 funInfoTable info_ptr
378 = cmmOffsetB info_ptr (- stdInfoTableSizeB - sIZEOF_StgFunInfoExtraRev)
380 = cmmOffsetW info_ptr (1 + stdInfoTableSizeW)
381 -- Past the entry code pointer
383 -------------------------------------------------------------------------
385 -- Emit the code for a closure (or return address)
386 -- and its associated info table
388 -------------------------------------------------------------------------
390 -- The complication here concerns whether or not we can
391 -- put the info table next to the code
394 :: CLabel -- Label of info table
395 -> CmmInfo -- ...the info table
396 -> CmmFormals -- ...args
397 -> [CmmBasicBlock] -- ...and body
400 emitInfoTableAndCode info_lbl info args blocks
401 = emitProc info entry_lbl args blocks
403 entry_lbl = infoLblToEntryLbl info_lbl
407 :: CLabel -- Label of info table
408 -> [CmmLit] -- ...its invariant part
409 -> [CmmLit] -- ...and its variant part
410 -> CmmFormals -- ...args
411 -> [CmmBasicBlock] -- ...and body
414 emitInfoTableAndCode info_lbl std_info extra_bits args blocks
415 | tablesNextToCode -- Reverse the extra_bits; and emit the top-level proc
416 = emitProc (reverse extra_bits ++ std_info)
417 entry_lbl args blocks
418 -- NB: the info_lbl is discarded
420 | null blocks -- No actual code; only the info table is significant
421 = -- Use a zero place-holder in place of the
422 -- entry-label in the info table
423 emitRODataLits info_lbl (zeroCLit : std_info ++ extra_bits)
425 | otherwise -- Separately emit info table (with the function entry
426 = -- point as first entry) and the entry code
427 do { emitDataLits info_lbl (CmmLabel entry_lbl : std_info ++ extra_bits)
428 ; emitProc [] entry_lbl args blocks }
431 entry_lbl = infoLblToEntryLbl info_lbl
434 -------------------------------------------------------------------------
436 -- Static reference tables
438 -------------------------------------------------------------------------
440 srtLabelAndLength :: C_SRT -> CLabel -> (CmmLit, StgHalfWord)
441 srtLabelAndLength NoC_SRT _
443 srtLabelAndLength (C_SRT lbl off bitmap) info_lbl
444 = (makeRelativeRefTo info_lbl $ cmmLabelOffW lbl off, bitmap)
446 -------------------------------------------------------------------------
448 -- Position independent code
450 -------------------------------------------------------------------------
451 -- In order to support position independent code, we mustn't put absolute
452 -- references into read-only space. Info tables in the tablesNextToCode
453 -- case must be in .text, which is read-only, so we doctor the CmmLits
454 -- to use relative offsets instead.
456 -- Note that this is done even when the -fPIC flag is not specified,
457 -- as we want to keep binary compatibility between PIC and non-PIC.
459 makeRelativeRefTo :: CLabel -> CmmLit -> CmmLit
461 makeRelativeRefTo info_lbl (CmmLabel lbl)
463 = CmmLabelDiffOff lbl info_lbl 0
464 makeRelativeRefTo info_lbl (CmmLabelOff lbl off)
466 = CmmLabelDiffOff lbl info_lbl off
467 makeRelativeRefTo _ lit = lit