| ... | @@ -22120,7 +22120,6 @@ pub const PanicId = enum { | ... | @@ -22120,7 +22120,6 @@ pub const PanicId = enum { |
| 22120 | shr_overflow, | 22120 | shr_overflow, |
| 22121 | divide_by_zero, | 22121 | divide_by_zero, |
| 22122 | exact_division_remainder, | 22122 | exact_division_remainder, |
| 22123 | /// TODO make this call `std.builtin.panicInactiveUnionField`. | | |
| 22124 | inactive_union_field, | 22123 | inactive_union_field, |
| 22125 | integer_part_out_of_bounds, | 22124 | integer_part_out_of_bounds, |
| 22126 | corrupt_switch, | 22125 | corrupt_switch, |
| ... | @@ -22296,90 +22295,40 @@ fn panicUnwrapError( | ... | @@ -22296,90 +22295,40 @@ fn panicUnwrapError( |
| 22296 | fn panicIndexOutOfBounds( | 22295 | fn panicIndexOutOfBounds( |
| 22297 | sema: *Sema, | 22296 | sema: *Sema, |
| 22298 | parent_block: *Block, | 22297 | parent_block: *Block, |
| 22299 | src: LazySrcLoc, | | |
| 22300 | index: Air.Inst.Ref, | 22298 | index: Air.Inst.Ref, |
| 22301 | len: Air.Inst.Ref, | 22299 | len: Air.Inst.Ref, |
| 22302 | cmp_op: Air.Inst.Tag, | 22300 | cmp_op: Air.Inst.Tag, |
| 22303 | ) !void { | 22301 | ) !void { |
| 22304 | assert(!parent_block.is_comptime); | 22302 | assert(!parent_block.is_comptime); |
| 22305 | const ok = try parent_block.addBinOp(cmp_op, index, len); | 22303 | const ok = try parent_block.addBinOp(cmp_op, index, len); |
| 22306 | const gpa = sema.gpa; | 22304 | try sema.safetyPanicFormatted(parent_block, ok, "panicOutOfBounds", &.{ index, len }); |
| 22307 | | | |
| 22308 | var fail_block: Block = .{ | | |
| 22309 | .parent = parent_block, | | |
| 22310 | .sema = sema, | | |
| 22311 | .src_decl = parent_block.src_decl, | | |
| 22312 | .namespace = parent_block.namespace, | | |
| 22313 | .wip_capture_scope = parent_block.wip_capture_scope, | | |
| 22314 | .instructions = .{}, | | |
| 22315 | .inlining = parent_block.inlining, | | |
| 22316 | .is_comptime = false, | | |
| 22317 | }; | | |
| 22318 | | | |
| 22319 | defer fail_block.instructions.deinit(gpa); | | |
| 22320 | | | |
| 22321 | { | | |
| 22322 | const this_feature_is_implemented_in_the_backend = | | |
| 22323 | sema.mod.comp.bin_file.options.use_llvm; | | |
| 22324 | | | |
| 22325 | if (!this_feature_is_implemented_in_the_backend) { | | |
| 22326 | // TODO implement this feature in all the backends and then delete this branch | | |
| 22327 | _ = try fail_block.addNoOp(.breakpoint); | | |
| 22328 | _ = try fail_block.addNoOp(.unreach); | | |
| 22329 | } else { | | |
| 22330 | const panic_fn = try sema.getBuiltin("panicOutOfBounds"); | | |
| 22331 | const args: [2]Air.Inst.Ref = .{ index, len }; | | |
| 22332 | _ = try sema.analyzeCall(&fail_block, panic_fn, src, src, .auto, false, &args, null); | | |
| 22333 | } | | |
| 22334 | } | | |
| 22335 | try sema.addSafetyCheckExtra(parent_block, ok, &fail_block); | | |
| 22336 | } | 22305 | } |
| 22337 | | 22306 | |
| 22338 | fn panicStartLargerThanEnd( | 22307 | fn panicStartLargerThanEnd( |
| 22339 | sema: *Sema, | 22308 | sema: *Sema, |
| 22340 | parent_block: *Block, | 22309 | parent_block: *Block, |
| 22341 | src: LazySrcLoc, | | |
| 22342 | start: Air.Inst.Ref, | 22310 | start: Air.Inst.Ref, |
| 22343 | end: Air.Inst.Ref, | 22311 | end: Air.Inst.Ref, |
| 22344 | ) !void { | 22312 | ) !void { |
| 22345 | assert(!parent_block.is_comptime); | 22313 | assert(!parent_block.is_comptime); |
| 22346 | const ok = try parent_block.addBinOp(.cmp_lte, start, end); | 22314 | const ok = try parent_block.addBinOp(.cmp_lte, start, end); |
| 22347 | const gpa = sema.gpa; | 22315 | try sema.safetyPanicFormatted(parent_block, ok, "panicStartGreaterThanEnd", &.{ start, end }); |
| 22348 | | 22316 | } |
| 22349 | var fail_block: Block = .{ | | |
| 22350 | .parent = parent_block, | | |
| 22351 | .sema = sema, | | |
| 22352 | .src_decl = parent_block.src_decl, | | |
| 22353 | .namespace = parent_block.namespace, | | |
| 22354 | .wip_capture_scope = parent_block.wip_capture_scope, | | |
| 22355 | .instructions = .{}, | | |
| 22356 | .inlining = parent_block.inlining, | | |
| 22357 | .is_comptime = false, | | |
| 22358 | }; | | |
| 22359 | | | |
| 22360 | defer fail_block.instructions.deinit(gpa); | | |
| 22361 | | | |
| 22362 | { | | |
| 22363 | const this_feature_is_implemented_in_the_backend = | | |
| 22364 | sema.mod.comp.bin_file.options.use_llvm; | | |
| 22365 | | 22317 | |
| 22366 | if (!this_feature_is_implemented_in_the_backend) { | 22318 | fn panicInactiveUnionField( |
| 22367 | // TODO implement this feature in all the backends and then delete this branch | 22319 | sema: *Sema, |
| 22368 | _ = try fail_block.addNoOp(.breakpoint); | 22320 | parent_block: *Block, |
| 22369 | _ = try fail_block.addNoOp(.unreach); | 22321 | active_tag: Air.Inst.Ref, |
| 22370 | } else { | 22322 | wanted_tag: Air.Inst.Ref, |
| 22371 | const panic_fn = try sema.getBuiltin("panicStartGreaterThanEnd"); | 22323 | ) !void { |
| 22372 | const args: [2]Air.Inst.Ref = .{ start, end }; | 22324 | assert(!parent_block.is_comptime); |
| 22373 | _ = try sema.analyzeCall(&fail_block, panic_fn, src, src, .auto, false, &args, null); | 22325 | const ok = try parent_block.addBinOp(.cmp_eq, active_tag, wanted_tag); |
| 22374 | } | 22326 | try sema.safetyPanicFormatted(parent_block, ok, "panicInactiveUnionField", &.{ active_tag, wanted_tag }); |
| 22375 | } | | |
| 22376 | try sema.addSafetyCheckExtra(parent_block, ok, &fail_block); | | |
| 22377 | } | 22327 | } |
| 22378 | | 22328 | |
| 22379 | fn panicSentinelMismatch( | 22329 | fn panicSentinelMismatch( |
| 22380 | sema: *Sema, | 22330 | sema: *Sema, |
| 22381 | parent_block: *Block, | 22331 | parent_block: *Block, |
| 22382 | src: LazySrcLoc, | | |
| 22383 | maybe_sentinel: ?Value, | 22332 | maybe_sentinel: ?Value, |
| 22384 | sentinel_ty: Type, | 22333 | sentinel_ty: Type, |
| 22385 | ptr: Air.Inst.Ref, | 22334 | ptr: Air.Inst.Ref, |
| ... | @@ -22413,9 +22362,20 @@ fn panicSentinelMismatch( | ... | @@ -22413,9 +22362,20 @@ fn panicSentinelMismatch( |
| 22413 | else { | 22362 | else { |
| 22414 | const panic_fn = try sema.getBuiltin("checkNonScalarSentinel"); | 22363 | const panic_fn = try sema.getBuiltin("checkNonScalarSentinel"); |
| 22415 | const args: [2]Air.Inst.Ref = .{ expected_sentinel, actual_sentinel }; | 22364 | const args: [2]Air.Inst.Ref = .{ expected_sentinel, actual_sentinel }; |
| 22416 | _ = try sema.analyzeCall(parent_block, panic_fn, src, src, .auto, false, &args, null); | 22365 | _ = try sema.analyzeCall(parent_block, panic_fn, sema.src, sema.src, .auto, false, &args, null); |
| 22417 | return; | 22366 | return; |
| 22418 | }; | 22367 | }; |
| | 22368 | |
| | 22369 | try sema.safetyPanicFormatted(parent_block, ok, "panicSentinelMismatch", &.{ expected_sentinel, actual_sentinel }); |
| | 22370 | } |
| | 22371 | |
| | 22372 | fn safetyPanicFormatted( |
| | 22373 | sema: *Sema, |
| | 22374 | parent_block: *Block, |
| | 22375 | ok: Air.Inst.Ref, |
| | 22376 | func: []const u8, |
| | 22377 | args: []const Air.Inst.Ref, |
| | 22378 | ) CompileError!void { |
| 22419 | const gpa = sema.gpa; | 22379 | const gpa = sema.gpa; |
| 22420 | | 22380 | |
| 22421 | var fail_block: Block = .{ | 22381 | var fail_block: Block = .{ |
| ... | @@ -22440,9 +22400,8 @@ fn panicSentinelMismatch( | ... | @@ -22440,9 +22400,8 @@ fn panicSentinelMismatch( |
| 22440 | _ = try fail_block.addNoOp(.breakpoint); | 22400 | _ = try fail_block.addNoOp(.breakpoint); |
| 22441 | _ = try fail_block.addNoOp(.unreach); | 22401 | _ = try fail_block.addNoOp(.unreach); |
| 22442 | } else { | 22402 | } else { |
| 22443 | const panic_fn = try sema.getBuiltin("panicSentinelMismatch"); | 22403 | const panic_fn = try sema.getBuiltin(func); |
| 22444 | const args: [2]Air.Inst.Ref = .{ expected_sentinel, actual_sentinel }; | 22404 | _ = try sema.analyzeCall(&fail_block, panic_fn, sema.src, sema.src, .auto, false, args, null); |
| 22445 | _ = try sema.analyzeCall(&fail_block, panic_fn, src, src, .auto, false, &args, null); | | |
| 22446 | } | 22405 | } |
| 22447 | } | 22406 | } |
| 22448 | try sema.addSafetyCheckExtra(parent_block, ok, &fail_block); | 22407 | try sema.addSafetyCheckExtra(parent_block, ok, &fail_block); |
| ... | @@ -23465,8 +23424,7 @@ fn unionFieldPtr( | ... | @@ -23465,8 +23424,7 @@ fn unionFieldPtr( |
| 23465 | // TODO would it be better if get_union_tag supported pointers to unions? | 23424 | // TODO would it be better if get_union_tag supported pointers to unions? |
| 23466 | const union_val = try block.addTyOp(.load, union_ty, union_ptr); | 23425 | const union_val = try block.addTyOp(.load, union_ty, union_ptr); |
| 23467 | const active_tag = try block.addTyOp(.get_union_tag, union_obj.tag_ty, union_val); | 23426 | const active_tag = try block.addTyOp(.get_union_tag, union_obj.tag_ty, union_val); |
| 23468 | const ok = try block.addBinOp(.cmp_eq, active_tag, wanted_tag); | 23427 | try sema.panicInactiveUnionField(block, active_tag, wanted_tag); |
| 23469 | try sema.addSafetyCheck(block, ok, .inactive_union_field); | | |
| 23470 | } | 23428 | } |
| 23471 | if (field.ty.zigTypeTag() == .NoReturn) { | 23429 | if (field.ty.zigTypeTag() == .NoReturn) { |
| 23472 | _ = try block.addNoOp(.unreach); | 23430 | _ = try block.addNoOp(.unreach); |
| ... | @@ -23537,8 +23495,7 @@ fn unionFieldVal( | ... | @@ -23537,8 +23495,7 @@ fn unionFieldVal( |
| 23537 | const wanted_tag_val = try Value.Tag.enum_field_index.create(sema.arena, enum_field_index); | 23495 | const wanted_tag_val = try Value.Tag.enum_field_index.create(sema.arena, enum_field_index); |
| 23538 | const wanted_tag = try sema.addConstant(union_obj.tag_ty, wanted_tag_val); | 23496 | const wanted_tag = try sema.addConstant(union_obj.tag_ty, wanted_tag_val); |
| 23539 | const active_tag = try block.addTyOp(.get_union_tag, union_obj.tag_ty, union_byval); | 23497 | const active_tag = try block.addTyOp(.get_union_tag, union_obj.tag_ty, union_byval); |
| 23540 | const ok = try block.addBinOp(.cmp_eq, active_tag, wanted_tag); | 23498 | try sema.panicInactiveUnionField(block, active_tag, wanted_tag); |
| 23541 | try sema.addSafetyCheck(block, ok, .inactive_union_field); | | |
| 23542 | } | 23499 | } |
| 23543 | if (field.ty.zigTypeTag() == .NoReturn) { | 23500 | if (field.ty.zigTypeTag() == .NoReturn) { |
| 23544 | _ = try block.addNoOp(.unreach); | 23501 | _ = try block.addNoOp(.unreach); |
| ... | @@ -23849,7 +23806,7 @@ fn elemValArray( | ... | @@ -23849,7 +23806,7 @@ fn elemValArray( |
| 23849 | if (maybe_index_val == null) { | 23806 | if (maybe_index_val == null) { |
| 23850 | const len_inst = try sema.addIntUnsigned(Type.usize, array_len); | 23807 | const len_inst = try sema.addIntUnsigned(Type.usize, array_len); |
| 23851 | const cmp_op: Air.Inst.Tag = if (array_sent != null) .cmp_lte else .cmp_lt; | 23808 | const cmp_op: Air.Inst.Tag = if (array_sent != null) .cmp_lte else .cmp_lt; |
| 23852 | try sema.panicIndexOutOfBounds(block, elem_index_src, elem_index, len_inst, cmp_op); | 23809 | try sema.panicIndexOutOfBounds(block, elem_index, len_inst, cmp_op); |
| 23853 | } | 23810 | } |
| 23854 | } | 23811 | } |
| 23855 | return block.addBinOp(.array_elem_val, array, elem_index); | 23812 | return block.addBinOp(.array_elem_val, array, elem_index); |
| ... | @@ -23910,7 +23867,7 @@ fn elemPtrArray( | ... | @@ -23910,7 +23867,7 @@ fn elemPtrArray( |
| 23910 | if (block.wantSafety() and offset == null) { | 23867 | if (block.wantSafety() and offset == null) { |
| 23911 | const len_inst = try sema.addIntUnsigned(Type.usize, array_len); | 23868 | const len_inst = try sema.addIntUnsigned(Type.usize, array_len); |
| 23912 | const cmp_op: Air.Inst.Tag = if (array_sent) .cmp_lte else .cmp_lt; | 23869 | const cmp_op: Air.Inst.Tag = if (array_sent) .cmp_lte else .cmp_lt; |
| 23913 | try sema.panicIndexOutOfBounds(block, elem_index_src, elem_index, len_inst, cmp_op); | 23870 | try sema.panicIndexOutOfBounds(block, elem_index, len_inst, cmp_op); |
| 23914 | } | 23871 | } |
| 23915 | | 23872 | |
| 23916 | return block.addPtrElemPtr(array_ptr, elem_index, elem_ptr_ty); | 23873 | return block.addPtrElemPtr(array_ptr, elem_index, elem_ptr_ty); |
| ... | @@ -23966,7 +23923,7 @@ fn elemValSlice( | ... | @@ -23966,7 +23923,7 @@ fn elemValSlice( |
| 23966 | else | 23923 | else |
| 23967 | try block.addTyOp(.slice_len, Type.usize, slice); | 23924 | try block.addTyOp(.slice_len, Type.usize, slice); |
| 23968 | const cmp_op: Air.Inst.Tag = if (slice_sent) .cmp_lte else .cmp_lt; | 23925 | const cmp_op: Air.Inst.Tag = if (slice_sent) .cmp_lte else .cmp_lt; |
| 23969 | try sema.panicIndexOutOfBounds(block, elem_index_src, elem_index, len_inst, cmp_op); | 23926 | try sema.panicIndexOutOfBounds(block, elem_index, len_inst, cmp_op); |
| 23970 | } | 23927 | } |
| 23971 | try sema.queueFullTypeResolution(sema.typeOf(slice)); | 23928 | try sema.queueFullTypeResolution(sema.typeOf(slice)); |
| 23972 | return block.addBinOp(.slice_elem_val, slice, elem_index); | 23929 | return block.addBinOp(.slice_elem_val, slice, elem_index); |
| ... | @@ -24025,7 +23982,7 @@ fn elemPtrSlice( | ... | @@ -24025,7 +23982,7 @@ fn elemPtrSlice( |
| 24025 | break :len try block.addTyOp(.slice_len, Type.usize, slice); | 23982 | break :len try block.addTyOp(.slice_len, Type.usize, slice); |
| 24026 | }; | 23983 | }; |
| 24027 | const cmp_op: Air.Inst.Tag = if (slice_sent) .cmp_lte else .cmp_lt; | 23984 | const cmp_op: Air.Inst.Tag = if (slice_sent) .cmp_lte else .cmp_lt; |
| 24028 | try sema.panicIndexOutOfBounds(block, elem_index_src, elem_index, len_inst, cmp_op); | 23985 | try sema.panicIndexOutOfBounds(block, elem_index, len_inst, cmp_op); |
| 24029 | } | 23986 | } |
| 24030 | return block.addSliceElemPtr(slice, elem_index, elem_ptr_ty); | 23987 | return block.addSliceElemPtr(slice, elem_index, elem_ptr_ty); |
| 24031 | } | 23988 | } |
| ... | @@ -28072,7 +28029,7 @@ fn analyzeSlice( | ... | @@ -28072,7 +28029,7 @@ fn analyzeSlice( |
| 28072 | | 28029 | |
| 28073 | if (block.wantSafety() and !block.is_comptime) { | 28030 | if (block.wantSafety() and !block.is_comptime) { |
| 28074 | // requirement: start <= end | 28031 | // requirement: start <= end |
| 28075 | try sema.panicStartLargerThanEnd(block, src, start, end); | 28032 | try sema.panicStartLargerThanEnd(block, start, end); |
| 28076 | } | 28033 | } |
| 28077 | const new_len = try sema.analyzeArithmetic(block, .sub, end, start, src, end_src, start_src, false); | 28034 | const new_len = try sema.analyzeArithmetic(block, .sub, end, start, src, end_src, start_src, false); |
| 28078 | const opt_new_len_val = try sema.resolveDefinedValue(block, src, new_len); | 28035 | const opt_new_len_val = try sema.resolveDefinedValue(block, src, new_len); |
| ... | @@ -28116,11 +28073,11 @@ fn analyzeSlice( | ... | @@ -28116,11 +28073,11 @@ fn analyzeSlice( |
| 28116 | else | 28073 | else |
| 28117 | end; | 28074 | end; |
| 28118 | | 28075 | |
| 28119 | try sema.panicIndexOutOfBounds(block, src, actual_end, actual_len, .cmp_lte); | 28076 | try sema.panicIndexOutOfBounds(block, actual_end, actual_len, .cmp_lte); |
| 28120 | } | 28077 | } |
| 28121 | | 28078 | |
| 28122 | // requirement: result[new_len] == slice_sentinel | 28079 | // requirement: result[new_len] == slice_sentinel |
| 28123 | try sema.panicSentinelMismatch(block, src, slice_sentinel, elem_ty, result, new_len); | 28080 | try sema.panicSentinelMismatch(block, slice_sentinel, elem_ty, result, new_len); |
| 28124 | } | 28081 | } |
| 28125 | return result; | 28082 | return result; |
| 28126 | }; | 28083 | }; |
| ... | @@ -28184,11 +28141,11 @@ fn analyzeSlice( | ... | @@ -28184,11 +28141,11 @@ fn analyzeSlice( |
| 28184 | try sema.analyzeArithmetic(block, .add, end, .one, src, end_src, end_src, true) | 28141 | try sema.analyzeArithmetic(block, .add, end, .one, src, end_src, end_src, true) |
| 28185 | else | 28142 | else |
| 28186 | end; | 28143 | end; |
| 28187 | try sema.panicIndexOutOfBounds(block, src, actual_end, len_inst, .cmp_lte); | 28144 | try sema.panicIndexOutOfBounds(block, actual_end, len_inst, .cmp_lte); |
| 28188 | } | 28145 | } |
| 28189 | | 28146 | |
| 28190 | // requirement: start <= end | 28147 | // requirement: start <= end |
| 28191 | try sema.panicIndexOutOfBounds(block, src, start, end, .cmp_lte); | 28148 | try sema.panicIndexOutOfBounds(block, start, end, .cmp_lte); |
| 28192 | } | 28149 | } |
| 28193 | const result = try block.addInst(.{ | 28150 | const result = try block.addInst(.{ |
| 28194 | .tag = .slice, | 28151 | .tag = .slice, |
| ... | @@ -28202,7 +28159,7 @@ fn analyzeSlice( | ... | @@ -28202,7 +28159,7 @@ fn analyzeSlice( |
| 28202 | }); | 28159 | }); |
| 28203 | if (block.wantSafety()) { | 28160 | if (block.wantSafety()) { |
| 28204 | // requirement: result[new_len] == slice_sentinel | 28161 | // requirement: result[new_len] == slice_sentinel |
| 28205 | try sema.panicSentinelMismatch(block, src, slice_sentinel, elem_ty, result, new_len); | 28162 | try sema.panicSentinelMismatch(block, slice_sentinel, elem_ty, result, new_len); |
| 28206 | } | 28163 | } |
| 28207 | return result; | 28164 | return result; |
| 28208 | } | 28165 | } |