| ... | ... | @@ -14249,7 +14249,7 @@ fn maybeErrorUnwrap( |
| 14249 | 14249 | .as_node => try sema.zirAsNode(block, inst), |
| 14250 | 14250 | .field_val => try sema.zirFieldVal(block, inst), |
| 14251 | 14251 | .@"unreachable" => { |
| 14252 | | try callPanic(sema, block, operand_src, .unwrap_error, operand, .@"safety check"); |
| 14252 | try safetyPanicUnwrapError(sema, block, operand_src, operand); |
| 14253 | 14253 | return true; |
| 14254 | 14254 | }, |
| 14255 | 14255 | .panic => { |
| ... | ... | @@ -27827,11 +27827,24 @@ fn addSafetyCheckUnwrapError( |
| 27827 | 27827 | defer fail_block.instructions.deinit(gpa); |
| 27828 | 27828 | |
| 27829 | 27829 | const err = try fail_block.addTyOp(unwrap_err_tag, Type.anyerror, operand); |
| 27830 | | try callPanic(sema, &fail_block, src, .unwrap_error, err, .@"safety check"); |
| 27830 | try safetyPanicUnwrapError(sema, &fail_block, src, err); |
| 27831 | 27831 | |
| 27832 | 27832 | try sema.addSafetyCheckExtra(parent_block, ok, &fail_block); |
| 27833 | 27833 | } |
| 27834 | 27834 | |
| 27835 | fn safetyPanicUnwrapError(sema: *Sema, block: *Block, src: LazySrcLoc, err: Air.Inst.Ref) !void { |
| 27836 | const pt = sema.pt; |
| 27837 | const zcu = pt.zcu; |
| 27838 | if (!zcu.backendSupportsFeature(.panic_fn)) { |
| 27839 | _ = try block.addNoOp(.trap); |
| 27840 | } else { |
| 27841 | const panic_fn = try pt.getBuiltin("panicUnwrapError"); |
| 27842 | const err_return_trace = try sema.getErrorReturnTrace(block); |
| 27843 | const args: [2]Air.Inst.Ref = .{ err_return_trace, err }; |
| 27844 | try sema.callBuiltin(block, src, panic_fn, .auto, &args, .@"safety check"); |
| 27845 | } |
| 27846 | } |
| 27847 | |
| 27835 | 27848 | fn addSafetyCheckIndexOob( |
| 27836 | 27849 | sema: *Sema, |
| 27837 | 27850 | parent_block: *Block, |
| ... | ... | @@ -27841,68 +27854,8 @@ fn addSafetyCheckIndexOob( |
| 27841 | 27854 | cmp_op: Air.Inst.Tag, |
| 27842 | 27855 | ) !void { |
| 27843 | 27856 | assert(!parent_block.is_comptime); |
| 27844 | | const gpa = sema.gpa; |
| 27845 | 27857 | const ok = try parent_block.addBinOp(cmp_op, index, len); |
| 27846 | | |
| 27847 | | var fail_block: Block = .{ |
| 27848 | | .parent = parent_block, |
| 27849 | | .sema = sema, |
| 27850 | | .namespace = parent_block.namespace, |
| 27851 | | .instructions = .{}, |
| 27852 | | .inlining = parent_block.inlining, |
| 27853 | | .is_comptime = false, |
| 27854 | | .src_base_inst = parent_block.src_base_inst, |
| 27855 | | .type_name_ctx = parent_block.type_name_ctx, |
| 27856 | | }; |
| 27857 | | |
| 27858 | | defer fail_block.instructions.deinit(gpa); |
| 27859 | | |
| 27860 | | const oob_ty = try getBuiltinInnerType(sema, &fail_block, src, "PanicCause", "IndexOutOfBounds"); |
| 27861 | | comptime { |
| 27862 | | const fields = @typeInfo(std.builtin.PanicCause.IndexOutOfBounds).@"struct".fields; |
| 27863 | | assert(std.mem.eql(u8, fields[0].name, "index")); |
| 27864 | | assert(std.mem.eql(u8, fields[1].name, "len")); |
| 27865 | | assert(fields.len == 2); |
| 27866 | | } |
| 27867 | | const panic_cause_payload = try fail_block.addAggregateInit(oob_ty, &.{ index, len }); |
| 27868 | | try callPanic(sema, &fail_block, src, .index_out_of_bounds, panic_cause_payload, .@"safety check"); |
| 27869 | | try sema.addSafetyCheckExtra(parent_block, ok, &fail_block); |
| 27870 | | } |
| 27871 | | |
| 27872 | | fn addSafetyCheckStartGreaterThanEnd( |
| 27873 | | sema: *Sema, |
| 27874 | | parent_block: *Block, |
| 27875 | | src: LazySrcLoc, |
| 27876 | | start: Air.Inst.Ref, |
| 27877 | | end: Air.Inst.Ref, |
| 27878 | | ) !void { |
| 27879 | | assert(!parent_block.is_comptime); |
| 27880 | | const gpa = sema.gpa; |
| 27881 | | const ok = try parent_block.addBinOp(.cmp_lte, start, end); |
| 27882 | | |
| 27883 | | var fail_block: Block = .{ |
| 27884 | | .parent = parent_block, |
| 27885 | | .sema = sema, |
| 27886 | | .namespace = parent_block.namespace, |
| 27887 | | .instructions = .{}, |
| 27888 | | .inlining = parent_block.inlining, |
| 27889 | | .is_comptime = false, |
| 27890 | | .src_base_inst = parent_block.src_base_inst, |
| 27891 | | .type_name_ctx = parent_block.type_name_ctx, |
| 27892 | | }; |
| 27893 | | |
| 27894 | | defer fail_block.instructions.deinit(gpa); |
| 27895 | | |
| 27896 | | const oob_ty = try getBuiltinInnerType(sema, &fail_block, src, "PanicCause", "StartIndexGreaterThanEnd"); |
| 27897 | | comptime { |
| 27898 | | const fields = @typeInfo(std.builtin.PanicCause.StartIndexGreaterThanEnd).@"struct".fields; |
| 27899 | | assert(std.mem.eql(u8, fields[0].name, "start")); |
| 27900 | | assert(std.mem.eql(u8, fields[1].name, "end")); |
| 27901 | | assert(fields.len == 2); |
| 27902 | | } |
| 27903 | | const panic_cause_payload = try fail_block.addAggregateInit(oob_ty, &.{ start, end }); |
| 27904 | | try callPanic(sema, &fail_block, src, .start_index_greater_than_end, panic_cause_payload, .@"safety check"); |
| 27905 | | try sema.addSafetyCheckExtra(parent_block, ok, &fail_block); |
| 27858 | return addSafetyCheckCall(sema, parent_block, src, ok, "panicOutOfBounds", &.{ index, len }); |
| 27906 | 27859 | } |
| 27907 | 27860 | |
| 27908 | 27861 | fn addSafetyCheckInactiveUnionField( |
| ... | ... | @@ -27913,36 +27866,8 @@ fn addSafetyCheckInactiveUnionField( |
| 27913 | 27866 | wanted_tag: Air.Inst.Ref, |
| 27914 | 27867 | ) !void { |
| 27915 | 27868 | assert(!parent_block.is_comptime); |
| 27916 | | const gpa = sema.gpa; |
| 27917 | 27869 | const ok = try parent_block.addBinOp(.cmp_eq, active_tag, wanted_tag); |
| 27918 | | |
| 27919 | | var fail_block: Block = .{ |
| 27920 | | .parent = parent_block, |
| 27921 | | .sema = sema, |
| 27922 | | .namespace = parent_block.namespace, |
| 27923 | | .instructions = .{}, |
| 27924 | | .inlining = parent_block.inlining, |
| 27925 | | .is_comptime = false, |
| 27926 | | .src_base_inst = parent_block.src_base_inst, |
| 27927 | | .type_name_ctx = parent_block.type_name_ctx, |
| 27928 | | }; |
| 27929 | | |
| 27930 | | defer fail_block.instructions.deinit(gpa); |
| 27931 | | |
| 27932 | | const payload_ty = try getBuiltinInnerType(sema, &fail_block, src, "PanicCause", "InactiveUnionField"); |
| 27933 | | comptime { |
| 27934 | | const fields = @typeInfo(std.builtin.PanicCause.InactiveUnionField).@"struct".fields; |
| 27935 | | assert(std.mem.eql(u8, fields[0].name, "active")); |
| 27936 | | assert(std.mem.eql(u8, fields[1].name, "accessed")); |
| 27937 | | assert(fields.len == 2); |
| 27938 | | } |
| 27939 | | // TODO: before merging the branch, check how many safety checks end up being emitted |
| 27940 | | // for union field accesses and avoid extraneous ones. |
| 27941 | | const active_str = try analyzeTagName(sema, &fail_block, src, src, active_tag); |
| 27942 | | const accessed_str = try analyzeTagName(sema, &fail_block, src, src, wanted_tag); |
| 27943 | | const panic_cause_payload = try fail_block.addAggregateInit(payload_ty, &.{ active_str, accessed_str }); |
| 27944 | | try callPanic(sema, &fail_block, src, .inactive_union_field, panic_cause_payload, .@"safety check"); |
| 27945 | | try sema.addSafetyCheckExtra(parent_block, ok, &fail_block); |
| 27870 | return addSafetyCheckCall(sema, parent_block, src, ok, "panicInactiveUnionField", &.{ active_tag, wanted_tag }); |
| 27946 | 27871 | } |
| 27947 | 27872 | |
| 27948 | 27873 | fn addSafetyCheckSentinelMismatch( |
| ... | ... | @@ -27955,7 +27880,6 @@ fn addSafetyCheckSentinelMismatch( |
| 27955 | 27880 | sentinel_index: Air.Inst.Ref, |
| 27956 | 27881 | ) !void { |
| 27957 | 27882 | assert(!parent_block.is_comptime); |
| 27958 | | const gpa = sema.gpa; |
| 27959 | 27883 | const pt = sema.pt; |
| 27960 | 27884 | const zcu = pt.zcu; |
| 27961 | 27885 | const expected_sentinel_val = maybe_sentinel orelse return; |
| ... | ... | @@ -27984,6 +27908,24 @@ fn addSafetyCheckSentinelMismatch( |
| 27984 | 27908 | break :ok try parent_block.addBinOp(.cmp_eq, expected_sentinel, actual_sentinel); |
| 27985 | 27909 | }; |
| 27986 | 27910 | |
| 27911 | return addSafetyCheckCall(sema, parent_block, src, ok, "panicSentinelMismatch", &.{ |
| 27912 | expected_sentinel, actual_sentinel, |
| 27913 | }); |
| 27914 | } |
| 27915 | |
| 27916 | fn addSafetyCheckCall( |
| 27917 | sema: *Sema, |
| 27918 | parent_block: *Block, |
| 27919 | src: LazySrcLoc, |
| 27920 | ok: Air.Inst.Ref, |
| 27921 | func_name: []const u8, |
| 27922 | args: []const Air.Inst.Ref, |
| 27923 | ) !void { |
| 27924 | assert(!parent_block.is_comptime); |
| 27925 | const gpa = sema.gpa; |
| 27926 | const pt = sema.pt; |
| 27927 | const zcu = pt.zcu; |
| 27928 | |
| 27987 | 27929 | var fail_block: Block = .{ |
| 27988 | 27930 | .parent = parent_block, |
| 27989 | 27931 | .sema = sema, |
| ... | ... | @@ -27997,23 +27939,13 @@ fn addSafetyCheckSentinelMismatch( |
| 27997 | 27939 | |
| 27998 | 27940 | defer fail_block.instructions.deinit(gpa); |
| 27999 | 27941 | |
| 28000 | | // A different PanicCause tag must be used depending on what payload type it can be fit into. |
| 28001 | | // If it cannot fit into any, the "other" tag can be used, which does not try to carry the |
| 28002 | | // sentinel value data. |
| 28003 | | |
| 28004 | | if (sentinel_ty.isUnsignedInt(zcu) and sentinel_ty.intInfo(zcu).bits <= Type.usize.intInfo(zcu).bits) { |
| 28005 | | const mm_ty = try getBuiltinInnerType(sema, &fail_block, src, "PanicCause", "SentinelMismatchUsize"); |
| 28006 | | comptime { |
| 28007 | | const fields = @typeInfo(std.builtin.PanicCause.SentinelMismatchUsize).@"struct".fields; |
| 28008 | | assert(std.mem.eql(u8, fields[0].name, "expected")); |
| 28009 | | assert(std.mem.eql(u8, fields[1].name, "found")); |
| 28010 | | assert(fields.len == 2); |
| 28011 | | } |
| 28012 | | const panic_cause_payload = try fail_block.addAggregateInit(mm_ty, &.{ expected_sentinel, actual_sentinel }); |
| 28013 | | try callPanic(sema, &fail_block, src, .sentinel_mismatch_usize, panic_cause_payload, .@"safety check"); |
| 27942 | if (!zcu.backendSupportsFeature(.panic_fn)) { |
| 27943 | _ = try fail_block.addNoOp(.trap); |
| 28014 | 27944 | } else { |
| 28015 | | try callPanic(sema, &fail_block, src, .sentinel_mismatch_other, .void_value, .@"safety check"); |
| 27945 | const panic_fn = try pt.getBuiltin(func_name); |
| 27946 | try sema.callBuiltin(&fail_block, src, panic_fn, .auto, args, .@"safety check"); |
| 28016 | 27947 | } |
| 27948 | |
| 28017 | 27949 | try sema.addSafetyCheckExtra(parent_block, ok, &fail_block); |
| 28018 | 27950 | } |
| 28019 | 27951 | |
| ... | ... | @@ -33512,7 +33444,8 @@ fn analyzeSlice( |
| 33512 | 33444 | // requirement: start <= end |
| 33513 | 33445 | assert(!block.is_comptime); |
| 33514 | 33446 | try sema.requireRuntimeBlock(block, src, runtime_src.?); |
| 33515 | | try sema.addSafetyCheckStartGreaterThanEnd(block, src, start, end); |
| 33447 | const ok = try block.addBinOp(.cmp_lte, start, end); |
| 33448 | try sema.addSafetyCheckCall(block, src, ok, "panicStartGreaterThanEnd", &.{ start, end }); |
| 33516 | 33449 | } |
| 33517 | 33450 | const new_len = if (by_length) |
| 33518 | 33451 | try sema.coerce(block, Type.usize, uncasted_end_opt, end_src) |