authorgravatar for miguel.p.paradinha@gmail.commparadinha <miguel.p.paradinha@gmail.com> 2022-01-25 14:44:57+00:00
committergravatar for miguel.p.paradinha@gmail.commparadinha <miguel.p.paradinha@gmail.com> 2022-01-25 23:53:26+00:00
log575d430f92633f5bf4e1e1663d0dc5fefe1e02f5
treeafc926a729d7d9227796781875aa51b078a717b0
parentfbe5336f3be7065ab84b797eb629ada9565341c2

stage2: x64: implement airTrunc


1 files changed, 40 insertions(+), 2 deletions(-)

src/arch/x86_64/CodeGen.zig+40-2
......@@ -905,8 +905,46 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {
905905 return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none });
906906
907907 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 });
910948}
911949
912950fn airBoolToInt(self: *Self, inst: Air.Inst.Index) !void {