aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-10-17 15:36:12 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-10-17 15:36:12 -0700
commit07691db3ae061d8122f6c53c1f34c2fb0df2f7ef (patch)
tree379046dbe83b30f007433360ad08d3bdee7e2234 /src
parent6534f2ef4f8161f4121326f19bc3cf89324f62c5 (diff)
downloadzig-07691db3ae061d8122f6c53c1f34c2fb0df2f7ef.tar.gz
zig-07691db3ae061d8122f6c53c1f34c2fb0df2f7ef.zip
stage2: fix handling of error unions as return type
* LLVM backend: fix phi instruction not respecting `isByRef` - Also fix `is_non_null` not respecting `isByRef` * Type: implement abiSize for error unions
Diffstat (limited to 'src')
-rw-r--r--src/codegen/llvm.zig20
-rw-r--r--src/type.zig40
2 files changed, 36 insertions, 24 deletions
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig
index 026046b29f..e8bfbef587 100644
--- a/src/codegen/llvm.zig
+++ b/src/codegen/llvm.zig
@@ -1804,14 +1804,16 @@ pub const FuncGen = struct {
const raw_llvm_ty = try self.dg.llvmType(inst_ty);
- // If the zig tag type is a function, this represents an actual function body; not
- // a pointer to it. LLVM IR allows the call instruction to use function bodies instead
- // of function pointers, however the phi makes it a runtime value and therefore
- // the LLVM type has to be wrapped in a pointer.
- const llvm_ty = if (inst_ty.zigTypeTag() == .Fn)
- raw_llvm_ty.pointerType(0)
- else
- raw_llvm_ty;
+ const llvm_ty = ty: {
+ // If the zig tag type is a function, this represents an actual function body; not
+ // a pointer to it. LLVM IR allows the call instruction to use function bodies instead
+ // of function pointers, however the phi makes it a runtime value and therefore
+ // the LLVM type has to be wrapped in a pointer.
+ if (inst_ty.zigTypeTag() == .Fn or isByRef(inst_ty)) {
+ break :ty raw_llvm_ty.pointerType(0);
+ }
+ break :ty raw_llvm_ty;
+ };
const phi_node = self.builder.buildPhi(llvm_ty, "");
phi_node.addIncoming(
@@ -2315,7 +2317,7 @@ pub const FuncGen = struct {
return self.builder.buildICmp(op, loaded, zero, "");
}
- if (operand_is_ptr) {
+ if (operand_is_ptr or isByRef(err_union_ty)) {
const err_field_ptr = self.builder.buildStructGEP(operand, 0, "");
const loaded = self.builder.buildLoad(err_field_ptr, "");
return self.builder.buildICmp(op, loaded, zero, "");
diff --git a/src/type.zig b/src/type.zig
index 31f6d57ad4..f7cd00dd06 100644
--- a/src/type.zig
+++ b/src/type.zig
@@ -1693,15 +1693,15 @@ pub const Type = extern union {
},
.error_union => {
- const payload = self.castTag(.error_union).?.data;
- if (!payload.error_set.hasCodeGenBits()) {
- return payload.payload.abiAlignment(target);
- } else if (!payload.payload.hasCodeGenBits()) {
- return payload.error_set.abiAlignment(target);
+ const data = self.castTag(.error_union).?.data;
+ if (!data.error_set.hasCodeGenBits()) {
+ return data.payload.abiAlignment(target);
+ } else if (!data.payload.hasCodeGenBits()) {
+ return data.error_set.abiAlignment(target);
}
- return std.math.max(
- payload.payload.abiAlignment(target),
- payload.error_set.abiAlignment(target),
+ return @maximum(
+ data.payload.abiAlignment(target),
+ data.error_set.abiAlignment(target),
);
},
@@ -1942,15 +1942,25 @@ pub const Type = extern union {
},
.error_union => {
- const payload = self.castTag(.error_union).?.data;
- if (!payload.error_set.hasCodeGenBits() and !payload.payload.hasCodeGenBits()) {
+ const data = self.castTag(.error_union).?.data;
+ if (!data.error_set.hasCodeGenBits() and !data.payload.hasCodeGenBits()) {
return 0;
- } else if (!payload.error_set.hasCodeGenBits()) {
- return payload.payload.abiSize(target);
- } else if (!payload.payload.hasCodeGenBits()) {
- return payload.error_set.abiSize(target);
+ } else if (!data.error_set.hasCodeGenBits()) {
+ return data.payload.abiSize(target);
+ } else if (!data.payload.hasCodeGenBits()) {
+ return data.error_set.abiSize(target);
}
- std.debug.panic("TODO abiSize error union {}", .{self});
+ const code_align = abiAlignment(data.error_set, target);
+ const payload_align = abiAlignment(data.payload, target);
+ const big_align = @maximum(code_align, payload_align);
+ const payload_size = abiSize(data.payload, target);
+
+ var size: u64 = 0;
+ size += abiSize(data.error_set, target);
+ size = std.mem.alignForwardGeneric(u64, size, payload_align);
+ size += payload_size;
+ size = std.mem.alignForwardGeneric(u64, size, big_align);
+ return size;
},
};
}