2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1995
4 \section[CgConTbls]{Info tables and update bits for constructors}
7 #include "HsVersions.h"
12 -- and to complete the interface...
13 TCE(..), UniqFM, CompilationInfo, AbstractC
16 import Pretty -- ToDo: rm (debugging)
22 import AbsUniType ( getTyConDataCons, kindFromType,
24 mkSpecTyCon, isLocalSpecTyCon,
25 TyVarTemplate, TyCon, Class,
26 TauType(..), UniType, ThetaType(..)
27 IF_ATTACK_PRAGMAS(COMMA cmpTyCon COMMA cmpClass)
28 IF_ATTACK_PRAGMAS(COMMA cmpUniType)
30 import CgHeapery ( heapCheck, allocDynClosure )
31 import CgRetConv ( dataReturnConvAlg, ctrlReturnConvAlg,
33 CtrlReturnConvention(..),
34 DataReturnConvention(..)
36 import CgTailCall ( performReturn, mkStaticAlgReturnCode )
37 import CgUsages ( getHpRelOffset )
38 import CLabelInfo ( mkConEntryLabel, mkStaticConEntryLabel,
39 --UNUSED: mkInfoTableLabel,
40 mkClosureLabel, --UNUSED: mkConUpdCodePtrUnvecLabel,
41 mkConUpdCodePtrVecLabel, mkStdUpdCodePtrVecLabel,
42 mkStdUpdVecTblLabel, CLabel
44 import ClosureInfo ( layOutStaticClosure, layOutDynCon,
45 closureSizeWithoutFixedHdr, closurePtrsSize,
46 fitsMinUpdSize, mkConLFInfo, layOutPhantomClosure,
47 infoTableLabelFromCI, dataConLiveness
49 import CmdLineOpts ( GlobalSwitch(..) )
51 import Id ( getDataConTag, getDataConSig, getDataConTyCon,
53 getDataConArity, fIRST_TAG, ConTag(..),
56 import CgCompInfo ( uF_UPDATEE )
57 import Maybes ( maybeToBool, Maybe(..) )
58 import PrimKind ( getKindSize, retKindSize )
60 import UniqSet -- ( emptyUniqSet, UniqSet(..) )
61 import TCE ( rngTCE, TCE(..), UniqFM )
65 For every constructor we generate the following info tables:
66 A static info table, for static instances of the constructor,
68 For constructors which return in registers (and only them),
69 an "inregs" info table. This info table is rather emaciated;
70 it only contains update code and tag.
75 Info tbls & Macro & Kind of constructor \\
77 info & @CONST_INFO_TABLE@& Zero arity (no info -- compiler uses static closure)\\
78 info & @CHARLIKE_INFO_TABLE@& Charlike (no info -- compiler indexes fixed array)\\
79 info & @INTLIKE_INFO_TABLE@& Intlike; the one macro generates both info tbls\\
80 info & @SPEC_INFO_TABLE@& SPECish, and bigger than or equal to @MIN_UPD_SIZE@\\
81 info & @GEN_INFO_TABLE@& GENish (hence bigger than or equal to @MIN_UPD_SIZE@)\\
84 Possible info tables for constructor con:
88 Used for dynamically let(rec)-bound occurrences of
89 the constructor, and for updates. For constructors
90 which are int-like, char-like or nullary, when GC occurs,
91 the closure tries to get rid of itself.
93 \item[@con_inregs_info@:]
94 Used when returning a new constructor in registers.
95 Only for return-in-regs constructors.
96 Macro: @INREGS_INFO_TABLE@.
98 \item[@con_static_info@:]
99 Static occurrences of the constructor
100 macro: @STATIC_INFO_TABLE@.
103 For zero-arity constructors, \tr{con}, we also generate a static closure:
106 \item[@con_closure@:]
107 A single static copy of the (zero-arity) constructor itself.
110 For charlike and intlike closures there is a fixed array of static
111 closures predeclared.
114 genStaticConBits :: CompilationInfo -- global info about the compilation
115 -> [TyCon] -- tycons to generate
116 -> FiniteMap TyCon [[Maybe UniType]]
117 -- tycon specialisation info
118 -> AbstractC -- output
120 genStaticConBits comp_info gen_tycons tycon_specs
121 = -- for each type constructor:
122 -- grab all its data constructors;
123 -- for each one, generate an info table
124 -- for each specialised type constructor
125 -- for each specialisation of the type constructor
126 -- grab data constructors, and generate info tables
128 -- ToDo: for tycons and specialisations which are not
129 -- declared in this module we must ensure that the
130 -- C labels are local to this module i.e. static
132 mkAbstractCs [ gen_for_tycon tc | tc <- gen_tycons ]
134 mkAbstractCs [ mkAbstractCs [ gen_for_spec_tycon tc spec
136 | (tc, specs) <- fmToList tycon_specs,
137 isLocalSpecTyCon (sw_chkr CompilingPrelude) tc
140 gen_for_tycon :: TyCon -> AbstractC
142 = mkAbstractCs (map (genConInfo comp_info tycon) data_cons)
143 `mkAbsCStmts` maybe_tycon_vtbl
146 data_cons = getTyConDataCons tycon
147 tycon_upd_label = mkStdUpdVecTblLabel tycon
150 case ctrlReturnConvAlg tycon of
151 UnvectoredReturn 1 -> CRetUnVector tycon_upd_label
152 (mk_upd_label tycon (head data_cons))
153 UnvectoredReturn _ -> AbsCNop
154 VectoredReturn _ -> CFlatRetVector tycon_upd_label
155 (map (mk_upd_label tycon) data_cons)
157 gen_for_spec_tycon :: TyCon -> [Maybe UniType] -> AbstractC
159 gen_for_spec_tycon tycon ty_maybes
160 = mkAbstractCs (map (genConInfo comp_info tycon) spec_data_cons)
162 maybe_spec_tycon_vtbl
164 data_cons = getTyConDataCons tycon
166 spec_tycon = mkSpecTyCon tycon ty_maybes
167 spec_data_cons = map (mkSameSpecCon ty_maybes) data_cons
169 spec_tycon_upd_label = mkStdUpdVecTblLabel spec_tycon
171 maybe_spec_tycon_vtbl =
172 case ctrlReturnConvAlg spec_tycon of
173 UnvectoredReturn 1 -> CRetUnVector spec_tycon_upd_label
174 (mk_upd_label spec_tycon (head spec_data_cons))
175 UnvectoredReturn _ -> AbsCNop
176 VectoredReturn _ -> CFlatRetVector spec_tycon_upd_label
177 (map (mk_upd_label spec_tycon) spec_data_cons)
179 mk_upd_label tycon con
181 (case (dataReturnConvAlg isw_chkr con) of
182 ReturnInRegs _ -> mkConUpdCodePtrVecLabel tycon tag
183 ReturnInHeap -> mkStdUpdCodePtrVecLabel tycon tag)
186 tag = getDataConTag con
189 (MkCompInfo sw_chkr isw_chkr _) = comp_info
192 %************************************************************************
194 \subsection[CgConTbls-info-tables]{Generating info tables for constructors}
196 %************************************************************************
198 Generate the entry code, info tables, and (for niladic constructor) the
199 static closure, for a constructor.
202 genConInfo :: CompilationInfo -> TyCon -> Id -> AbstractC
204 genConInfo comp_info@(MkCompInfo _ isw_chkr _) tycon data_con
211 -- Order of things is to reduce forward references
213 (closure_info, body_code) = mkConCodeAndInfo isw_chkr data_con
215 -- To allow the debuggers, interpreters, etc to cope with static
216 -- data structures (ie those built at compile time), we take care that
217 -- info-table contains the information we need.
218 (static_ci,_) = layOutStaticClosure data_con kindFromType arg_tys (mkConLFInfo data_con)
220 body = (initC comp_info (
221 profCtrC SLIT("ENT_CON") [CReg node] `thenC`
224 entry_addr = CLbl entry_label CodePtrKind
225 con_descr = _UNPK_ (getOccurrenceName data_con)
227 closure_code = CClosureInfoAndCode closure_info body Nothing
229 (dataConLiveness isw_chkr closure_info)
230 static_code = CClosureInfoAndCode static_ci body Nothing
232 (dataConLiveness isw_chkr static_ci)
234 inregs_upd_maybe = genPhantomUpdInfo comp_info tycon data_con
236 stdUpd = CLbl (mkStdUpdCodePtrVecLabel tycon tag) CodePtrKind
238 tag = getDataConTag data_con
240 cost_centre = mkCCostCentre dontCareCostCentre -- not worried about static data costs
242 -- For zero-arity data constructors, or, more accurately,
243 -- those which only have VoidKind args (or none):
244 -- We make the closure too (not just info tbl), so that we can share
245 -- one copy throughout.
246 closure_maybe = -- OLD: if con_arity /= 0 then
247 if not (all zero_size arg_tys) then
250 CStaticClosure closure_label -- Label for closure
251 static_ci -- Info table
253 [{-No args! A slight lie for constrs with VoidKind args-}]
255 zero_size arg_ty = getKindSize (kindFromType arg_ty) == 0
257 (_,_,arg_tys,_) = getDataConSig data_con
258 con_arity = getDataConArity data_con
259 entry_label = mkConEntryLabel data_con
260 closure_label = mkClosureLabel data_con
264 mkConCodeAndInfo :: IntSwitchChecker
265 -> Id -- Data constructor
266 -> (ClosureInfo, Code) -- The info table
268 mkConCodeAndInfo isw_chkr con
269 = case (dataReturnConvAlg isw_chkr con) of
273 (closure_info, regs_w_offsets)
274 = layOutDynCon con kindFromMagicId regs
277 = profCtrC SLIT("RET_OLD_IN_REGS") [mkIntCLit (length regs_w_offsets)] `thenC`
279 performReturn (mkAbstractCs (map move_to_reg regs_w_offsets))
280 (mkStaticAlgReturnCode con Nothing {- Info-ptr already loaded-})
281 emptyUniqSet{-no live vars-}
283 (closure_info, body_code)
287 (_, _, arg_tys, _) = getDataConSig con
289 (closure_info, arg_things)
290 = layOutDynCon con kindFromType arg_tys
293 = -- OLD: We don't set CC when entering data any more (WDP 94/06)
294 -- lexCostCentreC "ENTER_CC_DCL" [CReg node] `thenC`
295 profCtrC SLIT("RET_OLD_IN_HEAP") [mkIntCLit (length arg_things)] `thenC`
297 performReturn AbsCNop -- Ptr to thing already in Node
298 (mkStaticAlgReturnCode con Nothing {- Info-ptr already loaded-})
299 emptyUniqSet{-no live vars-}
301 (closure_info, body_code)
304 move_to_reg :: (MagicId, VirtualHeapOffset {-from Node-}) -> AbstractC
305 move_to_reg (reg, offset)
306 = CAssign (CReg reg) (CVal (NodeRel offset) (kindFromMagicId reg))
309 %************************************************************************
311 \subsection[CgConTbls-updates]{Generating update bits for constructors}
313 %************************************************************************
315 Generate the "phantom" info table and update code, iff the constructor returns in regs
319 genPhantomUpdInfo :: CompilationInfo -> TyCon -> Id{-data con-} -> AbstractC
321 genPhantomUpdInfo comp_info@(MkCompInfo _ isw_chkr _) tycon data_con
322 = case (dataReturnConvAlg isw_chkr data_con) of
324 ReturnInHeap -> --OLD: pprTrace "NoPhantom: " (ppr PprDebug data_con) $
325 AbsCNop -- No need for a phantom update
328 --OLD: pprTrace "YesPhantom! " (ppr PprDebug data_con) $
330 phantom_itbl = CClosureInfoAndCode phantom_ci AbsCNop Nothing
332 (dataConLiveness isw_chkr phantom_ci)
334 phantom_ci = layOutPhantomClosure data_con (mkConLFInfo data_con)
336 con_descr = _UNPK_ (getOccurrenceName data_con)
338 con_arity = getDataConArity data_con
340 upd_code = CLabelledCode upd_label (mkAbsCStmts build_closure perform_return)
341 upd_label = mkConUpdCodePtrVecLabel tycon tag
342 tag = getDataConTag data_con
344 updatee = CVal (SpBRel 0 (-uF_UPDATEE)) PtrKind
346 perform_return = mkAbstractCs
348 CMacroStmt POP_STD_UPD_FRAME [],
349 CReturn (CReg RetReg) return_info
353 -- OLD: pprTrace "ctrlReturn6:" (ppr PprDebug tycon) (
354 case (ctrlReturnConvAlg tycon) of
355 UnvectoredReturn _ -> DirectReturn
356 VectoredReturn _ -> StaticVectoredReturn (tag - fIRST_TAG)
359 -- Determine cost centre for the updated closures CC (and allocation)
360 -- CCC for lexical (now your only choice)
361 use_cc = CReg CurCostCentre -- what to put in the closure
362 blame_cc = use_cc -- who to blame for allocation
364 do_move (reg, virt_offset) =
365 CAssign (CVal (NodeRel virt_offset) (kindFromMagicId reg)) (CReg reg)
368 -- Code for building a new constructor in place over the updatee
370 = profCtrC SLIT("UPD_CON_IN_PLACE")
371 [mkIntCLit (length regs_w_offsets)] `thenC`
374 CAssign (CReg node) updatee,
376 -- Tell the storage mgr that we intend to update in place
377 -- This may (in complicated mgrs eg generational) cause gc,
378 -- and it may modify Node to point to another place to
379 -- actually update into.
380 CMacroStmt upd_inplace_macro [liveness_mask],
382 -- Initialise the closure pointed to by node
383 CInitHdr closure_info (NodeRel zeroOff) use_cc True,
384 mkAbstractCs (map do_move regs_w_offsets),
385 if con_arity /= 0 then
386 CAssign (CReg infoptr) (CLbl info_label DataPtrKind)
391 upd_inplace_macro = if closurePtrsSize closure_info == 0
392 then UPD_INPLACE_NOPTRS
393 else UPD_INPLACE_PTRS
395 -- Code for allocating a new constructor in the heap
398 amodes_w_offsets = [ (CReg r, o) | (r,o) <- regs_w_offsets ]
400 -- Allocate and build closure specifying upd_new_w_regs
401 allocDynClosure closure_info use_cc blame_cc amodes_w_offsets
402 `thenFC` \ hp_offset ->
403 getHpRelOffset hp_offset `thenFC` \ hp_rel ->
407 profCtrC SLIT("UPD_CON_IN_NEW")
408 [mkIntCLit (length amodes_w_offsets)] `thenC`
410 [ CMacroStmt UPD_IND [updatee, amode],
411 CAssign (CReg node) amode,
412 CAssign (CReg infoptr) (CLbl info_label DataPtrKind)
415 (closure_info, regs_w_offsets) = layOutDynCon data_con kindFromMagicId regs
416 info_label = infoTableLabelFromCI closure_info
417 liveness_mask = mkIntCLit (mkLiveRegsBitMask (node:regs))
420 if fitsMinUpdSize closure_info then
421 initC comp_info overwrite_code
423 initC comp_info (heapCheck regs False alloc_code)
425 in CClosureUpdInfo phantom_itbl