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"
49 -------------------------------------------------------------------------
51 -- Generating the info table and code for a closure
53 -------------------------------------------------------------------------
55 -- Here we make a concrete info table, represented as a list of CmmAddr
56 -- (it can't be simply a list of Word, because the SRT field is
57 -- represented by a label+offset expression).
59 -- With tablesNextToCode, the layout is
60 -- <reversed variable part>
61 -- <normal forward StgInfoTable, but without
62 -- an entry point at the front>
65 -- Without tablesNextToCode, the layout of an info table is
67 -- <normal forward rest of StgInfoTable>
68 -- <forward variable part>
70 -- See includes/InfoTables.h
72 emitClosureCodeAndInfoTable :: ClosureInfo -> CmmFormals -> CgStmts -> Code
73 emitClosureCodeAndInfoTable cl_info args body
74 = do { ty_descr_lit <-
76 then do lit <- mkStringCLit (closureTypeDescr cl_info)
77 return (makeRelativeRefTo info_lbl lit)
78 else return (mkIntCLit 0)
81 then do lit <- mkStringCLit cl_descr_string
82 return (makeRelativeRefTo info_lbl lit)
83 else return (mkIntCLit 0)
84 ; let std_info = mkStdInfoTable ty_descr_lit cl_descr_lit
85 cl_type srt_len layout_lit
87 ; blks <- cgStmtsToBlocks body
91 then do cstr <- mkByteStringCLit $ fromJust conIdentity
92 return (makeRelativeRefTo info_lbl cstr)
93 else return (mkIntCLit 0)
95 ; emitInfoTableAndCode info_lbl std_info (extra_bits conName) args blks }
97 info_lbl = infoTableLabelFromCI cl_info
99 cl_descr_string = closureValDescr cl_info
100 cl_type = smRepClosureTypeInt (closureSMRep cl_info)
102 srt = closureSRT cl_info
103 needs_srt = needsSRT srt
105 mb_con = isConstrClosure_maybe cl_info
106 is_con = isJust mb_con
108 (srt_label,srt_len,conIdentity)
110 Just con -> -- Constructors don't have an SRT
111 -- We keep the *zero-indexed* tag in the srt_len
112 -- field of the info table.
113 (mkIntCLit 0, fromIntegral (dataConTagZ con),
114 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)
190 emitReturnTarget name stmts
191 = do { live_slots <- getLiveStackSlots
192 ; liveness <- buildContLiveness name live_slots
193 ; srt_info <- getSRTInfo
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 -> Int -- family size
233 -> FCode (CLabel, SemiTaggingStuff)
235 emitAlgReturnTarget name branches mb_deflt fam_sz
236 = do { blks <- getCgStmts $
237 emitSwitch tag_expr branches mb_deflt 0 (fam_sz - 1)
238 -- NB: tag_expr is zero-based
239 ; lbl <- emitReturnTarget name blks
240 ; return (lbl, Nothing) }
241 -- Nothing: the internal branches in the switch don't have
242 -- global labels, so we can't use them at the 'call site'
244 tag_expr = getConstrTag (CmmReg nodeReg)
246 --------------------------------
247 emitReturnInstr :: Code
249 = do { info_amode <- getSequelAmode
250 ; stmtC (CmmJump (entryCode info_amode) []) }
252 -------------------------------------------------------------------------
254 -- Generating a standard info table
256 -------------------------------------------------------------------------
258 -- The standard bits of an info table. This part of the info table
259 -- corresponds to the StgInfoTable type defined in InfoTables.h.
261 -- Its shape varies with ticky/profiling/tables next to code etc
262 -- so we can't use constant offsets from Constants
265 :: CmmLit -- closure type descr (profiling)
266 -> CmmLit -- closure descr (profiling)
267 -> Int -- closure type
268 -> StgHalfWord -- SRT length
269 -> CmmLit -- layout field
272 mkStdInfoTable type_descr closure_descr cl_type srt_len layout_lit
273 = -- Parallel revertible-black hole field
275 -- Ticky info (none at present)
276 -- Debug info (none at present)
277 ++ [layout_lit, type_lit]
281 | opt_SccProfilingOn = [type_descr, closure_descr]
284 type_lit = packHalfWordsCLit cl_type srt_len
286 stdInfoTableSizeW :: WordOff
287 -- The size of a standard info table varies with profiling/ticky etc,
288 -- so we can't get it from Constants
289 -- It must vary in sync with mkStdInfoTable
291 = size_fixed + size_prof
293 size_fixed = 2 -- layout, type
294 size_prof | opt_SccProfilingOn = 2
297 stdInfoTableSizeB = stdInfoTableSizeW * wORD_SIZE :: ByteOff
299 stdSrtBitmapOffset :: ByteOff
300 -- Byte offset of the SRT bitmap half-word which is
301 -- in the *higher-addressed* part of the type_lit
302 stdSrtBitmapOffset = stdInfoTableSizeB - hALF_WORD_SIZE
304 stdClosureTypeOffset :: ByteOff
305 -- Byte offset of the closure type half-word
306 stdClosureTypeOffset = stdInfoTableSizeB - wORD_SIZE
308 stdPtrsOffset, stdNonPtrsOffset :: ByteOff
309 stdPtrsOffset = stdInfoTableSizeB - 2*wORD_SIZE
310 stdNonPtrsOffset = stdInfoTableSizeB - 2*wORD_SIZE + hALF_WORD_SIZE
312 -------------------------------------------------------------------------
314 -- Accessing fields of an info table
316 -------------------------------------------------------------------------
318 closureInfoPtr :: CmmExpr -> CmmExpr
319 -- Takes a closure pointer and returns the info table pointer
320 closureInfoPtr e = CmmLoad e wordRep
322 entryCode :: CmmExpr -> CmmExpr
323 -- Takes an info pointer (the first word of a closure)
324 -- and returns its entry code
325 entryCode e | tablesNextToCode = e
326 | otherwise = CmmLoad e wordRep
328 getConstrTag :: CmmExpr -> CmmExpr
329 -- Takes a closure pointer, and return the *zero-indexed*
330 -- constructor tag obtained from the info table
331 -- This lives in the SRT field of the info table
332 -- (constructors don't need SRTs).
333 getConstrTag closure_ptr
334 = CmmMachOp (MO_U_Conv halfWordRep wordRep) [infoTableConstrTag info_table]
336 info_table = infoTable (closureInfoPtr closure_ptr)
338 infoTable :: CmmExpr -> CmmExpr
339 -- Takes an info pointer (the first word of a closure)
340 -- and returns a pointer to the first word of the standard-form
341 -- info table, excluding the entry-code word (if present)
343 | tablesNextToCode = cmmOffsetB info_ptr (- stdInfoTableSizeB)
344 | otherwise = cmmOffsetW info_ptr 1 -- Past the entry code pointer
346 infoTableConstrTag :: CmmExpr -> CmmExpr
347 -- Takes an info table pointer (from infoTable) and returns the constr tag
348 -- field of the info table (same as the srt_bitmap field)
349 infoTableConstrTag = infoTableSrtBitmap
351 infoTableSrtBitmap :: CmmExpr -> CmmExpr
352 -- Takes an info table pointer (from infoTable) and returns the srt_bitmap
353 -- field of the info table
354 infoTableSrtBitmap info_tbl
355 = CmmLoad (cmmOffsetB info_tbl stdSrtBitmapOffset) halfWordRep
357 infoTableClosureType :: CmmExpr -> CmmExpr
358 -- Takes an info table pointer (from infoTable) and returns the closure type
359 -- field of the info table.
360 infoTableClosureType info_tbl
361 = CmmLoad (cmmOffsetB info_tbl stdClosureTypeOffset) halfWordRep
363 infoTablePtrs :: CmmExpr -> CmmExpr
364 infoTablePtrs info_tbl
365 = CmmLoad (cmmOffsetB info_tbl stdPtrsOffset) halfWordRep
367 infoTableNonPtrs :: CmmExpr -> CmmExpr
368 infoTableNonPtrs info_tbl
369 = CmmLoad (cmmOffsetB info_tbl stdNonPtrsOffset) halfWordRep
371 funInfoTable :: CmmExpr -> CmmExpr
372 -- Takes the info pointer of a function,
373 -- and returns a pointer to the first word of the StgFunInfoExtra struct
374 -- in the info table.
375 funInfoTable info_ptr
377 = cmmOffsetB info_ptr (- stdInfoTableSizeB - sIZEOF_StgFunInfoExtraRev)
379 = cmmOffsetW info_ptr (1 + stdInfoTableSizeW)
380 -- Past the entry code pointer
382 -------------------------------------------------------------------------
384 -- Emit the code for a closure (or return address)
385 -- and its associated info table
387 -------------------------------------------------------------------------
389 -- The complication here concerns whether or not we can
390 -- put the info table next to the code
393 :: CLabel -- Label of info table
394 -> [CmmLit] -- ...its invariant part
395 -> [CmmLit] -- ...and its variant part
396 -> CmmFormals -- ...args
397 -> [CmmBasicBlock] -- ...and body
400 emitInfoTableAndCode info_lbl std_info extra_bits args blocks
401 | tablesNextToCode -- Reverse the extra_bits; and emit the top-level proc
402 = emitProc (reverse extra_bits ++ std_info)
403 entry_lbl args blocks
404 -- NB: the info_lbl is discarded
406 | null blocks -- No actual code; only the info table is significant
407 = -- Use a zero place-holder in place of the
408 -- entry-label in the info table
409 emitRODataLits info_lbl (zeroCLit : std_info ++ extra_bits)
411 | otherwise -- Separately emit info table (with the function entry
412 = -- point as first entry) and the entry code
413 do { emitDataLits info_lbl (CmmLabel entry_lbl : std_info ++ extra_bits)
414 ; emitProc [] entry_lbl args blocks }
417 entry_lbl = infoLblToEntryLbl info_lbl
419 -------------------------------------------------------------------------
421 -- Static reference tables
423 -------------------------------------------------------------------------
425 srtLabelAndLength :: C_SRT -> CLabel -> (CmmLit, StgHalfWord)
426 srtLabelAndLength NoC_SRT _
428 srtLabelAndLength (C_SRT lbl off bitmap) info_lbl
429 = (makeRelativeRefTo info_lbl $ cmmLabelOffW lbl off, bitmap)
431 -------------------------------------------------------------------------
433 -- Position independent code
435 -------------------------------------------------------------------------
436 -- In order to support position independent code, we mustn't put absolute
437 -- references into read-only space. Info tables in the tablesNextToCode
438 -- case must be in .text, which is read-only, so we doctor the CmmLits
439 -- to use relative offsets instead.
441 -- Note that this is done even when the -fPIC flag is not specified,
442 -- as we want to keep binary compatibility between PIC and non-PIC.
444 makeRelativeRefTo :: CLabel -> CmmLit -> CmmLit
446 makeRelativeRefTo info_lbl (CmmLabel lbl)
448 = CmmLabelDiffOff lbl info_lbl 0
449 makeRelativeRefTo info_lbl (CmmLabelOff lbl off)
451 = CmmLabelDiffOff lbl info_lbl off
452 makeRelativeRefTo _ lit = lit