aboutsummaryrefslogtreecommitdiff
path: root/src/codegen/llvm.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-10-17 14:50:47 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-10-17 14:55:32 -0700
commit6534f2ef4f8161f4121326f19bc3cf89324f62c5 (patch)
tree87fb9d6f2b082a534402080f53febf483d81e7fc /src/codegen/llvm.zig
parent53b87fa78a3ee2c261f3bdd6a71d5733fe17ffd5 (diff)
downloadzig-6534f2ef4f8161f4121326f19bc3cf89324f62c5.tar.gz
zig-6534f2ef4f8161f4121326f19bc3cf89324f62c5.zip
stage2: implement error wrapping
* Sema: fix returned operands not coercing to the function return type in some cases. - When returning an error or an error union from a function with an inferred error set, it will now populate the inferred error set. - Implement error set coercion for the common case of inferred error set to inferred error set, without forcing a full resolution. * LLVM backend: update instruction lowering that handles error unions to respect `isByRef`. - Also implement `wrap_err_union_err`.
Diffstat (limited to 'src/codegen/llvm.zig')
-rw-r--r--src/codegen/llvm.zig48
1 files changed, 33 insertions, 15 deletions
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig
index 4349fce4d9..026046b29f 100644
--- a/src/codegen/llvm.zig
+++ b/src/codegen/llvm.zig
@@ -2301,8 +2301,7 @@ pub const FuncGen = struct {
op: llvm.IntPredicate,
operand_is_ptr: bool,
) !?*const llvm.Value {
- if (self.liveness.isUnused(inst))
- return null;
+ if (self.liveness.isUnused(inst)) return null;
const un_op = self.air.instructions.items(.data)[inst].un_op;
const operand = try self.resolveInst(un_op);
@@ -2363,22 +2362,16 @@ pub const FuncGen = struct {
inst: Air.Inst.Index,
operand_is_ptr: bool,
) !?*const llvm.Value {
- if (self.liveness.isUnused(inst))
- return null;
+ if (self.liveness.isUnused(inst)) return null;
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
const operand = try self.resolveInst(ty_op.operand);
const err_union_ty = self.air.typeOf(ty_op.operand);
const payload_ty = err_union_ty.errorUnionPayload();
-
- if (!payload_ty.hasCodeGenBits()) {
- return null;
- }
-
- if (operand_is_ptr) {
+ if (!payload_ty.hasCodeGenBits()) return null;
+ if (operand_is_ptr or isByRef(payload_ty)) {
return self.builder.buildStructGEP(operand, 1, "");
}
-
return self.builder.buildExtractValue(operand, 1, "");
}
@@ -2400,7 +2393,7 @@ pub const FuncGen = struct {
return self.builder.buildLoad(operand, "");
}
- if (operand_is_ptr) {
+ if (operand_is_ptr or isByRef(payload_ty)) {
const err_field_ptr = self.builder.buildStructGEP(operand, 0, "");
return self.builder.buildLoad(err_field_ptr, "");
}
@@ -2469,10 +2462,35 @@ pub const FuncGen = struct {
}
fn airWrapErrUnionErr(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
- if (self.liveness.isUnused(inst))
- return null;
+ if (self.liveness.isUnused(inst)) return null;
+
+ const ty_op = self.air.instructions.items(.data)[inst].ty_op;
+ const err_un_ty = self.air.typeOfIndex(inst);
+ const payload_ty = err_un_ty.errorUnionPayload();
+ const operand = try self.resolveInst(ty_op.operand);
+ if (!payload_ty.hasCodeGenBits()) {
+ return operand;
+ }
+ const err_un_llvm_ty = try self.dg.llvmType(err_un_ty);
+ if (isByRef(err_un_ty)) {
+ const result_ptr = self.buildAlloca(err_un_llvm_ty);
+ const err_ptr = self.builder.buildStructGEP(result_ptr, 0, "");
+ _ = self.builder.buildStore(operand, err_ptr);
+ const payload_ptr = self.builder.buildStructGEP(result_ptr, 1, "");
+ var ptr_ty_payload: Type.Payload.ElemType = .{
+ .base = .{ .tag = .single_mut_pointer },
+ .data = payload_ty,
+ };
+ const payload_ptr_ty = Type.initPayload(&ptr_ty_payload.base);
+ // TODO store undef to payload_ptr
+ _ = payload_ptr;
+ _ = payload_ptr_ty;
+ return result_ptr;
+ }
- return self.todo("implement llvm codegen for 'airWrapErrUnionErr'", .{});
+ const partial = self.builder.buildInsertValue(err_un_llvm_ty.getUndef(), operand, 0, "");
+ // TODO set payload bytes to undef
+ return partial;
}
fn airMin(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {