...
This commit is contained in:
211
src/codegen.zig
211
src/codegen.zig
@@ -117,6 +117,8 @@ pub const CodeGen = struct {
|
||||
tagged_enum_types: std.StringHashMap(TaggedEnumInfo),
|
||||
// Union registry: maps name to field info + LLVM type (untagged, C-style)
|
||||
union_types: std.StringHashMap(UnionInfo),
|
||||
// Unified type registry: single lookup for all named types
|
||||
type_registry: std.StringHashMap(TypeRegistryEntry),
|
||||
// Flags enum registry: tracks which enum names are flags
|
||||
flags_enum_types: std.StringHashMap(void),
|
||||
// Enum variant values: maps enum name → resolved i64 values per variant
|
||||
@@ -271,6 +273,14 @@ pub const CodeGen = struct {
|
||||
promoted_fields: std.StringHashMap(PromotedField),
|
||||
};
|
||||
|
||||
const TypeRegistryEntry = union(enum) {
|
||||
struct_info: StructInfo,
|
||||
tagged_enum: TaggedEnumInfo,
|
||||
union_info: UnionInfo,
|
||||
plain_enum: []const []const u8,
|
||||
alias: []const u8,
|
||||
};
|
||||
|
||||
// Scope stack entry: records what a name mapped to before being shadowed
|
||||
const ScopeEntry = struct {
|
||||
name: []const u8,
|
||||
@@ -326,6 +336,7 @@ pub const CodeGen = struct {
|
||||
.struct_types = std.StringHashMap(StructInfo).init(allocator),
|
||||
.tagged_enum_types = std.StringHashMap(TaggedEnumInfo).init(allocator),
|
||||
.union_types = std.StringHashMap(UnionInfo).init(allocator),
|
||||
.type_registry = std.StringHashMap(TypeRegistryEntry).init(allocator),
|
||||
.flags_enum_types = std.StringHashMap(void).init(allocator),
|
||||
.enum_variant_values = std.StringHashMap([]const i64).init(allocator),
|
||||
.enum_backing_types = std.StringHashMap(c.LLVMTypeRef).init(allocator),
|
||||
@@ -361,6 +372,7 @@ pub const CodeGen = struct {
|
||||
self.struct_types.deinit();
|
||||
self.tagged_enum_types.deinit();
|
||||
self.union_types.deinit();
|
||||
self.type_registry.deinit();
|
||||
self.comptime_globals.deinit();
|
||||
self.enum_backing_types.deinit();
|
||||
self.generic_templates.deinit();
|
||||
@@ -422,9 +434,21 @@ pub const CodeGen = struct {
|
||||
return c.LLVMBuildAlloca(tmp_builder, ty, name);
|
||||
}
|
||||
|
||||
/// Convert a Zig slice to a null-terminated C string using a caller-provided stack buffer.
|
||||
/// Returns the stack-based result when it fits, or falls back to allocator.dupeZ.
|
||||
fn nameToCStr(self: *CodeGen, name: []const u8, buf: *[256]u8) [*:0]const u8 {
|
||||
if (name.len < 256) {
|
||||
@memcpy(buf[0..name.len], name);
|
||||
buf[name.len] = 0;
|
||||
return @ptrCast(buf[0..name.len :0]);
|
||||
}
|
||||
const duped = self.allocator.dupeZ(u8, name) catch unreachable;
|
||||
return duped.ptr;
|
||||
}
|
||||
|
||||
fn buildNamedAlloca(self: *CodeGen, ty: c.LLVMTypeRef, name: []const u8) !c.LLVMValueRef {
|
||||
const name_z = try self.allocator.dupeZ(u8, name);
|
||||
return self.buildEntryBlockAlloca(ty, name_z.ptr);
|
||||
var buf: [256]u8 = undefined;
|
||||
return self.buildEntryBlockAlloca(ty, self.nameToCStr(name, &buf));
|
||||
}
|
||||
|
||||
pub fn typeToLLVM(self: *CodeGen, ty: Type) c.LLVMTypeRef {
|
||||
@@ -860,8 +884,12 @@ pub const CodeGen = struct {
|
||||
}
|
||||
|
||||
fn pushScope(self: *CodeGen) !void {
|
||||
try self.scope_saves.append(self.allocator, std.ArrayList(ScopeEntry).empty);
|
||||
try self.defer_stack.append(self.allocator, std.ArrayList(*Node).empty);
|
||||
var saves = std.ArrayList(ScopeEntry).empty;
|
||||
try saves.ensureTotalCapacity(self.allocator, 8);
|
||||
try self.scope_saves.append(self.allocator, saves);
|
||||
var defers = std.ArrayList(*Node).empty;
|
||||
try defers.ensureTotalCapacity(self.allocator, 4);
|
||||
try self.defer_stack.append(self.allocator, defers);
|
||||
}
|
||||
|
||||
fn popScope(self: *CodeGen) !void {
|
||||
@@ -955,6 +983,7 @@ pub const CodeGen = struct {
|
||||
} else {
|
||||
// Payload-less enum
|
||||
try self.enum_types.put(ed.name, ed.variant_names);
|
||||
try self.type_registry.put(ed.name, .{ .plain_enum = ed.variant_names });
|
||||
_ = try self.getAnyTypeId(ed.name, .{ .enum_type = ed.name });
|
||||
|
||||
if (ed.is_flags) {
|
||||
@@ -997,6 +1026,7 @@ pub const CodeGen = struct {
|
||||
try self.registerLambdaAsFunction(cd.name, cd.value.data.lambda);
|
||||
} else if (cd.value.data == .type_expr) {
|
||||
try self.type_aliases.put(cd.name, cd.value.data.type_expr.name);
|
||||
try self.type_registry.put(cd.name, .{ .alias = cd.value.data.type_expr.name });
|
||||
} else if (cd.value.data == .call) {
|
||||
// Check if this is a generic struct or type function instantiation
|
||||
const callee_name = if (cd.value.data.call.callee.data == .identifier)
|
||||
@@ -1009,20 +1039,24 @@ pub const CodeGen = struct {
|
||||
const result_ty = try self.instantiateGenericStruct(cn, tmpl, cd.value.data.call.args);
|
||||
if (result_ty.isStruct()) {
|
||||
try self.type_aliases.put(cd.name, result_ty.struct_type);
|
||||
try self.type_registry.put(cd.name, .{ .alias = result_ty.struct_type });
|
||||
}
|
||||
} else if (self.generic_templates.get(cn)) |tmpl| {
|
||||
// Type-returning function: Foo :: Complex(u32);
|
||||
const result_ty = try self.instantiateTypeFunction(cd.name, cn, tmpl, cd.value.data.call.args);
|
||||
if (result_ty.isStruct()) {
|
||||
try self.type_aliases.put(cd.name, result_ty.struct_type);
|
||||
try self.type_registry.put(cd.name, .{ .alias = result_ty.struct_type });
|
||||
} else if (result_ty.isUnion()) {
|
||||
try self.type_aliases.put(cd.name, result_ty.union_type);
|
||||
try self.type_registry.put(cd.name, .{ .alias = result_ty.union_type });
|
||||
}
|
||||
} else if (self.builtin_functions.contains(cn)) {
|
||||
// Builtin type function (e.g., Vector(4, f32), Array(5, s32))
|
||||
if (self.resolveBuiltinType(cn, cd.value.data.call.args)) |result_ty| {
|
||||
const display = try result_ty.displayName(self.allocator);
|
||||
try self.type_aliases.put(cd.name, display);
|
||||
try self.type_registry.put(cd.name, .{ .alias = display });
|
||||
} else {
|
||||
try self.registerTopLevelConstant(cd);
|
||||
}
|
||||
@@ -1054,26 +1088,6 @@ pub const CodeGen = struct {
|
||||
}
|
||||
}
|
||||
|
||||
// Pre-register all known types for Any type ID assignment
|
||||
{
|
||||
var it = self.struct_types.iterator();
|
||||
while (it.next()) |entry| {
|
||||
_ = try self.getAnyTypeId(entry.key_ptr.*, .{ .struct_type = entry.key_ptr.* });
|
||||
}
|
||||
}
|
||||
{
|
||||
var it = self.enum_types.iterator();
|
||||
while (it.next()) |entry| {
|
||||
_ = try self.getAnyTypeId(entry.key_ptr.*, .{ .enum_type = entry.key_ptr.* });
|
||||
}
|
||||
}
|
||||
{
|
||||
var it = self.tagged_enum_types.iterator();
|
||||
while (it.next()) |entry| {
|
||||
_ = try self.getAnyTypeId(entry.key_ptr.*, .{ .union_type = entry.key_ptr.* });
|
||||
}
|
||||
}
|
||||
|
||||
// Pass 2: Generate all function bodies
|
||||
// Functions with Any parameters (like any_to_string) are deferred to Pass 3
|
||||
// so that all types are registered before their type-match expressions are compiled.
|
||||
@@ -1311,30 +1325,42 @@ pub const CodeGen = struct {
|
||||
if (self.type_param_bindings) |bindings| {
|
||||
if (bindings.get(name)) |t| return t;
|
||||
}
|
||||
// Check type aliases
|
||||
if (self.type_aliases.get(name)) |target| {
|
||||
if (Type.fromName(target)) |t| return t;
|
||||
if (self.struct_types.contains(target)) return .{ .struct_type = target };
|
||||
if (self.tagged_enum_types.contains(target)) return .{ .union_type = target };
|
||||
if (self.union_types.contains(target)) return .{ .union_type = target };
|
||||
// Unified type registry lookup
|
||||
if (self.type_registry.get(name)) |entry| {
|
||||
switch (entry) {
|
||||
.struct_info => return .{ .struct_type = name },
|
||||
.tagged_enum => return .{ .union_type = name },
|
||||
.union_info => return .{ .union_type = name },
|
||||
.plain_enum => return .{ .enum_type = name },
|
||||
.alias => |target| {
|
||||
if (Type.fromName(target)) |t| return t;
|
||||
if (self.type_registry.get(target)) |inner| {
|
||||
switch (inner) {
|
||||
.struct_info => return .{ .struct_type = target },
|
||||
.tagged_enum => return .{ .union_type = target },
|
||||
.union_info => return .{ .union_type = target },
|
||||
.plain_enum => return .{ .enum_type = target },
|
||||
.alias => {},
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
// Check enum types
|
||||
if (self.enum_types.contains(name)) return .{ .enum_type = name };
|
||||
// Check struct types
|
||||
if (self.struct_types.contains(name)) return .{ .struct_type = name };
|
||||
// Check union types (tagged enums and C-style unions)
|
||||
if (self.tagged_enum_types.contains(name)) return .{ .union_type = name };
|
||||
if (self.union_types.contains(name)) return .{ .union_type = name };
|
||||
}
|
||||
// Safety net: inline declarations that should have been hoisted
|
||||
if (tn.data == .struct_decl) {
|
||||
const sn = tn.data.struct_decl.name;
|
||||
if (self.struct_types.contains(sn)) return .{ .struct_type = sn };
|
||||
if (self.type_registry.get(sn)) |e| {
|
||||
if (e == .struct_info) return .{ .struct_type = sn };
|
||||
}
|
||||
}
|
||||
if (tn.data == .enum_decl) {
|
||||
const en = tn.data.enum_decl.name;
|
||||
if (self.tagged_enum_types.contains(en)) return .{ .union_type = en };
|
||||
if (self.enum_types.contains(en)) return .{ .enum_type = en };
|
||||
if (self.type_registry.get(en)) |e| switch (e) {
|
||||
.tagged_enum => return .{ .union_type = en },
|
||||
.plain_enum => return .{ .enum_type = en },
|
||||
else => {},
|
||||
};
|
||||
}
|
||||
return .void_type;
|
||||
}
|
||||
@@ -1432,7 +1458,7 @@ pub const CodeGen = struct {
|
||||
}
|
||||
}
|
||||
|
||||
try self.struct_types.put(mangled_name, .{
|
||||
const si = StructInfo{
|
||||
.field_names = sd.field_names,
|
||||
.field_types = build.field_sx_types,
|
||||
.field_defaults = resolved_defaults,
|
||||
@@ -1441,7 +1467,9 @@ pub const CodeGen = struct {
|
||||
.type_param_names = try tp_names.toOwnedSlice(self.allocator),
|
||||
.type_param_types = try tp_types.toOwnedSlice(self.allocator),
|
||||
.template_name = template_name,
|
||||
});
|
||||
};
|
||||
try self.struct_types.put(mangled_name, si);
|
||||
try self.type_registry.put(mangled_name, .{ .struct_info = si });
|
||||
_ = try self.getAnyTypeId(mangled_name, .{ .struct_type = mangled_name });
|
||||
|
||||
return .{ .struct_type = mangled_name };
|
||||
@@ -1492,13 +1520,15 @@ pub const CodeGen = struct {
|
||||
const resolved_defaults = try self.allocator.dupe(?*Node, struct_decl.field_defaults);
|
||||
const display_name = try self.allocator.dupe(u8, alias_name);
|
||||
|
||||
try self.struct_types.put(mangled_name, .{
|
||||
const si2 = StructInfo{
|
||||
.field_names = struct_decl.field_names,
|
||||
.field_types = build.field_sx_types,
|
||||
.field_defaults = resolved_defaults,
|
||||
.llvm_type = build.llvm_type,
|
||||
.display_name = display_name,
|
||||
});
|
||||
};
|
||||
try self.struct_types.put(mangled_name, si2);
|
||||
try self.type_registry.put(mangled_name, .{ .struct_info = si2 });
|
||||
_ = try self.getAnyTypeId(mangled_name, .{ .struct_type = mangled_name });
|
||||
|
||||
return .{ .struct_type = mangled_name };
|
||||
@@ -1507,13 +1537,15 @@ pub const CodeGen = struct {
|
||||
fn registerInstantiatedTaggedEnum(self: *CodeGen, mangled_name: []const u8, union_decl: ast.EnumDecl) !Type {
|
||||
const build = try self.buildUnionFields(mangled_name, union_decl.variant_types);
|
||||
|
||||
try self.tagged_enum_types.put(mangled_name, .{
|
||||
const tei = TaggedEnumInfo{
|
||||
.variant_names = union_decl.variant_names,
|
||||
.variant_types = build.variant_sx_types,
|
||||
.llvm_type = build.llvm_type,
|
||||
.max_payload_size = build.max_payload_size,
|
||||
.payload_field_index = build.payload_field_index,
|
||||
});
|
||||
};
|
||||
try self.tagged_enum_types.put(mangled_name, tei);
|
||||
try self.type_registry.put(mangled_name, .{ .tagged_enum = tei });
|
||||
_ = try self.getAnyTypeId(mangled_name, .{ .union_type = mangled_name });
|
||||
|
||||
return .{ .union_type = mangled_name };
|
||||
@@ -1868,9 +1900,12 @@ pub const CodeGen = struct {
|
||||
try self.registerTaggedEnum(ed);
|
||||
const qualified_u = try std.fmt.allocPrint(self.allocator, "{s}.{s}", .{ ns.name, ed.name });
|
||||
try self.type_aliases.put(qualified_u, ed.name);
|
||||
try self.type_registry.put(qualified_u, .{ .alias = ed.name });
|
||||
} else {
|
||||
const qualified = try std.fmt.allocPrint(self.allocator, "{s}.{s}", .{ ns.name, ed.name });
|
||||
try self.enum_types.put(qualified, ed.variant_names);
|
||||
try self.type_registry.put(qualified, .{ .plain_enum = ed.variant_names });
|
||||
_ = try self.getAnyTypeId(qualified, .{ .enum_type = qualified });
|
||||
if (ed.backing_type) |bt_node| {
|
||||
const bt = self.resolveType(bt_node);
|
||||
try self.enum_backing_types.put(qualified, self.typeToLLVM(bt));
|
||||
@@ -1882,11 +1917,13 @@ pub const CodeGen = struct {
|
||||
// Register qualified alias so rl.Color resolves to Color
|
||||
const qualified_s = try std.fmt.allocPrint(self.allocator, "{s}.{s}", .{ ns.name, sd.name });
|
||||
try self.type_aliases.put(qualified_s, sd.name);
|
||||
try self.type_registry.put(qualified_s, .{ .alias = sd.name });
|
||||
},
|
||||
.union_decl => |ud| {
|
||||
try self.registerUnionType(ud);
|
||||
const qualified_u = try std.fmt.allocPrint(self.allocator, "{s}.{s}", .{ ns.name, ud.name });
|
||||
try self.type_aliases.put(qualified_u, ud.name);
|
||||
try self.type_registry.put(qualified_u, .{ .alias = ud.name });
|
||||
},
|
||||
.const_decl => |cd| {
|
||||
if (cd.value.data == .builtin_expr) {
|
||||
@@ -1897,6 +1934,7 @@ pub const CodeGen = struct {
|
||||
} else if (cd.value.data == .type_expr) {
|
||||
const qualified = try std.fmt.allocPrint(self.allocator, "{s}.{s}", .{ ns.name, cd.name });
|
||||
try self.type_aliases.put(qualified, cd.value.data.type_expr.name);
|
||||
try self.type_registry.put(qualified, .{ .alias = cd.value.data.type_expr.name });
|
||||
}
|
||||
},
|
||||
.library_decl => |ld| {
|
||||
@@ -1948,8 +1986,8 @@ pub const CodeGen = struct {
|
||||
// For function calls, look up the registered function's return type
|
||||
if (expr.data == .call) {
|
||||
if (self.resolveCalleeName(expr.data.call)) |callee_name| {
|
||||
const callee_name_z = self.allocator.dupeZ(u8, callee_name) catch return Type.s(64);
|
||||
const callee_fn = c.LLVMGetNamedFunction(self.module, callee_name_z.ptr) orelse return Type.s(64);
|
||||
var cnbuf: [256]u8 = undefined;
|
||||
const callee_fn = c.LLVMGetNamedFunction(self.module, self.nameToCStr(callee_name, &cnbuf)) orelse return Type.s(64);
|
||||
const fn_type = c.LLVMGlobalGetValueType(callee_fn);
|
||||
const ret_llvm = c.LLVMGetReturnType(fn_type);
|
||||
return self.llvmTypeToSxType(ret_llvm);
|
||||
@@ -2947,14 +2985,14 @@ pub const CodeGen = struct {
|
||||
}
|
||||
// Fall back to function name → function pointer value
|
||||
{
|
||||
const name_z = try self.allocator.dupeZ(u8, ident.name);
|
||||
var fn_val = c.LLVMGetNamedFunction(self.module, name_z.ptr);
|
||||
var nbuf: [256]u8 = undefined;
|
||||
var fn_val = c.LLVMGetNamedFunction(self.module, self.nameToCStr(ident.name, &nbuf));
|
||||
if (fn_val == null) {
|
||||
// Try qualified name with current namespace
|
||||
if (self.current_namespace) |ns| {
|
||||
const qualified = try std.fmt.allocPrint(self.allocator, "{s}.{s}", .{ ns, ident.name });
|
||||
const q_z = try self.allocator.dupeZ(u8, qualified);
|
||||
fn_val = c.LLVMGetNamedFunction(self.module, q_z.ptr);
|
||||
var qbuf: [256]u8 = undefined;
|
||||
fn_val = c.LLVMGetNamedFunction(self.module, self.nameToCStr(qualified, &qbuf));
|
||||
}
|
||||
}
|
||||
if (fn_val != null) return fn_val.?;
|
||||
@@ -3301,6 +3339,7 @@ pub const CodeGen = struct {
|
||||
try self.registerTaggedEnum(hoisted);
|
||||
} else {
|
||||
try self.enum_types.put(synthetic_name, inline_ed.variant_names);
|
||||
try self.type_registry.put(synthetic_name, .{ .plain_enum = inline_ed.variant_names });
|
||||
_ = try self.getAnyTypeId(synthetic_name, .{ .enum_type = synthetic_name });
|
||||
if (inline_ed.backing_type) |bt_node| {
|
||||
const bt = self.resolveType(bt_node);
|
||||
@@ -3342,12 +3381,14 @@ pub const CodeGen = struct {
|
||||
}
|
||||
}
|
||||
|
||||
try self.struct_types.put(sd.name, .{
|
||||
const sinfo = StructInfo{
|
||||
.field_names = sd.field_names,
|
||||
.field_types = build.field_sx_types,
|
||||
.field_defaults = resolved_defaults,
|
||||
.llvm_type = build.llvm_type,
|
||||
});
|
||||
};
|
||||
try self.struct_types.put(sd.name, sinfo);
|
||||
try self.type_registry.put(sd.name, .{ .struct_info = sinfo });
|
||||
_ = try self.getAnyTypeId(sd.name, .{ .struct_type = sd.name });
|
||||
}
|
||||
|
||||
@@ -3376,13 +3417,15 @@ pub const CodeGen = struct {
|
||||
}
|
||||
}
|
||||
|
||||
try self.tagged_enum_types.put(ud.name, .{
|
||||
const tei_layout = TaggedEnumInfo{
|
||||
.variant_names = ud.variant_names,
|
||||
.variant_types = try variant_sx_types.toOwnedSlice(self.allocator),
|
||||
.llvm_type = layout.llvm_type,
|
||||
.max_payload_size = layout.payload_size,
|
||||
.payload_field_index = layout.payload_field_index,
|
||||
});
|
||||
};
|
||||
try self.tagged_enum_types.put(ud.name, tei_layout);
|
||||
try self.type_registry.put(ud.name, .{ .tagged_enum = tei_layout });
|
||||
} else {
|
||||
// Primitive backing type (e.g. enum u32 { ... })
|
||||
if (ud.backing_type) |bt_node| {
|
||||
@@ -3392,13 +3435,15 @@ pub const CodeGen = struct {
|
||||
|
||||
const build = try self.buildUnionFields(ud.name, ud.variant_types);
|
||||
|
||||
try self.tagged_enum_types.put(ud.name, .{
|
||||
const tei_build = TaggedEnumInfo{
|
||||
.variant_names = ud.variant_names,
|
||||
.variant_types = build.variant_sx_types,
|
||||
.llvm_type = build.llvm_type,
|
||||
.max_payload_size = build.max_payload_size,
|
||||
.payload_field_index = build.payload_field_index,
|
||||
});
|
||||
};
|
||||
try self.tagged_enum_types.put(ud.name, tei_build);
|
||||
try self.type_registry.put(ud.name, .{ .tagged_enum = tei_build });
|
||||
}
|
||||
|
||||
_ = try self.getAnyTypeId(ud.name, .{ .union_type = ud.name });
|
||||
@@ -3575,13 +3620,15 @@ pub const CodeGen = struct {
|
||||
}
|
||||
}
|
||||
|
||||
try self.union_types.put(ud.name, .{
|
||||
const uinfo = UnionInfo{
|
||||
.field_names = ud.field_names,
|
||||
.field_types = resolved_field_types,
|
||||
.llvm_type = llvm_type,
|
||||
.total_size = max_size,
|
||||
.promoted_fields = promoted,
|
||||
});
|
||||
};
|
||||
try self.union_types.put(ud.name, uinfo);
|
||||
try self.type_registry.put(ud.name, .{ .union_info = uinfo });
|
||||
// Note: C-style unions are not registered with the Any type system.
|
||||
// They can't be meaningfully printed as a whole — access individual fields instead.
|
||||
}
|
||||
@@ -5112,22 +5159,22 @@ pub const CodeGen = struct {
|
||||
return self.genMemcpy(call_node.args);
|
||||
}
|
||||
|
||||
const name_z = try self.allocator.dupeZ(u8, callee_name);
|
||||
var callee_fn = c.LLVMGetNamedFunction(self.module, name_z.ptr);
|
||||
var nbuf: [256]u8 = undefined;
|
||||
var callee_fn = c.LLVMGetNamedFunction(self.module, self.nameToCStr(callee_name, &nbuf));
|
||||
// Foreign function fallback: qualified name "ns.Func" → try unqualified "Func" (the C symbol)
|
||||
if (callee_fn == null) {
|
||||
if (std.mem.lastIndexOfScalar(u8, callee_name, '.')) |dot_idx| {
|
||||
const base_name = callee_name[dot_idx + 1 ..];
|
||||
const base_z = try self.allocator.dupeZ(u8, base_name);
|
||||
callee_fn = c.LLVMGetNamedFunction(self.module, base_z.ptr);
|
||||
var bbuf: [256]u8 = undefined;
|
||||
callee_fn = c.LLVMGetNamedFunction(self.module, self.nameToCStr(base_name, &bbuf));
|
||||
}
|
||||
}
|
||||
// Intra-namespace fallback: try qualified name
|
||||
if (callee_fn == null) {
|
||||
if (self.current_namespace) |ns| {
|
||||
const qualified2 = try std.fmt.allocPrint(self.allocator, "{s}.{s}", .{ ns, callee_name });
|
||||
const qualified_z = try self.allocator.dupeZ(u8, qualified2);
|
||||
callee_fn = c.LLVMGetNamedFunction(self.module, qualified_z.ptr);
|
||||
var qbuf: [256]u8 = undefined;
|
||||
callee_fn = c.LLVMGetNamedFunction(self.module, self.nameToCStr(qualified2, &qbuf));
|
||||
}
|
||||
}
|
||||
// Function pointer indirect call: callee is a variable with function_type
|
||||
@@ -6677,13 +6724,23 @@ pub const CodeGen = struct {
|
||||
fn resolveTypeFromName(self: *CodeGen, name: []const u8) ?Type {
|
||||
// Primitives
|
||||
if (Type.fromName(name)) |t| return t;
|
||||
// Structs
|
||||
if (self.struct_types.contains(name)) return .{ .struct_type = name };
|
||||
// Unions (tagged enums and C-style)
|
||||
if (self.tagged_enum_types.contains(name)) return .{ .union_type = name };
|
||||
if (self.union_types.contains(name)) return .{ .union_type = name };
|
||||
// Enums
|
||||
if (self.enum_types.contains(name)) return .{ .enum_type = name };
|
||||
// Unified type registry lookup
|
||||
if (self.type_registry.get(name)) |entry| switch (entry) {
|
||||
.struct_info => return .{ .struct_type = name },
|
||||
.tagged_enum => return .{ .union_type = name },
|
||||
.union_info => return .{ .union_type = name },
|
||||
.plain_enum => return .{ .enum_type = name },
|
||||
.alias => |target| {
|
||||
if (Type.fromName(target)) |t| return t;
|
||||
if (self.type_registry.get(target)) |inner| switch (inner) {
|
||||
.struct_info => return .{ .struct_type = target },
|
||||
.tagged_enum => return .{ .union_type = target },
|
||||
.union_info => return .{ .union_type = target },
|
||||
.plain_enum => return .{ .enum_type = target },
|
||||
.alias => {},
|
||||
};
|
||||
},
|
||||
};
|
||||
// Vector display name: "Vector(N,T)"
|
||||
if (name.len > 8 and std.mem.startsWith(u8, name, "Vector(") and name[name.len - 1] == ')') {
|
||||
const inner = name[7 .. name.len - 1]; // "N,T"
|
||||
@@ -6847,14 +6904,14 @@ pub const CodeGen = struct {
|
||||
if (self.function_return_types.get(qualified)) |ret_ty| return ret_ty;
|
||||
}
|
||||
// Fallback: check non-generic LLVM functions
|
||||
const callee_name_z = self.allocator.dupeZ(u8, callee_name) catch return Type.s(64);
|
||||
var callee_fn_opt = c.LLVMGetNamedFunction(self.module, callee_name_z.ptr);
|
||||
var cnbuf2: [256]u8 = undefined;
|
||||
var callee_fn_opt = c.LLVMGetNamedFunction(self.module, self.nameToCStr(callee_name, &cnbuf2));
|
||||
// Intra-namespace fallback
|
||||
if (callee_fn_opt == null) {
|
||||
if (self.current_namespace) |ns2| {
|
||||
const q = std.fmt.allocPrint(self.allocator, "{s}.{s}", .{ ns2, callee_name }) catch return Type.s(64);
|
||||
const qz = self.allocator.dupeZ(u8, q) catch return Type.s(64);
|
||||
callee_fn_opt = c.LLVMGetNamedFunction(self.module, qz.ptr);
|
||||
var qbuf2: [256]u8 = undefined;
|
||||
callee_fn_opt = c.LLVMGetNamedFunction(self.module, self.nameToCStr(q, &qbuf2));
|
||||
}
|
||||
}
|
||||
if (callee_fn_opt) |callee_fn| {
|
||||
|
||||
Reference in New Issue
Block a user