Skip to content
← Back

src/ir/emitter/srm_handles.ghul

1
namespace IR.Emitter is
2
use System.Reflection.Metadata.TypeDefinitionHandle
3
use System.Reflection.Metadata.MethodDefinitionHandle
4
use System.Reflection.Metadata.FieldDefinitionHandle
5
6
use Semantic.Symbols.Symbol
7
use Semantic.Symbols.Classy
8
use Semantic.Symbols.Function
9
use Semantic.Symbols.Field
10
11
// The members a state-machine frame carries that no symbol declares.
12
// The lowering synthesises each one, so they are named by which
13
// member they are rather than by a declaration.
14
//
15
// The frame's constructor is not here: it is declared into the
16
// frame's own scope and has a symbol like any other method.
17
enum FrameMember is
18
MOVE_NEXT,
19
GET_CURRENT,
20
GET_ENUMERATOR,
21
DISPOSE,
22
RESET,
23
TO_STRING,
24
SET_STATE_MACHINE,
25
si
26
27
// The non-generic framework members an iterable or iterator type
28
// has to answer for, which its generic ones derive from. Neither
29
// is a declaration the symbol table holds, so like `FrameMember`
30
// each is named by which member it is.
31
enum BoilerplateMember is
32
ENUMERABLE_GET_ENUMERATOR,
33
ENUMERATOR_GET_CURRENT,
34
si
35
36
// Every metadata identity the emitter has assigned to a symbol, one
37
// map per table.
38
//
39
// These are deliberately not fields on the symbols themselves.
40
// `specialize` clones symbols, so a row number stored on a symbol
41
// would be copied onto every specialization and silently name the
42
// wrong row; a map forces each table to state which identity it
43
// keys on. Definitions key on the symbol, because a definition is
44
// never specialized in the assembly that emits it. References key
45
// on `root_specialized_from`, because the format expects one
46
// TypeRef / MemberRef per open definition, with instantiations
47
// expressed as TypeSpec / MethodSpec built on top of it.
48
class SRM_HANDLES is
49
_type_defs: Collections.MAP[Classy, TypeDefinitionHandle]
50
_method_defs: Collections.MAP[Function, MethodDefinitionHandle]
51
_field_defs: Collections.MAP[Field, FieldDefinitionHandle]
52
53
// Offsets into the method body stream, deposited by the tree
54
// walk as each body is encoded and read back when the owning
55
// MethodDef row is written. A function with no entry has no
56
// body, which is what an abstract or bodyless member is.
57
_bodies: Collections.MAP[Function, int]
58
59
// `@IL.output` ranges per method, set as each body is emitted and
60
// read when the method's attribute is written.
61
_il_outputs: Collections.MAP[Function, Collections.List[SRM_IL_OUTPUT_RANGE]]
62
63
// A unit variant carries one interned instance in a static
64
// field, initialized by a static constructor. Neither is
65
// declared: the back end synthesises both, so they are keyed on
66
// the variant they belong to rather than on a symbol of their
67
// own.
68
_unit_variant_instances: Collections.MAP[Classy, FieldDefinitionHandle]
69
_unit_variant_initializers: Collections.MAP[Classy, MethodDefinitionHandle]
70
_unit_variant_initializer_bodies: Collections.MAP[Classy, int]
71
72
// A state-machine frame's own members, which the lowering
73
// synthesises rather than declares. Keyed on the frame and which
74
// member it is, for the same reason the unit variant's are: the
75
// member has no symbol of its own to key on.
76
_frame_members: Collections.MAP[(frame: Classy, member: FrameMember), MethodDefinitionHandle]
77
_frame_member_bodies: Collections.MAP[(frame: Classy, member: FrameMember), int]
78
79
// The sequence the rows above were assigned in, so the pass
80
// that writes them replays the pass that numbered them.
81
emission_plan: SRM_EMISSION_PLAN
82
83
init() is
84
emission_plan = SRM_EMISSION_PLAN()
85
86
_type_defs = Collections.MAP[Classy, TypeDefinitionHandle]()
87
_method_defs = Collections.MAP[Function, MethodDefinitionHandle]()
88
_field_defs = Collections.MAP[Field, FieldDefinitionHandle]()
89
_bodies = Collections.MAP[Function, int]()
90
_il_outputs =
91
Collections.MAP[Function, Collections.List[SRM_IL_OUTPUT_RANGE]]()
92
_unit_variant_instances = Collections.MAP[Classy, FieldDefinitionHandle]()
93
_unit_variant_initializers = Collections.MAP[Classy, MethodDefinitionHandle]()
94
_unit_variant_initializer_bodies = Collections.MAP[Classy, int]()
95
_frame_members = Collections.MAP[(frame: Classy, member: FrameMember), MethodDefinitionHandle]()
96
_frame_member_bodies = Collections.MAP[(frame: Classy, member: FrameMember), int]()
97
si
98
99
set_frame_member(frame: Classy, member: FrameMember, handle: MethodDefinitionHandle) is
100
_frame_members[(frame = frame, member = member)] = handle
101
si
102
103
frame_member(frame: Classy, member: FrameMember) -> MethodDefinitionHandle? =>
104
if _frame_members.contains_key((frame = frame, member = member)) then
105
_frame_members[(frame = frame, member = member)]
106
else
107
null
108
fi
109
110
set_frame_member_body(frame: Classy, member: FrameMember, offset: int) is
111
_frame_member_bodies[(frame = frame, member = member)] = offset
112
si
113
114
frame_member_body(frame: Classy, member: FrameMember) -> int? =>
115
if _frame_member_bodies.contains_key((frame = frame, member = member)) then
116
_frame_member_bodies[(frame = frame, member = member)]
117
else
118
null
119
fi
120
121
set_type_definition(symbol: Classy, handle: TypeDefinitionHandle) is
122
_type_defs[symbol] = handle
123
si
124
125
set_method_definition(symbol: Function, handle: MethodDefinitionHandle) is
126
_method_defs[symbol] = handle
127
si
128
129
set_field_definition(symbol: Field, handle: FieldDefinitionHandle) is
130
_field_defs[symbol] = handle
131
si
132
133
// Type and method lookups take the root symbol, so a call
134
// through a specialization still finds the definition it was
135
// specialized from.
136
type_definition(symbol: Classy) -> TypeDefinitionHandle? is
137
let root = cast Classy?(symbol.root_specialized_from)
138
139
if root? /\ _type_defs.contains_key(root) then
140
return _type_defs[root]
141
fi
142
143
return null
144
si
145
146
method_definition(symbol: Function) -> MethodDefinitionHandle? is
147
let root = cast Function?(symbol.root_specialized_from)
148
149
if root? /\ _method_defs.contains_key(root) then
150
return _method_defs[root]
151
fi
152
153
return null
154
si
155
156
field_definition(symbol: Field) -> FieldDefinitionHandle? is
157
let root = cast Field?(symbol.root_specialized_from)
158
159
if root? /\ _field_defs.contains_key(root) then
160
return _field_defs[root]
161
fi
162
163
return null
164
si
165
166
set_unit_variant_instance(variant: Classy, handle: FieldDefinitionHandle) is
167
_unit_variant_instances[variant] = handle
168
si
169
170
set_unit_variant_initializer(variant: Classy, handle: MethodDefinitionHandle) is
171
_unit_variant_initializers[variant] = handle
172
si
173
174
set_unit_variant_initializer_body(variant: Classy, offset: int) is
175
_unit_variant_initializer_bodies[variant] = offset
176
si
177
178
unit_variant_instance(variant: Classy) -> FieldDefinitionHandle? is
179
let root = cast Classy?(variant.root_specialized_from)
180
181
if root? /\ _unit_variant_instances.contains_key(root) then
182
return _unit_variant_instances[root]
183
fi
184
185
return null
186
si
187
188
unit_variant_initializer_body(variant: Classy) -> int? =>
189
if _unit_variant_initializer_bodies.contains_key(variant) then
190
_unit_variant_initializer_bodies[variant]
191
else
192
null
193
fi
194
195
set_body_offset(symbol: Function, offset: int) is
196
_bodies[symbol] = offset
197
si
198
199
body_offset(symbol: Function) -> int? =>
200
if _bodies.contains_key(symbol) then _bodies[symbol] else null fi
201
202
// `@IL.output` ranges captured while the method's body was emitted,
203
// carried to the phase-3 structure walk that writes the method's
204
// attribute. Null/empty is stored as absent so the attribute is
205
// written only for methods that actually mark something.
206
set_il_outputs(
207
symbol: Function,
208
outputs: Collections.List[SRM_IL_OUTPUT_RANGE]?
209
) is
210
if outputs? /\ outputs.count > 0 then
211
_il_outputs[symbol] = outputs
212
fi
213
si
214
215
il_outputs(symbol: Function) -> Collections.List[SRM_IL_OUTPUT_RANGE]? =>
216
if _il_outputs.contains_key(symbol) then _il_outputs[symbol] else null fi
217
si
218
si