...
This commit is contained in:
115
src/codegen.zig
115
src/codegen.zig
@@ -480,7 +480,7 @@ pub const CodeGen = struct {
|
||||
}
|
||||
|
||||
fn resolveElementType(self: *CodeGen, name: []const u8, comptime kind: []const u8) !Type {
|
||||
return Type.fromName(name) orelse
|
||||
return self.resolveTypeFromName(name) orelse
|
||||
return self.emitErrorFmt("unknown " ++ kind ++ " element type '{s}'", .{name});
|
||||
}
|
||||
|
||||
@@ -557,11 +557,11 @@ pub const CodeGen = struct {
|
||||
.struct_type => |name| if (self.lookupStructInfo(name)) |info| info.llvm_type else unreachable,
|
||||
.union_type => |name| if (self.lookupTaggedEnumInfo(name)) |info| info.llvm_type else if (self.lookupUnionInfo(name)) |info| info.llvm_type else unreachable,
|
||||
.array_type => |info| {
|
||||
const elem_ty = Type.fromName(info.element_name) orelse unreachable;
|
||||
const elem_ty = self.resolveTypeFromName(info.element_name) orelse unreachable;
|
||||
return c.LLVMArrayType2(self.typeToLLVM(elem_ty), info.length);
|
||||
},
|
||||
.vector_type => |info| {
|
||||
const elem_ty = Type.fromName(info.element_name) orelse unreachable;
|
||||
const elem_ty = self.resolveTypeFromName(info.element_name) orelse unreachable;
|
||||
return c.LLVMVectorType(self.typeToLLVM(elem_ty), info.length);
|
||||
},
|
||||
.pointer_type, .many_pointer_type, .function_type => self.ptrType(),
|
||||
@@ -2381,9 +2381,8 @@ pub const CodeGen = struct {
|
||||
|
||||
const ret_val = try self.genExpr(lambda.body);
|
||||
if (ret_val) |val| {
|
||||
const src_ty = self.llvmTypeToSxType(c.LLVMTypeOf(val));
|
||||
const converted = self.convertValue(val, src_ty, ret_sx_type);
|
||||
self.ret(converted);
|
||||
const prepared = try self.prepareReturnValue(val, ret_sx_type);
|
||||
self.ret(prepared);
|
||||
} else {
|
||||
self.retVoid();
|
||||
}
|
||||
@@ -2461,9 +2460,8 @@ pub const CodeGen = struct {
|
||||
if (ret_sx_type == .void_type) {
|
||||
self.retVoid();
|
||||
} else if (last_val) |val| {
|
||||
const src_ty = self.llvmTypeToSxType(c.LLVMTypeOf(val));
|
||||
const converted = self.convertValue(val, src_ty, ret_sx_type);
|
||||
self.ret(converted);
|
||||
const ret_val = try self.prepareReturnValue(val, ret_sx_type);
|
||||
self.ret(ret_val);
|
||||
} else {
|
||||
self.retVoid();
|
||||
}
|
||||
@@ -2977,7 +2975,7 @@ pub const CodeGen = struct {
|
||||
// C-style union: full assignment not supported, use field assignment
|
||||
}
|
||||
|
||||
const new_val = try self.genExpr(asgn.value);
|
||||
const new_val = try self.genExprAsType(asgn.value, entry.ty);
|
||||
const llvm_ty = self.typeToLLVM(entry.ty);
|
||||
|
||||
const store_val = if (asgn.op == .assign) new_val else blk: {
|
||||
@@ -3150,7 +3148,7 @@ pub const CodeGen = struct {
|
||||
}
|
||||
if (obj_ty.isSlice()) {
|
||||
const slice_info = obj_ty.slice_type;
|
||||
const elem_ty = Type.fromName(slice_info.element_name) orelse return self.emitError("unknown slice element type");
|
||||
const elem_ty = self.resolveTypeFromName(slice_info.element_name) orelse return self.emitError("unknown slice element type");
|
||||
const elem_llvm_ty = self.typeToLLVM(elem_ty);
|
||||
// Load slice value to get ptr
|
||||
const slice_val = blk: {
|
||||
@@ -3558,25 +3556,22 @@ pub const CodeGen = struct {
|
||||
fn hoistInlineTypeDecl(self: *CodeGen, parent_name: []const u8, child_name: []const u8, type_node: *Node) anyerror!void {
|
||||
const synthetic_name = try std.fmt.allocPrint(self.allocator, "{s}.{s}", .{ parent_name, child_name });
|
||||
switch (type_node.data) {
|
||||
.struct_decl => |inline_sd| {
|
||||
var hoisted = inline_sd;
|
||||
hoisted.name = synthetic_name;
|
||||
try self.registerStructType(hoisted);
|
||||
.struct_decl => |*sd| {
|
||||
sd.name = synthetic_name;
|
||||
try self.registerStructType(sd.*);
|
||||
},
|
||||
.union_decl => |inline_ud| {
|
||||
var hoisted_ud = inline_ud;
|
||||
hoisted_ud.name = synthetic_name;
|
||||
try self.registerUnionType(hoisted_ud);
|
||||
.union_decl => |*ud| {
|
||||
ud.name = synthetic_name;
|
||||
try self.registerUnionType(ud.*);
|
||||
},
|
||||
.enum_decl => |inline_ed| {
|
||||
if (inline_ed.variant_types.len > 0) {
|
||||
var hoisted = inline_ed;
|
||||
hoisted.name = synthetic_name;
|
||||
try self.registerTaggedEnum(hoisted);
|
||||
.enum_decl => |*ed| {
|
||||
ed.name = synthetic_name;
|
||||
if (ed.variant_types.len > 0) {
|
||||
try self.registerTaggedEnum(ed.*);
|
||||
} else {
|
||||
try self.type_registry.put(synthetic_name, .{ .plain_enum = inline_ed.variant_names });
|
||||
try self.type_registry.put(synthetic_name, .{ .plain_enum = ed.variant_names });
|
||||
_ = try self.getAnyTypeId(synthetic_name, .{ .enum_type = synthetic_name });
|
||||
if (inline_ed.backing_type) |bt_node| {
|
||||
if (ed.backing_type) |bt_node| {
|
||||
const bt = self.resolveType(bt_node);
|
||||
try self.enum_backing_types.put(synthetic_name, self.typeToLLVM(bt));
|
||||
}
|
||||
@@ -3783,7 +3778,7 @@ pub const CodeGen = struct {
|
||||
// Validate payload is an array type
|
||||
const payload_size = switch (payload_ty) {
|
||||
.array_type => |info| blk: {
|
||||
const elem_ty = Type.fromName(info.element_name) orelse {
|
||||
const elem_ty = self.resolveTypeFromName(info.element_name) orelse {
|
||||
return self.emitErrorFmt(
|
||||
"enum '{s}': layout field 'payload' has unresolved element type '{s}'",
|
||||
.{ enum_name, info.element_name },
|
||||
@@ -4623,7 +4618,7 @@ pub const CodeGen = struct {
|
||||
// Vector: extractelement + box as Any
|
||||
if (val_ty.isVector()) {
|
||||
const info = val_ty.vector_type;
|
||||
const elem_ty = Type.fromName(info.element_name) orelse
|
||||
const elem_ty = self.resolveTypeFromName(info.element_name) orelse
|
||||
return self.emitErrorFmt("unknown vector element type '{s}'", .{info.element_name});
|
||||
const idx = try self.genExpr(call_node.args[1]);
|
||||
const elem = c.LLVMBuildExtractElement(self.builder, val, idx, "vec_elem");
|
||||
@@ -4685,7 +4680,7 @@ pub const CodeGen = struct {
|
||||
// Slice: extract ptr, GEP to element, load, box as Any
|
||||
if (val_ty.isSlice()) {
|
||||
const sinfo = val_ty.slice_type;
|
||||
const elem_ty = Type.fromName(sinfo.element_name) orelse
|
||||
const elem_ty = self.resolveTypeFromName(sinfo.element_name) orelse
|
||||
return self.emitErrorFmt("unknown slice element type '{s}'", .{sinfo.element_name});
|
||||
const elem_llvm_ty = self.typeToLLVM(elem_ty);
|
||||
// val is {ptr, i32} — extract ptr
|
||||
@@ -4699,7 +4694,7 @@ pub const CodeGen = struct {
|
||||
// Array: GEP + load + box as Any
|
||||
if (val_ty.isArray()) {
|
||||
const ainfo = val_ty.array_type;
|
||||
const elem_ty = Type.fromName(ainfo.element_name) orelse
|
||||
const elem_ty = self.resolveTypeFromName(ainfo.element_name) orelse
|
||||
return self.emitErrorFmt("unknown array element type '{s}'", .{ainfo.element_name});
|
||||
const arr_llvm_ty = self.typeToLLVM(val_ty);
|
||||
const elem_llvm_ty = self.typeToLLVM(elem_ty);
|
||||
@@ -5215,7 +5210,7 @@ pub const CodeGen = struct {
|
||||
const elem_llvm_ty = if (obj_ty == .string_type)
|
||||
self.i8Type()
|
||||
else
|
||||
self.typeToLLVM(Type.fromName(obj_ty.slice_type.element_name) orelse return self.emitError("unknown slice element type"));
|
||||
self.typeToLLVM(self.resolveTypeFromName(obj_ty.slice_type.element_name) orelse return self.emitError("unknown slice element type"));
|
||||
const new_ptr = self.gepPointerElement(elem_llvm_ty, base_ptr, start_val, "sslice_off");
|
||||
// len = end - start
|
||||
const len_val = c.LLVMBuildSub(self.builder, end_val, start_val, "sslice_len");
|
||||
@@ -5803,9 +5798,9 @@ pub const CodeGen = struct {
|
||||
if (i < call_node.args.len) {
|
||||
const arg_ty = self.inferType(call_node.args[i]);
|
||||
const elem_ty = if (arg_ty.isArray())
|
||||
Type.fromName(arg_ty.array_type.element_name) orelse arg_ty
|
||||
self.resolveTypeFromName(arg_ty.array_type.element_name) orelse arg_ty
|
||||
else if (arg_ty.isSlice())
|
||||
Type.fromName(arg_ty.slice_type.element_name) orelse arg_ty
|
||||
self.resolveTypeFromName(arg_ty.slice_type.element_name) orelse arg_ty
|
||||
else
|
||||
arg_ty;
|
||||
if (bindings.get(type_name)) |existing| {
|
||||
@@ -6036,9 +6031,9 @@ pub const CodeGen = struct {
|
||||
if (std.mem.eql(u8, tp.name, tp_name)) {
|
||||
// Extract element type from concrete slice type
|
||||
const elem_ty = if (sx_type.isSlice())
|
||||
Type.fromName(sx_type.slice_type.element_name) orelse sx_type
|
||||
self.resolveTypeFromName(sx_type.slice_type.element_name) orelse sx_type
|
||||
else if (sx_type.isArray())
|
||||
Type.fromName(sx_type.array_type.element_name) orelse sx_type
|
||||
self.resolveTypeFromName(sx_type.array_type.element_name) orelse sx_type
|
||||
else
|
||||
sx_type;
|
||||
try bindings.put(tp.name, elem_ty);
|
||||
@@ -6291,16 +6286,8 @@ pub const CodeGen = struct {
|
||||
if (ret_sx_type == .void_type) {
|
||||
self.retVoid();
|
||||
} else if (last_val) |val| {
|
||||
if (ret_sx_type.isStruct()) {
|
||||
const sname = ret_sx_type.struct_type;
|
||||
const info = try self.getStructInfo(sname);
|
||||
const loaded = c.LLVMBuildLoad2(self.builder, info.llvm_type, val, "retval");
|
||||
self.ret(loaded);
|
||||
} else {
|
||||
const src_ty = self.llvmTypeToSxType(c.LLVMTypeOf(val));
|
||||
const converted = self.convertValue(val, src_ty, ret_sx_type);
|
||||
self.ret(converted);
|
||||
}
|
||||
const ret_val = try self.prepareReturnValue(val, ret_sx_type);
|
||||
self.ret(ret_val);
|
||||
} else {
|
||||
_ = c.LLVMBuildUnreachable(self.builder);
|
||||
}
|
||||
@@ -6427,7 +6414,7 @@ pub const CodeGen = struct {
|
||||
if (iter_ty.isSlice()) {
|
||||
is_slice = true;
|
||||
const info = iter_ty.slice_type;
|
||||
elem_ty = Type.fromName(info.element_name) orelse Type.s(64);
|
||||
elem_ty = self.resolveTypeFromName(info.element_name) orelse Type.s(64);
|
||||
// Load slice value from alloca
|
||||
if (for_expr.iterable.data == .identifier) {
|
||||
if (self.named_values.get(for_expr.iterable.data.identifier.name)) |entry| {
|
||||
@@ -6438,7 +6425,7 @@ pub const CodeGen = struct {
|
||||
} else return self.emitError("for: slice iterable must be a variable");
|
||||
} else if (iter_ty.isArray()) {
|
||||
const info = iter_ty.array_type;
|
||||
elem_ty = Type.fromName(info.element_name) orelse Type.s(64);
|
||||
elem_ty = self.resolveTypeFromName(info.element_name) orelse Type.s(64);
|
||||
len_val = c.LLVMConstInt(i64_type, info.length, 0);
|
||||
// Get pointer to array
|
||||
if (for_expr.iterable.data == .identifier) {
|
||||
@@ -6571,12 +6558,23 @@ pub const CodeGen = struct {
|
||||
if (subject_ty.isUnion()) union_name = subject_ty.union_type;
|
||||
|
||||
// Get the switch value: for unions, load the tag from field 0; for enums, use the value directly
|
||||
// Get the switch value: for unions, load the tag from field 0; for enums, use the value directly
|
||||
// For union subjects, we need a pointer for both tag loading and payload capture.
|
||||
// If the subject is a simple identifier, use its existing alloca; otherwise generate
|
||||
// the expression and spill into a temporary alloca.
|
||||
var union_subject_ptr: c.LLVMValueRef = null;
|
||||
const subject_val: c.LLVMValueRef = if (union_name != null) blk: {
|
||||
// Union: load tag from field 0 of the alloca
|
||||
const entry = self.named_values.get(match.subject.data.identifier.name).?;
|
||||
const info = self.lookupTaggedEnumInfo(union_name.?).?;
|
||||
break :blk self.loadStructField(info.llvm_type, entry.ptr, 0, self.getEnumLLVMType(union_name.?));
|
||||
if (match.subject.data == .identifier) {
|
||||
const entry = self.named_values.get(match.subject.data.identifier.name).?;
|
||||
union_subject_ptr = entry.ptr;
|
||||
} else {
|
||||
// Non-identifier subject (e.g. function call): spill to temp alloca
|
||||
const val = try self.genExpr(match.subject);
|
||||
const tmp = c.LLVMBuildAlloca(self.builder, info.llvm_type, "match_tmp");
|
||||
_ = c.LLVMBuildStore(self.builder, val, tmp);
|
||||
union_subject_ptr = tmp;
|
||||
}
|
||||
break :blk self.loadStructField(info.llvm_type, union_subject_ptr.?, 0, self.getEnumLLVMType(union_name.?));
|
||||
} else try self.genExpr(match.subject);
|
||||
|
||||
const variants: ?[]const []const u8 = if (union_name) |un|
|
||||
@@ -6630,6 +6628,12 @@ pub const CodeGen = struct {
|
||||
for (tag_values) |tag| {
|
||||
c.LLVMAddCase(sw, c.LLVMConstInt(i64_type, tag, 0), case_bbs.items[i]);
|
||||
}
|
||||
} else if (pat.data == .int_literal) {
|
||||
const case_val = c.LLVMConstInt(case_int_type, @bitCast(@as(i64, pat.data.int_literal.value)), 0);
|
||||
c.LLVMAddCase(sw, case_val, case_bbs.items[i]);
|
||||
} else if (pat.data == .bool_literal) {
|
||||
const case_val = c.LLVMConstInt(case_int_type, @intFromBool(pat.data.bool_literal.value), 0);
|
||||
c.LLVMAddCase(sw, case_val, case_bbs.items[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6677,8 +6681,7 @@ pub const CodeGen = struct {
|
||||
if (vidx) |vi| {
|
||||
const variant_ty = uinfo.variant_types[vi];
|
||||
if (variant_ty != .void_type) {
|
||||
const subject_entry = self.named_values.get(match.subject.data.identifier.name).?;
|
||||
const payload_gep = self.structGEP(uinfo.llvm_type, subject_entry.ptr, uinfo.payload_field_index, "cap_payload");
|
||||
const payload_gep = self.structGEP(uinfo.llvm_type, union_subject_ptr.?, uinfo.payload_field_index, "cap_payload");
|
||||
const payload_llvm_ty = self.typeToLLVM(variant_ty);
|
||||
const payload_val = c.LLVMBuildLoad2(self.builder, payload_llvm_ty, payload_gep, "cap_load");
|
||||
const cap_alloca = c.LLVMBuildAlloca(self.builder, payload_llvm_ty, @ptrCast(cap_name.ptr));
|
||||
@@ -7245,9 +7248,11 @@ pub const CodeGen = struct {
|
||||
}
|
||||
if (obj_ty.isSlice()) {
|
||||
if (std.mem.eql(u8, fa.field, "len")) return Type.s(64);
|
||||
if (std.mem.eql(u8, fa.field, "ptr")) return .{ .many_pointer_type = .{ .element_name = obj_ty.slice_type.element_name } };
|
||||
}
|
||||
if (obj_ty.isArray()) {
|
||||
if (std.mem.eql(u8, fa.field, "len")) return Type.s(64);
|
||||
if (std.mem.eql(u8, fa.field, "ptr")) return .{ .many_pointer_type = .{ .element_name = obj_ty.array_type.element_name } };
|
||||
}
|
||||
if (obj_ty.isAny()) {
|
||||
if (std.mem.eql(u8, fa.field, "tag")) return Type.s(64);
|
||||
@@ -7289,10 +7294,10 @@ pub const CodeGen = struct {
|
||||
return obj_ty.vectorElementType() orelse Type.s(64);
|
||||
}
|
||||
if (obj_ty.isArray()) {
|
||||
return Type.fromName(obj_ty.array_type.element_name) orelse Type.s(64);
|
||||
return self.resolveTypeFromName(obj_ty.array_type.element_name) orelse Type.s(64);
|
||||
}
|
||||
if (obj_ty.isSlice()) {
|
||||
return obj_ty.sliceElementType() orelse Type.s(64);
|
||||
return self.resolveTypeFromName(obj_ty.slice_type.element_name) orelse Type.s(64);
|
||||
}
|
||||
if (obj_ty.isManyPointer()) {
|
||||
return self.resolveTypeFromName(obj_ty.many_pointer_type.element_name) orelse Type.s(64);
|
||||
|
||||
Reference in New Issue
Block a user