| ... | ... | @@ -9027,6 +9027,10 @@ fn validateSwitchRange( |
| 9027 | 9027 | ) CompileError!void { |
| 9028 | 9028 | const first_val = (try sema.resolveSwitchItemVal(block, first_ref, src_node_offset, switch_prong_src, .first)).val; |
| 9029 | 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 | 9034 | const maybe_prev_src = try range_set.add(first_val, last_val, operand_ty, switch_prong_src); |
| 9031 | 9035 | return sema.validateSwitchDupe(block, maybe_prev_src, switch_prong_src, src_node_offset); |
| 9032 | 9036 | } |
| ... | ... | @@ -9374,9 +9378,34 @@ fn zirShl( |
| 9374 | 9378 | if (rhs_val.isUndef()) { |
| 9375 | 9379 | return sema.addConstUndef(sema.typeOf(lhs)); |
| 9376 | 9380 | } |
| 9381 | // If rhs is 0, return lhs without doing any calculations. |
| 9377 | 9382 | if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 9378 | 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 | 9411 | const runtime_src = if (maybe_lhs_val) |lhs_val| rs: { |
| ... | ... | @@ -9488,16 +9517,44 @@ fn zirShr( |
| 9488 | 9517 | const rhs_ty = sema.typeOf(rhs); |
| 9489 | 9518 | try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src); |
| 9490 | 9519 | const target = sema.mod.getTarget(); |
| 9520 | const scalar_ty = lhs_ty.scalarType(); |
| 9491 | 9521 | |
| 9492 | 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 | 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 | 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 | 9558 | if (air_tag == .shr_exact) { |
| 9502 | 9559 | // Detect if any ones would be shifted out. |
| 9503 | 9560 | const truncated = try lhs_val.intTruncBitsAsValue(lhs_ty, sema.arena, .unsigned, rhs_val, target); |
| ... | ... | @@ -9508,12 +9565,6 @@ fn zirShr( |
| 9508 | 9565 | const val = try lhs_val.shr(rhs_val, lhs_ty, sema.arena, target); |
| 9509 | 9566 | return sema.addConstant(lhs_ty, val); |
| 9510 | 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 | 9568 | break :rs lhs_src; |
| 9518 | 9569 | } |
| 9519 | 9570 | } else rhs_src; |