| ... | @@ -4164,6 +4164,7 @@ fn validateStructInit( | ... | @@ -4164,6 +4164,7 @@ fn validateStructInit( |
| 4164 | // We expect to see something like this in the current block AIR: | 4164 | // We expect to see something like this in the current block AIR: |
| 4165 | // %a = field_ptr(...) | 4165 | // %a = field_ptr(...) |
| 4166 | // store(%a, %b) | 4166 | // store(%a, %b) |
| | 4167 | // With an optional bitcast between the store and the field_ptr. |
| 4167 | // If %b is a comptime operand, this field is comptime. | 4168 | // If %b is a comptime operand, this field is comptime. |
| 4168 | // | 4169 | // |
| 4169 | // However, in the case of a comptime-known pointer to a struct, the | 4170 | // However, in the case of a comptime-known pointer to a struct, the |
| ... | @@ -4374,75 +4375,65 @@ fn zirValidateArrayInit( | ... | @@ -4374,75 +4375,65 @@ fn zirValidateArrayInit( |
| 4374 | | 4375 | |
| 4375 | const elem_ptr_air_ref = sema.inst_map.get(elem_ptr).?; | 4376 | const elem_ptr_air_ref = sema.inst_map.get(elem_ptr).?; |
| 4376 | const elem_ptr_air_inst = Air.refToIndex(elem_ptr_air_ref).?; | 4377 | const elem_ptr_air_inst = Air.refToIndex(elem_ptr_air_ref).?; |
| 4377 | // Find the block index of the elem_ptr so that we can look at the next | 4378 | |
| 4378 | // instruction after it within the same block. | 4379 | // We expect to see something like this in the current block AIR: |
| | 4380 | // %a = elem_ptr(...) |
| | 4381 | // store(%a, %b) |
| | 4382 | // With an optional bitcast between the store and the elem_ptr. |
| | 4383 | // If %b is a comptime operand, this element is comptime. |
| | 4384 | // |
| | 4385 | // However, in the case of a comptime-known pointer to an array, the |
| | 4386 | // the elem_ptr instruction is missing, so we have to pattern-match |
| | 4387 | // based only on the store instructions. |
| | 4388 | // `first_block_index` needs to point to the `elem_ptr` if it exists; |
| | 4389 | // the `store` otherwise. |
| | 4390 | // |
| | 4391 | // It's also possible for there to be no store instruction, in the case |
| | 4392 | // of nested `coerce_result_ptr` instructions. If we see the `elem_ptr` |
| | 4393 | // but we have not found a `store`, treat as a runtime-known element. |
| | 4394 | // |
| | 4395 | // This is nearly identical to similar logic in `validateStructInit`. |
| | 4396 | |
| 4379 | // Possible performance enhancement: save the `block_index` between iterations | 4397 | // Possible performance enhancement: save the `block_index` between iterations |
| 4380 | // of the for loop. | 4398 | // of the for loop. |
| 4381 | var block_index = block.instructions.items.len - 1; | 4399 | var block_index = block.instructions.items.len - 1; |
| 4382 | while (block.instructions.items[block_index] != elem_ptr_air_inst) { | 4400 | while (block_index > 0) : (block_index -= 1) { |
| 4383 | if (block_index == 0) { | 4401 | const store_inst = block.instructions.items[block_index]; |
| | 4402 | if (store_inst == elem_ptr_air_inst) { |
| 4384 | array_is_comptime = false; | 4403 | array_is_comptime = false; |
| 4385 | continue :outer; | 4404 | continue :outer; |
| 4386 | } | 4405 | } |
| 4387 | block_index -= 1; | 4406 | if (air_tags[store_inst] != .store) continue; |
| 4388 | } | 4407 | const bin_op = air_datas[store_inst].bin_op; |
| 4389 | first_block_index = @min(first_block_index, block_index); | 4408 | var lhs = bin_op.lhs; |
| 4390 | | 4409 | { |
| 4391 | // If the next instructon is a store with a comptime operand, this element | 4410 | const lhs_index = Air.refToIndex(lhs) orelse continue; |
| 4392 | // is comptime. | 4411 | if (air_tags[lhs_index] == .bitcast) { |
| 4393 | const next_air_inst = block.instructions.items[block_index + 1]; | 4412 | lhs = air_datas[lhs_index].ty_op.operand; |
| 4394 | switch (air_tags[next_air_inst]) { | 4413 | block_index -= 1; |
| 4395 | .store => { | | |
| 4396 | const bin_op = air_datas[next_air_inst].bin_op; | | |
| 4397 | var lhs = bin_op.lhs; | | |
| 4398 | if (Air.refToIndex(lhs)) |lhs_index| { | | |
| 4399 | if (air_tags[lhs_index] == .bitcast) { | | |
| 4400 | lhs = air_datas[lhs_index].ty_op.operand; | | |
| 4401 | block_index -= 1; | | |
| 4402 | } | | |
| 4403 | } | | |
| 4404 | if (lhs != elem_ptr_air_ref) { | | |
| 4405 | array_is_comptime = false; | | |
| 4406 | continue; | | |
| 4407 | } | | |
| 4408 | if (try sema.resolveMaybeUndefValAllowVariablesMaybeRuntime(block, elem_src, bin_op.rhs, &make_runtime)) |val| { | | |
| 4409 | element_vals[i] = val; | | |
| 4410 | } else { | | |
| 4411 | array_is_comptime = false; | | |
| 4412 | } | | |
| 4413 | continue; | | |
| 4414 | }, | | |
| 4415 | .bitcast => { | | |
| 4416 | // %a = bitcast(*arr_ty, %array_base) | | |
| 4417 | // %b = ptr_elem_ptr(%a, %index) | | |
| 4418 | // %c = bitcast(*elem_ty, %b) | | |
| 4419 | // %d = store(%c, %val) | | |
| 4420 | if (air_datas[next_air_inst].ty_op.operand != elem_ptr_air_ref) { | | |
| 4421 | array_is_comptime = false; | | |
| 4422 | continue; | | |
| 4423 | } | | |
| 4424 | const store_inst = block.instructions.items[block_index + 2]; | | |
| 4425 | if (air_tags[store_inst] != .store) { | | |
| 4426 | array_is_comptime = false; | | |
| 4427 | continue; | | |
| 4428 | } | | |
| 4429 | const bin_op = air_datas[store_inst].bin_op; | | |
| 4430 | if (bin_op.lhs != Air.indexToRef(next_air_inst)) { | | |
| 4431 | array_is_comptime = false; | | |
| 4432 | continue; | | |
| 4433 | } | | |
| 4434 | if (try sema.resolveMaybeUndefValAllowVariablesMaybeRuntime(block, elem_src, bin_op.rhs, &make_runtime)) |val| { | | |
| 4435 | element_vals[i] = val; | | |
| 4436 | } else { | | |
| 4437 | array_is_comptime = false; | | |
| 4438 | } | 4414 | } |
| 4439 | continue; | 4415 | } |
| 4440 | }, | 4416 | if (lhs != elem_ptr_air_ref) continue; |
| 4441 | else => { | 4417 | while (block_index > 0) : (block_index -= 1) { |
| | 4418 | const block_inst = block.instructions.items[block_index - 1]; |
| | 4419 | if (air_tags[block_inst] != .dbg_stmt) break; |
| | 4420 | } |
| | 4421 | if (block_index > 0 and |
| | 4422 | elem_ptr_air_inst == block.instructions.items[block_index - 1]) |
| | 4423 | { |
| | 4424 | first_block_index = @min(first_block_index, block_index - 1); |
| | 4425 | } else { |
| | 4426 | first_block_index = @min(first_block_index, block_index); |
| | 4427 | } |
| | 4428 | if (try sema.resolveMaybeUndefValAllowVariablesMaybeRuntime(block, elem_src, bin_op.rhs, &make_runtime)) |val| { |
| | 4429 | element_vals[i] = val; |
| | 4430 | } else { |
| 4442 | array_is_comptime = false; | 4431 | array_is_comptime = false; |
| 4443 | continue; | 4432 | } |
| 4444 | }, | 4433 | continue :outer; |
| 4445 | } | 4434 | } |
| | 4435 | array_is_comptime = false; |
| | 4436 | continue :outer; |
| 4446 | } | 4437 | } |
| 4447 | | 4438 | |
| 4448 | if (array_is_comptime) { | 4439 | if (array_is_comptime) { |
| ... | @@ -8966,9 +8957,21 @@ fn intCast( | ... | @@ -8966,9 +8957,21 @@ fn intCast( |
| 8966 | const wanted_bits = wanted_info.bits; | 8957 | const wanted_bits = wanted_info.bits; |
| 8967 | | 8958 | |
| 8968 | if (wanted_bits == 0) { | 8959 | if (wanted_bits == 0) { |
| 8969 | const zero_inst = try sema.addConstant(sema.typeOf(operand), Value.zero); | 8960 | const ok = if (is_vector) ok: { |
| 8970 | const is_in_range = try block.addBinOp(.cmp_eq, operand, zero_inst); | 8961 | const zeros = try Value.Tag.repeated.create(sema.arena, Value.zero); |
| 8971 | try sema.addSafetyCheck(block, is_in_range, .cast_truncated_data); | 8962 | const zero_inst = try sema.addConstant(sema.typeOf(operand), zeros); |
| | 8963 | const is_in_range = try block.addCmpVector(operand, zero_inst, .eq, try sema.addType(operand_ty)); |
| | 8964 | const all_in_range = try block.addInst(.{ |
| | 8965 | .tag = .reduce, |
| | 8966 | .data = .{ .reduce = .{ .operand = is_in_range, .operation = .And } }, |
| | 8967 | }); |
| | 8968 | break :ok all_in_range; |
| | 8969 | } else ok: { |
| | 8970 | const zero_inst = try sema.addConstant(sema.typeOf(operand), Value.zero); |
| | 8971 | const is_in_range = try block.addBinOp(.cmp_lte, operand, zero_inst); |
| | 8972 | break :ok is_in_range; |
| | 8973 | }; |
| | 8974 | try sema.addSafetyCheck(block, ok, .cast_truncated_data); |
| 8972 | } | 8975 | } |
| 8973 | } | 8976 | } |
| 8974 | | 8977 | |
| ... | @@ -10330,8 +10333,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -10330,8 +10333,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 10330 | // Validation above ensured these will succeed. | 10333 | // Validation above ensured these will succeed. |
| 10331 | const first_tv = sema.resolveInstConst(&child_block, .unneeded, item_first, "") catch unreachable; | 10334 | const first_tv = sema.resolveInstConst(&child_block, .unneeded, item_first, "") catch unreachable; |
| 10332 | const last_tv = sema.resolveInstConst(&child_block, .unneeded, item_last, "") catch unreachable; | 10335 | const last_tv = sema.resolveInstConst(&child_block, .unneeded, item_last, "") catch unreachable; |
| 10333 | if ((try sema.compare(block, src, operand_val, .gte, first_tv.val, operand_ty)) and | 10336 | if ((try sema.compareAll(block, src, operand_val, .gte, first_tv.val, operand_ty)) and |
| 10334 | (try sema.compare(block, src, operand_val, .lte, last_tv.val, operand_ty))) | 10337 | (try sema.compareAll(block, src, operand_val, .lte, last_tv.val, operand_ty))) |
| 10335 | { | 10338 | { |
| 10336 | if (is_inline) child_block.inline_case_capture = operand; | 10339 | if (is_inline) child_block.inline_case_capture = operand; |
| 10337 | if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, body, operand); | 10340 | if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, body, operand); |
| ... | @@ -10479,7 +10482,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -10479,7 +10482,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 10479 | const item_last_ref = try sema.resolveInst(last_ref); | 10482 | const item_last_ref = try sema.resolveInst(last_ref); |
| 10480 | const item_last = sema.resolveConstValue(block, .unneeded, item_last_ref, undefined) catch unreachable; | 10483 | const item_last = sema.resolveConstValue(block, .unneeded, item_last_ref, undefined) catch unreachable; |
| 10481 | | 10484 | |
| 10482 | while (item.compare(.lte, item_last, operand_ty, sema.mod)) : ({ | 10485 | while (item.compareAll(.lte, item_last, operand_ty, sema.mod)) : ({ |
| 10483 | // Previous validation has resolved any possible lazy values. | 10486 | // Previous validation has resolved any possible lazy values. |
| 10484 | item = try sema.intAddScalar(block, .unneeded, item, Value.one); | 10487 | item = try sema.intAddScalar(block, .unneeded, item, Value.one); |
| 10485 | }) { | 10488 | }) { |
| ... | @@ -10934,7 +10937,7 @@ const RangeSetUnhandledIterator = struct { | ... | @@ -10934,7 +10937,7 @@ const RangeSetUnhandledIterator = struct { |
| 10934 | it.cur = try it.sema.intAdd(it.block, it.src, it.cur, Value.one, it.ty); | 10937 | it.cur = try it.sema.intAdd(it.block, it.src, it.cur, Value.one, it.ty); |
| 10935 | } | 10938 | } |
| 10936 | it.first = false; | 10939 | it.first = false; |
| 10937 | if (it.cur.compare(.lt, it.ranges[it.range_i].first, it.ty, it.sema.mod)) { | 10940 | if (it.cur.compareAll(.lt, it.ranges[it.range_i].first, it.ty, it.sema.mod)) { |
| 10938 | return it.cur; | 10941 | return it.cur; |
| 10939 | } | 10942 | } |
| 10940 | it.cur = it.ranges[it.range_i].last; | 10943 | it.cur = it.ranges[it.range_i].last; |
| ... | @@ -10943,7 +10946,7 @@ const RangeSetUnhandledIterator = struct { | ... | @@ -10943,7 +10946,7 @@ const RangeSetUnhandledIterator = struct { |
| 10943 | it.cur = try it.sema.intAdd(it.block, it.src, it.cur, Value.one, it.ty); | 10946 | it.cur = try it.sema.intAdd(it.block, it.src, it.cur, Value.one, it.ty); |
| 10944 | } | 10947 | } |
| 10945 | it.first = false; | 10948 | it.first = false; |
| 10946 | if (it.cur.compare(.lte, it.max, it.ty, it.sema.mod)) { | 10949 | if (it.cur.compareAll(.lte, it.max, it.ty, it.sema.mod)) { |
| 10947 | return it.cur; | 10950 | return it.cur; |
| 10948 | } | 10951 | } |
| 10949 | return null; | 10952 | return null; |
| ... | @@ -10989,7 +10992,7 @@ fn validateSwitchRange( | ... | @@ -10989,7 +10992,7 @@ fn validateSwitchRange( |
| 10989 | ) CompileError!void { | 10992 | ) CompileError!void { |
| 10990 | const first_val = (try sema.resolveSwitchItemVal(block, first_ref, src_node_offset, switch_prong_src, .first)).val; | 10993 | const first_val = (try sema.resolveSwitchItemVal(block, first_ref, src_node_offset, switch_prong_src, .first)).val; |
| 10991 | const last_val = (try sema.resolveSwitchItemVal(block, last_ref, src_node_offset, switch_prong_src, .last)).val; | 10994 | const last_val = (try sema.resolveSwitchItemVal(block, last_ref, src_node_offset, switch_prong_src, .last)).val; |
| 10992 | if (first_val.compare(.gt, last_val, operand_ty, sema.mod)) { | 10995 | if (first_val.compareAll(.gt, last_val, operand_ty, sema.mod)) { |
| 10993 | const src = switch_prong_src.resolve(sema.gpa, sema.mod.declPtr(block.src_decl), src_node_offset, .first); | 10996 | const src = switch_prong_src.resolve(sema.gpa, sema.mod.declPtr(block.src_decl), src_node_offset, .first); |
| 10994 | return sema.fail(block, src, "range start value is greater than the end value", .{}); | 10997 | return sema.fail(block, src, "range start value is greater than the end value", .{}); |
| 10995 | } | 10998 | } |
| ... | @@ -11453,7 +11456,7 @@ fn zirShl( | ... | @@ -11453,7 +11456,7 @@ fn zirShl( |
| 11453 | return sema.addConstUndef(sema.typeOf(lhs)); | 11456 | return sema.addConstUndef(sema.typeOf(lhs)); |
| 11454 | } | 11457 | } |
| 11455 | // If rhs is 0, return lhs without doing any calculations. | 11458 | // If rhs is 0, return lhs without doing any calculations. |
| 11456 | if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { | 11459 | if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 11457 | return lhs; | 11460 | return lhs; |
| 11458 | } | 11461 | } |
| 11459 | if (scalar_ty.zigTypeTag() != .ComptimeInt and air_tag != .shl_sat) { | 11462 | if (scalar_ty.zigTypeTag() != .ComptimeInt and air_tag != .shl_sat) { |
| ... | @@ -11497,7 +11500,7 @@ fn zirShl( | ... | @@ -11497,7 +11500,7 @@ fn zirShl( |
| 11497 | if (scalar_ty.zigTypeTag() == .ComptimeInt) { | 11500 | if (scalar_ty.zigTypeTag() == .ComptimeInt) { |
| 11498 | break :val shifted.wrapped_result; | 11501 | break :val shifted.wrapped_result; |
| 11499 | } | 11502 | } |
| 11500 | if (shifted.overflowed.compareWithZero(.eq)) { | 11503 | if (shifted.overflowed.compareAllWithZero(.eq)) { |
| 11501 | break :val shifted.wrapped_result; | 11504 | break :val shifted.wrapped_result; |
| 11502 | } | 11505 | } |
| 11503 | return sema.fail(block, src, "operation caused overflow", .{}); | 11506 | return sema.fail(block, src, "operation caused overflow", .{}); |
| ... | @@ -11622,7 +11625,7 @@ fn zirShr( | ... | @@ -11622,7 +11625,7 @@ fn zirShr( |
| 11622 | return sema.addConstUndef(lhs_ty); | 11625 | return sema.addConstUndef(lhs_ty); |
| 11623 | } | 11626 | } |
| 11624 | // If rhs is 0, return lhs without doing any calculations. | 11627 | // If rhs is 0, return lhs without doing any calculations. |
| 11625 | if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { | 11628 | if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 11626 | return lhs; | 11629 | return lhs; |
| 11627 | } | 11630 | } |
| 11628 | if (scalar_ty.zigTypeTag() != .ComptimeInt) { | 11631 | if (scalar_ty.zigTypeTag() != .ComptimeInt) { |
| ... | @@ -11656,7 +11659,7 @@ fn zirShr( | ... | @@ -11656,7 +11659,7 @@ fn zirShr( |
| 11656 | if (air_tag == .shr_exact) { | 11659 | if (air_tag == .shr_exact) { |
| 11657 | // Detect if any ones would be shifted out. | 11660 | // Detect if any ones would be shifted out. |
| 11658 | const truncated = try lhs_val.intTruncBitsAsValue(lhs_ty, sema.arena, .unsigned, rhs_val, target); | 11661 | const truncated = try lhs_val.intTruncBitsAsValue(lhs_ty, sema.arena, .unsigned, rhs_val, target); |
| 11659 | if (!(try truncated.compareWithZeroAdvanced(.eq, sema.kit(block, src)))) { | 11662 | if (!(try truncated.compareAllWithZeroAdvanced(.eq, sema.kit(block, src)))) { |
| 11660 | return sema.fail(block, src, "exact shift shifted out 1 bits", .{}); | 11663 | return sema.fail(block, src, "exact shift shifted out 1 bits", .{}); |
| 11661 | } | 11664 | } |
| 11662 | } | 11665 | } |
| ... | @@ -12385,6 +12388,8 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins | ... | @@ -12385,6 +12388,8 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins |
| 12385 | .override = &[_]LazySrcLoc{ lhs_src, rhs_src }, | 12388 | .override = &[_]LazySrcLoc{ lhs_src, rhs_src }, |
| 12386 | }); | 12389 | }); |
| 12387 | | 12390 | |
| | 12391 | const is_vector = resolved_type.zigTypeTag() == .Vector; |
| | 12392 | |
| 12388 | const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src); | 12393 | const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src); |
| 12389 | const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src); | 12394 | const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src); |
| 12390 | | 12395 | |
| ... | @@ -12409,7 +12414,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins | ... | @@ -12409,7 +12414,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins |
| 12409 | const lhs_val = maybe_lhs_val orelse unreachable; | 12414 | const lhs_val = maybe_lhs_val orelse unreachable; |
| 12410 | const rhs_val = maybe_rhs_val orelse unreachable; | 12415 | const rhs_val = maybe_rhs_val orelse unreachable; |
| 12411 | const rem = lhs_val.floatRem(rhs_val, resolved_type, sema.arena, target) catch unreachable; | 12416 | const rem = lhs_val.floatRem(rhs_val, resolved_type, sema.arena, target) catch unreachable; |
| 12412 | if (rem.compareWithZero(.neq)) { | 12417 | if (!rem.compareAllWithZero(.eq)) { |
| 12413 | return sema.fail(block, src, "ambiguous coercion of division operands '{s}' and '{s}'; non-zero remainder '{}'", .{ | 12418 | return sema.fail(block, src, "ambiguous coercion of division operands '{s}' and '{s}'; non-zero remainder '{}'", .{ |
| 12414 | @tagName(lhs_ty.tag()), @tagName(rhs_ty.tag()), rem.fmtValue(resolved_type, sema.mod), | 12419 | @tagName(lhs_ty.tag()), @tagName(rhs_ty.tag()), rem.fmtValue(resolved_type, sema.mod), |
| 12415 | }); | 12420 | }); |
| ... | @@ -12447,8 +12452,11 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins | ... | @@ -12447,8 +12452,11 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins |
| 12447 | .Int, .ComptimeInt, .ComptimeFloat => { | 12452 | .Int, .ComptimeInt, .ComptimeFloat => { |
| 12448 | if (maybe_lhs_val) |lhs_val| { | 12453 | if (maybe_lhs_val) |lhs_val| { |
| 12449 | if (!lhs_val.isUndef()) { | 12454 | if (!lhs_val.isUndef()) { |
| 12450 | if (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { | 12455 | if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 12451 | return sema.addConstant(resolved_type, Value.zero); | 12456 | const zero_val = if (is_vector) b: { |
| | 12457 | break :b try Value.Tag.repeated.create(sema.arena, Value.zero); |
| | 12458 | } else Value.zero; |
| | 12459 | return sema.addConstant(resolved_type, zero_val); |
| 12452 | } | 12460 | } |
| 12453 | } | 12461 | } |
| 12454 | } | 12462 | } |
| ... | @@ -12456,7 +12464,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins | ... | @@ -12456,7 +12464,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins |
| 12456 | if (rhs_val.isUndef()) { | 12464 | if (rhs_val.isUndef()) { |
| 12457 | return sema.failWithUseOfUndef(block, rhs_src); | 12465 | return sema.failWithUseOfUndef(block, rhs_src); |
| 12458 | } | 12466 | } |
| 12459 | if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { | 12467 | if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema.kit(block, src)))) { |
| 12460 | return sema.failWithDivideByZero(block, rhs_src); | 12468 | return sema.failWithDivideByZero(block, rhs_src); |
| 12461 | } | 12469 | } |
| 12462 | // TODO: if the RHS is one, return the LHS directly | 12470 | // TODO: if the RHS is one, return the LHS directly |
| ... | @@ -12470,7 +12478,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins | ... | @@ -12470,7 +12478,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins |
| 12470 | if (lhs_val.isUndef()) { | 12478 | if (lhs_val.isUndef()) { |
| 12471 | if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) { | 12479 | if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) { |
| 12472 | if (maybe_rhs_val) |rhs_val| { | 12480 | if (maybe_rhs_val) |rhs_val| { |
| 12473 | if (try sema.compare(block, src, rhs_val, .neq, Value.negative_one, resolved_type)) { | 12481 | if (try sema.compareAll(block, src, rhs_val, .neq, Value.negative_one, resolved_type)) { |
| 12474 | return sema.addConstUndef(resolved_type); | 12482 | return sema.addConstUndef(resolved_type); |
| 12475 | } | 12483 | } |
| 12476 | } | 12484 | } |
| ... | @@ -12541,6 +12549,8 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -12541,6 +12549,8 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 12541 | .override = &[_]LazySrcLoc{ lhs_src, rhs_src }, | 12549 | .override = &[_]LazySrcLoc{ lhs_src, rhs_src }, |
| 12542 | }); | 12550 | }); |
| 12543 | | 12551 | |
| | 12552 | const is_vector = resolved_type.zigTypeTag() == .Vector; |
| | 12553 | |
| 12544 | const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src); | 12554 | const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src); |
| 12545 | const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src); | 12555 | const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src); |
| 12546 | | 12556 | |
| ... | @@ -12577,8 +12587,11 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -12577,8 +12587,11 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 12577 | if (lhs_val.isUndef()) { | 12587 | if (lhs_val.isUndef()) { |
| 12578 | return sema.failWithUseOfUndef(block, rhs_src); | 12588 | return sema.failWithUseOfUndef(block, rhs_src); |
| 12579 | } else { | 12589 | } else { |
| 12580 | if (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { | 12590 | if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 12581 | return sema.addConstant(resolved_type, Value.zero); | 12591 | const zero_val = if (is_vector) b: { |
| | 12592 | break :b try Value.Tag.repeated.create(sema.arena, Value.zero); |
| | 12593 | } else Value.zero; |
| | 12594 | return sema.addConstant(resolved_type, zero_val); |
| 12582 | } | 12595 | } |
| 12583 | } | 12596 | } |
| 12584 | } | 12597 | } |
| ... | @@ -12586,7 +12599,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -12586,7 +12599,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 12586 | if (rhs_val.isUndef()) { | 12599 | if (rhs_val.isUndef()) { |
| 12587 | return sema.failWithUseOfUndef(block, rhs_src); | 12600 | return sema.failWithUseOfUndef(block, rhs_src); |
| 12588 | } | 12601 | } |
| 12589 | if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { | 12602 | if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema.kit(block, src)))) { |
| 12590 | return sema.failWithDivideByZero(block, rhs_src); | 12603 | return sema.failWithDivideByZero(block, rhs_src); |
| 12591 | } | 12604 | } |
| 12592 | // TODO: if the RHS is one, return the LHS directly | 12605 | // TODO: if the RHS is one, return the LHS directly |
| ... | @@ -12595,7 +12608,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -12595,7 +12608,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 12595 | if (maybe_rhs_val) |rhs_val| { | 12608 | if (maybe_rhs_val) |rhs_val| { |
| 12596 | if (is_int) { | 12609 | if (is_int) { |
| 12597 | const modulus_val = try lhs_val.intMod(rhs_val, resolved_type, sema.arena, target); | 12610 | const modulus_val = try lhs_val.intMod(rhs_val, resolved_type, sema.arena, target); |
| 12598 | if (modulus_val.compareWithZero(.neq)) { | 12611 | if (!(modulus_val.compareAllWithZero(.eq))) { |
| 12599 | return sema.fail(block, src, "exact division produced remainder", .{}); | 12612 | return sema.fail(block, src, "exact division produced remainder", .{}); |
| 12600 | } | 12613 | } |
| 12601 | const res = try lhs_val.intDiv(rhs_val, resolved_type, sema.arena, target); | 12614 | const res = try lhs_val.intDiv(rhs_val, resolved_type, sema.arena, target); |
| ... | @@ -12606,7 +12619,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -12606,7 +12619,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 12606 | return sema.addConstant(resolved_type, res); | 12619 | return sema.addConstant(resolved_type, res); |
| 12607 | } else { | 12620 | } else { |
| 12608 | const modulus_val = try lhs_val.floatMod(rhs_val, resolved_type, sema.arena, target); | 12621 | const modulus_val = try lhs_val.floatMod(rhs_val, resolved_type, sema.arena, target); |
| 12609 | if (modulus_val.compareWithZero(.neq)) { | 12622 | if (!(modulus_val.compareAllWithZero(.eq))) { |
| 12610 | return sema.fail(block, src, "exact division produced remainder", .{}); | 12623 | return sema.fail(block, src, "exact division produced remainder", .{}); |
| 12611 | } | 12624 | } |
| 12612 | return sema.addConstant( | 12625 | return sema.addConstant( |
| ... | @@ -12700,6 +12713,8 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -12700,6 +12713,8 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 12700 | .override = &[_]LazySrcLoc{ lhs_src, rhs_src }, | 12713 | .override = &[_]LazySrcLoc{ lhs_src, rhs_src }, |
| 12701 | }); | 12714 | }); |
| 12702 | | 12715 | |
| | 12716 | const is_vector = resolved_type.zigTypeTag() == .Vector; |
| | 12717 | |
| 12703 | const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src); | 12718 | const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src); |
| 12704 | const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src); | 12719 | const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src); |
| 12705 | | 12720 | |
| ... | @@ -12738,8 +12753,11 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -12738,8 +12753,11 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 12738 | // If the lhs is undefined, result is undefined. | 12753 | // If the lhs is undefined, result is undefined. |
| 12739 | if (maybe_lhs_val) |lhs_val| { | 12754 | if (maybe_lhs_val) |lhs_val| { |
| 12740 | if (!lhs_val.isUndef()) { | 12755 | if (!lhs_val.isUndef()) { |
| 12741 | if (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { | 12756 | if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 12742 | return sema.addConstant(resolved_type, Value.zero); | 12757 | const zero_val = if (is_vector) b: { |
| | 12758 | break :b try Value.Tag.repeated.create(sema.arena, Value.zero); |
| | 12759 | } else Value.zero; |
| | 12760 | return sema.addConstant(resolved_type, zero_val); |
| 12743 | } | 12761 | } |
| 12744 | } | 12762 | } |
| 12745 | } | 12763 | } |
| ... | @@ -12747,7 +12765,7 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -12747,7 +12765,7 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 12747 | if (rhs_val.isUndef()) { | 12765 | if (rhs_val.isUndef()) { |
| 12748 | return sema.failWithUseOfUndef(block, rhs_src); | 12766 | return sema.failWithUseOfUndef(block, rhs_src); |
| 12749 | } | 12767 | } |
| 12750 | if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { | 12768 | if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema.kit(block, src)))) { |
| 12751 | return sema.failWithDivideByZero(block, rhs_src); | 12769 | return sema.failWithDivideByZero(block, rhs_src); |
| 12752 | } | 12770 | } |
| 12753 | // TODO: if the RHS is one, return the LHS directly | 12771 | // TODO: if the RHS is one, return the LHS directly |
| ... | @@ -12756,7 +12774,7 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -12756,7 +12774,7 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 12756 | if (lhs_val.isUndef()) { | 12774 | if (lhs_val.isUndef()) { |
| 12757 | if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) { | 12775 | if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) { |
| 12758 | if (maybe_rhs_val) |rhs_val| { | 12776 | if (maybe_rhs_val) |rhs_val| { |
| 12759 | if (try sema.compare(block, src, rhs_val, .neq, Value.negative_one, resolved_type)) { | 12777 | if (try sema.compareAll(block, src, rhs_val, .neq, Value.negative_one, resolved_type)) { |
| 12760 | return sema.addConstUndef(resolved_type); | 12778 | return sema.addConstUndef(resolved_type); |
| 12761 | } | 12779 | } |
| 12762 | } | 12780 | } |
| ... | @@ -12812,6 +12830,8 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -12812,6 +12830,8 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 12812 | .override = &[_]LazySrcLoc{ lhs_src, rhs_src }, | 12830 | .override = &[_]LazySrcLoc{ lhs_src, rhs_src }, |
| 12813 | }); | 12831 | }); |
| 12814 | | 12832 | |
| | 12833 | const is_vector = resolved_type.zigTypeTag() == .Vector; |
| | 12834 | |
| 12815 | const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src); | 12835 | const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src); |
| 12816 | const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src); | 12836 | const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src); |
| 12817 | | 12837 | |
| ... | @@ -12850,8 +12870,11 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -12850,8 +12870,11 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 12850 | // If the lhs is undefined, result is undefined. | 12870 | // If the lhs is undefined, result is undefined. |
| 12851 | if (maybe_lhs_val) |lhs_val| { | 12871 | if (maybe_lhs_val) |lhs_val| { |
| 12852 | if (!lhs_val.isUndef()) { | 12872 | if (!lhs_val.isUndef()) { |
| 12853 | if (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { | 12873 | if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 12854 | return sema.addConstant(resolved_type, Value.zero); | 12874 | const zero_val = if (is_vector) b: { |
| | 12875 | break :b try Value.Tag.repeated.create(sema.arena, Value.zero); |
| | 12876 | } else Value.zero; |
| | 12877 | return sema.addConstant(resolved_type, zero_val); |
| 12855 | } | 12878 | } |
| 12856 | } | 12879 | } |
| 12857 | } | 12880 | } |
| ... | @@ -12859,7 +12882,7 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -12859,7 +12882,7 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 12859 | if (rhs_val.isUndef()) { | 12882 | if (rhs_val.isUndef()) { |
| 12860 | return sema.failWithUseOfUndef(block, rhs_src); | 12883 | return sema.failWithUseOfUndef(block, rhs_src); |
| 12861 | } | 12884 | } |
| 12862 | if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { | 12885 | if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema.kit(block, src)))) { |
| 12863 | return sema.failWithDivideByZero(block, rhs_src); | 12886 | return sema.failWithDivideByZero(block, rhs_src); |
| 12864 | } | 12887 | } |
| 12865 | } | 12888 | } |
| ... | @@ -12867,7 +12890,7 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -12867,7 +12890,7 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 12867 | if (lhs_val.isUndef()) { | 12890 | if (lhs_val.isUndef()) { |
| 12868 | if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) { | 12891 | if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) { |
| 12869 | if (maybe_rhs_val) |rhs_val| { | 12892 | if (maybe_rhs_val) |rhs_val| { |
| 12870 | if (try sema.compare(block, src, rhs_val, .neq, Value.negative_one, resolved_type)) { | 12893 | if (try sema.compareAll(block, src, rhs_val, .neq, Value.negative_one, resolved_type)) { |
| 12871 | return sema.addConstUndef(resolved_type); | 12894 | return sema.addConstUndef(resolved_type); |
| 12872 | } | 12895 | } |
| 12873 | } | 12896 | } |
| ... | @@ -12938,12 +12961,12 @@ fn addDivIntOverflowSafety( | ... | @@ -12938,12 +12961,12 @@ fn addDivIntOverflowSafety( |
| 12938 | // If the LHS is comptime-known to be not equal to the min int, | 12961 | // If the LHS is comptime-known to be not equal to the min int, |
| 12939 | // no overflow is possible. | 12962 | // no overflow is possible. |
| 12940 | if (maybe_lhs_val) |lhs_val| { | 12963 | if (maybe_lhs_val) |lhs_val| { |
| 12941 | if (!lhs_val.compare(.eq, min_int, resolved_type, mod)) return; | 12964 | if (lhs_val.compareAll(.neq, min_int, resolved_type, mod)) return; |
| 12942 | } | 12965 | } |
| 12943 | | 12966 | |
| 12944 | // If the RHS is comptime-known to not be equal to -1, no overflow is possible. | 12967 | // If the RHS is comptime-known to not be equal to -1, no overflow is possible. |
| 12945 | if (maybe_rhs_val) |rhs_val| { | 12968 | if (maybe_rhs_val) |rhs_val| { |
| 12946 | if (!rhs_val.compare(.eq, neg_one, resolved_type, mod)) return; | 12969 | if (rhs_val.compareAll(.neq, neg_one, resolved_type, mod)) return; |
| 12947 | } | 12970 | } |
| 12948 | | 12971 | |
| 12949 | var ok: Air.Inst.Ref = .none; | 12972 | var ok: Air.Inst.Ref = .none; |
| ... | @@ -13051,6 +13074,8 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. | ... | @@ -13051,6 +13074,8 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 13051 | .override = &[_]LazySrcLoc{ lhs_src, rhs_src }, | 13074 | .override = &[_]LazySrcLoc{ lhs_src, rhs_src }, |
| 13052 | }); | 13075 | }); |
| 13053 | | 13076 | |
| | 13077 | const is_vector = resolved_type.zigTypeTag() == .Vector; |
| | 13078 | |
| 13054 | const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src); | 13079 | const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src); |
| 13055 | const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src); | 13080 | const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src); |
| 13056 | | 13081 | |
| ... | @@ -13086,8 +13111,11 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. | ... | @@ -13086,8 +13111,11 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 13086 | if (lhs_val.isUndef()) { | 13111 | if (lhs_val.isUndef()) { |
| 13087 | return sema.failWithUseOfUndef(block, lhs_src); | 13112 | return sema.failWithUseOfUndef(block, lhs_src); |
| 13088 | } | 13113 | } |
| 13089 | if (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { | 13114 | if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 13090 | return sema.addConstant(resolved_type, Value.zero); | 13115 | const zero_val = if (is_vector) b: { |
| | 13116 | break :b try Value.Tag.repeated.create(sema.arena, Value.zero); |
| | 13117 | } else Value.zero; |
| | 13118 | return sema.addConstant(resolved_type, zero_val); |
| 13091 | } | 13119 | } |
| 13092 | } else if (lhs_scalar_ty.isSignedInt()) { | 13120 | } else if (lhs_scalar_ty.isSignedInt()) { |
| 13093 | return sema.failWithModRemNegative(block, lhs_src, lhs_ty, rhs_ty); | 13121 | return sema.failWithModRemNegative(block, lhs_src, lhs_ty, rhs_ty); |
| ... | @@ -13096,25 +13124,20 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. | ... | @@ -13096,25 +13124,20 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 13096 | if (rhs_val.isUndef()) { | 13124 | if (rhs_val.isUndef()) { |
| 13097 | return sema.failWithUseOfUndef(block, rhs_src); | 13125 | return sema.failWithUseOfUndef(block, rhs_src); |
| 13098 | } | 13126 | } |
| 13099 | if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { | 13127 | if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema.kit(block, src)))) { |
| 13100 | return sema.failWithDivideByZero(block, rhs_src); | 13128 | return sema.failWithDivideByZero(block, rhs_src); |
| 13101 | } | 13129 | } |
| | 13130 | if (!(try rhs_val.compareAllWithZeroAdvanced(.gte, sema.kit(block, src)))) { |
| | 13131 | return sema.failWithModRemNegative(block, rhs_src, lhs_ty, rhs_ty); |
| | 13132 | } |
| 13102 | if (maybe_lhs_val) |lhs_val| { | 13133 | if (maybe_lhs_val) |lhs_val| { |
| 13103 | const rem_result = try sema.intRem(block, resolved_type, lhs_val, lhs_src, rhs_val, rhs_src); | 13134 | const rem_result = try sema.intRem(block, resolved_type, lhs_val, lhs_src, rhs_val, rhs_src); |
| 13104 | // If this answer could possibly be different by doing `intMod`, | 13135 | // If this answer could possibly be different by doing `intMod`, |
| 13105 | // we must emit a compile error. Otherwise, it's OK. | 13136 | // we must emit a compile error. Otherwise, it's OK. |
| 13106 | if ((try rhs_val.compareWithZeroAdvanced(.lt, sema.kit(block, src))) != (try lhs_val.compareWithZeroAdvanced(.lt, sema.kit(block, src))) and | 13137 | if (!(try lhs_val.compareAllWithZeroAdvanced(.gte, sema.kit(block, src))) and |
| 13107 | !(try rem_result.compareWithZeroAdvanced(.eq, sema.kit(block, src)))) | 13138 | !(try rem_result.compareAllWithZeroAdvanced(.eq, sema.kit(block, src)))) |
| 13108 | { | 13139 | { |
| 13109 | const bad_src = if (try lhs_val.compareWithZeroAdvanced(.lt, sema.kit(block, src))) | 13140 | return sema.failWithModRemNegative(block, lhs_src, lhs_ty, rhs_ty); |
| 13110 | lhs_src | | |
| 13111 | else | | |
| 13112 | rhs_src; | | |
| 13113 | return sema.failWithModRemNegative(block, bad_src, lhs_ty, rhs_ty); | | |
| 13114 | } | | |
| 13115 | if (try lhs_val.compareWithZeroAdvanced(.lt, sema.kit(block, src))) { | | |
| 13116 | // Negative | | |
| 13117 | return sema.addConstant(resolved_type, Value.zero); | | |
| 13118 | } | 13141 | } |
| 13119 | return sema.addConstant(resolved_type, rem_result); | 13142 | return sema.addConstant(resolved_type, rem_result); |
| 13120 | } | 13143 | } |
| ... | @@ -13130,14 +13153,14 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. | ... | @@ -13130,14 +13153,14 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 13130 | if (rhs_val.isUndef()) { | 13153 | if (rhs_val.isUndef()) { |
| 13131 | return sema.failWithUseOfUndef(block, rhs_src); | 13154 | return sema.failWithUseOfUndef(block, rhs_src); |
| 13132 | } | 13155 | } |
| 13133 | if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { | 13156 | if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema.kit(block, src)))) { |
| 13134 | return sema.failWithDivideByZero(block, rhs_src); | 13157 | return sema.failWithDivideByZero(block, rhs_src); |
| 13135 | } | 13158 | } |
| 13136 | if (try rhs_val.compareWithZeroAdvanced(.lt, sema.kit(block, src))) { | 13159 | if (!(try rhs_val.compareAllWithZeroAdvanced(.gte, sema.kit(block, src)))) { |
| 13137 | return sema.failWithModRemNegative(block, rhs_src, lhs_ty, rhs_ty); | 13160 | return sema.failWithModRemNegative(block, rhs_src, lhs_ty, rhs_ty); |
| 13138 | } | 13161 | } |
| 13139 | if (maybe_lhs_val) |lhs_val| { | 13162 | if (maybe_lhs_val) |lhs_val| { |
| 13140 | if (lhs_val.isUndef() or (try lhs_val.compareWithZeroAdvanced(.lt, sema.kit(block, src)))) { | 13163 | if (lhs_val.isUndef() or !(try lhs_val.compareAllWithZeroAdvanced(.gte, sema.kit(block, src)))) { |
| 13141 | return sema.failWithModRemNegative(block, lhs_src, lhs_ty, rhs_ty); | 13164 | return sema.failWithModRemNegative(block, lhs_src, lhs_ty, rhs_ty); |
| 13142 | } | 13165 | } |
| 13143 | return sema.addConstant( | 13166 | return sema.addConstant( |
| ... | @@ -13273,7 +13296,7 @@ fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins | ... | @@ -13273,7 +13296,7 @@ fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins |
| 13273 | if (rhs_val.isUndef()) { | 13296 | if (rhs_val.isUndef()) { |
| 13274 | return sema.failWithUseOfUndef(block, rhs_src); | 13297 | return sema.failWithUseOfUndef(block, rhs_src); |
| 13275 | } | 13298 | } |
| 13276 | if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { | 13299 | if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema.kit(block, src)))) { |
| 13277 | return sema.failWithDivideByZero(block, rhs_src); | 13300 | return sema.failWithDivideByZero(block, rhs_src); |
| 13278 | } | 13301 | } |
| 13279 | if (maybe_lhs_val) |lhs_val| { | 13302 | if (maybe_lhs_val) |lhs_val| { |
| ... | @@ -13292,7 +13315,7 @@ fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins | ... | @@ -13292,7 +13315,7 @@ fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins |
| 13292 | if (rhs_val.isUndef()) { | 13315 | if (rhs_val.isUndef()) { |
| 13293 | return sema.failWithUseOfUndef(block, rhs_src); | 13316 | return sema.failWithUseOfUndef(block, rhs_src); |
| 13294 | } | 13317 | } |
| 13295 | if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { | 13318 | if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema.kit(block, src)))) { |
| 13296 | return sema.failWithDivideByZero(block, rhs_src); | 13319 | return sema.failWithDivideByZero(block, rhs_src); |
| 13297 | } | 13320 | } |
| 13298 | } | 13321 | } |
| ... | @@ -13376,7 +13399,7 @@ fn zirRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins | ... | @@ -13376,7 +13399,7 @@ fn zirRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins |
| 13376 | if (rhs_val.isUndef()) { | 13399 | if (rhs_val.isUndef()) { |
| 13377 | return sema.failWithUseOfUndef(block, rhs_src); | 13400 | return sema.failWithUseOfUndef(block, rhs_src); |
| 13378 | } | 13401 | } |
| 13379 | if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { | 13402 | if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema.kit(block, src)))) { |
| 13380 | return sema.failWithDivideByZero(block, rhs_src); | 13403 | return sema.failWithDivideByZero(block, rhs_src); |
| 13381 | } | 13404 | } |
| 13382 | if (maybe_lhs_val) |lhs_val| { | 13405 | if (maybe_lhs_val) |lhs_val| { |
| ... | @@ -13395,7 +13418,7 @@ fn zirRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins | ... | @@ -13395,7 +13418,7 @@ fn zirRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins |
| 13395 | if (rhs_val.isUndef()) { | 13418 | if (rhs_val.isUndef()) { |
| 13396 | return sema.failWithUseOfUndef(block, rhs_src); | 13419 | return sema.failWithUseOfUndef(block, rhs_src); |
| 13397 | } | 13420 | } |
| 13398 | if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { | 13421 | if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema.kit(block, src)))) { |
| 13399 | return sema.failWithDivideByZero(block, rhs_src); | 13422 | return sema.failWithDivideByZero(block, rhs_src); |
| 13400 | } | 13423 | } |
| 13401 | } | 13424 | } |
| ... | @@ -13474,12 +13497,12 @@ fn zirOverflowArithmetic( | ... | @@ -13474,12 +13497,12 @@ fn zirOverflowArithmetic( |
| 13474 | // to the result, even if it is undefined.. | 13497 | // to the result, even if it is undefined.. |
| 13475 | // Otherwise, if either of the argument is undefined, undefined is returned. | 13498 | // Otherwise, if either of the argument is undefined, undefined is returned. |
| 13476 | if (maybe_lhs_val) |lhs_val| { | 13499 | if (maybe_lhs_val) |lhs_val| { |
| 13477 | if (!lhs_val.isUndef() and (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src)))) { | 13500 | if (!lhs_val.isUndef() and (try lhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src)))) { |
| 13478 | break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = rhs }; | 13501 | break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = rhs }; |
| 13479 | } | 13502 | } |
| 13480 | } | 13503 | } |
| 13481 | if (maybe_rhs_val) |rhs_val| { | 13504 | if (maybe_rhs_val) |rhs_val| { |
| 13482 | if (!rhs_val.isUndef() and (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src)))) { | 13505 | if (!rhs_val.isUndef() and (try rhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src)))) { |
| 13483 | break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs }; | 13506 | break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs }; |
| 13484 | } | 13507 | } |
| 13485 | } | 13508 | } |
| ... | @@ -13502,7 +13525,7 @@ fn zirOverflowArithmetic( | ... | @@ -13502,7 +13525,7 @@ fn zirOverflowArithmetic( |
| 13502 | if (maybe_rhs_val) |rhs_val| { | 13525 | if (maybe_rhs_val) |rhs_val| { |
| 13503 | if (rhs_val.isUndef()) { | 13526 | if (rhs_val.isUndef()) { |
| 13504 | break :result .{ .overflowed = try sema.addConstUndef(overflowed_ty), .wrapped = try sema.addConstUndef(dest_ty) }; | 13527 | break :result .{ .overflowed = try sema.addConstUndef(overflowed_ty), .wrapped = try sema.addConstUndef(dest_ty) }; |
| 13505 | } else if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { | 13528 | } else if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 13506 | break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs }; | 13529 | break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs }; |
| 13507 | } else if (maybe_lhs_val) |lhs_val| { | 13530 | } else if (maybe_lhs_val) |lhs_val| { |
| 13508 | if (lhs_val.isUndef()) { | 13531 | if (lhs_val.isUndef()) { |
| ... | @@ -13522,9 +13545,9 @@ fn zirOverflowArithmetic( | ... | @@ -13522,9 +13545,9 @@ fn zirOverflowArithmetic( |
| 13522 | // Otherwise, if either of the arguments is undefined, both results are undefined. | 13545 | // Otherwise, if either of the arguments is undefined, both results are undefined. |
| 13523 | if (maybe_lhs_val) |lhs_val| { | 13546 | if (maybe_lhs_val) |lhs_val| { |
| 13524 | if (!lhs_val.isUndef()) { | 13547 | if (!lhs_val.isUndef()) { |
| 13525 | if (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { | 13548 | if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 13526 | break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs }; | 13549 | break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs }; |
| 13527 | } else if (try sema.compare(block, src, lhs_val, .eq, Value.one, dest_ty)) { | 13550 | } else if (try sema.compareAll(block, src, lhs_val, .eq, Value.one, dest_ty)) { |
| 13528 | break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = rhs }; | 13551 | break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = rhs }; |
| 13529 | } | 13552 | } |
| 13530 | } | 13553 | } |
| ... | @@ -13532,9 +13555,9 @@ fn zirOverflowArithmetic( | ... | @@ -13532,9 +13555,9 @@ fn zirOverflowArithmetic( |
| 13532 | | 13555 | |
| 13533 | if (maybe_rhs_val) |rhs_val| { | 13556 | if (maybe_rhs_val) |rhs_val| { |
| 13534 | if (!rhs_val.isUndef()) { | 13557 | if (!rhs_val.isUndef()) { |
| 13535 | if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { | 13558 | if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 13536 | break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = rhs }; | 13559 | break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = rhs }; |
| 13537 | } else if (try sema.compare(block, src, rhs_val, .eq, Value.one, dest_ty)) { | 13560 | } else if (try sema.compareAll(block, src, rhs_val, .eq, Value.one, dest_ty)) { |
| 13538 | break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs }; | 13561 | break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs }; |
| 13539 | } | 13562 | } |
| 13540 | } | 13563 | } |
| ... | @@ -13558,12 +13581,12 @@ fn zirOverflowArithmetic( | ... | @@ -13558,12 +13581,12 @@ fn zirOverflowArithmetic( |
| 13558 | // If rhs is zero, the result is lhs (even if undefined) and no overflow occurred. | 13581 | // If rhs is zero, the result is lhs (even if undefined) and no overflow occurred. |
| 13559 | // Oterhwise if either of the arguments is undefined, both results are undefined. | 13582 | // Oterhwise if either of the arguments is undefined, both results are undefined. |
| 13560 | if (maybe_lhs_val) |lhs_val| { | 13583 | if (maybe_lhs_val) |lhs_val| { |
| 13561 | if (!lhs_val.isUndef() and (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src)))) { | 13584 | if (!lhs_val.isUndef() and (try lhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src)))) { |
| 13562 | break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs }; | 13585 | break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs }; |
| 13563 | } | 13586 | } |
| 13564 | } | 13587 | } |
| 13565 | if (maybe_rhs_val) |rhs_val| { | 13588 | if (maybe_rhs_val) |rhs_val| { |
| 13566 | if (!rhs_val.isUndef() and (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src)))) { | 13589 | if (!rhs_val.isUndef() and (try rhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src)))) { |
| 13567 | break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs }; | 13590 | break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs }; |
| 13568 | } | 13591 | } |
| 13569 | } | 13592 | } |
| ... | @@ -13680,6 +13703,8 @@ fn analyzeArithmetic( | ... | @@ -13680,6 +13703,8 @@ fn analyzeArithmetic( |
| 13680 | .override = &[_]LazySrcLoc{ lhs_src, rhs_src }, | 13703 | .override = &[_]LazySrcLoc{ lhs_src, rhs_src }, |
| 13681 | }); | 13704 | }); |
| 13682 | | 13705 | |
| | 13706 | const is_vector = resolved_type.zigTypeTag() == .Vector; |
| | 13707 | |
| 13683 | const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src); | 13708 | const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src); |
| 13684 | const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src); | 13709 | const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src); |
| 13685 | | 13710 | |
| ... | @@ -13704,7 +13729,7 @@ fn analyzeArithmetic( | ... | @@ -13704,7 +13729,7 @@ fn analyzeArithmetic( |
| 13704 | // overflow (max_int), causing illegal behavior. | 13729 | // overflow (max_int), causing illegal behavior. |
| 13705 | // For floats: either operand being undef makes the result undef. | 13730 | // For floats: either operand being undef makes the result undef. |
| 13706 | if (maybe_lhs_val) |lhs_val| { | 13731 | if (maybe_lhs_val) |lhs_val| { |
| 13707 | if (!lhs_val.isUndef() and (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src)))) { | 13732 | if (!lhs_val.isUndef() and (try lhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src)))) { |
| 13708 | return casted_rhs; | 13733 | return casted_rhs; |
| 13709 | } | 13734 | } |
| 13710 | } | 13735 | } |
| ... | @@ -13716,7 +13741,7 @@ fn analyzeArithmetic( | ... | @@ -13716,7 +13741,7 @@ fn analyzeArithmetic( |
| 13716 | return sema.addConstUndef(resolved_type); | 13741 | return sema.addConstUndef(resolved_type); |
| 13717 | } | 13742 | } |
| 13718 | } | 13743 | } |
| 13719 | if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { | 13744 | if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 13720 | return casted_lhs; | 13745 | return casted_lhs; |
| 13721 | } | 13746 | } |
| 13722 | } | 13747 | } |
| ... | @@ -13751,7 +13776,7 @@ fn analyzeArithmetic( | ... | @@ -13751,7 +13776,7 @@ fn analyzeArithmetic( |
| 13751 | // If either of the operands are zero, the other operand is returned. | 13776 | // If either of the operands are zero, the other operand is returned. |
| 13752 | // If either of the operands are undefined, the result is undefined. | 13777 | // If either of the operands are undefined, the result is undefined. |
| 13753 | if (maybe_lhs_val) |lhs_val| { | 13778 | if (maybe_lhs_val) |lhs_val| { |
| 13754 | if (!lhs_val.isUndef() and (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src)))) { | 13779 | if (!lhs_val.isUndef() and (try lhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src)))) { |
| 13755 | return casted_rhs; | 13780 | return casted_rhs; |
| 13756 | } | 13781 | } |
| 13757 | } | 13782 | } |
| ... | @@ -13760,7 +13785,7 @@ fn analyzeArithmetic( | ... | @@ -13760,7 +13785,7 @@ fn analyzeArithmetic( |
| 13760 | if (rhs_val.isUndef()) { | 13785 | if (rhs_val.isUndef()) { |
| 13761 | return sema.addConstUndef(resolved_type); | 13786 | return sema.addConstUndef(resolved_type); |
| 13762 | } | 13787 | } |
| 13763 | if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { | 13788 | if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 13764 | return casted_lhs; | 13789 | return casted_lhs; |
| 13765 | } | 13790 | } |
| 13766 | if (maybe_lhs_val) |lhs_val| { | 13791 | if (maybe_lhs_val) |lhs_val| { |
| ... | @@ -13776,7 +13801,7 @@ fn analyzeArithmetic( | ... | @@ -13776,7 +13801,7 @@ fn analyzeArithmetic( |
| 13776 | // If either of the operands are zero, then the other operand is returned. | 13801 | // If either of the operands are zero, then the other operand is returned. |
| 13777 | // If either of the operands are undefined, the result is undefined. | 13802 | // If either of the operands are undefined, the result is undefined. |
| 13778 | if (maybe_lhs_val) |lhs_val| { | 13803 | if (maybe_lhs_val) |lhs_val| { |
| 13779 | if (!lhs_val.isUndef() and (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src)))) { | 13804 | if (!lhs_val.isUndef() and (try lhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src)))) { |
| 13780 | return casted_rhs; | 13805 | return casted_rhs; |
| 13781 | } | 13806 | } |
| 13782 | } | 13807 | } |
| ... | @@ -13784,7 +13809,7 @@ fn analyzeArithmetic( | ... | @@ -13784,7 +13809,7 @@ fn analyzeArithmetic( |
| 13784 | if (rhs_val.isUndef()) { | 13809 | if (rhs_val.isUndef()) { |
| 13785 | return sema.addConstUndef(resolved_type); | 13810 | return sema.addConstUndef(resolved_type); |
| 13786 | } | 13811 | } |
| 13787 | if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { | 13812 | if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 13788 | return casted_lhs; | 13813 | return casted_lhs; |
| 13789 | } | 13814 | } |
| 13790 | if (maybe_lhs_val) |lhs_val| { | 13815 | if (maybe_lhs_val) |lhs_val| { |
| ... | @@ -13813,7 +13838,7 @@ fn analyzeArithmetic( | ... | @@ -13813,7 +13838,7 @@ fn analyzeArithmetic( |
| 13813 | return sema.addConstUndef(resolved_type); | 13838 | return sema.addConstUndef(resolved_type); |
| 13814 | } | 13839 | } |
| 13815 | } | 13840 | } |
| 13816 | if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { | 13841 | if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 13817 | return casted_lhs; | 13842 | return casted_lhs; |
| 13818 | } | 13843 | } |
| 13819 | } | 13844 | } |
| ... | @@ -13851,7 +13876,7 @@ fn analyzeArithmetic( | ... | @@ -13851,7 +13876,7 @@ fn analyzeArithmetic( |
| 13851 | if (rhs_val.isUndef()) { | 13876 | if (rhs_val.isUndef()) { |
| 13852 | return sema.addConstUndef(resolved_type); | 13877 | return sema.addConstUndef(resolved_type); |
| 13853 | } | 13878 | } |
| 13854 | if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { | 13879 | if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 13855 | return casted_lhs; | 13880 | return casted_lhs; |
| 13856 | } | 13881 | } |
| 13857 | } | 13882 | } |
| ... | @@ -13876,7 +13901,7 @@ fn analyzeArithmetic( | ... | @@ -13876,7 +13901,7 @@ fn analyzeArithmetic( |
| 13876 | if (rhs_val.isUndef()) { | 13901 | if (rhs_val.isUndef()) { |
| 13877 | return sema.addConstUndef(resolved_type); | 13902 | return sema.addConstUndef(resolved_type); |
| 13878 | } | 13903 | } |
| 13879 | if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { | 13904 | if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 13880 | return casted_lhs; | 13905 | return casted_lhs; |
| 13881 | } | 13906 | } |
| 13882 | } | 13907 | } |
| ... | @@ -13905,10 +13930,13 @@ fn analyzeArithmetic( | ... | @@ -13905,10 +13930,13 @@ fn analyzeArithmetic( |
| 13905 | // For floats: either operand being undef makes the result undef. | 13930 | // For floats: either operand being undef makes the result undef. |
| 13906 | if (maybe_lhs_val) |lhs_val| { | 13931 | if (maybe_lhs_val) |lhs_val| { |
| 13907 | if (!lhs_val.isUndef()) { | 13932 | if (!lhs_val.isUndef()) { |
| 13908 | if (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { | 13933 | if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 13909 | return sema.addConstant(resolved_type, Value.zero); | 13934 | const zero_val = if (is_vector) b: { |
| | 13935 | break :b try Value.Tag.repeated.create(sema.arena, Value.zero); |
| | 13936 | } else Value.zero; |
| | 13937 | return sema.addConstant(resolved_type, zero_val); |
| 13910 | } | 13938 | } |
| 13911 | if (try sema.compare(block, src, lhs_val, .eq, Value.one, resolved_type)) { | 13939 | if (try sema.compareAll(block, src, lhs_val, .eq, Value.one, resolved_type)) { |
| 13912 | return casted_rhs; | 13940 | return casted_rhs; |
| 13913 | } | 13941 | } |
| 13914 | } | 13942 | } |
| ... | @@ -13922,10 +13950,13 @@ fn analyzeArithmetic( | ... | @@ -13922,10 +13950,13 @@ fn analyzeArithmetic( |
| 13922 | return sema.addConstUndef(resolved_type); | 13950 | return sema.addConstUndef(resolved_type); |
| 13923 | } | 13951 | } |
| 13924 | } | 13952 | } |
| 13925 | if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { | 13953 | if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 13926 | return sema.addConstant(resolved_type, Value.zero); | 13954 | const zero_val = if (is_vector) b: { |
| | 13955 | break :b try Value.Tag.repeated.create(sema.arena, Value.zero); |
| | 13956 | } else Value.zero; |
| | 13957 | return sema.addConstant(resolved_type, zero_val); |
| 13927 | } | 13958 | } |
| 13928 | if (try sema.compare(block, src, rhs_val, .eq, Value.one, resolved_type)) { | 13959 | if (try sema.compareAll(block, src, rhs_val, .eq, Value.one, resolved_type)) { |
| 13929 | return casted_lhs; | 13960 | return casted_lhs; |
| 13930 | } | 13961 | } |
| 13931 | if (maybe_lhs_val) |lhs_val| { | 13962 | if (maybe_lhs_val) |lhs_val| { |
| ... | @@ -13959,10 +13990,13 @@ fn analyzeArithmetic( | ... | @@ -13959,10 +13990,13 @@ fn analyzeArithmetic( |
| 13959 | // If either of the operands are undefined, result is undefined. | 13990 | // If either of the operands are undefined, result is undefined. |
| 13960 | if (maybe_lhs_val) |lhs_val| { | 13991 | if (maybe_lhs_val) |lhs_val| { |
| 13961 | if (!lhs_val.isUndef()) { | 13992 | if (!lhs_val.isUndef()) { |
| 13962 | if (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { | 13993 | if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 13963 | return sema.addConstant(resolved_type, Value.zero); | 13994 | const zero_val = if (is_vector) b: { |
| | 13995 | break :b try Value.Tag.repeated.create(sema.arena, Value.zero); |
| | 13996 | } else Value.zero; |
| | 13997 | return sema.addConstant(resolved_type, zero_val); |
| 13964 | } | 13998 | } |
| 13965 | if (try sema.compare(block, src, lhs_val, .eq, Value.one, resolved_type)) { | 13999 | if (try sema.compareAll(block, src, lhs_val, .eq, Value.one, resolved_type)) { |
| 13966 | return casted_rhs; | 14000 | return casted_rhs; |
| 13967 | } | 14001 | } |
| 13968 | } | 14002 | } |
| ... | @@ -13972,10 +14006,13 @@ fn analyzeArithmetic( | ... | @@ -13972,10 +14006,13 @@ fn analyzeArithmetic( |
| 13972 | if (rhs_val.isUndef()) { | 14006 | if (rhs_val.isUndef()) { |
| 13973 | return sema.addConstUndef(resolved_type); | 14007 | return sema.addConstUndef(resolved_type); |
| 13974 | } | 14008 | } |
| 13975 | if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { | 14009 | if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 13976 | return sema.addConstant(resolved_type, Value.zero); | 14010 | const zero_val = if (is_vector) b: { |
| | 14011 | break :b try Value.Tag.repeated.create(sema.arena, Value.zero); |
| | 14012 | } else Value.zero; |
| | 14013 | return sema.addConstant(resolved_type, zero_val); |
| 13977 | } | 14014 | } |
| 13978 | if (try sema.compare(block, src, rhs_val, .eq, Value.one, resolved_type)) { | 14015 | if (try sema.compareAll(block, src, rhs_val, .eq, Value.one, resolved_type)) { |
| 13979 | return casted_lhs; | 14016 | return casted_lhs; |
| 13980 | } | 14017 | } |
| 13981 | if (maybe_lhs_val) |lhs_val| { | 14018 | if (maybe_lhs_val) |lhs_val| { |
| ... | @@ -13996,10 +14033,13 @@ fn analyzeArithmetic( | ... | @@ -13996,10 +14033,13 @@ fn analyzeArithmetic( |
| 13996 | // If either of the operands are undefined, result is undefined. | 14033 | // If either of the operands are undefined, result is undefined. |
| 13997 | if (maybe_lhs_val) |lhs_val| { | 14034 | if (maybe_lhs_val) |lhs_val| { |
| 13998 | if (!lhs_val.isUndef()) { | 14035 | if (!lhs_val.isUndef()) { |
| 13999 | if (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { | 14036 | if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 14000 | return sema.addConstant(resolved_type, Value.zero); | 14037 | const zero_val = if (is_vector) b: { |
| | 14038 | break :b try Value.Tag.repeated.create(sema.arena, Value.zero); |
| | 14039 | } else Value.zero; |
| | 14040 | return sema.addConstant(resolved_type, zero_val); |
| 14001 | } | 14041 | } |
| 14002 | if (try sema.compare(block, src, lhs_val, .eq, Value.one, resolved_type)) { | 14042 | if (try sema.compareAll(block, src, lhs_val, .eq, Value.one, resolved_type)) { |
| 14003 | return casted_rhs; | 14043 | return casted_rhs; |
| 14004 | } | 14044 | } |
| 14005 | } | 14045 | } |
| ... | @@ -14008,10 +14048,13 @@ fn analyzeArithmetic( | ... | @@ -14008,10 +14048,13 @@ fn analyzeArithmetic( |
| 14008 | if (rhs_val.isUndef()) { | 14048 | if (rhs_val.isUndef()) { |
| 14009 | return sema.addConstUndef(resolved_type); | 14049 | return sema.addConstUndef(resolved_type); |
| 14010 | } | 14050 | } |
| 14011 | if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { | 14051 | if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 14012 | return sema.addConstant(resolved_type, Value.zero); | 14052 | const zero_val = if (is_vector) b: { |
| | 14053 | break :b try Value.Tag.repeated.create(sema.arena, Value.zero); |
| | 14054 | } else Value.zero; |
| | 14055 | return sema.addConstant(resolved_type, zero_val); |
| 14013 | } | 14056 | } |
| 14014 | if (try sema.compare(block, src, rhs_val, .eq, Value.one, resolved_type)) { | 14057 | if (try sema.compareAll(block, src, rhs_val, .eq, Value.one, resolved_type)) { |
| 14015 | return casted_lhs; | 14058 | return casted_lhs; |
| 14016 | } | 14059 | } |
| 14017 | if (maybe_lhs_val) |lhs_val| { | 14060 | if (maybe_lhs_val) |lhs_val| { |
| ... | @@ -14563,7 +14606,7 @@ fn cmpSelf( | ... | @@ -14563,7 +14606,7 @@ fn cmpSelf( |
| 14563 | return sema.addConstant(result_ty, cmp_val); | 14606 | return sema.addConstant(result_ty, cmp_val); |
| 14564 | } | 14607 | } |
| 14565 | | 14608 | |
| 14566 | if (try sema.compare(block, lhs_src, lhs_val, op, rhs_val, resolved_type)) { | 14609 | if (try sema.compareAll(block, lhs_src, lhs_val, op, rhs_val, resolved_type)) { |
| 14567 | return Air.Inst.Ref.bool_true; | 14610 | return Air.Inst.Ref.bool_true; |
| 14568 | } else { | 14611 | } else { |
| 14569 | return Air.Inst.Ref.bool_false; | 14612 | return Air.Inst.Ref.bool_false; |
| ... | @@ -27769,7 +27812,7 @@ fn analyzeSlice( | ... | @@ -27769,7 +27812,7 @@ fn analyzeSlice( |
| 27769 | sema.arena, | 27812 | sema.arena, |
| 27770 | array_ty.arrayLenIncludingSentinel(), | 27813 | array_ty.arrayLenIncludingSentinel(), |
| 27771 | ); | 27814 | ); |
| 27772 | if (try sema.compare(block, src, end_val, .gt, len_s_val, Type.usize)) { | 27815 | if (!(try sema.compareAll(block, src, end_val, .lte, len_s_val, Type.usize))) { |
| 27773 | const sentinel_label: []const u8 = if (array_ty.sentinel() != null) | 27816 | const sentinel_label: []const u8 = if (array_ty.sentinel() != null) |
| 27774 | " +1 (sentinel)" | 27817 | " +1 (sentinel)" |
| 27775 | else | 27818 | else |
| ... | @@ -27812,7 +27855,7 @@ fn analyzeSlice( | ... | @@ -27812,7 +27855,7 @@ fn analyzeSlice( |
| 27812 | .data = slice_val.sliceLen(mod) + @boolToInt(has_sentinel), | 27855 | .data = slice_val.sliceLen(mod) + @boolToInt(has_sentinel), |
| 27813 | }; | 27856 | }; |
| 27814 | const slice_len_val = Value.initPayload(&int_payload.base); | 27857 | const slice_len_val = Value.initPayload(&int_payload.base); |
| 27815 | if (try sema.compare(block, src, end_val, .gt, slice_len_val, Type.usize)) { | 27858 | if (!(try sema.compareAll(block, src, end_val, .lte, slice_len_val, Type.usize))) { |
| 27816 | const sentinel_label: []const u8 = if (has_sentinel) | 27859 | const sentinel_label: []const u8 = if (has_sentinel) |
| 27817 | " +1 (sentinel)" | 27860 | " +1 (sentinel)" |
| 27818 | else | 27861 | else |
| ... | @@ -27871,7 +27914,7 @@ fn analyzeSlice( | ... | @@ -27871,7 +27914,7 @@ fn analyzeSlice( |
| 27871 | // requirement: start <= end | 27914 | // requirement: start <= end |
| 27872 | if (try sema.resolveDefinedValue(block, end_src, end)) |end_val| { | 27915 | if (try sema.resolveDefinedValue(block, end_src, end)) |end_val| { |
| 27873 | if (try sema.resolveDefinedValue(block, start_src, start)) |start_val| { | 27916 | if (try sema.resolveDefinedValue(block, start_src, start)) |start_val| { |
| 27874 | if (try sema.compare(block, src, start_val, .gt, end_val, Type.usize)) { | 27917 | if (!(try sema.compareAll(block, src, start_val, .lte, end_val, Type.usize))) { |
| 27875 | return sema.fail( | 27918 | return sema.fail( |
| 27876 | block, | 27919 | block, |
| 27877 | start_src, | 27920 | start_src, |
| ... | @@ -28160,11 +28203,11 @@ fn cmpNumeric( | ... | @@ -28160,11 +28203,11 @@ fn cmpNumeric( |
| 28160 | // a signed integer with mantissa bits + 1, and if there was any non-integral part of the float, | 28203 | // a signed integer with mantissa bits + 1, and if there was any non-integral part of the float, |
| 28161 | // add/subtract 1. | 28204 | // add/subtract 1. |
| 28162 | const lhs_is_signed = if (try sema.resolveDefinedValue(block, lhs_src, lhs)) |lhs_val| | 28205 | const lhs_is_signed = if (try sema.resolveDefinedValue(block, lhs_src, lhs)) |lhs_val| |
| 28163 | (try lhs_val.compareWithZeroAdvanced(.lt, sema.kit(block, src))) | 28206 | !(try lhs_val.compareAllWithZeroAdvanced(.gte, sema.kit(block, src))) |
| 28164 | else | 28207 | else |
| 28165 | (lhs_ty.isRuntimeFloat() or lhs_ty.isSignedInt()); | 28208 | (lhs_ty.isRuntimeFloat() or lhs_ty.isSignedInt()); |
| 28166 | const rhs_is_signed = if (try sema.resolveDefinedValue(block, rhs_src, rhs)) |rhs_val| | 28209 | const rhs_is_signed = if (try sema.resolveDefinedValue(block, rhs_src, rhs)) |rhs_val| |
| 28167 | (try rhs_val.compareWithZeroAdvanced(.lt, sema.kit(block, src))) | 28210 | !(try rhs_val.compareAllWithZeroAdvanced(.gte, sema.kit(block, src))) |
| 28168 | else | 28211 | else |
| 28169 | (rhs_ty.isRuntimeFloat() or rhs_ty.isSignedInt()); | 28212 | (rhs_ty.isRuntimeFloat() or rhs_ty.isSignedInt()); |
| 28170 | const dest_int_is_signed = lhs_is_signed or rhs_is_signed; | 28213 | const dest_int_is_signed = lhs_is_signed or rhs_is_signed; |
| ... | @@ -31744,6 +31787,8 @@ fn floatToIntScalar( | ... | @@ -31744,6 +31787,8 @@ fn floatToIntScalar( |
| 31744 | | 31787 | |
| 31745 | /// Asserts the value is an integer, and the destination type is ComptimeInt or Int. | 31788 | /// Asserts the value is an integer, and the destination type is ComptimeInt or Int. |
| 31746 | /// Vectors are also accepted. Vector results are reduced with AND. | 31789 | /// Vectors are also accepted. Vector results are reduced with AND. |
| | 31790 | /// |
| | 31791 | /// If provided, `vector_index` reports the first element that failed the range check. |
| 31747 | fn intFitsInType( | 31792 | fn intFitsInType( |
| 31748 | sema: *Sema, | 31793 | sema: *Sema, |
| 31749 | block: *Block, | 31794 | block: *Block, |
| ... | @@ -31889,13 +31934,13 @@ fn intInRange( | ... | @@ -31889,13 +31934,13 @@ fn intInRange( |
| 31889 | int_val: Value, | 31934 | int_val: Value, |
| 31890 | end: usize, | 31935 | end: usize, |
| 31891 | ) !bool { | 31936 | ) !bool { |
| 31892 | if (try int_val.compareWithZeroAdvanced(.lt, sema.kit(block, src))) return false; | 31937 | if (!(try int_val.compareAllWithZeroAdvanced(.gte, sema.kit(block, src)))) return false; |
| 31893 | var end_payload: Value.Payload.U64 = .{ | 31938 | var end_payload: Value.Payload.U64 = .{ |
| 31894 | .base = .{ .tag = .int_u64 }, | 31939 | .base = .{ .tag = .int_u64 }, |
| 31895 | .data = end, | 31940 | .data = end, |
| 31896 | }; | 31941 | }; |
| 31897 | const end_val = Value.initPayload(&end_payload.base); | 31942 | const end_val = Value.initPayload(&end_payload.base); |
| 31898 | if (try sema.compare(block, src, int_val, .gte, end_val, tag_ty)) return false; | 31943 | if (!(try sema.compareAll(block, src, int_val, .lt, end_val, tag_ty))) return false; |
| 31899 | return true; | 31944 | return true; |
| 31900 | } | 31945 | } |
| 31901 | | 31946 | |
| ... | @@ -32013,8 +32058,10 @@ fn intAddWithOverflowScalar( | ... | @@ -32013,8 +32058,10 @@ fn intAddWithOverflowScalar( |
| 32013 | } | 32058 | } |
| 32014 | | 32059 | |
| 32015 | /// Asserts the values are comparable. Both operands have type `ty`. | 32060 | /// Asserts the values are comparable. Both operands have type `ty`. |
| 32016 | /// Vector results will be reduced with AND. | 32061 | /// For vectors, returns true if the comparison is true for ALL elements. |
| 32017 | fn compare( | 32062 | /// |
| | 32063 | /// Note that `!compareAll(.eq, ...) != compareAll(.neq, ...)` |
| | 32064 | fn compareAll( |
| 32018 | sema: *Sema, | 32065 | sema: *Sema, |
| 32019 | block: *Block, | 32066 | block: *Block, |
| 32020 | src: LazySrcLoc, | 32067 | src: LazySrcLoc, |