| ... | ... | @@ -16857,7 +16857,6 @@ pub const PanicId = enum { |
| 16857 | 16857 | cast_to_null, |
| 16858 | 16858 | incorrect_alignment, |
| 16859 | 16859 | invalid_error_code, |
| 16860 | | index_out_of_bounds, |
| 16861 | 16860 | cast_truncated_data, |
| 16862 | 16861 | integer_overflow, |
| 16863 | 16862 | shl_overflow, |
| ... | ... | @@ -16886,6 +16885,17 @@ fn addSafetyCheck( |
| 16886 | 16885 | |
| 16887 | 16886 | _ = try sema.safetyPanic(&fail_block, .unneeded, panic_id); |
| 16888 | 16887 | |
| 16888 | try sema.addSafetyCheckExtra(parent_block, ok, &fail_block); |
| 16889 | } |
| 16890 | |
| 16891 | fn addSafetyCheckExtra( |
| 16892 | sema: *Sema, |
| 16893 | parent_block: *Block, |
| 16894 | ok: Air.Inst.Ref, |
| 16895 | fail_block: *Block, |
| 16896 | ) !void { |
| 16897 | const gpa = sema.gpa; |
| 16898 | |
| 16889 | 16899 | try parent_block.instructions.ensureUnusedCapacity(gpa, 1); |
| 16890 | 16900 | |
| 16891 | 16901 | try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Block).Struct.fields.len + |
| ... | ... | @@ -16994,7 +17004,6 @@ fn panicUnwrapError( |
| 16994 | 17004 | |
| 16995 | 17005 | { |
| 16996 | 17006 | const this_feature_is_implemented_in_the_backend = |
| 16997 | | sema.mod.comp.bin_file.options.object_format == .c or |
| 16998 | 17007 | sema.mod.comp.bin_file.options.use_llvm; |
| 16999 | 17008 | |
| 17000 | 17009 | if (!this_feature_is_implemented_in_the_backend) { |
| ... | ... | @@ -17009,52 +17018,48 @@ fn panicUnwrapError( |
| 17009 | 17018 | _ = try sema.analyzeCall(&fail_block, panic_fn, src, src, .auto, false, &args); |
| 17010 | 17019 | } |
| 17011 | 17020 | } |
| 17021 | try sema.addSafetyCheckExtra(parent_block, ok, &fail_block); |
| 17022 | } |
| 17012 | 17023 | |
| 17013 | | try parent_block.instructions.ensureUnusedCapacity(gpa, 1); |
| 17014 | | |
| 17015 | | try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Block).Struct.fields.len + |
| 17016 | | 1 + // The main block only needs space for the cond_br. |
| 17017 | | @typeInfo(Air.CondBr).Struct.fields.len + |
| 17018 | | 1 + // The ok branch of the cond_br only needs space for the br. |
| 17019 | | fail_block.instructions.items.len); |
| 17024 | fn panicIndexOutOfBounds( |
| 17025 | sema: *Sema, |
| 17026 | parent_block: *Block, |
| 17027 | src: LazySrcLoc, |
| 17028 | index: Air.Inst.Ref, |
| 17029 | len: Air.Inst.Ref, |
| 17030 | cmp_op: Air.Inst.Tag, |
| 17031 | ) !void { |
| 17032 | const ok = try parent_block.addBinOp(cmp_op, index, len); |
| 17033 | const gpa = sema.gpa; |
| 17020 | 17034 | |
| 17021 | | try sema.air_instructions.ensureUnusedCapacity(gpa, 3); |
| 17022 | | const block_inst = @intCast(Air.Inst.Index, sema.air_instructions.len); |
| 17023 | | const cond_br_inst = block_inst + 1; |
| 17024 | | const br_inst = cond_br_inst + 1; |
| 17025 | | sema.air_instructions.appendAssumeCapacity(.{ |
| 17026 | | .tag = .block, |
| 17027 | | .data = .{ .ty_pl = .{ |
| 17028 | | .ty = .void_type, |
| 17029 | | .payload = sema.addExtraAssumeCapacity(Air.Block{ |
| 17030 | | .body_len = 1, |
| 17031 | | }), |
| 17032 | | } }, |
| 17033 | | }); |
| 17034 | | sema.air_extra.appendAssumeCapacity(cond_br_inst); |
| 17035 | var fail_block: Block = .{ |
| 17036 | .parent = parent_block, |
| 17037 | .sema = sema, |
| 17038 | .src_decl = parent_block.src_decl, |
| 17039 | .namespace = parent_block.namespace, |
| 17040 | .wip_capture_scope = parent_block.wip_capture_scope, |
| 17041 | .instructions = .{}, |
| 17042 | .inlining = parent_block.inlining, |
| 17043 | .is_comptime = parent_block.is_comptime, |
| 17044 | }; |
| 17035 | 17045 | |
| 17036 | | sema.air_instructions.appendAssumeCapacity(.{ |
| 17037 | | .tag = .cond_br, |
| 17038 | | .data = .{ .pl_op = .{ |
| 17039 | | .operand = ok, |
| 17040 | | .payload = sema.addExtraAssumeCapacity(Air.CondBr{ |
| 17041 | | .then_body_len = 1, |
| 17042 | | .else_body_len = @intCast(u32, fail_block.instructions.items.len), |
| 17043 | | }), |
| 17044 | | } }, |
| 17045 | | }); |
| 17046 | | sema.air_extra.appendAssumeCapacity(br_inst); |
| 17047 | | sema.air_extra.appendSliceAssumeCapacity(fail_block.instructions.items); |
| 17046 | defer fail_block.instructions.deinit(gpa); |
| 17048 | 17047 | |
| 17049 | | sema.air_instructions.appendAssumeCapacity(.{ |
| 17050 | | .tag = .br, |
| 17051 | | .data = .{ .br = .{ |
| 17052 | | .block_inst = block_inst, |
| 17053 | | .operand = .void_value, |
| 17054 | | } }, |
| 17055 | | }); |
| 17048 | { |
| 17049 | const this_feature_is_implemented_in_the_backend = |
| 17050 | sema.mod.comp.bin_file.options.use_llvm; |
| 17056 | 17051 | |
| 17057 | | parent_block.instructions.appendAssumeCapacity(block_inst); |
| 17052 | if (!this_feature_is_implemented_in_the_backend) { |
| 17053 | // TODO implement this feature in all the backends and then delete this branch |
| 17054 | _ = try fail_block.addNoOp(.breakpoint); |
| 17055 | _ = try fail_block.addNoOp(.unreach); |
| 17056 | } else { |
| 17057 | const panic_fn = try sema.getBuiltin(&fail_block, src, "panicOutOfBounds"); |
| 17058 | const args: [2]Air.Inst.Ref = .{ index, len }; |
| 17059 | _ = try sema.analyzeCall(&fail_block, panic_fn, src, src, .auto, false, &args); |
| 17060 | } |
| 17061 | } |
| 17062 | try sema.addSafetyCheckExtra(parent_block, ok, &fail_block); |
| 17058 | 17063 | } |
| 17059 | 17064 | |
| 17060 | 17065 | fn safetyPanic( |
| ... | ... | @@ -17069,7 +17074,6 @@ fn safetyPanic( |
| 17069 | 17074 | .cast_to_null => "cast causes pointer to be null", |
| 17070 | 17075 | .incorrect_alignment => "incorrect alignment", |
| 17071 | 17076 | .invalid_error_code => "invalid error code", |
| 17072 | | .index_out_of_bounds => "attempt to index out of bounds", |
| 17073 | 17077 | .cast_truncated_data => "integer cast truncated bits", |
| 17074 | 17078 | .integer_overflow => "integer overflow", |
| 17075 | 17079 | .shl_overflow => "left shift overflowed bits", |
| ... | ... | @@ -18261,8 +18265,7 @@ fn elemValArray( |
| 18261 | 18265 | if (maybe_index_val == null) { |
| 18262 | 18266 | const len_inst = try sema.addIntUnsigned(Type.usize, array_len); |
| 18263 | 18267 | const cmp_op: Air.Inst.Tag = if (array_sent) .cmp_lte else .cmp_lt; |
| 18264 | | const is_in_bounds = try block.addBinOp(cmp_op, elem_index, len_inst); |
| 18265 | | try sema.addSafetyCheck(block, is_in_bounds, .index_out_of_bounds); |
| 18268 | try sema.panicIndexOutOfBounds(block, elem_index_src, elem_index, len_inst, cmp_op); |
| 18266 | 18269 | } |
| 18267 | 18270 | } |
| 18268 | 18271 | return block.addBinOp(.array_elem_val, array, elem_index); |
| ... | ... | @@ -18317,8 +18320,7 @@ fn elemPtrArray( |
| 18317 | 18320 | if (maybe_index_val == null) { |
| 18318 | 18321 | const len_inst = try sema.addIntUnsigned(Type.usize, array_len); |
| 18319 | 18322 | const cmp_op: Air.Inst.Tag = if (array_sent) .cmp_lte else .cmp_lt; |
| 18320 | | const is_in_bounds = try block.addBinOp(cmp_op, elem_index, len_inst); |
| 18321 | | try sema.addSafetyCheck(block, is_in_bounds, .index_out_of_bounds); |
| 18323 | try sema.panicIndexOutOfBounds(block, elem_index_src, elem_index, len_inst, cmp_op); |
| 18322 | 18324 | } |
| 18323 | 18325 | } |
| 18324 | 18326 | return block.addPtrElemPtr(array_ptr, elem_index, elem_ptr_ty); |
| ... | ... | @@ -18371,8 +18373,7 @@ fn elemValSlice( |
| 18371 | 18373 | else |
| 18372 | 18374 | try block.addTyOp(.slice_len, Type.usize, slice); |
| 18373 | 18375 | const cmp_op: Air.Inst.Tag = if (slice_sent) .cmp_lte else .cmp_lt; |
| 18374 | | const is_in_bounds = try block.addBinOp(cmp_op, elem_index, len_inst); |
| 18375 | | try sema.addSafetyCheck(block, is_in_bounds, .index_out_of_bounds); |
| 18376 | try sema.panicIndexOutOfBounds(block, elem_index_src, elem_index, len_inst, cmp_op); |
| 18376 | 18377 | } |
| 18377 | 18378 | try sema.queueFullTypeResolution(sema.typeOf(slice)); |
| 18378 | 18379 | return block.addBinOp(.slice_elem_val, slice, elem_index); |
| ... | ... | @@ -18425,8 +18426,7 @@ fn elemPtrSlice( |
| 18425 | 18426 | break :len try block.addTyOp(.slice_len, Type.usize, slice); |
| 18426 | 18427 | }; |
| 18427 | 18428 | const cmp_op: Air.Inst.Tag = if (slice_sent) .cmp_lte else .cmp_lt; |
| 18428 | | const is_in_bounds = try block.addBinOp(cmp_op, elem_index, len_inst); |
| 18429 | | try sema.addSafetyCheck(block, is_in_bounds, .index_out_of_bounds); |
| 18429 | try sema.panicIndexOutOfBounds(block, elem_index_src, elem_index, len_inst, cmp_op); |
| 18430 | 18430 | } |
| 18431 | 18431 | return block.addSliceElemPtr(slice, elem_index, elem_ptr_ty); |
| 18432 | 18432 | } |
| ... | ... | @@ -21111,13 +21111,11 @@ fn analyzeSlice( |
| 21111 | 21111 | break :blk try sema.analyzeArithmetic(block, .add, slice_len_inst, .one, src, end_src, end_src); |
| 21112 | 21112 | } else null; |
| 21113 | 21113 | if (opt_len_inst) |len_inst| { |
| 21114 | | const end_is_in_bounds = try block.addBinOp(.cmp_lte, end, len_inst); |
| 21115 | | try sema.addSafetyCheck(block, end_is_in_bounds, .index_out_of_bounds); |
| 21114 | try sema.panicIndexOutOfBounds(block, src, end, len_inst, .cmp_lte); |
| 21116 | 21115 | } |
| 21117 | 21116 | |
| 21118 | 21117 | // requirement: start <= end |
| 21119 | | const start_is_in_bounds = try block.addBinOp(.cmp_lte, start, end); |
| 21120 | | try sema.addSafetyCheck(block, start_is_in_bounds, .index_out_of_bounds); |
| 21118 | try sema.panicIndexOutOfBounds(block, src, start, end, .cmp_lte); |
| 21121 | 21119 | } |
| 21122 | 21120 | return block.addInst(.{ |
| 21123 | 21121 | .tag = .slice, |