| ... | ... | @@ -4164,6 +4164,7 @@ fn validateStructInit( |
| 4164 | 4164 | // We expect to see something like this in the current block AIR: |
| 4165 | 4165 | // %a = field_ptr(...) |
| 4166 | 4166 | // store(%a, %b) |
| 4167 | // With an optional bitcast between the store and the field_ptr. |
| 4167 | 4168 | // If %b is a comptime operand, this field is comptime. |
| 4168 | 4169 | // |
| 4169 | 4170 | // However, in the case of a comptime-known pointer to a struct, the |
| ... | ... | @@ -4374,75 +4375,65 @@ fn zirValidateArrayInit( |
| 4374 | 4375 | |
| 4375 | 4376 | const elem_ptr_air_ref = sema.inst_map.get(elem_ptr).?; |
| 4376 | 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 | | // instruction after it within the same block. |
| 4378 | |
| 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 | 4397 | // Possible performance enhancement: save the `block_index` between iterations |
| 4380 | 4398 | // of the for loop. |
| 4381 | 4399 | var block_index = block.instructions.items.len - 1; |
| 4382 | | while (block.instructions.items[block_index] != elem_ptr_air_inst) { |
| 4383 | | if (block_index == 0) { |
| 4400 | while (block_index > 0) : (block_index -= 1) { |
| 4401 | const store_inst = block.instructions.items[block_index]; |
| 4402 | if (store_inst == elem_ptr_air_inst) { |
| 4384 | 4403 | array_is_comptime = false; |
| 4385 | 4404 | continue :outer; |
| 4386 | 4405 | } |
| 4387 | | block_index -= 1; |
| 4388 | | } |
| 4389 | | first_block_index = @min(first_block_index, block_index); |
| 4390 | | |
| 4391 | | // If the next instructon is a store with a comptime operand, this element |
| 4392 | | // is comptime. |
| 4393 | | const next_air_inst = block.instructions.items[block_index + 1]; |
| 4394 | | switch (air_tags[next_air_inst]) { |
| 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; |
| 4406 | if (air_tags[store_inst] != .store) continue; |
| 4407 | const bin_op = air_datas[store_inst].bin_op; |
| 4408 | var lhs = bin_op.lhs; |
| 4409 | { |
| 4410 | const lhs_index = Air.refToIndex(lhs) orelse continue; |
| 4411 | if (air_tags[lhs_index] == .bitcast) { |
| 4412 | lhs = air_datas[lhs_index].ty_op.operand; |
| 4413 | block_index -= 1; |
| 4438 | 4414 | } |
| 4439 | | continue; |
| 4440 | | }, |
| 4441 | | else => { |
| 4415 | } |
| 4416 | if (lhs != elem_ptr_air_ref) continue; |
| 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 | 4431 | array_is_comptime = false; |
| 4443 | | continue; |
| 4444 | | }, |
| 4432 | } |
| 4433 | continue :outer; |
| 4445 | 4434 | } |
| 4435 | array_is_comptime = false; |
| 4436 | continue :outer; |
| 4446 | 4437 | } |
| 4447 | 4438 | |
| 4448 | 4439 | if (array_is_comptime) { |
| ... | ... | @@ -8966,9 +8957,21 @@ fn intCast( |
| 8966 | 8957 | const wanted_bits = wanted_info.bits; |
| 8967 | 8958 | |
| 8968 | 8959 | if (wanted_bits == 0) { |
| 8969 | | const zero_inst = try sema.addConstant(sema.typeOf(operand), Value.zero); |
| 8970 | | const is_in_range = try block.addBinOp(.cmp_eq, operand, zero_inst); |
| 8971 | | try sema.addSafetyCheck(block, is_in_range, .cast_truncated_data); |
| 8960 | const ok = if (is_vector) ok: { |
| 8961 | const zeros = try Value.Tag.repeated.create(sema.arena, Value.zero); |
| 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 | 10333 | // Validation above ensured these will succeed. |
| 10331 | 10334 | const first_tv = sema.resolveInstConst(&child_block, .unneeded, item_first, "") catch unreachable; |
| 10332 | 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 |
| 10334 | | (try sema.compare(block, src, operand_val, .lte, last_tv.val, operand_ty))) |
| 10336 | if ((try sema.compareAll(block, src, operand_val, .gte, first_tv.val, operand_ty)) and |
| 10337 | (try sema.compareAll(block, src, operand_val, .lte, last_tv.val, operand_ty))) |
| 10335 | 10338 | { |
| 10336 | 10339 | if (is_inline) child_block.inline_case_capture = operand; |
| 10337 | 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 | 10482 | const item_last_ref = try sema.resolveInst(last_ref); |
| 10480 | 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 | 10486 | // Previous validation has resolved any possible lazy values. |
| 10484 | 10487 | item = try sema.intAddScalar(block, .unneeded, item, Value.one); |
| 10485 | 10488 | }) { |
| ... | ... | @@ -10934,7 +10937,7 @@ const RangeSetUnhandledIterator = struct { |
| 10934 | 10937 | it.cur = try it.sema.intAdd(it.block, it.src, it.cur, Value.one, it.ty); |
| 10935 | 10938 | } |
| 10936 | 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 | 10941 | return it.cur; |
| 10939 | 10942 | } |
| 10940 | 10943 | it.cur = it.ranges[it.range_i].last; |
| ... | ... | @@ -10943,7 +10946,7 @@ const RangeSetUnhandledIterator = struct { |
| 10943 | 10946 | it.cur = try it.sema.intAdd(it.block, it.src, it.cur, Value.one, it.ty); |
| 10944 | 10947 | } |
| 10945 | 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 | 10950 | return it.cur; |
| 10948 | 10951 | } |
| 10949 | 10952 | return null; |
| ... | ... | @@ -10989,7 +10992,7 @@ fn validateSwitchRange( |
| 10989 | 10992 | ) CompileError!void { |
| 10990 | 10993 | const first_val = (try sema.resolveSwitchItemVal(block, first_ref, src_node_offset, switch_prong_src, .first)).val; |
| 10991 | 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 | 10996 | const src = switch_prong_src.resolve(sema.gpa, sema.mod.declPtr(block.src_decl), src_node_offset, .first); |
| 10994 | 10997 | return sema.fail(block, src, "range start value is greater than the end value", .{}); |
| 10995 | 10998 | } |
| ... | ... | @@ -11453,7 +11456,7 @@ fn zirShl( |
| 11453 | 11456 | return sema.addConstUndef(sema.typeOf(lhs)); |
| 11454 | 11457 | } |
| 11455 | 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 | 11460 | return lhs; |
| 11458 | 11461 | } |
| 11459 | 11462 | if (scalar_ty.zigTypeTag() != .ComptimeInt and air_tag != .shl_sat) { |
| ... | ... | @@ -11497,7 +11500,7 @@ fn zirShl( |
| 11497 | 11500 | if (scalar_ty.zigTypeTag() == .ComptimeInt) { |
| 11498 | 11501 | break :val shifted.wrapped_result; |
| 11499 | 11502 | } |
| 11500 | | if (shifted.overflowed.compareWithZero(.eq)) { |
| 11503 | if (shifted.overflowed.compareAllWithZero(.eq)) { |
| 11501 | 11504 | break :val shifted.wrapped_result; |
| 11502 | 11505 | } |
| 11503 | 11506 | return sema.fail(block, src, "operation caused overflow", .{}); |
| ... | ... | @@ -11622,7 +11625,7 @@ fn zirShr( |
| 11622 | 11625 | return sema.addConstUndef(lhs_ty); |
| 11623 | 11626 | } |
| 11624 | 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 | 11629 | return lhs; |
| 11627 | 11630 | } |
| 11628 | 11631 | if (scalar_ty.zigTypeTag() != .ComptimeInt) { |
| ... | ... | @@ -11656,7 +11659,7 @@ fn zirShr( |
| 11656 | 11659 | if (air_tag == .shr_exact) { |
| 11657 | 11660 | // Detect if any ones would be shifted out. |
| 11658 | 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 | 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 | 12388 | .override = &[_]LazySrcLoc{ lhs_src, rhs_src }, |
| 12386 | 12389 | }); |
| 12387 | 12390 | |
| 12391 | const is_vector = resolved_type.zigTypeTag() == .Vector; |
| 12392 | |
| 12388 | 12393 | const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src); |
| 12389 | 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 | 12414 | const lhs_val = maybe_lhs_val orelse unreachable; |
| 12410 | 12415 | const rhs_val = maybe_rhs_val orelse unreachable; |
| 12411 | 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 | 12418 | return sema.fail(block, src, "ambiguous coercion of division operands '{s}' and '{s}'; non-zero remainder '{}'", .{ |
| 12414 | 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 | 12452 | .Int, .ComptimeInt, .ComptimeFloat => { |
| 12448 | 12453 | if (maybe_lhs_val) |lhs_val| { |
| 12449 | 12454 | if (!lhs_val.isUndef()) { |
| 12450 | | if (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 12451 | | return sema.addConstant(resolved_type, Value.zero); |
| 12455 | if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 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 | 12464 | if (rhs_val.isUndef()) { |
| 12457 | 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 | 12468 | return sema.failWithDivideByZero(block, rhs_src); |
| 12461 | 12469 | } |
| 12462 | 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 | 12478 | if (lhs_val.isUndef()) { |
| 12471 | 12479 | if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) { |
| 12472 | 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 | 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 | 12549 | .override = &[_]LazySrcLoc{ lhs_src, rhs_src }, |
| 12542 | 12550 | }); |
| 12543 | 12551 | |
| 12552 | const is_vector = resolved_type.zigTypeTag() == .Vector; |
| 12553 | |
| 12544 | 12554 | const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src); |
| 12545 | 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 | 12587 | if (lhs_val.isUndef()) { |
| 12578 | 12588 | return sema.failWithUseOfUndef(block, rhs_src); |
| 12579 | 12589 | } else { |
| 12580 | | if (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 12581 | | return sema.addConstant(resolved_type, Value.zero); |
| 12590 | if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 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 | 12599 | if (rhs_val.isUndef()) { |
| 12587 | 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 | 12603 | return sema.failWithDivideByZero(block, rhs_src); |
| 12591 | 12604 | } |
| 12592 | 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 | 12608 | if (maybe_rhs_val) |rhs_val| { |
| 12596 | 12609 | if (is_int) { |
| 12597 | 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 | 12612 | return sema.fail(block, src, "exact division produced remainder", .{}); |
| 12600 | 12613 | } |
| 12601 | 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 | 12619 | return sema.addConstant(resolved_type, res); |
| 12607 | 12620 | } else { |
| 12608 | 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 | 12623 | return sema.fail(block, src, "exact division produced remainder", .{}); |
| 12611 | 12624 | } |
| 12612 | 12625 | return sema.addConstant( |
| ... | ... | @@ -12700,6 +12713,8 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 12700 | 12713 | .override = &[_]LazySrcLoc{ lhs_src, rhs_src }, |
| 12701 | 12714 | }); |
| 12702 | 12715 | |
| 12716 | const is_vector = resolved_type.zigTypeTag() == .Vector; |
| 12717 | |
| 12703 | 12718 | const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src); |
| 12704 | 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 | 12753 | // If the lhs is undefined, result is undefined. |
| 12739 | 12754 | if (maybe_lhs_val) |lhs_val| { |
| 12740 | 12755 | if (!lhs_val.isUndef()) { |
| 12741 | | if (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 12742 | | return sema.addConstant(resolved_type, Value.zero); |
| 12756 | if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 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 | 12765 | if (rhs_val.isUndef()) { |
| 12748 | 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 | 12769 | return sema.failWithDivideByZero(block, rhs_src); |
| 12752 | 12770 | } |
| 12753 | 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 | 12774 | if (lhs_val.isUndef()) { |
| 12757 | 12775 | if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) { |
| 12758 | 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 | 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 | 12830 | .override = &[_]LazySrcLoc{ lhs_src, rhs_src }, |
| 12813 | 12831 | }); |
| 12814 | 12832 | |
| 12833 | const is_vector = resolved_type.zigTypeTag() == .Vector; |
| 12834 | |
| 12815 | 12835 | const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src); |
| 12816 | 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 | 12870 | // If the lhs is undefined, result is undefined. |
| 12851 | 12871 | if (maybe_lhs_val) |lhs_val| { |
| 12852 | 12872 | if (!lhs_val.isUndef()) { |
| 12853 | | if (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 12854 | | return sema.addConstant(resolved_type, Value.zero); |
| 12873 | if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 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 | 12882 | if (rhs_val.isUndef()) { |
| 12860 | 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 | 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 | 12890 | if (lhs_val.isUndef()) { |
| 12868 | 12891 | if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) { |
| 12869 | 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 | 12894 | return sema.addConstUndef(resolved_type); |
| 12872 | 12895 | } |
| 12873 | 12896 | } |
| ... | ... | @@ -12938,12 +12961,12 @@ fn addDivIntOverflowSafety( |
| 12938 | 12961 | // If the LHS is comptime-known to be not equal to the min int, |
| 12939 | 12962 | // no overflow is possible. |
| 12940 | 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 | 12967 | // If the RHS is comptime-known to not be equal to -1, no overflow is possible. |
| 12945 | 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 | 12972 | var ok: Air.Inst.Ref = .none; |
| ... | ... | @@ -13051,6 +13074,8 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 13051 | 13074 | .override = &[_]LazySrcLoc{ lhs_src, rhs_src }, |
| 13052 | 13075 | }); |
| 13053 | 13076 | |
| 13077 | const is_vector = resolved_type.zigTypeTag() == .Vector; |
| 13078 | |
| 13054 | 13079 | const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src); |
| 13055 | 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 | 13111 | if (lhs_val.isUndef()) { |
| 13087 | 13112 | return sema.failWithUseOfUndef(block, lhs_src); |
| 13088 | 13113 | } |
| 13089 | | if (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 13090 | | return sema.addConstant(resolved_type, Value.zero); |
| 13114 | if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 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 | 13120 | } else if (lhs_scalar_ty.isSignedInt()) { |
| 13093 | 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 | 13124 | if (rhs_val.isUndef()) { |
| 13097 | 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 | 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 | 13133 | if (maybe_lhs_val) |lhs_val| { |
| 13103 | 13134 | const rem_result = try sema.intRem(block, resolved_type, lhs_val, lhs_src, rhs_val, rhs_src); |
| 13104 | 13135 | // If this answer could possibly be different by doing `intMod`, |
| 13105 | 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 |
| 13107 | | !(try rem_result.compareWithZeroAdvanced(.eq, sema.kit(block, src)))) |
| 13137 | if (!(try lhs_val.compareAllWithZeroAdvanced(.gte, sema.kit(block, src))) and |
| 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))) |
| 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); |
| 13140 | return sema.failWithModRemNegative(block, lhs_src, lhs_ty, rhs_ty); |
| 13118 | 13141 | } |
| 13119 | 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 | 13153 | if (rhs_val.isUndef()) { |
| 13131 | 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 | 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 | 13160 | return sema.failWithModRemNegative(block, rhs_src, lhs_ty, rhs_ty); |
| 13138 | 13161 | } |
| 13139 | 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 | 13164 | return sema.failWithModRemNegative(block, lhs_src, lhs_ty, rhs_ty); |
| 13142 | 13165 | } |
| 13143 | 13166 | return sema.addConstant( |
| ... | ... | @@ -13273,7 +13296,7 @@ fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins |
| 13273 | 13296 | if (rhs_val.isUndef()) { |
| 13274 | 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 | 13300 | return sema.failWithDivideByZero(block, rhs_src); |
| 13278 | 13301 | } |
| 13279 | 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 | 13315 | if (rhs_val.isUndef()) { |
| 13293 | 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 | 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 | 13399 | if (rhs_val.isUndef()) { |
| 13377 | 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 | 13403 | return sema.failWithDivideByZero(block, rhs_src); |
| 13381 | 13404 | } |
| 13382 | 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 | 13418 | if (rhs_val.isUndef()) { |
| 13396 | 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 | 13422 | return sema.failWithDivideByZero(block, rhs_src); |
| 13400 | 13423 | } |
| 13401 | 13424 | } |
| ... | ... | @@ -13474,12 +13497,12 @@ fn zirOverflowArithmetic( |
| 13474 | 13497 | // to the result, even if it is undefined.. |
| 13475 | 13498 | // Otherwise, if either of the argument is undefined, undefined is returned. |
| 13476 | 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 | 13501 | break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = rhs }; |
| 13479 | 13502 | } |
| 13480 | 13503 | } |
| 13481 | 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 | 13506 | break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs }; |
| 13484 | 13507 | } |
| 13485 | 13508 | } |
| ... | ... | @@ -13502,7 +13525,7 @@ fn zirOverflowArithmetic( |
| 13502 | 13525 | if (maybe_rhs_val) |rhs_val| { |
| 13503 | 13526 | if (rhs_val.isUndef()) { |
| 13504 | 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 | 13529 | break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs }; |
| 13507 | 13530 | } else if (maybe_lhs_val) |lhs_val| { |
| 13508 | 13531 | if (lhs_val.isUndef()) { |
| ... | ... | @@ -13522,9 +13545,9 @@ fn zirOverflowArithmetic( |
| 13522 | 13545 | // Otherwise, if either of the arguments is undefined, both results are undefined. |
| 13523 | 13546 | if (maybe_lhs_val) |lhs_val| { |
| 13524 | 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 | 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 | 13551 | break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = rhs }; |
| 13529 | 13552 | } |
| 13530 | 13553 | } |
| ... | ... | @@ -13532,9 +13555,9 @@ fn zirOverflowArithmetic( |
| 13532 | 13555 | |
| 13533 | 13556 | if (maybe_rhs_val) |rhs_val| { |
| 13534 | 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 | 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 | 13561 | break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs }; |
| 13539 | 13562 | } |
| 13540 | 13563 | } |
| ... | ... | @@ -13558,12 +13581,12 @@ fn zirOverflowArithmetic( |
| 13558 | 13581 | // If rhs is zero, the result is lhs (even if undefined) and no overflow occurred. |
| 13559 | 13582 | // Oterhwise if either of the arguments is undefined, both results are undefined. |
| 13560 | 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 | 13585 | break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs }; |
| 13563 | 13586 | } |
| 13564 | 13587 | } |
| 13565 | 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 | 13590 | break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs }; |
| 13568 | 13591 | } |
| 13569 | 13592 | } |
| ... | ... | @@ -13680,6 +13703,8 @@ fn analyzeArithmetic( |
| 13680 | 13703 | .override = &[_]LazySrcLoc{ lhs_src, rhs_src }, |
| 13681 | 13704 | }); |
| 13682 | 13705 | |
| 13706 | const is_vector = resolved_type.zigTypeTag() == .Vector; |
| 13707 | |
| 13683 | 13708 | const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src); |
| 13684 | 13709 | const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src); |
| 13685 | 13710 | |
| ... | ... | @@ -13704,7 +13729,7 @@ fn analyzeArithmetic( |
| 13704 | 13729 | // overflow (max_int), causing illegal behavior. |
| 13705 | 13730 | // For floats: either operand being undef makes the result undef. |
| 13706 | 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 | 13733 | return casted_rhs; |
| 13709 | 13734 | } |
| 13710 | 13735 | } |
| ... | ... | @@ -13716,7 +13741,7 @@ fn analyzeArithmetic( |
| 13716 | 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 | 13745 | return casted_lhs; |
| 13721 | 13746 | } |
| 13722 | 13747 | } |
| ... | ... | @@ -13751,7 +13776,7 @@ fn analyzeArithmetic( |
| 13751 | 13776 | // If either of the operands are zero, the other operand is returned. |
| 13752 | 13777 | // If either of the operands are undefined, the result is undefined. |
| 13753 | 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 | 13780 | return casted_rhs; |
| 13756 | 13781 | } |
| 13757 | 13782 | } |
| ... | ... | @@ -13760,7 +13785,7 @@ fn analyzeArithmetic( |
| 13760 | 13785 | if (rhs_val.isUndef()) { |
| 13761 | 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 | 13789 | return casted_lhs; |
| 13765 | 13790 | } |
| 13766 | 13791 | if (maybe_lhs_val) |lhs_val| { |
| ... | ... | @@ -13776,7 +13801,7 @@ fn analyzeArithmetic( |
| 13776 | 13801 | // If either of the operands are zero, then the other operand is returned. |
| 13777 | 13802 | // If either of the operands are undefined, the result is undefined. |
| 13778 | 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 | 13805 | return casted_rhs; |
| 13781 | 13806 | } |
| 13782 | 13807 | } |
| ... | ... | @@ -13784,7 +13809,7 @@ fn analyzeArithmetic( |
| 13784 | 13809 | if (rhs_val.isUndef()) { |
| 13785 | 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 | 13813 | return casted_lhs; |
| 13789 | 13814 | } |
| 13790 | 13815 | if (maybe_lhs_val) |lhs_val| { |
| ... | ... | @@ -13813,7 +13838,7 @@ fn analyzeArithmetic( |
| 13813 | 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 | 13842 | return casted_lhs; |
| 13818 | 13843 | } |
| 13819 | 13844 | } |
| ... | ... | @@ -13851,7 +13876,7 @@ fn analyzeArithmetic( |
| 13851 | 13876 | if (rhs_val.isUndef()) { |
| 13852 | 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 | 13880 | return casted_lhs; |
| 13856 | 13881 | } |
| 13857 | 13882 | } |
| ... | ... | @@ -13876,7 +13901,7 @@ fn analyzeArithmetic( |
| 13876 | 13901 | if (rhs_val.isUndef()) { |
| 13877 | 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 | 13905 | return casted_lhs; |
| 13881 | 13906 | } |
| 13882 | 13907 | } |
| ... | ... | @@ -13905,10 +13930,13 @@ fn analyzeArithmetic( |
| 13905 | 13930 | // For floats: either operand being undef makes the result undef. |
| 13906 | 13931 | if (maybe_lhs_val) |lhs_val| { |
| 13907 | 13932 | if (!lhs_val.isUndef()) { |
| 13908 | | if (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 13909 | | return sema.addConstant(resolved_type, Value.zero); |
| 13933 | if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 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 | 13940 | return casted_rhs; |
| 13913 | 13941 | } |
| 13914 | 13942 | } |
| ... | ... | @@ -13922,10 +13950,13 @@ fn analyzeArithmetic( |
| 13922 | 13950 | return sema.addConstUndef(resolved_type); |
| 13923 | 13951 | } |
| 13924 | 13952 | } |
| 13925 | | if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 13926 | | return sema.addConstant(resolved_type, Value.zero); |
| 13953 | if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 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 | 13960 | return casted_lhs; |
| 13930 | 13961 | } |
| 13931 | 13962 | if (maybe_lhs_val) |lhs_val| { |
| ... | ... | @@ -13959,10 +13990,13 @@ fn analyzeArithmetic( |
| 13959 | 13990 | // If either of the operands are undefined, result is undefined. |
| 13960 | 13991 | if (maybe_lhs_val) |lhs_val| { |
| 13961 | 13992 | if (!lhs_val.isUndef()) { |
| 13962 | | if (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 13963 | | return sema.addConstant(resolved_type, Value.zero); |
| 13993 | if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 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 | 14000 | return casted_rhs; |
| 13967 | 14001 | } |
| 13968 | 14002 | } |
| ... | ... | @@ -13972,10 +14006,13 @@ fn analyzeArithmetic( |
| 13972 | 14006 | if (rhs_val.isUndef()) { |
| 13973 | 14007 | return sema.addConstUndef(resolved_type); |
| 13974 | 14008 | } |
| 13975 | | if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 13976 | | return sema.addConstant(resolved_type, Value.zero); |
| 14009 | if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 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 | 14016 | return casted_lhs; |
| 13980 | 14017 | } |
| 13981 | 14018 | if (maybe_lhs_val) |lhs_val| { |
| ... | ... | @@ -13996,10 +14033,13 @@ fn analyzeArithmetic( |
| 13996 | 14033 | // If either of the operands are undefined, result is undefined. |
| 13997 | 14034 | if (maybe_lhs_val) |lhs_val| { |
| 13998 | 14035 | if (!lhs_val.isUndef()) { |
| 13999 | | if (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 14000 | | return sema.addConstant(resolved_type, Value.zero); |
| 14036 | if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 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 | 14043 | return casted_rhs; |
| 14004 | 14044 | } |
| 14005 | 14045 | } |
| ... | ... | @@ -14008,10 +14048,13 @@ fn analyzeArithmetic( |
| 14008 | 14048 | if (rhs_val.isUndef()) { |
| 14009 | 14049 | return sema.addConstUndef(resolved_type); |
| 14010 | 14050 | } |
| 14011 | | if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 14012 | | return sema.addConstant(resolved_type, Value.zero); |
| 14051 | if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 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 | 14058 | return casted_lhs; |
| 14016 | 14059 | } |
| 14017 | 14060 | if (maybe_lhs_val) |lhs_val| { |
| ... | ... | @@ -14563,7 +14606,7 @@ fn cmpSelf( |
| 14563 | 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 | 14610 | return Air.Inst.Ref.bool_true; |
| 14568 | 14611 | } else { |
| 14569 | 14612 | return Air.Inst.Ref.bool_false; |
| ... | ... | @@ -27769,7 +27812,7 @@ fn analyzeSlice( |
| 27769 | 27812 | sema.arena, |
| 27770 | 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 | 27816 | const sentinel_label: []const u8 = if (array_ty.sentinel() != null) |
| 27774 | 27817 | " +1 (sentinel)" |
| 27775 | 27818 | else |
| ... | ... | @@ -27812,7 +27855,7 @@ fn analyzeSlice( |
| 27812 | 27855 | .data = slice_val.sliceLen(mod) + @boolToInt(has_sentinel), |
| 27813 | 27856 | }; |
| 27814 | 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 | 27859 | const sentinel_label: []const u8 = if (has_sentinel) |
| 27817 | 27860 | " +1 (sentinel)" |
| 27818 | 27861 | else |
| ... | ... | @@ -27871,7 +27914,7 @@ fn analyzeSlice( |
| 27871 | 27914 | // requirement: start <= end |
| 27872 | 27915 | if (try sema.resolveDefinedValue(block, end_src, end)) |end_val| { |
| 27873 | 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 | 27918 | return sema.fail( |
| 27876 | 27919 | block, |
| 27877 | 27920 | start_src, |
| ... | ... | @@ -28160,11 +28203,11 @@ fn cmpNumeric( |
| 28160 | 28203 | // a signed integer with mantissa bits + 1, and if there was any non-integral part of the float, |
| 28161 | 28204 | // add/subtract 1. |
| 28162 | 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 | 28207 | else |
| 28165 | 28208 | (lhs_ty.isRuntimeFloat() or lhs_ty.isSignedInt()); |
| 28166 | 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 | 28211 | else |
| 28169 | 28212 | (rhs_ty.isRuntimeFloat() or rhs_ty.isSignedInt()); |
| 28170 | 28213 | const dest_int_is_signed = lhs_is_signed or rhs_is_signed; |
| ... | ... | @@ -31744,6 +31787,8 @@ fn floatToIntScalar( |
| 31744 | 31787 | |
| 31745 | 31788 | /// Asserts the value is an integer, and the destination type is ComptimeInt or Int. |
| 31746 | 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 | 31792 | fn intFitsInType( |
| 31748 | 31793 | sema: *Sema, |
| 31749 | 31794 | block: *Block, |
| ... | ... | @@ -31889,13 +31934,13 @@ fn intInRange( |
| 31889 | 31934 | int_val: Value, |
| 31890 | 31935 | end: usize, |
| 31891 | 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 | 31938 | var end_payload: Value.Payload.U64 = .{ |
| 31894 | 31939 | .base = .{ .tag = .int_u64 }, |
| 31895 | 31940 | .data = end, |
| 31896 | 31941 | }; |
| 31897 | 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 | 31944 | return true; |
| 31900 | 31945 | } |
| 31901 | 31946 | |
| ... | ... | @@ -32013,8 +32058,10 @@ fn intAddWithOverflowScalar( |
| 32013 | 32058 | } |
| 32014 | 32059 | |
| 32015 | 32060 | /// Asserts the values are comparable. Both operands have type `ty`. |
| 32016 | | /// Vector results will be reduced with AND. |
| 32017 | | fn compare( |
| 32061 | /// For vectors, returns true if the comparison is true for ALL elements. |
| 32062 | /// |
| 32063 | /// Note that `!compareAll(.eq, ...) != compareAll(.neq, ...)` |
| 32064 | fn compareAll( |
| 32018 | 32065 | sema: *Sema, |
| 32019 | 32066 | block: *Block, |
| 32020 | 32067 | src: LazySrcLoc, |