| ... | @@ -9027,6 +9027,10 @@ fn validateSwitchRange( | ... | @@ -9027,6 +9027,10 @@ fn validateSwitchRange( |
| 9027 | ) CompileError!void { | 9027 | ) CompileError!void { |
| 9028 | const first_val = (try sema.resolveSwitchItemVal(block, first_ref, src_node_offset, switch_prong_src, .first)).val; | 9028 | const first_val = (try sema.resolveSwitchItemVal(block, first_ref, src_node_offset, switch_prong_src, .first)).val; |
| 9029 | const last_val = (try sema.resolveSwitchItemVal(block, last_ref, src_node_offset, switch_prong_src, .last)).val; | 9029 | const last_val = (try sema.resolveSwitchItemVal(block, last_ref, src_node_offset, switch_prong_src, .last)).val; |
| | 9030 | if (first_val.compare(.gt, last_val, operand_ty, sema.mod)) { |
| | 9031 | const src = switch_prong_src.resolve(sema.gpa, sema.mod.declPtr(block.src_decl), src_node_offset, .first); |
| | 9032 | return sema.fail(block, src, "range start value is greater than the end value", .{}); |
| | 9033 | } |
| 9030 | const maybe_prev_src = try range_set.add(first_val, last_val, operand_ty, switch_prong_src); | 9034 | const maybe_prev_src = try range_set.add(first_val, last_val, operand_ty, switch_prong_src); |
| 9031 | return sema.validateSwitchDupe(block, maybe_prev_src, switch_prong_src, src_node_offset); | 9035 | return sema.validateSwitchDupe(block, maybe_prev_src, switch_prong_src, src_node_offset); |
| 9032 | } | 9036 | } |
| ... | @@ -9374,9 +9378,34 @@ fn zirShl( | ... | @@ -9374,9 +9378,34 @@ fn zirShl( |
| 9374 | if (rhs_val.isUndef()) { | 9378 | if (rhs_val.isUndef()) { |
| 9375 | return sema.addConstUndef(sema.typeOf(lhs)); | 9379 | return sema.addConstUndef(sema.typeOf(lhs)); |
| 9376 | } | 9380 | } |
| | 9381 | // If rhs is 0, return lhs without doing any calculations. |
| 9377 | if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { | 9382 | if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 9378 | return lhs; | 9383 | return lhs; |
| 9379 | } | 9384 | } |
| | 9385 | if (scalar_ty.zigTypeTag() != .ComptimeInt and air_tag != .shl_sat) { |
| | 9386 | var bits_payload = Value.Payload.U64{ |
| | 9387 | .base = .{ .tag = .int_u64 }, |
| | 9388 | .data = scalar_ty.intInfo(target).bits, |
| | 9389 | }; |
| | 9390 | const bit_value = Value.initPayload(&bits_payload.base); |
| | 9391 | if (rhs_ty.zigTypeTag() == .Vector) { |
| | 9392 | var i: usize = 0; |
| | 9393 | while (i < rhs_ty.vectorLen()) : (i += 1) { |
| | 9394 | if (rhs_val.indexVectorlike(i).compareHetero(.gte, bit_value, target)) { |
| | 9395 | return sema.fail(block, rhs_src, "shift amount '{}' at index '{d}' is too large for operand type '{}'", .{ |
| | 9396 | rhs_val.indexVectorlike(i).fmtValue(scalar_ty, sema.mod), |
| | 9397 | i, |
| | 9398 | scalar_ty.fmt(sema.mod), |
| | 9399 | }); |
| | 9400 | } |
| | 9401 | } |
| | 9402 | } else if (rhs_val.compareHetero(.gte, bit_value, target)) { |
| | 9403 | return sema.fail(block, rhs_src, "shift amount '{}' is too large for operand type '{}'", .{ |
| | 9404 | rhs_val.fmtValue(scalar_ty, sema.mod), |
| | 9405 | scalar_ty.fmt(sema.mod), |
| | 9406 | }); |
| | 9407 | } |
| | 9408 | } |
| 9380 | } | 9409 | } |
| 9381 | | 9410 | |
| 9382 | const runtime_src = if (maybe_lhs_val) |lhs_val| rs: { | 9411 | const runtime_src = if (maybe_lhs_val) |lhs_val| rs: { |
| ... | @@ -9488,16 +9517,44 @@ fn zirShr( | ... | @@ -9488,16 +9517,44 @@ fn zirShr( |
| 9488 | const rhs_ty = sema.typeOf(rhs); | 9517 | const rhs_ty = sema.typeOf(rhs); |
| 9489 | try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src); | 9518 | try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src); |
| 9490 | const target = sema.mod.getTarget(); | 9519 | const target = sema.mod.getTarget(); |
| | 9520 | const scalar_ty = lhs_ty.scalarType(); |
| 9491 | | 9521 | |
| 9492 | const runtime_src = if (try sema.resolveMaybeUndefVal(block, rhs_src, rhs)) |rhs_val| rs: { | 9522 | const runtime_src = if (try sema.resolveMaybeUndefVal(block, rhs_src, rhs)) |rhs_val| rs: { |
| | 9523 | if (rhs_val.isUndef()) { |
| | 9524 | return sema.addConstUndef(lhs_ty); |
| | 9525 | } |
| | 9526 | // If rhs is 0, return lhs without doing any calculations. |
| | 9527 | if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| | 9528 | return lhs; |
| | 9529 | } |
| | 9530 | if (scalar_ty.zigTypeTag() != .ComptimeInt) { |
| | 9531 | var bits_payload = Value.Payload.U64{ |
| | 9532 | .base = .{ .tag = .int_u64 }, |
| | 9533 | .data = scalar_ty.intInfo(target).bits, |
| | 9534 | }; |
| | 9535 | const bit_value = Value.initPayload(&bits_payload.base); |
| | 9536 | if (rhs_ty.zigTypeTag() == .Vector) { |
| | 9537 | var i: usize = 0; |
| | 9538 | while (i < rhs_ty.vectorLen()) : (i += 1) { |
| | 9539 | if (rhs_val.indexVectorlike(i).compareHetero(.gte, bit_value, target)) { |
| | 9540 | return sema.fail(block, rhs_src, "shift amount '{}' at index '{d}' is too large for operand type '{}'", .{ |
| | 9541 | rhs_val.indexVectorlike(i).fmtValue(scalar_ty, sema.mod), |
| | 9542 | i, |
| | 9543 | scalar_ty.fmt(sema.mod), |
| | 9544 | }); |
| | 9545 | } |
| | 9546 | } |
| | 9547 | } else if (rhs_val.compareHetero(.gte, bit_value, target)) { |
| | 9548 | return sema.fail(block, rhs_src, "shift amount '{}' is too large for operand type '{}'", .{ |
| | 9549 | rhs_val.fmtValue(scalar_ty, sema.mod), |
| | 9550 | scalar_ty.fmt(sema.mod), |
| | 9551 | }); |
| | 9552 | } |
| | 9553 | } |
| 9493 | if (try sema.resolveMaybeUndefVal(block, lhs_src, lhs)) |lhs_val| { | 9554 | if (try sema.resolveMaybeUndefVal(block, lhs_src, lhs)) |lhs_val| { |
| 9494 | if (lhs_val.isUndef() or rhs_val.isUndef()) { | 9555 | if (lhs_val.isUndef()) { |
| 9495 | return sema.addConstUndef(lhs_ty); | 9556 | return sema.addConstUndef(lhs_ty); |
| 9496 | } | 9557 | } |
| 9497 | // If rhs is 0, return lhs without doing any calculations. | | |
| 9498 | if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { | | |
| 9499 | return sema.addConstant(lhs_ty, lhs_val); | | |
| 9500 | } | | |
| 9501 | if (air_tag == .shr_exact) { | 9558 | if (air_tag == .shr_exact) { |
| 9502 | // Detect if any ones would be shifted out. | 9559 | // Detect if any ones would be shifted out. |
| 9503 | const truncated = try lhs_val.intTruncBitsAsValue(lhs_ty, sema.arena, .unsigned, rhs_val, target); | 9560 | const truncated = try lhs_val.intTruncBitsAsValue(lhs_ty, sema.arena, .unsigned, rhs_val, target); |
| ... | @@ -9508,12 +9565,6 @@ fn zirShr( | ... | @@ -9508,12 +9565,6 @@ fn zirShr( |
| 9508 | const val = try lhs_val.shr(rhs_val, lhs_ty, sema.arena, target); | 9565 | const val = try lhs_val.shr(rhs_val, lhs_ty, sema.arena, target); |
| 9509 | return sema.addConstant(lhs_ty, val); | 9566 | return sema.addConstant(lhs_ty, val); |
| 9510 | } else { | 9567 | } else { |
| 9511 | // Even if lhs is not comptime known, we can still deduce certain things based | | |
| 9512 | // on rhs. | | |
| 9513 | // If rhs is 0, return lhs without doing any calculations. | | |
| 9514 | if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { | | |
| 9515 | return lhs; | | |
| 9516 | } | | |
| 9517 | break :rs lhs_src; | 9568 | break :rs lhs_src; |
| 9518 | } | 9569 | } |
| 9519 | } else rhs_src; | 9570 | } else rhs_src; |