% % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998 % \section[CgConTbls]{Info tables and update bits for constructors} \begin{code} module CgConTbls ( genStaticConBits ) where #include "HsVersions.h" import AbsCSyn import CgMonad import AbsCUtils ( mkAbstractCs, mkAbsCStmts ) import CgTailCall ( performReturn, mkStaticAlgReturnCode ) import ClosureInfo ( layOutStaticClosure, layOutDynCon, mkConLFInfo, ClosureInfo ) import DataCon ( DataCon, dataConName, dataConRepArgTys, isNullaryDataCon ) import Name ( getOccName ) import OccName ( occNameUserString ) import TyCon ( tyConDataCons, isEnumerationTyCon, TyCon ) import Type ( typePrimRep ) \end{code} For every constructor we generate the following info tables: A static info table, for static instances of the constructor, Plus: \begin{tabular}{lll} Info tbls & Macro & Kind of constructor \\ \hline info & @CONST_INFO_TABLE@& Zero arity (no info -- compiler uses static closure)\\ info & @CHARLIKE_INFO_TABLE@& Charlike (no info -- compiler indexes fixed array)\\ info & @INTLIKE_INFO_TABLE@& Intlike; the one macro generates both info tbls\\ info & @SPEC_INFO_TABLE@& SPECish, and bigger than or equal to @MIN_UPD_SIZE@\\ info & @GEN_INFO_TABLE@& GENish (hence bigger than or equal to @MIN_UPD_SIZE@)\\ \end{tabular} Possible info tables for constructor con: \begin{description} \item[@_con_info@:] Used for dynamically let(rec)-bound occurrences of the constructor, and for updates. For constructors which are int-like, char-like or nullary, when GC occurs, the closure tries to get rid of itself. \item[@_static_info@:] Static occurrences of the constructor macro: @STATIC_INFO_TABLE@. \end{description} For zero-arity constructors, \tr{con}, we NO LONGER generate a static closure; it's place is taken by the top level defn of the constructor. For charlike and intlike closures there is a fixed array of static closures predeclared. \begin{code} genStaticConBits :: CompilationInfo -- global info about the compilation -> [TyCon] -- tycons to generate -> AbstractC -- output genStaticConBits comp_info gen_tycons = -- for each type constructor: -- grab all its data constructors; -- for each one, generate an info table -- for each specialised type constructor -- for each specialisation of the type constructor -- grab data constructors, and generate info tables -- ToDo: for tycons and specialisations which are not -- declared in this module we must ensure that the -- C labels are local to this module i.e. static -- since they may be duplicated in other modules mkAbstractCs [ gen_for_tycon tc | tc <- gen_tycons ] where gen_for_tycon :: TyCon -> AbstractC gen_for_tycon tycon = mkAbstractCs (map (genConInfo comp_info tycon) (tyConDataCons tycon)) `mkAbsCStmts` ( -- after the con decls, so we don't need to declare the constructor labels if (isEnumerationTyCon tycon) then CClosureTbl tycon else AbsCNop ) \end{code} %************************************************************************ %* * \subsection[CgConTbls-info-tables]{Generating info tables for constructors} %* * %************************************************************************ Generate the entry code, info tables, and (for niladic constructor) the static closure, for a constructor. \begin{code} genConInfo :: CompilationInfo -> TyCon -> DataCon -> AbstractC genConInfo comp_info tycon data_con = mkAbstractCs [ CSplitMarker, closure_code, static_code] -- Order of things is to reduce forward references where (closure_info, body_code) = mkConCodeAndInfo data_con -- To allow the debuggers, interpreters, etc to cope with static -- data structures (ie those built at compile time), we take care that -- info-table contains the information we need. (static_ci,_) = layOutStaticClosure con_name typePrimRep arg_tys (mkConLFInfo data_con) body = (initC comp_info ( profCtrC SLIT("TICK_ENT_CON") [CReg node] `thenC` body_code)) con_descr = occNameUserString (getOccName data_con) -- Don't need any dynamic closure code for zero-arity constructors closure_code = if zero_arity_con then AbsCNop else CClosureInfoAndCode closure_info body Nothing con_descr static_code = CClosureInfoAndCode static_ci body Nothing con_descr zero_arity_con = isNullaryDataCon data_con -- We used to check that all the arg-sizes were zero, but we don't -- really have any constructors with only zero-size args, and it's -- just one more thing to go wrong. arg_tys = dataConRepArgTys data_con con_name = dataConName data_con \end{code} \begin{code} mkConCodeAndInfo :: DataCon -- Data constructor -> (ClosureInfo, Code) -- The info table mkConCodeAndInfo con = let arg_tys = dataConRepArgTys con (closure_info, arg_things) = layOutDynCon con typePrimRep arg_tys body_code = -- NB: We don't set CC when entering data (WDP 94/06) profCtrC SLIT("TICK_RET_OLD") [mkIntCLit (length arg_things)] `thenC` performReturn AbsCNop -- Ptr to thing already in Node (mkStaticAlgReturnCode con) in (closure_info, body_code) \end{code}