| author | |
| committer | |
| log | 40eac90280db34afd31da5ad0e6be8a4795f858b |
| tree | eda808f0f9b422d4bd92ae5ad6dc56ab97586bd7 |
| parent | cb901e578cbc321003d5e4327d51d349d91f6dd6 |
| parent | 09f273136c74639d18695f63ba9c0fdc68ad678c |
| signature |
Stage2 error set safety improvements14 files changed, 99 insertions(+), 20 deletions(-)
src/Air.zig+5| ... | @@ -673,6 +673,10 @@ pub const Inst = struct { | ... | @@ -673,6 +673,10 @@ pub const Inst = struct { |
| 673 | /// Uses the `un_op` field. | 673 | /// Uses the `un_op` field. |
| 674 | error_name, | 674 | error_name, |
| 675 | 675 | ||
| 676 | /// Returns true if error set has error with value. | ||
| 677 | /// Uses the `ty_op` field. | ||
| 678 | error_set_has_value, | ||
| 679 | |||
| 676 | /// Constructs a vector, tuple, struct, or array value out of runtime-known elements. | 680 | /// Constructs a vector, tuple, struct, or array value out of runtime-known elements. |
| 677 | /// Some of the elements may be comptime-known. | 681 | /// Some of the elements may be comptime-known. |
| 678 | /// Uses the `ty_pl` field, payload is index of an array of elements, each of which | 682 | /// Uses the `ty_pl` field, payload is index of an array of elements, each of which |
| ... | @@ -1062,6 +1066,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type { | ... | @@ -1062,6 +1066,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type { |
| 1062 | .is_err_ptr, | 1066 | .is_err_ptr, |
| 1063 | .is_non_err_ptr, | 1067 | .is_non_err_ptr, |
| 1064 | .is_named_enum_value, | 1068 | .is_named_enum_value, |
| 1069 | .error_set_has_value, | ||
| 1065 | => return Type.bool, | 1070 | => return Type.bool, |
| 1066 | 1071 | ||
| 1067 | .const_ty => return Type.type, | 1072 | .const_ty => return Type.type, |
src/Liveness.zig+2| ... | @@ -267,6 +267,7 @@ pub fn categorizeOperand( | ... | @@ -267,6 +267,7 @@ pub fn categorizeOperand( |
| 267 | .byte_swap, | 267 | .byte_swap, |
| 268 | .bit_reverse, | 268 | .bit_reverse, |
| 269 | .splat, | 269 | .splat, |
| 270 | .error_set_has_value, | ||
| 270 | => { | 271 | => { |
| 271 | const o = air_datas[inst].ty_op; | 272 | const o = air_datas[inst].ty_op; |
| 272 | if (o.operand == operand_ref) return matchOperandSmallIndex(l, inst, 0, .none); | 273 | if (o.operand == operand_ref) return matchOperandSmallIndex(l, inst, 0, .none); |
| ... | @@ -842,6 +843,7 @@ fn analyzeInst( | ... | @@ -842,6 +843,7 @@ fn analyzeInst( |
| 842 | .byte_swap, | 843 | .byte_swap, |
| 843 | .bit_reverse, | 844 | .bit_reverse, |
| 844 | .splat, | 845 | .splat, |
| 846 | .error_set_has_value, | ||
| 845 | => { | 847 | => { |
| 846 | const o = inst_datas[inst].ty_op; | 848 | const o = inst_datas[inst].ty_op; |
| 847 | return trackOperands(a, new_set, inst, main_tomb, .{ o.operand, .none, .none }); | 849 | return trackOperands(a, new_set, inst, main_tomb, .{ o.operand, .none, .none }); |
src/Sema.zig+15-20| ... | @@ -6804,11 +6804,10 @@ fn zirErrorToInt(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat | ... | @@ -6804,11 +6804,10 @@ fn zirErrorToInt(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat |
| 6804 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node }; | 6804 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node }; |
| 6805 | const uncasted_operand = try sema.resolveInst(extra.operand); | 6805 | const uncasted_operand = try sema.resolveInst(extra.operand); |
| 6806 | const operand = try sema.coerce(block, Type.anyerror, uncasted_operand, operand_src); | 6806 | const operand = try sema.coerce(block, Type.anyerror, uncasted_operand, operand_src); |
| 6807 | const result_ty = Type.u16; | ||
| 6808 | 6807 | ||
| 6809 | if (try sema.resolveMaybeUndefVal(block, src, operand)) |val| { | 6808 | if (try sema.resolveMaybeUndefVal(block, src, operand)) |val| { |
| 6810 | if (val.isUndef()) { | 6809 | if (val.isUndef()) { |
| 6811 | return sema.addConstUndef(result_ty); | 6810 | return sema.addConstUndef(Type.err_int); |
| 6812 | } | 6811 | } |
| 6813 | switch (val.tag()) { | 6812 | switch (val.tag()) { |
| 6814 | .@"error" => { | 6813 | .@"error" => { |
| ... | @@ -6817,14 +6816,14 @@ fn zirErrorToInt(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat | ... | @@ -6817,14 +6816,14 @@ fn zirErrorToInt(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat |
| 6817 | .base = .{ .tag = .int_u64 }, | 6816 | .base = .{ .tag = .int_u64 }, |
| 6818 | .data = (try sema.mod.getErrorValue(val.castTag(.@"error").?.data.name)).value, | 6817 | .data = (try sema.mod.getErrorValue(val.castTag(.@"error").?.data.name)).value, |
| 6819 | }; | 6818 | }; |
| 6820 | return sema.addConstant(result_ty, Value.initPayload(&payload.base)); | 6819 | return sema.addConstant(Type.err_int, Value.initPayload(&payload.base)); |
| 6821 | }, | 6820 | }, |
| 6822 | 6821 | ||
| 6823 | // This is not a valid combination with the type `anyerror`. | 6822 | // This is not a valid combination with the type `anyerror`. |
| 6824 | .the_only_possible_value => unreachable, | 6823 | .the_only_possible_value => unreachable, |
| 6825 | 6824 | ||
| 6826 | // Assume it's already encoded as an integer. | 6825 | // Assume it's already encoded as an integer. |
| 6827 | else => return sema.addConstant(result_ty, val), | 6826 | else => return sema.addConstant(Type.err_int, val), |
| 6828 | } | 6827 | } |
| 6829 | } | 6828 | } |
| 6830 | 6829 | ||
| ... | @@ -6833,14 +6832,14 @@ fn zirErrorToInt(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat | ... | @@ -6833,14 +6832,14 @@ fn zirErrorToInt(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat |
| 6833 | if (!op_ty.isAnyError()) { | 6832 | if (!op_ty.isAnyError()) { |
| 6834 | const names = op_ty.errorSetNames(); | 6833 | const names = op_ty.errorSetNames(); |
| 6835 | switch (names.len) { | 6834 | switch (names.len) { |
| 6836 | 0 => return sema.addConstant(result_ty, Value.zero), | 6835 | 0 => return sema.addConstant(Type.err_int, Value.zero), |
| 6837 | 1 => return sema.addIntUnsigned(result_ty, sema.mod.global_error_set.get(names[0]).?), | 6836 | 1 => return sema.addIntUnsigned(Type.err_int, sema.mod.global_error_set.get(names[0]).?), |
| 6838 | else => {}, | 6837 | else => {}, |
| 6839 | } | 6838 | } |
| 6840 | } | 6839 | } |
| 6841 | 6840 | ||
| 6842 | try sema.requireRuntimeBlock(block, src, operand_src); | 6841 | try sema.requireRuntimeBlock(block, src, operand_src); |
| 6843 | return block.addBitCast(result_ty, operand); | 6842 | return block.addBitCast(Type.err_int, operand); |
| 6844 | } | 6843 | } |
| 6845 | 6844 | ||
| 6846 | fn zirIntToError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { | 6845 | fn zirIntToError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { |
| ... | @@ -6851,7 +6850,7 @@ fn zirIntToError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat | ... | @@ -6851,7 +6850,7 @@ fn zirIntToError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat |
| 6851 | const src = LazySrcLoc.nodeOffset(extra.node); | 6850 | const src = LazySrcLoc.nodeOffset(extra.node); |
| 6852 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node }; | 6851 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node }; |
| 6853 | const uncasted_operand = try sema.resolveInst(extra.operand); | 6852 | const uncasted_operand = try sema.resolveInst(extra.operand); |
| 6854 | const operand = try sema.coerce(block, Type.u16, uncasted_operand, operand_src); | 6853 | const operand = try sema.coerce(block, Type.err_int, uncasted_operand, operand_src); |
| 6855 | const target = sema.mod.getTarget(); | 6854 | const target = sema.mod.getTarget(); |
| 6856 | 6855 | ||
| 6857 | if (try sema.resolveDefinedValue(block, operand_src, operand)) |value| { | 6856 | if (try sema.resolveDefinedValue(block, operand_src, operand)) |value| { |
| ... | @@ -6868,7 +6867,10 @@ fn zirIntToError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat | ... | @@ -6868,7 +6867,10 @@ fn zirIntToError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat |
| 6868 | try sema.requireRuntimeBlock(block, src, operand_src); | 6867 | try sema.requireRuntimeBlock(block, src, operand_src); |
| 6869 | if (block.wantSafety()) { | 6868 | if (block.wantSafety()) { |
| 6870 | const is_lt_len = try block.addUnOp(.cmp_lt_errors_len, operand); | 6869 | const is_lt_len = try block.addUnOp(.cmp_lt_errors_len, operand); |
| 6871 | try sema.addSafetyCheck(block, is_lt_len, .invalid_error_code); | 6870 | const zero_val = try sema.addConstant(Type.err_int, Value.zero); |
| 6871 | const is_non_zero = try block.addBinOp(.cmp_neq, operand, zero_val); | ||
| 6872 | const ok = try block.addBinOp(.bit_and, is_lt_len, is_non_zero); | ||
| 6873 | try sema.addSafetyCheck(block, ok, .invalid_error_code); | ||
| 6872 | } | 6874 | } |
| 6873 | return block.addInst(.{ | 6875 | return block.addInst(.{ |
| 6874 | .tag = .bitcast, | 6876 | .tag = .bitcast, |
| ... | @@ -17370,17 +17372,10 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat | ... | @@ -17370,17 +17372,10 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat |
| 17370 | } | 17372 | } |
| 17371 | 17373 | ||
| 17372 | try sema.requireRuntimeBlock(block, src, operand_src); | 17374 | try sema.requireRuntimeBlock(block, src, operand_src); |
| 17373 | if (block.wantSafety() and !dest_ty.isAnyError()) { | 17375 | if (block.wantSafety() and !dest_ty.isAnyError() and sema.mod.comp.bin_file.options.use_llvm) { |
| 17374 | const err_int_inst = try block.addBitCast(Type.u16, operand); | 17376 | const err_int_inst = try block.addBitCast(Type.err_int, operand); |
| 17375 | // TODO: Output a switch instead of chained OR's. | 17377 | const ok = try block.addTyOp(.error_set_has_value, dest_ty, err_int_inst); |
| 17376 | var found_match: Air.Inst.Ref = undefined; | 17378 | try sema.addSafetyCheck(block, ok, .invalid_error_code); |
| 17377 | for (dest_ty.errorSetNames()) |dest_err_name, i| { | ||
| 17378 | const dest_err_int = (try sema.mod.getErrorValue(dest_err_name)).value; | ||
| 17379 | const dest_err_int_inst = try sema.addIntUnsigned(Type.u16, dest_err_int); | ||
| 17380 | const next_match = try block.addBinOp(.cmp_eq, dest_err_int_inst, err_int_inst); | ||
| 17381 | found_match = if (i == 0) next_match else try block.addBinOp(.bool_or, found_match, next_match); | ||
| 17382 | } | ||
| 17383 | try sema.addSafetyCheck(block, found_match, .invalid_error_code); | ||
| 17384 | } | 17379 | } |
| 17385 | return block.addBitCast(dest_ty, operand); | 17380 | return block.addBitCast(dest_ty, operand); |
| 17386 | } | 17381 | } |
src/arch/aarch64/CodeGen.zig+1| ... | @@ -778,6 +778,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -778,6 +778,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 778 | => return self.fail("TODO implement optimized float mode", .{}), | 778 | => return self.fail("TODO implement optimized float mode", .{}), |
| 779 | 779 | ||
| 780 | .is_named_enum_value => return self.fail("TODO implement is_named_enum_value", .{}), | 780 | .is_named_enum_value => return self.fail("TODO implement is_named_enum_value", .{}), |
| 781 | .error_set_has_value => return self.fail("TODO implement error_set_has_value", .{}), | ||
| 781 | 782 | ||
| 782 | .wasm_memory_size => unreachable, | 783 | .wasm_memory_size => unreachable, |
| 783 | .wasm_memory_grow => unreachable, | 784 | .wasm_memory_grow => unreachable, |
src/arch/arm/CodeGen.zig+1| ... | @@ -796,6 +796,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -796,6 +796,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 796 | => return self.fail("TODO implement optimized float mode", .{}), | 796 | => return self.fail("TODO implement optimized float mode", .{}), |
| 797 | 797 | ||
| 798 | .is_named_enum_value => return self.fail("TODO implement is_named_enum_value", .{}), | 798 | .is_named_enum_value => return self.fail("TODO implement is_named_enum_value", .{}), |
| 799 | .error_set_has_value => return self.fail("TODO implement error_set_has_value", .{}), | ||
| 799 | 800 | ||
| 800 | .wasm_memory_size => unreachable, | 801 | .wasm_memory_size => unreachable, |
| 801 | .wasm_memory_grow => unreachable, | 802 | .wasm_memory_grow => unreachable, |
src/arch/riscv64/CodeGen.zig+1| ... | @@ -694,6 +694,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -694,6 +694,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 694 | => return self.fail("TODO implement optimized float mode", .{}), | 694 | => return self.fail("TODO implement optimized float mode", .{}), |
| 695 | 695 | ||
| 696 | .is_named_enum_value => return self.fail("TODO implement is_named_enum_value", .{}), | 696 | .is_named_enum_value => return self.fail("TODO implement is_named_enum_value", .{}), |
| 697 | .error_set_has_value => return self.fail("TODO implement error_set_has_value", .{}), | ||
| 697 | 698 | ||
| 698 | .wasm_memory_size => unreachable, | 699 | .wasm_memory_size => unreachable, |
| 699 | .wasm_memory_grow => unreachable, | 700 | .wasm_memory_grow => unreachable, |
src/arch/sparc64/CodeGen.zig+1| ... | @@ -706,6 +706,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -706,6 +706,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 706 | => @panic("TODO implement optimized float mode"), | 706 | => @panic("TODO implement optimized float mode"), |
| 707 | 707 | ||
| 708 | .is_named_enum_value => @panic("TODO implement is_named_enum_value"), | 708 | .is_named_enum_value => @panic("TODO implement is_named_enum_value"), |
| 709 | .error_set_has_value => @panic("TODO implement error_set_has_value"), | ||
| 709 | 710 | ||
| 710 | .wasm_memory_size => unreachable, | 711 | .wasm_memory_size => unreachable, |
| 711 | .wasm_memory_grow => unreachable, | 712 | .wasm_memory_grow => unreachable, |
src/arch/wasm/CodeGen.zig+1| ... | @@ -1694,6 +1694,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { | ... | @@ -1694,6 +1694,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { |
| 1694 | .err_return_trace, | 1694 | .err_return_trace, |
| 1695 | .set_err_return_trace, | 1695 | .set_err_return_trace, |
| 1696 | .is_named_enum_value, | 1696 | .is_named_enum_value, |
| 1697 | .error_set_has_value, | ||
| 1697 | => |tag| return self.fail("TODO: Implement wasm inst: {s}", .{@tagName(tag)}), | 1698 | => |tag| return self.fail("TODO: Implement wasm inst: {s}", .{@tagName(tag)}), |
| 1698 | 1699 | ||
| 1699 | .add_optimized, | 1700 | .add_optimized, |
src/arch/x86_64/CodeGen.zig+1| ... | @@ -776,6 +776,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -776,6 +776,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 776 | => return self.fail("TODO implement optimized float mode", .{}), | 776 | => return self.fail("TODO implement optimized float mode", .{}), |
| 777 | 777 | ||
| 778 | .is_named_enum_value => return self.fail("TODO implement is_named_enum_value", .{}), | 778 | .is_named_enum_value => return self.fail("TODO implement is_named_enum_value", .{}), |
| 779 | .error_set_has_value => return self.fail("TODO implement error_set_has_value", .{}), | ||
| 779 | 780 | ||
| 780 | .wasm_memory_size => unreachable, | 781 | .wasm_memory_size => unreachable, |
| 781 | .wasm_memory_grow => unreachable, | 782 | .wasm_memory_grow => unreachable, |
src/codegen/c.zig+1| ... | @@ -1954,6 +1954,7 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO | ... | @@ -1954,6 +1954,7 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO |
| 1954 | => return f.fail("TODO implement optimized float mode", .{}), | 1954 | => return f.fail("TODO implement optimized float mode", .{}), |
| 1955 | 1955 | ||
| 1956 | .is_named_enum_value => return f.fail("TODO: C backend: implement is_named_enum_value", .{}), | 1956 | .is_named_enum_value => return f.fail("TODO: C backend: implement is_named_enum_value", .{}), |
| 1957 | .error_set_has_value => return f.fail("TODO: C backend: implement error_set_has_value", .{}), | ||
| 1957 | // zig fmt: on | 1958 | // zig fmt: on |
| 1958 | }; | 1959 | }; |
| 1959 | switch (result_value) { | 1960 | switch (result_value) { |
src/codegen/llvm.zig+48| ... | @@ -4247,6 +4247,7 @@ pub const FuncGen = struct { | ... | @@ -4247,6 +4247,7 @@ pub const FuncGen = struct { |
| 4247 | .prefetch => try self.airPrefetch(inst), | 4247 | .prefetch => try self.airPrefetch(inst), |
| 4248 | 4248 | ||
| 4249 | .is_named_enum_value => try self.airIsNamedEnumValue(inst), | 4249 | .is_named_enum_value => try self.airIsNamedEnumValue(inst), |
| 4250 | .error_set_has_value => try self.airErrorSetHasValue(inst), | ||
| 4250 | 4251 | ||
| 4251 | .reduce => try self.airReduce(inst, false), | 4252 | .reduce => try self.airReduce(inst, false), |
| 4252 | .reduce_optimized => try self.airReduce(inst, true), | 4253 | .reduce_optimized => try self.airReduce(inst, true), |
| ... | @@ -7983,6 +7984,53 @@ pub const FuncGen = struct { | ... | @@ -7983,6 +7984,53 @@ pub const FuncGen = struct { |
| 7983 | } | 7984 | } |
| 7984 | } | 7985 | } |
| 7985 | 7986 | ||
| 7987 | fn airErrorSetHasValue(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { | ||
| 7988 | if (self.liveness.isUnused(inst)) return null; | ||
| 7989 | |||
| 7990 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | ||
| 7991 | const operand = try self.resolveInst(ty_op.operand); | ||
| 7992 | const error_set_ty = self.air.getRefType(ty_op.ty); | ||
| 7993 | |||
| 7994 | const names = error_set_ty.errorSetNames(); | ||
| 7995 | const valid_block = self.dg.context.appendBasicBlock(self.llvm_func, "Valid"); | ||
| 7996 | const invalid_block = self.dg.context.appendBasicBlock(self.llvm_func, "Invalid"); | ||
| 7997 | const end_block = self.context.appendBasicBlock(self.llvm_func, "End"); | ||
| 7998 | const switch_instr = self.builder.buildSwitch(operand, invalid_block, @intCast(c_uint, names.len)); | ||
| 7999 | |||
| 8000 | for (names) |name| { | ||
| 8001 | const err_int = self.dg.module.global_error_set.get(name).?; | ||
| 8002 | const this_tag_int_value = int: { | ||
| 8003 | var tag_val_payload: Value.Payload.U64 = .{ | ||
| 8004 | .base = .{ .tag = .int_u64 }, | ||
| 8005 | .data = err_int, | ||
| 8006 | }; | ||
| 8007 | break :int try self.dg.lowerValue(.{ | ||
| 8008 | .ty = Type.err_int, | ||
| 8009 | .val = Value.initPayload(&tag_val_payload.base), | ||
| 8010 | }); | ||
| 8011 | }; | ||
| 8012 | switch_instr.addCase(this_tag_int_value, valid_block); | ||
| 8013 | } | ||
| 8014 | self.builder.positionBuilderAtEnd(valid_block); | ||
| 8015 | _ = self.builder.buildBr(end_block); | ||
| 8016 | |||
| 8017 | self.builder.positionBuilderAtEnd(invalid_block); | ||
| 8018 | _ = self.builder.buildBr(end_block); | ||
| 8019 | |||
| 8020 | self.builder.positionBuilderAtEnd(end_block); | ||
| 8021 | |||
| 8022 | const llvm_type = self.dg.context.intType(1); | ||
| 8023 | const incoming_values: [2]*const llvm.Value = .{ | ||
| 8024 | llvm_type.constInt(1, .False), llvm_type.constInt(0, .False), | ||
| 8025 | }; | ||
| 8026 | const incoming_blocks: [2]*const llvm.BasicBlock = .{ | ||
| 8027 | valid_block, invalid_block, | ||
| 8028 | }; | ||
| 8029 | const phi_node = self.builder.buildPhi(llvm_type, ""); | ||
| 8030 | phi_node.addIncoming(&incoming_values, &incoming_blocks, 2); | ||
| 8031 | return phi_node; | ||
| 8032 | } | ||
| 8033 | |||
| 7986 | fn airIsNamedEnumValue(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { | 8034 | fn airIsNamedEnumValue(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { |
| 7987 | if (self.liveness.isUnused(inst)) return null; | 8035 | if (self.liveness.isUnused(inst)) return null; |
| 7988 | 8036 |
src/print_air.zig+1| ... | @@ -243,6 +243,7 @@ const Writer = struct { | ... | @@ -243,6 +243,7 @@ const Writer = struct { |
| 243 | .popcount, | 243 | .popcount, |
| 244 | .byte_swap, | 244 | .byte_swap, |
| 245 | .bit_reverse, | 245 | .bit_reverse, |
| 246 | .error_set_has_value, | ||
| 246 | => try w.writeTyOp(s, inst), | 247 | => try w.writeTyOp(s, inst), |
| 247 | 248 | ||
| 248 | .block, | 249 | .block, |
src/type.zig+2| ... | @@ -6303,6 +6303,8 @@ pub const Type = extern union { | ... | @@ -6303,6 +6303,8 @@ pub const Type = extern union { |
| 6303 | pub const @"anyopaque" = initTag(.anyopaque); | 6303 | pub const @"anyopaque" = initTag(.anyopaque); |
| 6304 | pub const @"null" = initTag(.@"null"); | 6304 | pub const @"null" = initTag(.@"null"); |
| 6305 | 6305 | ||
| 6306 | pub const err_int = Type.u16; | ||
| 6307 | |||
| 6306 | pub fn ptr(arena: Allocator, mod: *Module, data: Payload.Pointer.Data) !Type { | 6308 | pub fn ptr(arena: Allocator, mod: *Module, data: Payload.Pointer.Data) !Type { |
| 6307 | const target = mod.getTarget(); | 6309 | const target = mod.getTarget(); |
| 6308 | 6310 |
test/cases/safety/zero casted to error.zig	 created+19| ... | @@ -0,0 +1,19 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | ||
| 4 | _ = stack_trace; | ||
| 5 | if (std.mem.eql(u8, message, "invalid error code")) { | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | std.process.exit(1); | ||
| 9 | } | ||
| 10 | pub fn main() !void { | ||
| 11 | bar(0) catch {}; | ||
| 12 | return error.TestFailed; | ||
| 13 | } | ||
| 14 | fn bar(x: u16) anyerror { | ||
| 15 | return @intToError(x); | ||
| 16 | } | ||
| 17 | // run | ||
| 18 | // backend=llvm | ||
| 19 | // target=native | ||