1 -----------------------------------------------------------------------------
3 -- Building info tables.
5 -- (c) The University of Glasgow 2004-2006
7 -----------------------------------------------------------------------------
10 emitClosureCodeAndInfoTable,
14 emitDirectReturnTarget, emitAlgReturnTarget,
15 emitDirectReturnInstr, emitVectoredReturnInstr,
19 mkFunGenInfoExtraBits,
20 entryCode, closureInfoPtr,
22 infoTable, infoTableClosureType,
23 infoTablePtrs, infoTableNonPtrs,
29 #include "HsVersions.h"
55 -------------------------------------------------------------------------
57 -- Generating the info table and code for a closure
59 -------------------------------------------------------------------------
61 -- Here we make a concrete info table, represented as a list of CmmAddr
62 -- (it can't be simply a list of Word, because the SRT field is
63 -- represented by a label+offset expression).
65 -- With tablesNextToCode, the layout is
66 -- <reversed variable part>
67 -- <normal forward StgInfoTable, but without
68 -- an entry point at the front>
71 -- Without tablesNextToCode, the layout of an info table is
73 -- <normal forward rest of StgInfoTable>
74 -- <forward variable part>
76 -- See includes/InfoTables.h
78 emitClosureCodeAndInfoTable :: ClosureInfo -> [LocalReg] -> CgStmts -> Code
79 emitClosureCodeAndInfoTable cl_info args body
80 = do { ty_descr_lit <-
82 then mkStringCLit (closureTypeDescr cl_info)
83 else return (mkIntCLit 0)
86 then mkStringCLit cl_descr_string
87 else return (mkIntCLit 0)
88 ; let std_info = mkStdInfoTable ty_descr_lit cl_descr_lit
89 cl_type srt_len layout_lit
91 ; blks <- cgStmtsToBlocks body
95 then mkStringCLit $ fromJust conIdentity
96 else return (mkIntCLit 0)
98 ; emitInfoTableAndCode info_lbl std_info (extra_bits conName) args blks }
100 info_lbl = infoTableLabelFromCI cl_info
102 cl_descr_string = closureValDescr cl_info
103 cl_type = smRepClosureTypeInt (closureSMRep cl_info)
105 srt = closureSRT cl_info
106 needs_srt = needsSRT srt
108 mb_con = isConstrClosure_maybe cl_info
109 is_con = isJust mb_con
111 (srt_label,srt_len,conIdentity)
113 Just con -> -- Constructors don't have an SRT
114 -- We keep the *zero-indexed* tag in the srt_len
115 -- field of the info table.
116 (mkIntCLit 0, fromIntegral (dataConTagZ con), Just $ dataConIdentity con)
118 Nothing -> -- Not a constructor
119 let (label, len) = srtLabelAndLength srt info_lbl
120 in (label, len, Nothing)
122 ptrs = closurePtrsSize cl_info
124 size = closureNonHdrSize cl_info
125 layout_lit = packHalfWordsCLit ptrs nptrs
128 | is_fun = fun_extra_bits
130 | needs_srt = [srt_label]
133 maybe_fun_stuff = closureFunInfo cl_info
134 is_fun = isJust maybe_fun_stuff
135 (Just (arity, arg_descr)) = maybe_fun_stuff
138 | ArgGen liveness <- arg_descr
141 makeRelativeRefTo info_lbl $ mkLivenessCLit liveness,
143 | needs_srt = [fun_amode, srt_label]
144 | otherwise = [fun_amode]
146 slow_entry = makeRelativeRefTo info_lbl (CmmLabel slow_entry_label)
147 slow_entry_label = mkSlowEntryLabel (closureName cl_info)
149 fun_amode = packHalfWordsCLit fun_type arity
150 fun_type = argDescrType arg_descr
152 -- We keep the *zero-indexed* tag in the srt_len field of the info
153 -- table of a data constructor.
154 dataConTagZ :: DataCon -> ConTagZ
155 dataConTagZ con = dataConTag con - fIRST_TAG
157 -- A low-level way to generate the variable part of a fun-style info table.
158 -- (must match fun_extra_bits above). Used by the C-- parser.
159 mkFunGenInfoExtraBits :: Int -> Int -> CmmLit -> CmmLit -> CmmLit -> [CmmLit]
160 mkFunGenInfoExtraBits fun_type arity srt_label liveness slow_entry
161 = [ packHalfWordsCLit fun_type arity,
166 -------------------------------------------------------------------------
168 -- Generating the info table and code for a return point
170 -------------------------------------------------------------------------
172 -- Here's the layout of a return-point info table
174 -- Tables next to code:
176 -- <reversed vector table>
178 -- <standard info table>
179 -- ret-addr --> <entry code (if any)>
181 -- Not tables-next-to-code:
183 -- ret-addr --> <ptr to entry code>
184 -- <standard info table>
186 -- <forward vector table>
188 -- * The vector table is only present for vectored returns
190 -- * The SRT slot is only there if either
191 -- (a) there is SRT info to record, OR
192 -- (b) if the return is vectored
193 -- The latter (b) is necessary so that the vector is in a
196 vectorSlot :: CmmExpr -> CmmExpr -> CmmExpr
197 -- Get the vector slot from the info pointer
198 vectorSlot info_amode zero_indexed_tag
200 = cmmOffsetExprW (cmmOffsetW info_amode (- (stdInfoTableSizeW + 2)))
201 (cmmNegate zero_indexed_tag)
202 -- The "2" is one for the SRT slot, and one more
203 -- to get to the first word of the vector
206 = cmmOffsetExprW (cmmOffsetW info_amode (stdInfoTableSizeW + 2))
208 -- The "2" is one for the entry-code slot and one for the SRT slot
210 retVec :: CmmExpr -> CmmExpr -> CmmExpr
211 -- Get a return vector from the info pointer
212 retVec info_amode zero_indexed_tag
213 = let slot = vectorSlot info_amode zero_indexed_tag
214 table_slot = CmmLoad slot wordRep
215 #if defined(x86_64_TARGET_ARCH)
216 offset_slot = CmmMachOp (MO_S_Conv I32 I64) [CmmLoad slot I32]
217 -- offsets are 32-bits on x86-64, due to the inability of
218 -- the tools to handle 64-bit PC-relative relocations. See also
219 -- PprMach.pprDataItem, and InfoTables.h:OFFSET_FIELD().
221 offset_slot = table_slot
223 in if tablesNextToCode
224 then CmmMachOp (MO_Add wordRep) [offset_slot, info_amode]
229 -> CgStmts -- The direct-return code (if any)
230 -- (empty for vectored returns)
231 -> [CmmLit] -- Vector of return points
232 -- (empty for non-vectored returns)
235 emitReturnTarget name stmts vector srt
236 = do { live_slots <- getLiveStackSlots
237 ; liveness <- buildContLiveness name live_slots
238 ; srt_info <- getSRTInfo name srt
241 cl_type = case (null vector, isBigLiveness liveness) of
242 (True, True) -> rET_BIG
243 (True, False) -> rET_SMALL
244 (False, True) -> rET_VEC_BIG
245 (False, False) -> rET_VEC_SMALL
247 (std_info, extra_bits) =
248 mkRetInfoTable info_lbl liveness srt_info cl_type vector
250 ; blks <- cgStmtsToBlocks stmts
251 ; emitInfoTableAndCode info_lbl std_info extra_bits args blks
254 args = {- trace "emitReturnTarget: missing args" -} []
255 uniq = getUnique name
256 info_lbl = mkReturnInfoLabel uniq
260 :: CLabel -- info label
261 -> Liveness -- liveness
263 -> Int -- type (eg. rET_SMALL)
264 -> [CmmLit] -- vector
265 -> ([CmmLit],[CmmLit])
266 mkRetInfoTable info_lbl liveness srt_info cl_type vector
267 = (std_info, extra_bits)
269 (srt_label, srt_len) = srtLabelAndLength srt_info info_lbl
271 srt_slot | need_srt = [srt_label]
274 need_srt = needsSRT srt_info || not (null vector)
275 -- If there's a vector table then we must allocate
276 -- an SRT slot, so that the vector table is at a
277 -- known offset from the info pointer
279 liveness_lit = makeRelativeRefTo info_lbl $ mkLivenessCLit liveness
280 std_info = mkStdInfoTable zeroCLit zeroCLit cl_type srt_len liveness_lit
281 extra_bits = srt_slot ++ map (makeRelativeRefTo info_lbl) vector
284 emitDirectReturnTarget
286 -> CgStmts -- The direct-return code
289 emitDirectReturnTarget name code srt
290 = emitReturnTarget name code [] srt
293 :: Name -- Just for its unique
294 -> [(ConTagZ, CgStmts)] -- Tagged branches
295 -> Maybe CgStmts -- Default branch (if any)
296 -> SRT -- Continuation's SRT
297 -> CtrlReturnConvention
298 -> FCode (CLabel, SemiTaggingStuff)
300 emitAlgReturnTarget name branches mb_deflt srt ret_conv
302 UnvectoredReturn fam_sz -> do
303 { blks <- getCgStmts $
304 emitSwitch tag_expr branches mb_deflt 0 (fam_sz - 1)
305 -- NB: tag_expr is zero-based
306 ; lbl <- emitDirectReturnTarget name blks srt
307 ; return (lbl, Nothing) }
308 -- Nothing: the internal branches in the switch don't have
309 -- global labels, so we can't use them at the 'call site'
311 VectoredReturn fam_sz -> do
312 { let tagged_lbls = zip (map fst branches) $
313 map (CmmLabel . mkAltLabel uniq . fst) branches
314 deflt_lbl | isJust mb_deflt = CmmLabel $ mkDefaultLabel uniq
315 | otherwise = mkIntCLit 0
316 ; let vector = [ assocDefault deflt_lbl tagged_lbls i
317 | i <- [0..fam_sz-1]]
318 ; lbl <- emitReturnTarget name noCgStmts vector srt
319 ; mapFCs emit_alt branches
320 ; emit_deflt mb_deflt
321 ; return (lbl, Just (tagged_lbls, deflt_lbl)) }
323 uniq = getUnique name
324 tag_expr = getConstrTag (CmmReg nodeReg)
326 emit_alt :: (Int, CgStmts) -> FCode (Int, CmmLit)
327 -- Emit the code for the alternative as a top-level
328 -- code block returning a label for it
329 emit_alt (tag, stmts) = do { let lbl = mkAltLabel uniq tag
330 ; blks <- cgStmtsToBlocks stmts
331 ; emitProc [] lbl [] blks
332 ; return (tag, CmmLabel lbl) }
334 emit_deflt (Just stmts) = do { let lbl = mkDefaultLabel uniq
335 ; blks <- cgStmtsToBlocks stmts
336 ; emitProc [] lbl [] blks
337 ; return (CmmLabel lbl) }
338 emit_deflt Nothing = return (mkIntCLit 0)
339 -- Nothing case: the simplifier might have eliminated a case
340 -- so we may have e.g. case xs of
342 -- In that situation the default should never be taken,
343 -- so we just use a NULL pointer
345 --------------------------------
346 emitDirectReturnInstr :: Code
347 emitDirectReturnInstr
348 = do { info_amode <- getSequelAmode
349 ; stmtC (CmmJump (entryCode info_amode) []) }
351 emitVectoredReturnInstr :: CmmExpr -- _Zero-indexed_ constructor tag
353 emitVectoredReturnInstr zero_indexed_tag
354 = do { info_amode <- getSequelAmode
355 -- HACK! assign info_amode to a temp, because retVec
356 -- uses it twice and the NCG doesn't have any CSE yet.
357 -- Only do this for the NCG, because gcc is too stupid
358 -- to optimise away the extra tmp (grrr).
359 ; dflags <- getDynFlags
360 ; x <- if hscTarget dflags == HscAsm
361 then do z <- newTemp wordRep
362 stmtC (CmmAssign z info_amode)
366 ; let target = retVec x zero_indexed_tag
367 ; stmtC (CmmJump target []) }
370 -------------------------------------------------------------------------
372 -- Generating a standard info table
374 -------------------------------------------------------------------------
376 -- The standard bits of an info table. This part of the info table
377 -- corresponds to the StgInfoTable type defined in InfoTables.h.
379 -- Its shape varies with ticky/profiling/tables next to code etc
380 -- so we can't use constant offsets from Constants
383 :: CmmLit -- closure type descr (profiling)
384 -> CmmLit -- closure descr (profiling)
385 -> Int -- closure type
386 -> StgHalfWord -- SRT length
387 -> CmmLit -- layout field
390 mkStdInfoTable type_descr closure_descr cl_type srt_len layout_lit
391 = -- Parallel revertible-black hole field
393 -- Ticky info (none at present)
394 -- Debug info (none at present)
395 ++ [layout_lit, type_lit]
399 | opt_SccProfilingOn = [type_descr, closure_descr]
402 type_lit = packHalfWordsCLit cl_type srt_len
404 stdInfoTableSizeW :: WordOff
405 -- The size of a standard info table varies with profiling/ticky etc,
406 -- so we can't get it from Constants
407 -- It must vary in sync with mkStdInfoTable
409 = size_fixed + size_prof
411 size_fixed = 2 -- layout, type
412 size_prof | opt_SccProfilingOn = 2
415 stdInfoTableSizeB = stdInfoTableSizeW * wORD_SIZE :: ByteOff
417 stdSrtBitmapOffset :: ByteOff
418 -- Byte offset of the SRT bitmap half-word which is
419 -- in the *higher-addressed* part of the type_lit
420 stdSrtBitmapOffset = stdInfoTableSizeB - hALF_WORD_SIZE
422 stdClosureTypeOffset :: ByteOff
423 -- Byte offset of the closure type half-word
424 stdClosureTypeOffset = stdInfoTableSizeB - wORD_SIZE
426 stdPtrsOffset, stdNonPtrsOffset :: ByteOff
427 stdPtrsOffset = stdInfoTableSizeB - 2*wORD_SIZE
428 stdNonPtrsOffset = stdInfoTableSizeB - 2*wORD_SIZE + hALF_WORD_SIZE
430 -------------------------------------------------------------------------
432 -- Accessing fields of an info table
434 -------------------------------------------------------------------------
436 closureInfoPtr :: CmmExpr -> CmmExpr
437 -- Takes a closure pointer and returns the info table pointer
438 closureInfoPtr e = CmmLoad e wordRep
440 entryCode :: CmmExpr -> CmmExpr
441 -- Takes an info pointer (the first word of a closure)
442 -- and returns its entry code
443 entryCode e | tablesNextToCode = e
444 | otherwise = CmmLoad e wordRep
446 getConstrTag :: CmmExpr -> CmmExpr
447 -- Takes a closure pointer, and return the *zero-indexed*
448 -- constructor tag obtained from the info table
449 -- This lives in the SRT field of the info table
450 -- (constructors don't need SRTs).
451 getConstrTag closure_ptr
452 = CmmMachOp (MO_U_Conv halfWordRep wordRep) [infoTableConstrTag info_table]
454 info_table = infoTable (closureInfoPtr closure_ptr)
456 infoTable :: CmmExpr -> CmmExpr
457 -- Takes an info pointer (the first word of a closure)
458 -- and returns a pointer to the first word of the standard-form
459 -- info table, excluding the entry-code word (if present)
461 | tablesNextToCode = cmmOffsetB info_ptr (- stdInfoTableSizeB)
462 | otherwise = cmmOffsetW info_ptr 1 -- Past the entry code pointer
464 infoTableConstrTag :: CmmExpr -> CmmExpr
465 -- Takes an info table pointer (from infoTable) and returns the constr tag
466 -- field of the info table (same as the srt_bitmap field)
467 infoTableConstrTag = infoTableSrtBitmap
469 infoTableSrtBitmap :: CmmExpr -> CmmExpr
470 -- Takes an info table pointer (from infoTable) and returns the srt_bitmap
471 -- field of the info table
472 infoTableSrtBitmap info_tbl
473 = CmmLoad (cmmOffsetB info_tbl stdSrtBitmapOffset) halfWordRep
475 infoTableClosureType :: CmmExpr -> CmmExpr
476 -- Takes an info table pointer (from infoTable) and returns the closure type
477 -- field of the info table.
478 infoTableClosureType info_tbl
479 = CmmLoad (cmmOffsetB info_tbl stdClosureTypeOffset) halfWordRep
481 infoTablePtrs :: CmmExpr -> CmmExpr
482 infoTablePtrs info_tbl
483 = CmmLoad (cmmOffsetB info_tbl stdPtrsOffset) halfWordRep
485 infoTableNonPtrs :: CmmExpr -> CmmExpr
486 infoTableNonPtrs info_tbl
487 = CmmLoad (cmmOffsetB info_tbl stdNonPtrsOffset) halfWordRep
489 funInfoTable :: CmmExpr -> CmmExpr
490 -- Takes the info pointer of a function,
491 -- and returns a pointer to the first word of the StgFunInfoExtra struct
492 -- in the info table.
493 funInfoTable info_ptr
495 = cmmOffsetB info_ptr (- stdInfoTableSizeB - sIZEOF_StgFunInfoExtraRev)
497 = cmmOffsetW info_ptr (1 + stdInfoTableSizeW)
498 -- Past the entry code pointer
500 -------------------------------------------------------------------------
502 -- Emit the code for a closure (or return address)
503 -- and its associated info table
505 -------------------------------------------------------------------------
507 -- The complication here concerns whether or not we can
508 -- put the info table next to the code
511 :: CLabel -- Label of info table
512 -> [CmmLit] -- ...its invariant part
513 -> [CmmLit] -- ...and its variant part
514 -> [LocalReg] -- ...args
515 -> [CmmBasicBlock] -- ...and body
518 emitInfoTableAndCode info_lbl std_info extra_bits args blocks
519 | tablesNextToCode -- Reverse the extra_bits; and emit the top-level proc
520 = emitProc (reverse extra_bits ++ std_info)
521 entry_lbl args blocks
522 -- NB: the info_lbl is discarded
524 | null blocks -- No actual code; only the info table is significant
525 = -- Use a zero place-holder in place of the
526 -- entry-label in the info table
527 emitRODataLits info_lbl (zeroCLit : std_info ++ extra_bits)
529 | otherwise -- Separately emit info table (with the function entry
530 = -- point as first entry) and the entry code
531 do { emitDataLits info_lbl (CmmLabel entry_lbl : std_info ++ extra_bits)
532 ; emitProc [] entry_lbl args blocks }
535 entry_lbl = infoLblToEntryLbl info_lbl
537 -------------------------------------------------------------------------
539 -- Static reference tables
541 -------------------------------------------------------------------------
543 -- There is just one SRT for each top level binding; all the nested
544 -- bindings use sub-sections of this SRT. The label is passed down to
545 -- the nested bindings via the monad.
547 getSRTInfo :: Name -> SRT -> FCode C_SRT
548 getSRTInfo id NoSRT = return NoC_SRT
549 getSRTInfo id (SRT off len bmp)
550 | len > hALF_WORD_SIZE_IN_BITS || bmp == [fromIntegral srt_escape]
551 = do { srt_lbl <- getSRTLabel
552 ; let srt_desc_lbl = mkSRTDescLabel id
553 ; emitRODataLits srt_desc_lbl
554 ( cmmLabelOffW srt_lbl off
555 : mkWordCLit (fromIntegral len)
556 : map mkWordCLit bmp)
557 ; return (C_SRT srt_desc_lbl 0 srt_escape) }
560 = do { srt_lbl <- getSRTLabel
561 ; return (C_SRT srt_lbl off (fromIntegral (head bmp))) }
562 -- The fromIntegral converts to StgHalfWord
564 srt_escape = (-1) :: StgHalfWord
566 srtLabelAndLength :: C_SRT -> CLabel -> (CmmLit, StgHalfWord)
567 srtLabelAndLength NoC_SRT _
569 srtLabelAndLength (C_SRT lbl off bitmap) info_lbl
570 = (makeRelativeRefTo info_lbl $ cmmLabelOffW lbl off, bitmap)
572 -------------------------------------------------------------------------
574 -- Position independent code
576 -------------------------------------------------------------------------
577 -- In order to support position independent code, we mustn't put absolute
578 -- references into read-only space. Info tables in the tablesNextToCode
579 -- case must be in .text, which is read-only, so we doctor the CmmLits
580 -- to use relative offsets instead.
582 -- Note that this is done even when the -fPIC flag is not specified,
583 -- as we want to keep binary compatibility between PIC and non-PIC.
585 makeRelativeRefTo :: CLabel -> CmmLit -> CmmLit
587 makeRelativeRefTo info_lbl (CmmLabel lbl)
589 = CmmLabelDiffOff lbl info_lbl 0
590 makeRelativeRefTo info_lbl (CmmLabelOff lbl off)
592 = CmmLabelDiffOff lbl info_lbl off
593 makeRelativeRefTo _ lit = lit