| ... | ... | @@ -905,8 +905,46 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void { |
| 905 | 905 | return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none }); |
| 906 | 906 | |
| 907 | 907 | const operand = try self.resolveInst(ty_op.operand); |
| 908 | | _ = operand; |
| 909 | | return self.fail("TODO implement trunc for {}", .{self.target.cpu.arch}); |
| 908 | |
| 909 | const src_ty = self.air.typeOf(ty_op.operand); |
| 910 | const dst_ty = self.air.typeOfIndex(inst); |
| 911 | |
| 912 | const src_ty_size = src_ty.abiSize(self.target.*); |
| 913 | const dst_ty_size = dst_ty.abiSize(self.target.*); |
| 914 | if (src_ty_size > 8 or dst_ty_size > 8) { |
| 915 | return self.fail("TODO implement trunc for abi sizes larger than 8", .{}); |
| 916 | } |
| 917 | |
| 918 | const src_reg = if (operand == .register) operand.register else blk: { |
| 919 | const tmp_reg = try self.register_manager.allocReg(inst, &.{}); |
| 920 | try self.genSetReg(dst_ty, tmp_reg, operand); |
| 921 | break :blk tmp_reg; |
| 922 | }; |
| 923 | const dst_reg = try self.register_manager.allocReg(inst, &.{}); |
| 924 | |
| 925 | // "convert" the src register to the smaller type so only those bytes are moved |
| 926 | const small_src = MCValue{ .register = registerAlias(src_reg, @intCast(u32, dst_ty_size)) }; |
| 927 | |
| 928 | try self.genSetReg(dst_ty, dst_reg, small_src); |
| 929 | |
| 930 | const result = MCValue{ .register = registerAlias(dst_reg, @intCast(u32, dst_ty_size)) }; |
| 931 | |
| 932 | // when truncating a `u16` to `u5`, for example, those top 3 bits in the result |
| 933 | // have to be removed. this only happens if the dst if not a power-of-two size. |
| 934 | const dst_bit_size = dst_ty.bitSize(self.target.*); |
| 935 | const is_power_of_two = (dst_bit_size & (dst_bit_size - 1)) == 0; |
| 936 | if (!is_power_of_two or dst_bit_size < 8) { |
| 937 | const mask = (~@as(u64, 0)) >> @intCast(u6, (64 - dst_ty.bitSize(self.target.*))); |
| 938 | try self.genBinMathOpMir( |
| 939 | .@"and", |
| 940 | dst_ty, |
| 941 | dst_ty.intInfo(self.target.*).signedness, |
| 942 | result, |
| 943 | .{ .immediate = mask }, |
| 944 | ); |
| 945 | } |
| 946 | |
| 947 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 910 | 948 | } |
| 911 | 949 | |
| 912 | 950 | fn airBoolToInt(self: *Self, inst: Air.Inst.Index) !void { |