| author | |
| committer | |
| log | 27c63bf433f27b06bed92111cbc96e8574de8d11 |
| tree | 33a3ffae8217196b22d5fbe9786dee7a34bfbe7b |
| parent | 89f6ff177178dba4e66680227a02de7b4068123c |
12 files changed, 85 insertions(+), 2 deletions(-)
src/Air.zig+4| ... | ... | @@ -429,6 +429,9 @@ pub const Inst = struct { |
| 429 | 429 | /// *(E!T) -> E. If the value is not an error, undefined behavior. |
| 430 | 430 | /// Uses the `ty_op` field. |
| 431 | 431 | unwrap_errunion_err_ptr, |
| 432 | /// *(E!T) => *T. Sets the value to non-error with an undefined payload value. | |
| 433 | /// Uses the `ty_op` field. | |
| 434 | errunion_payload_ptr_set, | |
| 432 | 435 | /// wrap from T to E!T |
| 433 | 436 | /// Uses the `ty_op` field. |
| 434 | 437 | wrap_errunion_payload, |
| ... | ... | @@ -865,6 +868,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type { |
| 865 | 868 | .optional_payload, |
| 866 | 869 | .optional_payload_ptr, |
| 867 | 870 | .optional_payload_ptr_set, |
| 871 | .errunion_payload_ptr_set, | |
| 868 | 872 | .wrap_optional, |
| 869 | 873 | .unwrap_errunion_payload, |
| 870 | 874 | .unwrap_errunion_err, |
src/Liveness.zig+1| ... | ... | @@ -293,6 +293,7 @@ fn analyzeInst( |
| 293 | 293 | .optional_payload, |
| 294 | 294 | .optional_payload_ptr, |
| 295 | 295 | .optional_payload_ptr_set, |
| 296 | .errunion_payload_ptr_set, | |
| 296 | 297 | .wrap_optional, |
| 297 | 298 | .unwrap_errunion_payload, |
| 298 | 299 | .unwrap_errunion_err, |
src/Sema.zig+7-1| ... | ... | @@ -1636,7 +1636,13 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE |
| 1636 | 1636 | return sema.fail(block, src, "TODO coerce_result_ptr wrap_errunion_err", .{}); |
| 1637 | 1637 | }, |
| 1638 | 1638 | .wrap_errunion_payload => { |
| 1639 | return sema.fail(block, src, "TODO coerce_result_ptr wrap_errunion_payload", .{}); | |
| 1639 | const ty_op = air_datas[trash_inst].ty_op; | |
| 1640 | const payload_ty = sema.getTmpAir().typeOf(ty_op.operand); | |
| 1641 | const ptr_payload_ty = try Type.ptr(sema.arena, .{ | |
| 1642 | .pointee_type = payload_ty, | |
| 1643 | .@"addrspace" = addr_space, | |
| 1644 | }); | |
| 1645 | new_ptr = try block.addTyOp(.errunion_payload_ptr_set, ptr_payload_ty, new_ptr); | |
| 1640 | 1646 | }, |
| 1641 | 1647 | else => { |
| 1642 | 1648 | if (std.debug.runtime_safety) { |
src/arch/aarch64/CodeGen.zig+7| ... | ... | @@ -662,6 +662,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 662 | 662 | .unwrap_errunion_payload => try self.airUnwrapErrPayload(inst), |
| 663 | 663 | .unwrap_errunion_err_ptr => try self.airUnwrapErrErrPtr(inst), |
| 664 | 664 | .unwrap_errunion_payload_ptr=> try self.airUnwrapErrPayloadPtr(inst), |
| 665 | .errunion_payload_ptr_set => try self.airErrUnionPayloadPtrSet(inst), | |
| 665 | 666 | |
| 666 | 667 | .wrap_optional => try self.airWrapOptional(inst), |
| 667 | 668 | .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst), |
| ... | ... | @@ -1443,6 +1444,12 @@ fn airUnwrapErrPayloadPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 1443 | 1444 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 1444 | 1445 | } |
| 1445 | 1446 | |
| 1447 | fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void { | |
| 1448 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | |
| 1449 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement .errunion_payload_ptr_set for {}", .{self.target.cpu.arch}); | |
| 1450 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | |
| 1451 | } | |
| 1452 | ||
| 1446 | 1453 | fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { |
| 1447 | 1454 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 1448 | 1455 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
src/arch/arm/CodeGen.zig+7| ... | ... | @@ -646,6 +646,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 646 | 646 | .unwrap_errunion_payload => try self.airUnwrapErrPayload(inst), |
| 647 | 647 | .unwrap_errunion_err_ptr => try self.airUnwrapErrErrPtr(inst), |
| 648 | 648 | .unwrap_errunion_payload_ptr=> try self.airUnwrapErrPayloadPtr(inst), |
| 649 | .errunion_payload_ptr_set => try self.airErrUnionPayloadPtrSet(inst), | |
| 649 | 650 | |
| 650 | 651 | .wrap_optional => try self.airWrapOptional(inst), |
| 651 | 652 | .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst), |
| ... | ... | @@ -1128,6 +1129,12 @@ fn airUnwrapErrPayloadPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 1128 | 1129 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 1129 | 1130 | } |
| 1130 | 1131 | |
| 1132 | fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void { | |
| 1133 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | |
| 1134 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement .errunion_payload_ptr_set for {}", .{self.target.cpu.arch}); | |
| 1135 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | |
| 1136 | } | |
| 1137 | ||
| 1131 | 1138 | fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { |
| 1132 | 1139 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 1133 | 1140 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
src/arch/riscv64/CodeGen.zig+7| ... | ... | @@ -633,6 +633,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 633 | 633 | .unwrap_errunion_payload => try self.airUnwrapErrPayload(inst), |
| 634 | 634 | .unwrap_errunion_err_ptr => try self.airUnwrapErrErrPtr(inst), |
| 635 | 635 | .unwrap_errunion_payload_ptr=> try self.airUnwrapErrPayloadPtr(inst), |
| 636 | .errunion_payload_ptr_set => try self.airErrUnionPayloadPtrSet(inst), | |
| 636 | 637 | |
| 637 | 638 | .wrap_optional => try self.airWrapOptional(inst), |
| 638 | 639 | .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst), |
| ... | ... | @@ -1065,6 +1066,12 @@ fn airUnwrapErrPayloadPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 1065 | 1066 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 1066 | 1067 | } |
| 1067 | 1068 | |
| 1069 | fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void { | |
| 1070 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | |
| 1071 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement .errunion_payload_ptr_set for {}", .{self.target.cpu.arch}); | |
| 1072 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | |
| 1073 | } | |
| 1074 | ||
| 1068 | 1075 | fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { |
| 1069 | 1076 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 1070 | 1077 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
src/arch/wasm/CodeGen.zig+1| ... | ... | @@ -1725,6 +1725,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { |
| 1725 | 1725 | .atomic_rmw, |
| 1726 | 1726 | .tag_name, |
| 1727 | 1727 | .error_name, |
| 1728 | .errunion_payload_ptr_set, | |
| 1728 | 1729 | |
| 1729 | 1730 | // For these 4, probably best to wait until https://github.com/ziglang/zig/issues/10248 |
| 1730 | 1731 | // is implemented in the frontend before implementing them here in the wasm backend. |
src/arch/x86_64/CodeGen.zig+10| ... | ... | @@ -727,6 +727,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 727 | 727 | .unwrap_errunion_payload => try self.airUnwrapErrPayload(inst), |
| 728 | 728 | .unwrap_errunion_err_ptr => try self.airUnwrapErrErrPtr(inst), |
| 729 | 729 | .unwrap_errunion_payload_ptr=> try self.airUnwrapErrPayloadPtr(inst), |
| 730 | .errunion_payload_ptr_set => try self.airErrUnionPayloadPtrSet(inst), | |
| 730 | 731 | |
| 731 | 732 | .wrap_optional => try self.airWrapOptional(inst), |
| 732 | 733 | .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst), |
| ... | ... | @@ -1406,6 +1407,15 @@ fn airUnwrapErrPayloadPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 1406 | 1407 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 1407 | 1408 | } |
| 1408 | 1409 | |
| 1410 | fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void { | |
| 1411 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | |
| 1412 | const result: MCValue = if (self.liveness.isUnused(inst)) | |
| 1413 | .dead | |
| 1414 | else | |
| 1415 | return self.fail("TODO implement .errunion_payload_ptr_set for {}", .{self.target.cpu.arch}); | |
| 1416 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | |
| 1417 | } | |
| 1418 | ||
| 1409 | 1419 | fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { |
| 1410 | 1420 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 1411 | 1421 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
src/codegen/c.zig+7| ... | ... | @@ -1753,6 +1753,7 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO |
| 1753 | 1753 | .unwrap_errunion_err_ptr => try airUnwrapErrUnionErr(f, inst), |
| 1754 | 1754 | .wrap_errunion_payload => try airWrapErrUnionPay(f, inst), |
| 1755 | 1755 | .wrap_errunion_err => try airWrapErrUnionErr(f, inst), |
| 1756 | .errunion_payload_ptr_set => try airErrUnionPayloadPtrSet(f, inst), | |
| 1756 | 1757 | // zig fmt: on |
| 1757 | 1758 | }; |
| 1758 | 1759 | switch (result_value) { |
| ... | ... | @@ -3164,6 +3165,7 @@ fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3164 | 3165 | try writer.writeAll("};\n"); |
| 3165 | 3166 | return local; |
| 3166 | 3167 | } |
| 3168 | ||
| 3167 | 3169 | fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3168 | 3170 | if (f.liveness.isUnused(inst)) return CValue.none; |
| 3169 | 3171 | |
| ... | ... | @@ -3183,6 +3185,11 @@ fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3183 | 3185 | return local; |
| 3184 | 3186 | } |
| 3185 | 3187 | |
| 3188 | fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue { | |
| 3189 | _ = inst; | |
| 3190 | return f.fail("TODO: C backend: implement airErrUnionPayloadPtrSet", .{}); | |
| 3191 | } | |
| 3192 | ||
| 3186 | 3193 | fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3187 | 3194 | if (f.liveness.isUnused(inst)) |
| 3188 | 3195 | return CValue.none; |
src/codegen/llvm.zig+32| ... | ... | @@ -2238,6 +2238,7 @@ pub const FuncGen = struct { |
| 2238 | 2238 | .unwrap_errunion_payload_ptr => try self.airErrUnionPayload(inst, true), |
| 2239 | 2239 | .unwrap_errunion_err => try self.airErrUnionErr(inst, false), |
| 2240 | 2240 | .unwrap_errunion_err_ptr => try self.airErrUnionErr(inst, true), |
| 2241 | .errunion_payload_ptr_set => try self.airErrUnionPayloadPtrSet(inst), | |
| 2241 | 2242 | |
| 2242 | 2243 | .wrap_optional => try self.airWrapOptional(inst), |
| 2243 | 2244 | .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst), |
| ... | ... | @@ -3202,6 +3203,37 @@ pub const FuncGen = struct { |
| 3202 | 3203 | return self.builder.buildExtractValue(operand, 0, ""); |
| 3203 | 3204 | } |
| 3204 | 3205 | |
| 3206 | fn airErrUnionPayloadPtrSet(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { | |
| 3207 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | |
| 3208 | const operand = try self.resolveInst(ty_op.operand); | |
| 3209 | const error_set_ty = self.air.typeOf(ty_op.operand).childType(); | |
| 3210 | ||
| 3211 | const error_ty = error_set_ty.errorUnionSet(); | |
| 3212 | const payload_ty = error_set_ty.errorUnionPayload(); | |
| 3213 | const non_error_val = try self.dg.genTypedValue(.{ .ty = error_ty, .val = Value.zero }); | |
| 3214 | if (!payload_ty.hasRuntimeBits()) { | |
| 3215 | // We have a pointer to a i1. We need to set it to 1 and then return the same pointer. | |
| 3216 | _ = self.builder.buildStore(non_error_val, operand); | |
| 3217 | return operand; | |
| 3218 | } | |
| 3219 | const index_type = self.context.intType(32); | |
| 3220 | { | |
| 3221 | // First set the non-error value. | |
| 3222 | const indices: [2]*const llvm.Value = .{ | |
| 3223 | index_type.constNull(), // dereference the pointer | |
| 3224 | index_type.constNull(), // first field is the payload | |
| 3225 | }; | |
| 3226 | const non_null_ptr = self.builder.buildInBoundsGEP(operand, &indices, indices.len, ""); | |
| 3227 | _ = self.builder.buildStore(non_error_val, non_null_ptr); | |
| 3228 | } | |
| 3229 | // Then return the payload pointer. | |
| 3230 | const indices: [2]*const llvm.Value = .{ | |
| 3231 | index_type.constNull(), // dereference the pointer | |
| 3232 | index_type.constInt(1, .False), // second field is the payload | |
| 3233 | }; | |
| 3234 | return self.builder.buildInBoundsGEP(operand, &indices, indices.len, ""); | |
| 3235 | } | |
| 3236 | ||
| 3205 | 3237 | fn airWrapOptional(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { |
| 3206 | 3238 | if (self.liveness.isUnused(inst)) return null; |
| 3207 | 3239 |
src/print_air.zig+1| ... | ... | @@ -189,6 +189,7 @@ const Writer = struct { |
| 189 | 189 | .optional_payload, |
| 190 | 190 | .optional_payload_ptr, |
| 191 | 191 | .optional_payload_ptr_set, |
| 192 | .errunion_payload_ptr_set, | |
| 192 | 193 | .wrap_optional, |
| 193 | 194 | .unwrap_errunion_payload, |
| 194 | 195 | .unwrap_errunion_err, |
test/behavior.zig+1-1| ... | ... | @@ -118,6 +118,7 @@ test { |
| 118 | 118 | _ = @import("behavior/sizeof_and_typeof.zig"); |
| 119 | 119 | _ = @import("behavior/switch.zig"); |
| 120 | 120 | _ = @import("behavior/widening.zig"); |
| 121 | _ = @import("behavior/bugs/1442.zig"); | |
| 121 | 122 | |
| 122 | 123 | if (builtin.zig_backend == .stage1) { |
| 123 | 124 | // Tests that only pass for the stage1 backend. |
| ... | ... | @@ -134,7 +135,6 @@ test { |
| 134 | 135 | _ = @import("behavior/bugs/920.zig"); |
| 135 | 136 | _ = @import("behavior/bugs/1120.zig"); |
| 136 | 137 | _ = @import("behavior/bugs/1421.zig"); |
| 137 | _ = @import("behavior/bugs/1442.zig"); | |
| 138 | 138 | _ = @import("behavior/bugs/1607.zig"); |
| 139 | 139 | _ = @import("behavior/bugs/1851.zig"); |
| 140 | 140 | _ = @import("behavior/bugs/2114.zig"); |