1 -----------------------------------------------------------------------------
3 -- Building info tables.
5 -- (c) The University of Glasgow 2004-2006
7 -----------------------------------------------------------------------------
10 -- The above warning supression flag is a temporary kludge.
11 -- While working on this module you are encouraged to remove it and fix
12 -- any warnings in the module. See
13 -- http://hackage.haskell.org/trac/ghc/wiki/Commentary/CodingStyle#Warnings
20 emitClosureCodeAndInfoTable,
24 mkVirtHeapOffsets, getHpRelOffset, hpRel,
27 entryCode, closureInfoPtr,
30 infoTable, infoTableClosureType,
31 infoTablePtrs, infoTableNonPtrs,
32 funInfoTable, makeRelativeRefTo
36 #include "HsVersions.h"
52 import TyCon ( PrimRep(..) )
54 import BasicTypes ( Arity )
65 import FastString ( LitString, sLit )
67 ------------------------------------------------------------------------
68 -- Call and return sequences
69 ------------------------------------------------------------------------
71 emitReturn :: [CmmExpr] -> FCode ()
72 -- Return multiple values to the sequel
74 -- If the sequel is Return
76 -- If the sequel is AssignTo [p,q]
79 = do { adjustHpBackwards
80 ; sequel <- getSequel;
82 Return _ -> emit (mkReturn results)
83 AssignTo regs _ -> emit (mkMultiAssign regs results)
86 emitCall :: CmmExpr -> [CmmExpr] -> FCode ()
87 -- (cgCall fun args) makes a call to the entry-code of 'fun',
88 -- passing 'args', and returning the results to the current sequel
90 = do { adjustHpBackwards
91 ; sequel <- getSequel;
93 Return _ -> emit (mkJump fun args)
94 AssignTo res_regs srt -> emit (mkCmmCall fun res_regs args srt)
97 adjustHpBackwards :: FCode ()
98 -- This function adjusts and heap pointers just before a tail call or
99 -- return. At a call or return, the virtual heap pointer may be less
100 -- than the real Hp, because the latter was advanced to deal with
101 -- the worst-case branch of the code, and we may be in a better-case
102 -- branch. In that case, move the real Hp *back* and retract some
103 -- ticky allocation count.
105 -- It *does not* deal with high-water-mark adjustment.
106 -- That's done by functions which allocate heap.
108 = do { hp_usg <- getHpUsage
109 ; let rHp = realHp hp_usg
111 adjust_words = vHp -rHp
112 ; new_hp <- getHpRelOffset vHp
114 ; emit (if adjust_words == 0
116 else mkAssign hpReg new_hp) -- Generates nothing when vHp==rHp
118 ; tickyAllocHeap adjust_words -- ...ditto
124 -------------------------------------------------------------------------
125 -- Making calls: directCall and slowCall
126 -------------------------------------------------------------------------
128 directCall :: CLabel -> Arity -> [StgArg] -> FCode ()
129 -- (directCall f n args)
130 -- calls f(arg1, ..., argn), and applies the result to the remaining args
131 -- The function f has arity n, and there are guaranteed at least n args
132 -- Both arity and args include void args
133 directCall lbl arity stg_args
134 = do { cmm_args <- getNonVoidArgAmodes stg_args
135 ; direct_call lbl arity cmm_args (argsLReps stg_args) }
137 slowCall :: CmmExpr -> [StgArg] -> FCode ()
138 -- (slowCall fun args) applies fun to args, returning the results to Sequel
139 slowCall fun stg_args
140 = do { cmm_args <- getNonVoidArgAmodes stg_args
141 ; slow_call fun cmm_args (argsLReps stg_args) }
144 direct_call :: CLabel -> Arity -> [CmmExpr] -> [LRep] -> FCode ()
145 -- NB1: (length args) maybe less than (length reps), because
146 -- the args exclude the void ones
147 -- NB2: 'arity' refers to the *reps*
148 direct_call lbl arity args reps
150 = ASSERT( arity == length args)
154 = ASSERT( arity == length initial_reps )
155 do { pap_id <- newTemp gcWord
156 ; let srt = pprTrace "Urk! SRT for over-sat call"
158 -- XXX: what if rest_args contains static refs?
159 ; withSequel (AssignTo [pap_id] srt)
160 (emitCall target args)
161 ; slow_call (CmmReg (CmmLocal pap_id))
162 rest_args rest_reps }
164 target = CmmLit (CmmLabel lbl)
165 (initial_reps, rest_reps) = splitAt arity reps
166 arg_arity = count isNonV initial_reps
167 (_, rest_args) = splitAt arg_arity args
170 slow_call :: CmmExpr -> [CmmExpr] -> [LRep] -> FCode ()
171 slow_call fun args reps
172 = direct_call (mkRtsApFastLabel rts_fun) (arity+1)
173 (fun : args) (P : reps)
175 (rts_fun, arity) = slowCallPattern reps
177 -- These cases were found to cover about 99% of all slow calls:
178 slowCallPattern :: [LRep] -> (LitString, Arity)
179 -- Returns the generic apply function and arity
180 slowCallPattern (P: P: P: P: P: P: _) = (sLit "stg_ap_pppppp", 6)
181 slowCallPattern (P: P: P: P: P: _) = (sLit "stg_ap_ppppp", 5)
182 slowCallPattern (P: P: P: P: _) = (sLit "stg_ap_pppp", 4)
183 slowCallPattern (P: P: P: V: _) = (sLit "stg_ap_pppv", 4)
184 slowCallPattern (P: P: P: _) = (sLit "stg_ap_ppp", 3)
185 slowCallPattern (P: P: V: _) = (sLit "stg_ap_ppv", 3)
186 slowCallPattern (P: P: _) = (sLit "stg_ap_pp", 2)
187 slowCallPattern (P: V: _) = (sLit "stg_ap_pv", 2)
188 slowCallPattern (P: _) = (sLit "stg_ap_p", 1)
189 slowCallPattern (V: _) = (sLit "stg_ap_v", 1)
190 slowCallPattern (N: _) = (sLit "stg_ap_n", 1)
191 slowCallPattern (F: _) = (sLit "stg_ap_f", 1)
192 slowCallPattern (D: _) = (sLit "stg_ap_d", 1)
193 slowCallPattern (L: _) = (sLit "stg_ap_l", 1)
194 slowCallPattern [] = (sLit "stg_ap_0", 0)
197 -------------------------------------------------------------------------
198 -- Classifying arguments: LRep
199 -------------------------------------------------------------------------
201 -- LRep is not exported (even abstractly)
202 -- It's a local helper type for classification
204 data LRep = P -- GC Ptr
205 | N -- One-word non-ptr
206 | L -- Two-word non-ptr (long)
211 toLRep :: PrimRep -> LRep
222 isNonV :: LRep -> Bool
226 argsLReps :: [StgArg] -> [LRep]
227 argsLReps = map (toLRep . argPrimRep)
229 lRepSizeW :: LRep -> WordOff -- Size in words
233 lRepSizeW L = wORD64_SIZE `quot` wORD_SIZE
234 lRepSizeW D = dOUBLE_SIZE `quot` wORD_SIZE
237 -------------------------------------------------------------------------
238 ---- Laying out objects on the heap and stack
239 -------------------------------------------------------------------------
241 -- The heap always grows upwards, so hpRel is easy
242 hpRel :: VirtualHpOffset -- virtual offset of Hp
243 -> VirtualHpOffset -- virtual offset of The Thing
244 -> WordOff -- integer word offset
245 hpRel hp off = off - hp
247 getHpRelOffset :: VirtualHpOffset -> FCode CmmExpr
248 getHpRelOffset virtual_offset
249 = do { hp_usg <- getHpUsage
250 ; return (cmmRegOffW hpReg (hpRel (realHp hp_usg) virtual_offset)) }
253 :: Bool -- True <=> is a thunk
254 -> [(PrimRep,a)] -- Things to make offsets for
255 -> (WordOff, -- _Total_ number of words allocated
256 WordOff, -- Number of words allocated for *pointers*
257 [(a, VirtualHpOffset)])
259 -- Things with their offsets from start of object in order of
260 -- increasing offset; BUT THIS MAY BE DIFFERENT TO INPUT ORDER
261 -- First in list gets lowest offset, which is initial offset + 1.
263 -- Void arguments are removed, so output list may be shorter than
266 -- mkVirtHeapOffsets always returns boxed things with smaller offsets
267 -- than the unboxed things
269 mkVirtHeapOffsets is_thunk things
270 = let non_void_things = filterOut (isVoidRep . fst) things
271 (ptrs, non_ptrs) = partition (isGcPtrRep . fst) non_void_things
272 (wds_of_ptrs, ptrs_w_offsets) = mapAccumL computeOffset 0 ptrs
273 (tot_wds, non_ptrs_w_offsets) = mapAccumL computeOffset wds_of_ptrs non_ptrs
275 (tot_wds, wds_of_ptrs, ptrs_w_offsets ++ non_ptrs_w_offsets)
277 hdr_size | is_thunk = thunkHdrSize
278 | otherwise = fixedHdrSize
280 computeOffset wds_so_far (rep, thing)
281 = (wds_so_far + lRepSizeW (toLRep rep),
282 (thing, hdr_size + wds_so_far))
285 -------------------------------------------------------------------------
287 -- Making argument descriptors
289 -- An argument descriptor describes the layout of args on the stack,
290 -- both for * GC (stack-layout) purposes, and
291 -- * saving/restoring registers when a heap-check fails
293 -- Void arguments aren't important, therefore (contrast constructSlowCall)
295 -------------------------------------------------------------------------
297 -- bring in ARG_P, ARG_N, etc.
298 #include "../includes/StgFun.h"
300 -------------------------
301 -- argDescrType :: ArgDescr -> StgHalfWord
302 -- -- The "argument type" RTS field type
303 -- argDescrType (ArgSpec n) = n
304 -- argDescrType (ArgGen liveness)
305 -- | isBigLiveness liveness = ARG_GEN_BIG
306 -- | otherwise = ARG_GEN
309 mkArgDescr :: Name -> [Id] -> FCode ArgDescr
311 = case stdPattern arg_reps of
312 Just spec_id -> return (ArgSpec spec_id)
313 Nothing -> do { liveness <- mkLiveness nm size bitmap
314 ; return (ArgGen liveness) }
316 arg_reps = filter isNonV (map (toLRep . idPrimRep) args)
317 -- Getting rid of voids eases matching of standard patterns
319 bitmap = mkBitmap arg_bits
320 arg_bits = argBits arg_reps
321 size = length arg_bits
323 argBits :: [LRep] -> [Bool] -- True for non-ptr, False for ptr
325 argBits (P : args) = False : argBits args
326 argBits (arg : args) = take (lRepSizeW arg) (repeat True) ++ argBits args
328 ----------------------
329 stdPattern :: [LRep] -> Maybe StgHalfWord
332 [] -> Just ARG_NONE -- just void args, probably
344 [N,N,N] -> Just ARG_NNN
345 [N,N,P] -> Just ARG_NNP
346 [N,P,N] -> Just ARG_NPN
347 [N,P,P] -> Just ARG_NPP
348 [P,N,N] -> Just ARG_PNN
349 [P,N,P] -> Just ARG_PNP
350 [P,P,N] -> Just ARG_PPN
351 [P,P,P] -> Just ARG_PPP
353 [P,P,P,P] -> Just ARG_PPPP
354 [P,P,P,P,P] -> Just ARG_PPPPP
355 [P,P,P,P,P,P] -> Just ARG_PPPPPP
359 -------------------------------------------------------------------------
363 -------------------------------------------------------------------------
365 -- TODO: This along with 'mkArgDescr' should be unified
366 -- with 'CmmInfo.mkLiveness'. However that would require
367 -- potentially invasive changes to the 'ClosureInfo' type.
368 -- For now, 'CmmInfo.mkLiveness' handles only continuations and
369 -- this one handles liveness everything else. Another distinction
370 -- between these two is that 'CmmInfo.mkLiveness' information
371 -- about the stack layout, and this one is information about
372 -- the heap layout of PAPs.
373 mkLiveness :: Name -> Int -> Bitmap -> FCode Liveness
374 mkLiveness name size bits
375 | size > mAX_SMALL_BITMAP_SIZE -- Bitmap does not fit in one word
376 = do { let lbl = mkBitmapLabel (getUnique name)
377 ; emitRODataLits lbl ( mkWordCLit (fromIntegral size)
378 : map mkWordCLit bits)
379 ; return (BigLiveness lbl) }
381 | otherwise -- Bitmap fits in one word
383 small_bits = case bits of
385 [b] -> fromIntegral b
386 _ -> panic "livenessToAddrMode"
388 return (smallLiveness size small_bits)
390 smallLiveness :: Int -> StgWord -> Liveness
391 smallLiveness size small_bits = SmallLiveness bits
392 where bits = fromIntegral size .|. (small_bits `shiftL` bITMAP_BITS_SHIFT)
395 -- isBigLiveness :: Liveness -> Bool
396 -- isBigLiveness (BigLiveness _) = True
397 -- isBigLiveness (SmallLiveness _) = False
400 -- mkLivenessCLit :: Liveness -> CmmLit
401 -- mkLivenessCLit (BigLiveness lbl) = CmmLabel lbl
402 -- mkLivenessCLit (SmallLiveness bits) = mkWordCLit bits
405 -------------------------------------------------------------------------
407 -- Bitmap describing register liveness
408 -- across GC when doing a "generic" heap check
409 -- (a RET_DYN stack frame).
411 -- NB. Must agree with these macros (currently in StgMacros.h):
412 -- GET_NON_PTRS(), GET_PTRS(), GET_LIVENESS().
413 -------------------------------------------------------------------------
415 {- Not used in new code gen
416 mkRegLiveness :: [(Id, GlobalReg)] -> Int -> Int -> StgWord
417 mkRegLiveness regs ptrs nptrs
418 = (fromIntegral nptrs `shiftL` 16) .|.
419 (fromIntegral ptrs `shiftL` 24) .|.
420 all_non_ptrs `xor` reg_bits regs
425 reg_bits ((id, VanillaReg i) : regs) | isGcPtrRep (idPrimRep id)
426 = (1 `shiftL` (i - 1)) .|. reg_bits regs
431 -------------------------------------------------------------------------
433 -- Generating the info table and code for a closure
435 -------------------------------------------------------------------------
437 -- Here we make an info table of type 'CmmInfo'. The concrete
438 -- representation as a list of 'CmmAddr' is handled later
439 -- in the pipeline by 'cmmToRawCmm'.
441 emitClosureCodeAndInfoTable :: ClosureInfo -> CmmFormals
442 -> CmmAGraph -> FCode ()
443 emitClosureCodeAndInfoTable cl_info args body
444 = do { info <- mkCmmInfo cl_info
445 ; emitProc info (infoLblToEntryLbl info_lbl) args body }
447 info_lbl = infoTableLabelFromCI cl_info
449 -- Convert from 'ClosureInfo' to 'CmmInfo'.
450 -- Not used for return points. (The 'smRepClosureTypeInt' call would panic.)
451 mkCmmInfo :: ClosureInfo -> FCode CmmInfo
453 = do { prof <- if opt_SccProfilingOn then
454 do fd_lit <- mkStringCLit (closureTypeDescr cl_info)
455 ad_lit <- mkStringCLit (closureValDescr cl_info)
456 return $ ProfilingInfo fd_lit ad_lit
457 else return $ ProfilingInfo (mkIntCLit 0) (mkIntCLit 0)
458 ; return (CmmInfo gc_target Nothing (CmmInfoTable prof cl_type info)) }
460 info = closureTypeInfo cl_info
461 cl_type = smRepClosureTypeInt (closureSMRep cl_info)
463 -- The gc_target is to inform the CPS pass when it inserts a stack check.
464 -- Since that pass isn't used yet we'll punt for now.
465 -- When the CPS pass is fully integrated, this should
466 -- be replaced by the label that any heap check jumped to,
467 -- so that branch can be shared by both the heap (from codeGen)
468 -- and stack checks (from the CPS pass).
469 -- JD: Actually, we've decided to go a different route here:
470 -- the code generator is now responsible for producing the
471 -- stack limit check explicitly, so this field is now obsolete.
474 -----------------------------------------------------------------------------
476 -- Info table offsets
478 -----------------------------------------------------------------------------
480 stdInfoTableSizeW :: WordOff
481 -- The size of a standard info table varies with profiling/ticky etc,
482 -- so we can't get it from Constants
483 -- It must vary in sync with mkStdInfoTable
485 = size_fixed + size_prof
487 size_fixed = 2 -- layout, type
488 size_prof | opt_SccProfilingOn = 2
491 stdInfoTableSizeB :: ByteOff
492 stdInfoTableSizeB = stdInfoTableSizeW * wORD_SIZE :: ByteOff
494 stdSrtBitmapOffset :: ByteOff
495 -- Byte offset of the SRT bitmap half-word which is
496 -- in the *higher-addressed* part of the type_lit
497 stdSrtBitmapOffset = stdInfoTableSizeB - hALF_WORD_SIZE
499 stdClosureTypeOffset :: ByteOff
500 -- Byte offset of the closure type half-word
501 stdClosureTypeOffset = stdInfoTableSizeB - wORD_SIZE
503 stdPtrsOffset, stdNonPtrsOffset :: ByteOff
504 stdPtrsOffset = stdInfoTableSizeB - 2*wORD_SIZE
505 stdNonPtrsOffset = stdInfoTableSizeB - 2*wORD_SIZE + hALF_WORD_SIZE
507 -------------------------------------------------------------------------
509 -- Accessing fields of an info table
511 -------------------------------------------------------------------------
513 closureInfoPtr :: CmmExpr -> CmmExpr
514 -- Takes a closure pointer and returns the info table pointer
515 closureInfoPtr e = CmmLoad e bWord
517 entryCode :: CmmExpr -> CmmExpr
518 -- Takes an info pointer (the first word of a closure)
519 -- and returns its entry code
520 entryCode e | tablesNextToCode = e
521 | otherwise = CmmLoad e bWord
523 getConstrTag :: CmmExpr -> CmmExpr
524 -- Takes a closure pointer, and return the *zero-indexed*
525 -- constructor tag obtained from the info table
526 -- This lives in the SRT field of the info table
527 -- (constructors don't need SRTs).
528 getConstrTag closure_ptr
529 = CmmMachOp (MO_UU_Conv halfWordWidth wordWidth) [infoTableConstrTag info_table]
531 info_table = infoTable (closureInfoPtr closure_ptr)
533 cmmGetClosureType :: CmmExpr -> CmmExpr
534 -- Takes a closure pointer, and return the closure type
535 -- obtained from the info table
536 cmmGetClosureType closure_ptr
537 = CmmMachOp (MO_UU_Conv halfWordWidth wordWidth) [infoTableClosureType info_table]
539 info_table = infoTable (closureInfoPtr closure_ptr)
541 infoTable :: CmmExpr -> CmmExpr
542 -- Takes an info pointer (the first word of a closure)
543 -- and returns a pointer to the first word of the standard-form
544 -- info table, excluding the entry-code word (if present)
546 | tablesNextToCode = cmmOffsetB info_ptr (- stdInfoTableSizeB)
547 | otherwise = cmmOffsetW info_ptr 1 -- Past the entry code pointer
549 infoTableConstrTag :: CmmExpr -> CmmExpr
550 -- Takes an info table pointer (from infoTable) and returns the constr tag
551 -- field of the info table (same as the srt_bitmap field)
552 infoTableConstrTag = infoTableSrtBitmap
554 infoTableSrtBitmap :: CmmExpr -> CmmExpr
555 -- Takes an info table pointer (from infoTable) and returns the srt_bitmap
556 -- field of the info table
557 infoTableSrtBitmap info_tbl
558 = CmmLoad (cmmOffsetB info_tbl stdSrtBitmapOffset) bHalfWord
560 infoTableClosureType :: CmmExpr -> CmmExpr
561 -- Takes an info table pointer (from infoTable) and returns the closure type
562 -- field of the info table.
563 infoTableClosureType info_tbl
564 = CmmLoad (cmmOffsetB info_tbl stdClosureTypeOffset) bHalfWord
566 infoTablePtrs :: CmmExpr -> CmmExpr
567 infoTablePtrs info_tbl
568 = CmmLoad (cmmOffsetB info_tbl stdPtrsOffset) bHalfWord
570 infoTableNonPtrs :: CmmExpr -> CmmExpr
571 infoTableNonPtrs info_tbl
572 = CmmLoad (cmmOffsetB info_tbl stdNonPtrsOffset) bHalfWord
574 funInfoTable :: CmmExpr -> CmmExpr
575 -- Takes the info pointer of a function,
576 -- and returns a pointer to the first word of the StgFunInfoExtra struct
577 -- in the info table.
578 funInfoTable info_ptr
580 = cmmOffsetB info_ptr (- stdInfoTableSizeB - sIZEOF_StgFunInfoExtraRev)
582 = cmmOffsetW info_ptr (1 + stdInfoTableSizeW)
583 -- Past the entry code pointer
585 -------------------------------------------------------------------------
587 -- Static reference tables
589 -------------------------------------------------------------------------
591 -- srtLabelAndLength :: C_SRT -> CLabel -> (CmmLit, StgHalfWord)
592 -- srtLabelAndLength NoC_SRT _
594 -- srtLabelAndLength (C_SRT lbl off bitmap) info_lbl
595 -- = (makeRelativeRefTo info_lbl $ cmmLabelOffW lbl off, bitmap)
597 -------------------------------------------------------------------------
599 -- Position independent code
601 -------------------------------------------------------------------------
602 -- In order to support position independent code, we mustn't put absolute
603 -- references into read-only space. Info tables in the tablesNextToCode
604 -- case must be in .text, which is read-only, so we doctor the CmmLits
605 -- to use relative offsets instead.
607 -- Note that this is done even when the -fPIC flag is not specified,
608 -- as we want to keep binary compatibility between PIC and non-PIC.
610 makeRelativeRefTo :: CLabel -> CmmLit -> CmmLit
612 makeRelativeRefTo info_lbl (CmmLabel lbl)
614 = CmmLabelDiffOff lbl info_lbl 0
615 makeRelativeRefTo info_lbl (CmmLabelOff lbl off)
617 = CmmLabelDiffOff lbl info_lbl off
618 makeRelativeRefTo _ lit = lit