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"
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 -> [LocalReg] -> CgStmts -> Code
74 emitClosureCodeAndInfoTable cl_info args body
75 = do { ty_descr_lit <-
77 then mkStringCLit (closureTypeDescr cl_info)
78 else return (mkIntCLit 0)
81 then mkStringCLit cl_descr_string
82 else return (mkIntCLit 0)
83 ; let std_info = mkStdInfoTable ty_descr_lit cl_descr_lit
84 cl_type srt_len layout_lit
86 ; blks <- cgStmtsToBlocks body
90 then do cstr <- mkByteStringCLit $ fromJust conIdentity
91 return (makeRelativeRefTo info_lbl cstr)
92 else return (mkIntCLit 0)
94 ; emitInfoTableAndCode info_lbl std_info (extra_bits conName) args blks }
96 info_lbl = infoTableLabelFromCI cl_info
98 cl_descr_string = closureValDescr cl_info
99 cl_type = smRepClosureTypeInt (closureSMRep cl_info)
101 srt = closureSRT cl_info
102 needs_srt = needsSRT srt
104 mb_con = isConstrClosure_maybe cl_info
105 is_con = isJust mb_con
107 (srt_label,srt_len,conIdentity)
109 Just con -> -- Constructors don't have an SRT
110 -- We keep the *zero-indexed* tag in the srt_len
111 -- field of the info table.
112 (mkIntCLit 0, fromIntegral (dataConTagZ con),
113 Just $ dataConIdentity con)
115 Nothing -> -- Not a constructor
116 let (label, len) = srtLabelAndLength srt info_lbl
117 in (label, len, Nothing)
119 ptrs = closurePtrsSize cl_info
121 size = closureNonHdrSize cl_info
122 layout_lit = packHalfWordsCLit ptrs nptrs
125 | is_fun = fun_extra_bits
127 | needs_srt = [srt_label]
130 maybe_fun_stuff = closureFunInfo cl_info
131 is_fun = isJust maybe_fun_stuff
132 (Just (arity, arg_descr)) = maybe_fun_stuff
135 | ArgGen liveness <- arg_descr
138 makeRelativeRefTo info_lbl $ mkLivenessCLit liveness,
140 | needs_srt = [fun_amode, srt_label]
141 | otherwise = [fun_amode]
143 slow_entry = makeRelativeRefTo info_lbl (CmmLabel slow_entry_label)
144 slow_entry_label = mkSlowEntryLabel (closureName cl_info)
146 fun_amode = packHalfWordsCLit fun_type arity
147 fun_type = argDescrType arg_descr
149 -- We keep the *zero-indexed* tag in the srt_len field of the info
150 -- table of a data constructor.
151 dataConTagZ :: DataCon -> ConTagZ
152 dataConTagZ con = dataConTag con - fIRST_TAG
154 -- A low-level way to generate the variable part of a fun-style info table.
155 -- (must match fun_extra_bits above). Used by the C-- parser.
156 mkFunGenInfoExtraBits :: Int -> Int -> CmmLit -> CmmLit -> CmmLit -> [CmmLit]
157 mkFunGenInfoExtraBits fun_type arity srt_label liveness slow_entry
158 = [ packHalfWordsCLit fun_type arity,
163 -------------------------------------------------------------------------
165 -- Generating the info table and code for a return point
167 -------------------------------------------------------------------------
169 -- Here's the layout of a return-point info table
171 -- Tables next to code:
174 -- <standard info table>
175 -- ret-addr --> <entry code (if any)>
177 -- Not tables-next-to-code:
179 -- ret-addr --> <ptr to entry code>
180 -- <standard info table>
183 -- * The SRT slot is only there is SRT info to record
187 -> CgStmts -- The direct-return code (if any)
190 emitReturnTarget name stmts srt
191 = do { live_slots <- getLiveStackSlots
192 ; liveness <- buildContLiveness name live_slots
193 ; srt_info <- getSRTInfo name srt
196 cl_type | isBigLiveness liveness = rET_BIG
197 | otherwise = rET_SMALL
199 (std_info, extra_bits) =
200 mkRetInfoTable info_lbl liveness srt_info cl_type
202 ; blks <- cgStmtsToBlocks stmts
203 ; emitInfoTableAndCode info_lbl std_info extra_bits args blks
206 args = {- trace "emitReturnTarget: missing args" -} []
207 uniq = getUnique name
208 info_lbl = mkReturnInfoLabel uniq
212 :: CLabel -- info label
213 -> Liveness -- liveness
215 -> Int -- type (eg. rET_SMALL)
216 -> ([CmmLit],[CmmLit])
217 mkRetInfoTable info_lbl liveness srt_info cl_type
218 = (std_info, srt_slot)
220 (srt_label, srt_len) = srtLabelAndLength srt_info info_lbl
222 srt_slot | needsSRT srt_info = [srt_label]
225 liveness_lit = makeRelativeRefTo info_lbl $ mkLivenessCLit liveness
226 std_info = mkStdInfoTable zeroCLit zeroCLit cl_type srt_len liveness_lit
229 :: Name -- Just for its unique
230 -> [(ConTagZ, CgStmts)] -- Tagged branches
231 -> Maybe CgStmts -- Default branch (if any)
232 -> SRT -- Continuation's SRT
233 -> Int -- family size
234 -> FCode (CLabel, SemiTaggingStuff)
236 emitAlgReturnTarget name branches mb_deflt srt 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 srt
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 -> Int -- 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 -> [CmmLit] -- ...its invariant part
396 -> [CmmLit] -- ...and its variant part
397 -> [LocalReg] -- ...args
398 -> [CmmBasicBlock] -- ...and body
401 emitInfoTableAndCode info_lbl std_info extra_bits args blocks
402 | tablesNextToCode -- Reverse the extra_bits; and emit the top-level proc
403 = emitProc (reverse extra_bits ++ std_info)
404 entry_lbl args blocks
405 -- NB: the info_lbl is discarded
407 | null blocks -- No actual code; only the info table is significant
408 = -- Use a zero place-holder in place of the
409 -- entry-label in the info table
410 emitRODataLits info_lbl (zeroCLit : std_info ++ extra_bits)
412 | otherwise -- Separately emit info table (with the function entry
413 = -- point as first entry) and the entry code
414 do { emitDataLits info_lbl (CmmLabel entry_lbl : std_info ++ extra_bits)
415 ; emitProc [] entry_lbl args blocks }
418 entry_lbl = infoLblToEntryLbl info_lbl
420 -------------------------------------------------------------------------
422 -- Static reference tables
424 -------------------------------------------------------------------------
426 -- There is just one SRT for each top level binding; all the nested
427 -- bindings use sub-sections of this SRT. The label is passed down to
428 -- the nested bindings via the monad.
430 getSRTInfo :: Name -> SRT -> FCode C_SRT
431 getSRTInfo id NoSRT = return NoC_SRT
432 getSRTInfo id (SRT off len bmp)
433 | len > hALF_WORD_SIZE_IN_BITS || bmp == [fromIntegral srt_escape]
434 = do { srt_lbl <- getSRTLabel
435 ; let srt_desc_lbl = mkSRTDescLabel id
436 ; emitRODataLits srt_desc_lbl
437 ( cmmLabelOffW srt_lbl off
438 : mkWordCLit (fromIntegral len)
439 : map mkWordCLit bmp)
440 ; return (C_SRT srt_desc_lbl 0 srt_escape) }
443 = do { srt_lbl <- getSRTLabel
444 ; return (C_SRT srt_lbl off (fromIntegral (head bmp))) }
445 -- The fromIntegral converts to StgHalfWord
447 srt_escape = (-1) :: StgHalfWord
449 srtLabelAndLength :: C_SRT -> CLabel -> (CmmLit, StgHalfWord)
450 srtLabelAndLength NoC_SRT _
452 srtLabelAndLength (C_SRT lbl off bitmap) info_lbl
453 = (makeRelativeRefTo info_lbl $ cmmLabelOffW lbl off, bitmap)
455 -------------------------------------------------------------------------
457 -- Position independent code
459 -------------------------------------------------------------------------
460 -- In order to support position independent code, we mustn't put absolute
461 -- references into read-only space. Info tables in the tablesNextToCode
462 -- case must be in .text, which is read-only, so we doctor the CmmLits
463 -- to use relative offsets instead.
465 -- Note that this is done even when the -fPIC flag is not specified,
466 -- as we want to keep binary compatibility between PIC and non-PIC.
468 makeRelativeRefTo :: CLabel -> CmmLit -> CmmLit
470 makeRelativeRefTo info_lbl (CmmLabel lbl)
472 = CmmLabelDiffOff lbl info_lbl 0
473 makeRelativeRefTo info_lbl (CmmLabelOff lbl off)
475 = CmmLabelDiffOff lbl info_lbl off
476 makeRelativeRefTo _ lit = lit