This commit is contained in:
agra
2026-02-21 00:49:37 +02:00
parent be99b26c1d
commit ff2b2a69ab
2 changed files with 73 additions and 77 deletions

View File

@@ -2401,13 +2401,24 @@ pub const CodeGen = struct {
if (ret_type.isStruct()) {
const sname = self.resolveAlias(ret_type.struct_type);
const info = try self.getStructInfo(sname);
// If raw_val is already a struct value (not a pointer), return it directly
if (c.LLVMGetTypeKind(c.LLVMTypeOf(raw_val)) != c.LLVMPointerTypeKind)
return raw_val;
return c.LLVMBuildLoad2(self.builder, info.llvm_type, raw_val, "retval");
} else if (ret_type.isTuple()) {
const llvm_ty = self.typeToLLVM(ret_type);
if (c.LLVMGetTypeKind(c.LLVMTypeOf(raw_val)) != c.LLVMPointerTypeKind)
return raw_val;
return c.LLVMBuildLoad2(self.builder, llvm_ty, raw_val, "retval");
} else if (ret_type.isUnion()) {
const uname = ret_type.union_type;
const resolved = self.resolveAlias(uname);
// Try C-style (untagged) union first
if (self.lookupUnionInfo(resolved)) |info| {
if (c.LLVMGetTypeKind(c.LLVMTypeOf(raw_val)) != c.LLVMPointerTypeKind)
return raw_val;
return c.LLVMBuildLoad2(self.builder, info.llvm_type, raw_val, "retval");
}
const info = try self.getTaggedEnumInfo(resolved);
return self.loadIfPointer(raw_val, info.llvm_type, "retval");
} else {
@@ -2811,7 +2822,10 @@ pub const CodeGen = struct {
} else if (vd.value.?.data == .undef_literal) {
self.storeUndef(info.llvm_type, alloca);
} else {
return self.emitErrorFmt("union '{s}' must be initialized with '---' or field assignment", .{uname});
// Allow initialization from expression (e.g. function call returning union)
var val = try self.genExpr(vd.value.?);
val = self.loadIfPointer(val, info.llvm_type, "union_init");
_ = c.LLVMBuildStore(self.builder, val, alloca);
}
try self.registerVariable(vd.name, alloca, sx_ty);
@@ -5530,6 +5544,20 @@ pub const CodeGen = struct {
const slice_val = c.LLVMBuildLoad2(self.builder, self.getStringStructType(), loaded_ptr, "pslice_load");
return self.extractFatPtrField(slice_val, fa.field, "*slice");
}
if (pointee_ty.isUnion()) {
const uname = pointee_ty.union_type;
if (self.lookupUnionInfo(uname)) |info| {
if (self.findNameIndex(info.field_names, fa.field)) |fidx| {
const field_ty = info.field_types[fidx];
return self.loadTyped(field_ty, loaded_ptr, "punion_field");
}
if (info.promoted_fields.get(fa.field)) |pf| {
const sinfo = try self.getStructInfo(pf.struct_name);
return self.loadStructField(sinfo.llvm_type, loaded_ptr, @intCast(pf.field_index), self.typeToLLVM(pf.field_type));
}
return self.emitErrorFmt("no field '{s}' in union '{s}'", .{ fa.field, uname });
}
}
return self.emitErrorFmt("no field '{s}' on pointer", .{fa.field});
}
if (entry.ty.isStruct()) {