diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/Air.zig | 4 | ||||
| -rw-r--r-- | src/Liveness.zig | 1 | ||||
| -rw-r--r-- | src/Sema.zig | 8 | ||||
| -rw-r--r-- | src/arch/aarch64/CodeGen.zig | 7 | ||||
| -rw-r--r-- | src/arch/arm/CodeGen.zig | 7 | ||||
| -rw-r--r-- | src/arch/riscv64/CodeGen.zig | 7 | ||||
| -rw-r--r-- | src/arch/wasm/CodeGen.zig | 1 | ||||
| -rw-r--r-- | src/arch/x86_64/CodeGen.zig | 10 | ||||
| -rw-r--r-- | src/codegen/c.zig | 7 | ||||
| -rw-r--r-- | src/codegen/llvm.zig | 32 | ||||
| -rw-r--r-- | src/print_air.zig | 1 |
11 files changed, 84 insertions, 1 deletions
diff --git a/src/Air.zig b/src/Air.zig index 070b43ac49..b9a565ad2e 100644 --- a/src/Air.zig +++ b/src/Air.zig @@ -429,6 +429,9 @@ pub const Inst = struct { /// *(E!T) -> E. If the value is not an error, undefined behavior. /// Uses the `ty_op` field. unwrap_errunion_err_ptr, + /// *(E!T) => *T. Sets the value to non-error with an undefined payload value. + /// Uses the `ty_op` field. + errunion_payload_ptr_set, /// wrap from T to E!T /// Uses the `ty_op` field. wrap_errunion_payload, @@ -865,6 +868,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type { .optional_payload, .optional_payload_ptr, .optional_payload_ptr_set, + .errunion_payload_ptr_set, .wrap_optional, .unwrap_errunion_payload, .unwrap_errunion_err, diff --git a/src/Liveness.zig b/src/Liveness.zig index 71f1221b23..5a329d2a7a 100644 --- a/src/Liveness.zig +++ b/src/Liveness.zig @@ -293,6 +293,7 @@ fn analyzeInst( .optional_payload, .optional_payload_ptr, .optional_payload_ptr_set, + .errunion_payload_ptr_set, .wrap_optional, .unwrap_errunion_payload, .unwrap_errunion_err, diff --git a/src/Sema.zig b/src/Sema.zig index acccc0e3bf..2d9381493a 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -1636,7 +1636,13 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE return sema.fail(block, src, "TODO coerce_result_ptr wrap_errunion_err", .{}); }, .wrap_errunion_payload => { - return sema.fail(block, src, "TODO coerce_result_ptr wrap_errunion_payload", .{}); + const ty_op = air_datas[trash_inst].ty_op; + const payload_ty = sema.getTmpAir().typeOf(ty_op.operand); + const ptr_payload_ty = try Type.ptr(sema.arena, .{ + .pointee_type = payload_ty, + .@"addrspace" = addr_space, + }); + new_ptr = try block.addTyOp(.errunion_payload_ptr_set, ptr_payload_ty, new_ptr); }, else => { if (std.debug.runtime_safety) { diff --git a/src/arch/aarch64/CodeGen.zig b/src/arch/aarch64/CodeGen.zig index 7a3d049ae6..2267a156f9 100644 --- a/src/arch/aarch64/CodeGen.zig +++ b/src/arch/aarch64/CodeGen.zig @@ -662,6 +662,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { .unwrap_errunion_payload => try self.airUnwrapErrPayload(inst), .unwrap_errunion_err_ptr => try self.airUnwrapErrErrPtr(inst), .unwrap_errunion_payload_ptr=> try self.airUnwrapErrPayloadPtr(inst), + .errunion_payload_ptr_set => try self.airErrUnionPayloadPtrSet(inst), .wrap_optional => try self.airWrapOptional(inst), .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst), @@ -1443,6 +1444,12 @@ fn airUnwrapErrPayloadPtr(self: *Self, inst: Air.Inst.Index) !void { return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); } +fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void { + const ty_op = self.air.instructions.items(.data)[inst].ty_op; + const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement .errunion_payload_ptr_set for {}", .{self.target.cpu.arch}); + return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); +} + fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { const ty_op = self.air.instructions.items(.data)[inst].ty_op; const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { diff --git a/src/arch/arm/CodeGen.zig b/src/arch/arm/CodeGen.zig index 6f87c56503..3633b5ccd0 100644 --- a/src/arch/arm/CodeGen.zig +++ b/src/arch/arm/CodeGen.zig @@ -646,6 +646,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { .unwrap_errunion_payload => try self.airUnwrapErrPayload(inst), .unwrap_errunion_err_ptr => try self.airUnwrapErrErrPtr(inst), .unwrap_errunion_payload_ptr=> try self.airUnwrapErrPayloadPtr(inst), + .errunion_payload_ptr_set => try self.airErrUnionPayloadPtrSet(inst), .wrap_optional => try self.airWrapOptional(inst), .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst), @@ -1128,6 +1129,12 @@ fn airUnwrapErrPayloadPtr(self: *Self, inst: Air.Inst.Index) !void { return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); } +fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void { + const ty_op = self.air.instructions.items(.data)[inst].ty_op; + const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement .errunion_payload_ptr_set for {}", .{self.target.cpu.arch}); + return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); +} + fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { const ty_op = self.air.instructions.items(.data)[inst].ty_op; const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { diff --git a/src/arch/riscv64/CodeGen.zig b/src/arch/riscv64/CodeGen.zig index d73e083dbc..10764ad6cd 100644 --- a/src/arch/riscv64/CodeGen.zig +++ b/src/arch/riscv64/CodeGen.zig @@ -633,6 +633,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { .unwrap_errunion_payload => try self.airUnwrapErrPayload(inst), .unwrap_errunion_err_ptr => try self.airUnwrapErrErrPtr(inst), .unwrap_errunion_payload_ptr=> try self.airUnwrapErrPayloadPtr(inst), + .errunion_payload_ptr_set => try self.airErrUnionPayloadPtrSet(inst), .wrap_optional => try self.airWrapOptional(inst), .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst), @@ -1065,6 +1066,12 @@ fn airUnwrapErrPayloadPtr(self: *Self, inst: Air.Inst.Index) !void { return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); } +fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void { + const ty_op = self.air.instructions.items(.data)[inst].ty_op; + const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement .errunion_payload_ptr_set for {}", .{self.target.cpu.arch}); + return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); +} + fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { const ty_op = self.air.instructions.items(.data)[inst].ty_op; const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig index 2bd6b92963..b776f30346 100644 --- a/src/arch/wasm/CodeGen.zig +++ b/src/arch/wasm/CodeGen.zig @@ -1725,6 +1725,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { .atomic_rmw, .tag_name, .error_name, + .errunion_payload_ptr_set, // For these 4, probably best to wait until https://github.com/ziglang/zig/issues/10248 // is implemented in the frontend before implementing them here in the wasm backend. diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index 441af51de2..d7d6ac9da8 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -727,6 +727,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { .unwrap_errunion_payload => try self.airUnwrapErrPayload(inst), .unwrap_errunion_err_ptr => try self.airUnwrapErrErrPtr(inst), .unwrap_errunion_payload_ptr=> try self.airUnwrapErrPayloadPtr(inst), + .errunion_payload_ptr_set => try self.airErrUnionPayloadPtrSet(inst), .wrap_optional => try self.airWrapOptional(inst), .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst), @@ -1406,6 +1407,15 @@ fn airUnwrapErrPayloadPtr(self: *Self, inst: Air.Inst.Index) !void { return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); } +fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void { + const ty_op = self.air.instructions.items(.data)[inst].ty_op; + const result: MCValue = if (self.liveness.isUnused(inst)) + .dead + else + return self.fail("TODO implement .errunion_payload_ptr_set for {}", .{self.target.cpu.arch}); + return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); +} + fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { const ty_op = self.air.instructions.items(.data)[inst].ty_op; const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { diff --git a/src/codegen/c.zig b/src/codegen/c.zig index f6e2d467a7..fe0184849d 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -1753,6 +1753,7 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO .unwrap_errunion_err_ptr => try airUnwrapErrUnionErr(f, inst), .wrap_errunion_payload => try airWrapErrUnionPay(f, inst), .wrap_errunion_err => try airWrapErrUnionErr(f, inst), + .errunion_payload_ptr_set => try airErrUnionPayloadPtrSet(f, inst), // zig fmt: on }; switch (result_value) { @@ -3164,6 +3165,7 @@ fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue { try writer.writeAll("};\n"); return local; } + fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { if (f.liveness.isUnused(inst)) return CValue.none; @@ -3183,6 +3185,11 @@ fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { return local; } +fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue { + _ = inst; + return f.fail("TODO: C backend: implement airErrUnionPayloadPtrSet", .{}); +} + fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue { if (f.liveness.isUnused(inst)) return CValue.none; diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 8af74fce64..d8c19fba71 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -2238,6 +2238,7 @@ pub const FuncGen = struct { .unwrap_errunion_payload_ptr => try self.airErrUnionPayload(inst, true), .unwrap_errunion_err => try self.airErrUnionErr(inst, false), .unwrap_errunion_err_ptr => try self.airErrUnionErr(inst, true), + .errunion_payload_ptr_set => try self.airErrUnionPayloadPtrSet(inst), .wrap_optional => try self.airWrapOptional(inst), .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst), @@ -3202,6 +3203,37 @@ pub const FuncGen = struct { return self.builder.buildExtractValue(operand, 0, ""); } + fn airErrUnionPayloadPtrSet(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { + const ty_op = self.air.instructions.items(.data)[inst].ty_op; + const operand = try self.resolveInst(ty_op.operand); + const error_set_ty = self.air.typeOf(ty_op.operand).childType(); + + const error_ty = error_set_ty.errorUnionSet(); + const payload_ty = error_set_ty.errorUnionPayload(); + const non_error_val = try self.dg.genTypedValue(.{ .ty = error_ty, .val = Value.zero }); + if (!payload_ty.hasRuntimeBits()) { + // We have a pointer to a i1. We need to set it to 1 and then return the same pointer. + _ = self.builder.buildStore(non_error_val, operand); + return operand; + } + const index_type = self.context.intType(32); + { + // First set the non-error value. + const indices: [2]*const llvm.Value = .{ + index_type.constNull(), // dereference the pointer + index_type.constNull(), // first field is the payload + }; + const non_null_ptr = self.builder.buildInBoundsGEP(operand, &indices, indices.len, ""); + _ = self.builder.buildStore(non_error_val, non_null_ptr); + } + // Then return the payload pointer. + const indices: [2]*const llvm.Value = .{ + index_type.constNull(), // dereference the pointer + index_type.constInt(1, .False), // second field is the payload + }; + return self.builder.buildInBoundsGEP(operand, &indices, indices.len, ""); + } + fn airWrapOptional(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { if (self.liveness.isUnused(inst)) return null; diff --git a/src/print_air.zig b/src/print_air.zig index 5dc8219b12..289fcca669 100644 --- a/src/print_air.zig +++ b/src/print_air.zig @@ -189,6 +189,7 @@ const Writer = struct { .optional_payload, .optional_payload_ptr, .optional_payload_ptr_set, + .errunion_payload_ptr_set, .wrap_optional, .unwrap_errunion_payload, .unwrap_errunion_err, |
