1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
|
%
% (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}
|