191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269 | @VisitorCore.visit.dispatch
def visit(self, node: astx.ClassDefStmt) -> None:
"""
title: Visit ClassDefStmt nodes.
parameters:
node:
type: astx.ClassDefStmt
"""
class_key = semantic_class_key(node, node.name)
semantic = getattr(node, "semantic", None)
resolved_class = getattr(semantic, "resolved_class", None)
layout = getattr(resolved_class, "layout", None)
initialization = getattr(resolved_class, "initialization", None)
if layout is None:
raise Exception("codegen: unresolved class layout.")
if initialization is None:
raise Exception("codegen: unresolved class initialization.")
field_types: list[ir.Type] = [
self._llvm.OPAQUE_POINTER_TYPE for _ in layout.header_fields
]
for field in layout.instance_fields:
llvm_type = self._llvm_type_for_ast_type(field.member.type_)
if llvm_type is None:
raise Exception(
f"codegen: Unknown LLVM type for class field "
f"'{field.member.name}'."
)
field_types.append(llvm_type)
self._ensure_identified_type(
class_key,
semantic_class_name(node, node.name),
field_types,
)
for static_initializer in initialization.static_initializers:
storage = static_initializer.storage
llvm_type = self._llvm_type_for_ast_type(storage.member.type_)
if llvm_type is None:
raise Exception(
f"codegen: Unknown LLVM type for static class field "
f"'{storage.member.name}'."
)
initializer = self._literal_global_initializer(
static_initializer.value,
llvm_type,
)
existing = self._llvm.module.globals.get(storage.global_name)
if existing is None:
global_var = ir.GlobalVariable(
self._llvm.module,
llvm_type,
name=storage.global_name,
)
else:
global_var = existing
global_var.linkage = "internal"
global_var.global_constant = storage.member.is_constant
global_var.initializer = initializer
dispatch_table = self._dispatch_table_initializer(node)
if dispatch_table is not None:
dispatch_type, dispatch_initializer = dispatch_table
dispatch_global = self._llvm.module.globals.get(
layout.dispatch_global_name
)
if dispatch_global is None:
dispatch_global = ir.GlobalVariable(
self._llvm.module,
dispatch_type,
name=layout.dispatch_global_name,
)
dispatch_global.linkage = "internal"
dispatch_global.global_constant = True
dispatch_global.initializer = dispatch_initializer
for method in node.methods:
self.visit(method)
|