| ... | ... | @@ -13637,6 +13637,8 @@ fn zirShl( |
| 13637 | 13637 | const scalar_ty = lhs_ty.scalarType(zcu); |
| 13638 | 13638 | const scalar_rhs_ty = rhs_ty.scalarType(zcu); |
| 13639 | 13639 | |
| 13640 | // AstGen currently forces the rhs of `<<` to coerce to the correct type before the `.shl` instruction, so |
| 13641 | // we already know `scalar_rhs_ty` is valid for `.shl` -- we only need to validate for `.shl_sat`. |
| 13640 | 13642 | if (air_tag == .shl_sat) _ = try sema.checkIntType(block, rhs_src, scalar_rhs_ty); |
| 13641 | 13643 | |
| 13642 | 13644 | const maybe_lhs_val = try sema.resolveValueResolveLazy(lhs); |
| ... | ... | @@ -13645,25 +13647,29 @@ fn zirShl( |
| 13645 | 13647 | const runtime_src = rs: { |
| 13646 | 13648 | if (maybe_rhs_val) |rhs_val| { |
| 13647 | 13649 | if (maybe_lhs_val) |lhs_val| { |
| 13648 | | return Air.internedToRef((try arith.shl(sema, block, lhs_ty, lhs_val, rhs_val, lhs_src, rhs_src, switch (air_tag) { |
| 13650 | return .fromValue(try arith.shl(sema, block, lhs_ty, lhs_val, rhs_val, src, lhs_src, rhs_src, switch (air_tag) { |
| 13649 | 13651 | .shl => .shl, |
| 13650 | 13652 | .shl_sat => .shl_sat, |
| 13651 | 13653 | .shl_exact => .shl_exact, |
| 13652 | 13654 | else => unreachable, |
| 13653 | | })).toIntern()); |
| 13655 | })); |
| 13654 | 13656 | } |
| 13655 | 13657 | if (rhs_val.isUndef(zcu)) switch (air_tag) { |
| 13656 | 13658 | .shl_sat => return pt.undefRef(lhs_ty), |
| 13657 | 13659 | .shl, .shl_exact => return sema.failWithUseOfUndef(block, rhs_src, null), |
| 13658 | 13660 | else => unreachable, |
| 13659 | 13661 | }; |
| 13660 | | const bits_val = try pt.intValue(.comptime_int, scalar_ty.intInfo(zcu).bits); |
| 13662 | const bits = scalar_ty.intInfo(zcu).bits; |
| 13661 | 13663 | switch (rhs_ty.zigTypeTag(zcu)) { |
| 13662 | 13664 | .int, .comptime_int => { |
| 13663 | 13665 | switch (try rhs_val.orderAgainstZeroSema(pt)) { |
| 13664 | 13666 | .gt => { |
| 13665 | | if (air_tag != .shl_sat and try rhs_val.compareHeteroSema(.gte, bits_val, pt)) { |
| 13666 | | return sema.failWithTooLargeShiftAmount(block, lhs_ty, rhs_val, rhs_src, null); |
| 13667 | if (air_tag != .shl_sat) { |
| 13668 | var rhs_space: Value.BigIntSpace = undefined; |
| 13669 | const rhs_bigint = try rhs_val.toBigIntSema(&rhs_space, pt); |
| 13670 | if (rhs_bigint.orderAgainstScalar(bits) != .lt) { |
| 13671 | return sema.failWithTooLargeShiftAmount(block, lhs_ty, rhs_val, rhs_src, null); |
| 13672 | } |
| 13667 | 13673 | } |
| 13668 | 13674 | }, |
| 13669 | 13675 | .eq => return lhs, |
| ... | ... | @@ -13672,8 +13678,7 @@ fn zirShl( |
| 13672 | 13678 | }, |
| 13673 | 13679 | .vector => { |
| 13674 | 13680 | var any_positive: bool = false; |
| 13675 | | var elem_idx: usize = 0; |
| 13676 | | while (elem_idx < rhs_ty.vectorLen(zcu)) : (elem_idx += 1) { |
| 13681 | for (0..rhs_ty.vectorLen(zcu)) |elem_idx| { |
| 13677 | 13682 | const rhs_elem = try rhs_val.elemValue(pt, elem_idx); |
| 13678 | 13683 | if (rhs_elem.isUndef(zcu)) switch (air_tag) { |
| 13679 | 13684 | .shl_sat => continue, |
| ... | ... | @@ -13682,8 +13687,12 @@ fn zirShl( |
| 13682 | 13687 | }; |
| 13683 | 13688 | switch (try rhs_elem.orderAgainstZeroSema(pt)) { |
| 13684 | 13689 | .gt => { |
| 13685 | | if (air_tag != .shl_sat and try rhs_elem.compareHeteroSema(.gte, bits_val, pt)) { |
| 13686 | | return sema.failWithTooLargeShiftAmount(block, lhs_ty, rhs_elem, rhs_src, elem_idx); |
| 13690 | if (air_tag != .shl_sat) { |
| 13691 | var rhs_elem_space: Value.BigIntSpace = undefined; |
| 13692 | const rhs_elem_bigint = try rhs_elem.toBigIntSema(&rhs_elem_space, pt); |
| 13693 | if (rhs_elem_bigint.orderAgainstScalar(bits) != .lt) { |
| 13694 | return sema.failWithTooLargeShiftAmount(block, lhs_ty, rhs_elem, rhs_src, elem_idx); |
| 13695 | } |
| 13687 | 13696 | } |
| 13688 | 13697 | any_positive = true; |
| 13689 | 13698 | }, |
| ... | ... | @@ -13713,29 +13722,29 @@ fn zirShl( |
| 13713 | 13722 | } |
| 13714 | 13723 | break :rs rhs_src; |
| 13715 | 13724 | }; |
| 13716 | | const rt_rhs = switch (air_tag) { |
| 13725 | const rt_rhs: Air.Inst.Ref = switch (air_tag) { |
| 13717 | 13726 | else => unreachable, |
| 13718 | 13727 | .shl, .shl_exact => rhs, |
| 13719 | 13728 | // The backend can handle a large runtime rhs better than we can, but |
| 13720 | 13729 | // we can limit a large comptime rhs better here. This also has the |
| 13721 | 13730 | // necessary side effect of preventing rhs from being a `comptime_int`. |
| 13722 | | .shl_sat => if (maybe_rhs_val) |rhs_val| Air.internedToRef(rt_rhs: { |
| 13731 | .shl_sat => if (maybe_rhs_val) |rhs_val| .fromValue(rt_rhs: { |
| 13723 | 13732 | const bit_count = scalar_ty.intInfo(zcu).bits; |
| 13724 | 13733 | const rt_rhs_scalar_ty = try pt.smallestUnsignedInt(bit_count); |
| 13725 | | if (!rhs_ty.isVector(zcu)) break :rt_rhs (try pt.intValue( |
| 13734 | if (!rhs_ty.isVector(zcu)) break :rt_rhs try pt.intValue( |
| 13726 | 13735 | rt_rhs_scalar_ty, |
| 13727 | 13736 | @min(try rhs_val.getUnsignedIntSema(pt) orelse bit_count, bit_count), |
| 13728 | | )).toIntern(); |
| 13737 | ); |
| 13729 | 13738 | const rhs_len = rhs_ty.vectorLen(zcu); |
| 13730 | 13739 | const rhs_elems = try sema.arena.alloc(InternPool.Index, rhs_len); |
| 13731 | 13740 | for (rhs_elems, 0..) |*rhs_elem, i| rhs_elem.* = (try pt.intValue( |
| 13732 | 13741 | rt_rhs_scalar_ty, |
| 13733 | 13742 | @min(try (try rhs_val.elemValue(pt, i)).getUnsignedIntSema(pt) orelse bit_count, bit_count), |
| 13734 | 13743 | )).toIntern(); |
| 13735 | | break :rt_rhs (try pt.aggregateValue(try pt.vectorType(.{ |
| 13744 | break :rt_rhs try pt.aggregateValue(try pt.vectorType(.{ |
| 13736 | 13745 | .len = rhs_len, |
| 13737 | 13746 | .child = rt_rhs_scalar_ty.toIntern(), |
| 13738 | | }), rhs_elems)).toIntern(); |
| 13747 | }), rhs_elems); |
| 13739 | 13748 | }) else rhs, |
| 13740 | 13749 | }; |
| 13741 | 13750 | |
| ... | ... | @@ -13760,7 +13769,7 @@ fn zirShl( |
| 13760 | 13769 | const op_ov = try block.addInst(.{ |
| 13761 | 13770 | .tag = .shl_with_overflow, |
| 13762 | 13771 | .data = .{ .ty_pl = .{ |
| 13763 | | .ty = Air.internedToRef(op_ov_tuple_ty.toIntern()), |
| 13772 | .ty = .fromIntern(op_ov_tuple_ty.toIntern()), |
| 13764 | 13773 | .payload = try sema.addExtra(Air.Bin{ |
| 13765 | 13774 | .lhs = lhs, |
| 13766 | 13775 | .rhs = rhs, |
| ... | ... | @@ -13820,21 +13829,23 @@ fn zirShr( |
| 13820 | 13829 | const runtime_src = rs: { |
| 13821 | 13830 | if (maybe_rhs_val) |rhs_val| { |
| 13822 | 13831 | if (maybe_lhs_val) |lhs_val| { |
| 13823 | | return Air.internedToRef((try arith.shr(sema, block, lhs_ty, rhs_ty, lhs_val, rhs_val, src, lhs_src, rhs_src, switch (air_tag) { |
| 13832 | return .fromValue(try arith.shr(sema, block, lhs_ty, rhs_ty, lhs_val, rhs_val, src, lhs_src, rhs_src, switch (air_tag) { |
| 13824 | 13833 | .shr => .shr, |
| 13825 | 13834 | .shr_exact => .shr_exact, |
| 13826 | 13835 | else => unreachable, |
| 13827 | | })).toIntern()); |
| 13836 | })); |
| 13828 | 13837 | } |
| 13829 | 13838 | if (rhs_val.isUndef(zcu)) { |
| 13830 | 13839 | return sema.failWithUseOfUndef(block, rhs_src, null); |
| 13831 | 13840 | } |
| 13832 | | const bits_val = try pt.intValue(.comptime_int, scalar_ty.intInfo(zcu).bits); |
| 13841 | const bits = scalar_ty.intInfo(zcu).bits; |
| 13833 | 13842 | switch (rhs_ty.zigTypeTag(zcu)) { |
| 13834 | 13843 | .int, .comptime_int => { |
| 13835 | 13844 | switch (try rhs_val.orderAgainstZeroSema(pt)) { |
| 13836 | 13845 | .gt => { |
| 13837 | | if (try rhs_val.compareHeteroSema(.gte, bits_val, pt)) { |
| 13846 | var rhs_space: Value.BigIntSpace = undefined; |
| 13847 | const rhs_bigint = try rhs_val.toBigIntSema(&rhs_space, pt); |
| 13848 | if (rhs_bigint.orderAgainstScalar(bits) != .lt) { |
| 13838 | 13849 | return sema.failWithTooLargeShiftAmount(block, lhs_ty, rhs_val, rhs_src, null); |
| 13839 | 13850 | } |
| 13840 | 13851 | }, |
| ... | ... | @@ -13844,16 +13855,17 @@ fn zirShr( |
| 13844 | 13855 | }, |
| 13845 | 13856 | .vector => { |
| 13846 | 13857 | var any_positive: bool = false; |
| 13847 | | var elem_idx: usize = 0; |
| 13848 | | while (elem_idx < rhs_ty.vectorLen(zcu)) : (elem_idx += 1) { |
| 13858 | for (0..rhs_ty.vectorLen(zcu)) |elem_idx| { |
| 13849 | 13859 | const rhs_elem = try rhs_val.elemValue(pt, elem_idx); |
| 13850 | 13860 | if (rhs_elem.isUndef(zcu)) { |
| 13851 | 13861 | return sema.failWithUseOfUndef(block, rhs_src, elem_idx); |
| 13852 | 13862 | } |
| 13853 | 13863 | switch (try rhs_elem.orderAgainstZeroSema(pt)) { |
| 13854 | 13864 | .gt => { |
| 13855 | | if (try rhs_elem.compareHeteroSema(.gte, bits_val, pt)) { |
| 13856 | | return sema.failWithTooLargeShiftAmount(block, lhs_ty, rhs_val, rhs_src, elem_idx); |
| 13865 | var rhs_elem_space: Value.BigIntSpace = undefined; |
| 13866 | const rhs_elem_bigint = try rhs_elem.toBigIntSema(&rhs_elem_space, pt); |
| 13867 | if (rhs_elem_bigint.orderAgainstScalar(bits) != .lt) { |
| 13868 | return sema.failWithTooLargeShiftAmount(block, lhs_ty, rhs_elem, rhs_src, elem_idx); |
| 13857 | 13869 | } |
| 13858 | 13870 | any_positive = true; |
| 13859 | 13871 | }, |
| ... | ... | @@ -22718,7 +22730,6 @@ fn zirByteSwap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 22718 | 22730 | const pt = sema.pt; |
| 22719 | 22731 | const zcu = pt.zcu; |
| 22720 | 22732 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; |
| 22721 | | const src = block.nodeOffset(inst_data.src_node); |
| 22722 | 22733 | const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); |
| 22723 | 22734 | const operand = try sema.resolveInst(inst_data.operand); |
| 22724 | 22735 | const operand_ty = sema.typeOf(operand); |
| ... | ... | @@ -22733,30 +22744,27 @@ fn zirByteSwap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 22733 | 22744 | ); |
| 22734 | 22745 | } |
| 22735 | 22746 | if (try sema.typeHasOnePossibleValue(operand_ty)) |val| { |
| 22736 | | return Air.internedToRef(val.toIntern()); |
| 22747 | return .fromValue(val); |
| 22737 | 22748 | } |
| 22738 | 22749 | if (try sema.resolveValue(operand)) |operand_val| { |
| 22739 | | return Air.internedToRef((try arith.byteSwap(sema, operand_val, operand_ty)).toIntern()); |
| 22750 | return .fromValue(try arith.byteSwap(sema, operand_val, operand_ty)); |
| 22740 | 22751 | } |
| 22741 | | try sema.requireRuntimeBlock(block, src, operand_src); |
| 22742 | 22752 | return block.addTyOp(.byte_swap, operand_ty, operand); |
| 22743 | 22753 | } |
| 22744 | 22754 | |
| 22745 | 22755 | fn zirBitReverse(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 22746 | 22756 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; |
| 22747 | | const src = block.nodeOffset(inst_data.src_node); |
| 22748 | 22757 | const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); |
| 22749 | 22758 | const operand = try sema.resolveInst(inst_data.operand); |
| 22750 | 22759 | const operand_ty = sema.typeOf(operand); |
| 22751 | 22760 | _ = try sema.checkIntOrVector(block, operand, operand_src); |
| 22752 | 22761 | |
| 22753 | 22762 | if (try sema.typeHasOnePossibleValue(operand_ty)) |val| { |
| 22754 | | return Air.internedToRef(val.toIntern()); |
| 22763 | return .fromValue(val); |
| 22755 | 22764 | } |
| 22756 | 22765 | if (try sema.resolveValue(operand)) |operand_val| { |
| 22757 | | return Air.internedToRef((try arith.bitReverse(sema, operand_val, operand_ty)).toIntern()); |
| 22766 | return .fromValue(try arith.bitReverse(sema, operand_val, operand_ty)); |
| 22758 | 22767 | } |
| 22759 | | try sema.requireRuntimeBlock(block, src, operand_src); |
| 22760 | 22768 | return block.addTyOp(.bit_reverse, operand_ty, operand); |
| 22761 | 22769 | } |
| 22762 | 22770 | |