| ... | @@ -14249,7 +14249,7 @@ fn maybeErrorUnwrap( | ... | @@ -14249,7 +14249,7 @@ fn maybeErrorUnwrap( |
| 14249 | .as_node => try sema.zirAsNode(block, inst), | 14249 | .as_node => try sema.zirAsNode(block, inst), |
| 14250 | .field_val => try sema.zirFieldVal(block, inst), | 14250 | .field_val => try sema.zirFieldVal(block, inst), |
| 14251 | .@"unreachable" => { | 14251 | .@"unreachable" => { |
| 14252 | try callPanic(sema, block, operand_src, .unwrap_error, operand, .@"safety check"); | 14252 | try safetyPanicUnwrapError(sema, block, operand_src, operand); |
| 14253 | return true; | 14253 | return true; |
| 14254 | }, | 14254 | }, |
| 14255 | .panic => { | 14255 | .panic => { |
| ... | @@ -27827,11 +27827,24 @@ fn addSafetyCheckUnwrapError( | ... | @@ -27827,11 +27827,24 @@ fn addSafetyCheckUnwrapError( |
| 27827 | defer fail_block.instructions.deinit(gpa); | 27827 | defer fail_block.instructions.deinit(gpa); |
| 27828 | | 27828 | |
| 27829 | const err = try fail_block.addTyOp(unwrap_err_tag, Type.anyerror, operand); | 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 | try sema.addSafetyCheckExtra(parent_block, ok, &fail_block); | 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 | fn addSafetyCheckIndexOob( | 27848 | fn addSafetyCheckIndexOob( |
| 27836 | sema: *Sema, | 27849 | sema: *Sema, |
| 27837 | parent_block: *Block, | 27850 | parent_block: *Block, |
| ... | @@ -27841,68 +27854,8 @@ fn addSafetyCheckIndexOob( | ... | @@ -27841,68 +27854,8 @@ fn addSafetyCheckIndexOob( |
| 27841 | cmp_op: Air.Inst.Tag, | 27854 | cmp_op: Air.Inst.Tag, |
| 27842 | ) !void { | 27855 | ) !void { |
| 27843 | assert(!parent_block.is_comptime); | 27856 | assert(!parent_block.is_comptime); |
| 27844 | const gpa = sema.gpa; | | |
| 27845 | const ok = try parent_block.addBinOp(cmp_op, index, len); | 27857 | const ok = try parent_block.addBinOp(cmp_op, index, len); |
| 27846 | | 27858 | return addSafetyCheckCall(sema, parent_block, src, ok, "panicOutOfBounds", &.{ index, len }); |
| 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); | | |
| 27906 | } | 27859 | } |
| 27907 | | 27860 | |
| 27908 | fn addSafetyCheckInactiveUnionField( | 27861 | fn addSafetyCheckInactiveUnionField( |
| ... | @@ -27913,36 +27866,8 @@ fn addSafetyCheckInactiveUnionField( | ... | @@ -27913,36 +27866,8 @@ fn addSafetyCheckInactiveUnionField( |
| 27913 | wanted_tag: Air.Inst.Ref, | 27866 | wanted_tag: Air.Inst.Ref, |
| 27914 | ) !void { | 27867 | ) !void { |
| 27915 | assert(!parent_block.is_comptime); | 27868 | assert(!parent_block.is_comptime); |
| 27916 | const gpa = sema.gpa; | | |
| 27917 | const ok = try parent_block.addBinOp(.cmp_eq, active_tag, wanted_tag); | 27869 | const ok = try parent_block.addBinOp(.cmp_eq, active_tag, wanted_tag); |
| 27918 | | 27870 | return addSafetyCheckCall(sema, parent_block, src, ok, "panicInactiveUnionField", &.{ active_tag, wanted_tag }); |
| 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); | | |
| 27946 | } | 27871 | } |
| 27947 | | 27872 | |
| 27948 | fn addSafetyCheckSentinelMismatch( | 27873 | fn addSafetyCheckSentinelMismatch( |
| ... | @@ -27955,7 +27880,6 @@ fn addSafetyCheckSentinelMismatch( | ... | @@ -27955,7 +27880,6 @@ fn addSafetyCheckSentinelMismatch( |
| 27955 | sentinel_index: Air.Inst.Ref, | 27880 | sentinel_index: Air.Inst.Ref, |
| 27956 | ) !void { | 27881 | ) !void { |
| 27957 | assert(!parent_block.is_comptime); | 27882 | assert(!parent_block.is_comptime); |
| 27958 | const gpa = sema.gpa; | | |
| 27959 | const pt = sema.pt; | 27883 | const pt = sema.pt; |
| 27960 | const zcu = pt.zcu; | 27884 | const zcu = pt.zcu; |
| 27961 | const expected_sentinel_val = maybe_sentinel orelse return; | 27885 | const expected_sentinel_val = maybe_sentinel orelse return; |
| ... | @@ -27984,6 +27908,24 @@ fn addSafetyCheckSentinelMismatch( | ... | @@ -27984,6 +27908,24 @@ fn addSafetyCheckSentinelMismatch( |
| 27984 | break :ok try parent_block.addBinOp(.cmp_eq, expected_sentinel, actual_sentinel); | 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 | var fail_block: Block = .{ | 27929 | var fail_block: Block = .{ |
| 27988 | .parent = parent_block, | 27930 | .parent = parent_block, |
| 27989 | .sema = sema, | 27931 | .sema = sema, |
| ... | @@ -27997,23 +27939,13 @@ fn addSafetyCheckSentinelMismatch( | ... | @@ -27997,23 +27939,13 @@ fn addSafetyCheckSentinelMismatch( |
| 27997 | | 27939 | |
| 27998 | defer fail_block.instructions.deinit(gpa); | 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. | 27942 | if (!zcu.backendSupportsFeature(.panic_fn)) { |
| 28001 | // If it cannot fit into any, the "other" tag can be used, which does not try to carry the | 27943 | _ = try fail_block.addNoOp(.trap); |
| 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"); | | |
| 28014 | } else { | 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 | try sema.addSafetyCheckExtra(parent_block, ok, &fail_block); | 27949 | try sema.addSafetyCheckExtra(parent_block, ok, &fail_block); |
| 28018 | } | 27950 | } |
| 28019 | | 27951 | |
| ... | @@ -33512,7 +33444,8 @@ fn analyzeSlice( | ... | @@ -33512,7 +33444,8 @@ fn analyzeSlice( |
| 33512 | // requirement: start <= end | 33444 | // requirement: start <= end |
| 33513 | assert(!block.is_comptime); | 33445 | assert(!block.is_comptime); |
| 33514 | try sema.requireRuntimeBlock(block, src, runtime_src.?); | 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 | const new_len = if (by_length) | 33450 | const new_len = if (by_length) |
| 33518 | try sema.coerce(block, Type.usize, uncasted_end_opt, end_src) | 33451 | try sema.coerce(block, Type.usize, uncasted_end_opt, end_src) |