| ... | @@ -1708,7 +1708,7 @@ fn airOptionalPayload(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1708,7 +1708,7 @@ fn airOptionalPayload(self: *Self, inst: Air.Inst.Index) !void { |
| 1708 | // TODO reuse the operand | 1708 | // TODO reuse the operand |
| 1709 | const result = try self.copyToRegisterWithInstTracking(inst, optional_ty, operand); | 1709 | const result = try self.copyToRegisterWithInstTracking(inst, optional_ty, operand); |
| 1710 | const shift = @intCast(u8, offset * @sizeOf(usize)); | 1710 | const shift = @intCast(u8, offset * @sizeOf(usize)); |
| 1711 | try self.genShiftBinOpMir(optional_ty, result.register, .{ .immediate = @intCast(u8, shift) }, .right); | 1711 | try self.genShiftBinOpMir(.shr, optional_ty, result.register, .{ .immediate = @intCast(u8, shift) }); |
| 1712 | break :result result; | 1712 | break :result result; |
| 1713 | }, | 1713 | }, |
| 1714 | else => return self.fail("TODO implement optional_payload when operand is {}", .{operand}), | 1714 | else => return self.fail("TODO implement optional_payload when operand is {}", .{operand}), |
| ... | @@ -1795,7 +1795,7 @@ fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1795,7 +1795,7 @@ fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void { |
| 1795 | // TODO reuse operand | 1795 | // TODO reuse operand |
| 1796 | const shift = @intCast(u6, err_abi_size * @sizeOf(usize)); | 1796 | const shift = @intCast(u6, err_abi_size * @sizeOf(usize)); |
| 1797 | const result = try self.copyToRegisterWithInstTracking(inst, err_union_ty, operand); | 1797 | const result = try self.copyToRegisterWithInstTracking(inst, err_union_ty, operand); |
| 1798 | try self.genShiftBinOpMir(Type.usize, result.register, .{ .immediate = shift }, .right); | 1798 | try self.genShiftBinOpMir(.shr, Type.usize, result.register, .{ .immediate = shift }); |
| 1799 | break :result MCValue{ | 1799 | break :result MCValue{ |
| 1800 | .register = registerAlias(result.register, @intCast(u32, payload_ty.abiSize(self.target.*))), | 1800 | .register = registerAlias(result.register, @intCast(u32, payload_ty.abiSize(self.target.*))), |
| 1801 | }; | 1801 | }; |
| ... | @@ -2307,7 +2307,7 @@ fn airGetUnionTag(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2307,7 +2307,7 @@ fn airGetUnionTag(self: *Self, inst: Air.Inst.Index) !void { |
| 2307 | else | 2307 | else |
| 2308 | 0; | 2308 | 0; |
| 2309 | const result = try self.copyToRegisterWithInstTracking(inst, union_ty, operand); | 2309 | const result = try self.copyToRegisterWithInstTracking(inst, union_ty, operand); |
| 2310 | try self.genShiftBinOpMir(Type.usize, result.register, .{ .immediate = shift }, .right); | 2310 | try self.genShiftBinOpMir(.shr, Type.usize, result.register, .{ .immediate = shift }); |
| 2311 | break :blk MCValue{ | 2311 | break :blk MCValue{ |
| 2312 | .register = registerAlias(result.register, @intCast(u32, layout.tag_size)), | 2312 | .register = registerAlias(result.register, @intCast(u32, layout.tag_size)), |
| 2313 | }; | 2313 | }; |
| ... | @@ -2906,7 +2906,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2906,7 +2906,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 2906 | | 2906 | |
| 2907 | // Shift by struct_field_offset. | 2907 | // Shift by struct_field_offset. |
| 2908 | const shift = @intCast(u8, struct_field_offset * @sizeOf(usize)); | 2908 | const shift = @intCast(u8, struct_field_offset * @sizeOf(usize)); |
| 2909 | try self.genShiftBinOpMir(Type.usize, dst_mcv.register, .{ .immediate = shift }, .right); | 2909 | try self.genShiftBinOpMir(.shr, Type.usize, dst_mcv.register, .{ .immediate = shift }); |
| 2910 | | 2910 | |
| 2911 | // Mask with reg.size() - struct_field_size | 2911 | // Mask with reg.size() - struct_field_size |
| 2912 | const max_reg_bit_width = Register.rax.size(); | 2912 | const max_reg_bit_width = Register.rax.size(); |
| ... | @@ -2983,26 +2983,15 @@ fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2983,26 +2983,15 @@ fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 2983 | } | 2983 | } |
| 2984 | | 2984 | |
| 2985 | /// Clobbers .rcx for non-immediate shift value. | 2985 | /// Clobbers .rcx for non-immediate shift value. |
| 2986 | fn genShiftBinOpMir(self: *Self, ty: Type, reg: Register, shift: MCValue, direction: enum { left, right }) !void { | 2986 | fn genShiftBinOpMir(self: *Self, tag: Mir.Inst.Tag, ty: Type, reg: Register, shift: MCValue) !void { |
| 2987 | assert(reg.to64() != .rcx); | 2987 | assert(reg.to64() != .rcx); |
| 2988 | | 2988 | |
| 2989 | const abi_size = @intCast(u32, ty.abiSize(self.target.*)); | 2989 | switch (tag) { |
| 2990 | const signedness: std.builtin.Signedness = blk: { | 2990 | .sal, .sar, .shl, .shr => {}, |
| 2991 | if (ty.zigTypeTag() != .Int) break :blk .unsigned; | 2991 | else => unreachable, |
| 2992 | break :blk ty.intInfo(self.target.*).signedness; | 2992 | } |
| 2993 | }; | | |
| 2994 | | | |
| 2995 | const tag: Mir.Inst.Tag = switch (signedness) { | | |
| 2996 | .signed => switch (direction) { | | |
| 2997 | .left => Mir.Inst.Tag.sal, | | |
| 2998 | .right => Mir.Inst.Tag.sar, | | |
| 2999 | }, | | |
| 3000 | .unsigned => switch (direction) { | | |
| 3001 | .left => Mir.Inst.Tag.shl, | | |
| 3002 | .right => Mir.Inst.Tag.shr, | | |
| 3003 | }, | | |
| 3004 | }; | | |
| 3005 | | 2993 | |
| | 2994 | const abi_size = @intCast(u32, ty.abiSize(self.target.*)); |
| 3006 | blk: { | 2995 | blk: { |
| 3007 | switch (shift) { | 2996 | switch (shift) { |
| 3008 | .immediate => |imm| switch (imm) { | 2997 | .immediate => |imm| switch (imm) { |
| ... | @@ -3100,9 +3089,22 @@ fn genShiftBinOp( | ... | @@ -3100,9 +3089,22 @@ fn genShiftBinOp( |
| 3100 | break :blk MCValue{ .register = try self.copyToTmpRegister(lhs_ty, lhs) }; | 3089 | break :blk MCValue{ .register = try self.copyToTmpRegister(lhs_ty, lhs) }; |
| 3101 | }; | 3090 | }; |
| 3102 | | 3091 | |
| | 3092 | const signedness = lhs_ty.intInfo(self.target.*).signedness; |
| 3103 | switch (tag) { | 3093 | switch (tag) { |
| 3104 | .shl => try self.genShiftBinOpMir(lhs_ty, dst.register, rhs, .left), | 3094 | .shl => try self.genShiftBinOpMir(switch (signedness) { |
| 3105 | .shr => try self.genShiftBinOpMir(lhs_ty, dst.register, rhs, .right), | 3095 | .signed => .sal, |
| | 3096 | .unsigned => .shl, |
| | 3097 | }, lhs_ty, dst.register, rhs), |
| | 3098 | |
| | 3099 | .shl_exact => try self.genShiftBinOpMir(.shl, lhs_ty, dst.register, rhs), |
| | 3100 | |
| | 3101 | .shr, |
| | 3102 | .shr_exact, |
| | 3103 | => try self.genShiftBinOpMir(switch (signedness) { |
| | 3104 | .signed => .sar, |
| | 3105 | .unsigned => .shr, |
| | 3106 | }, lhs_ty, dst.register, rhs), |
| | 3107 | |
| 3106 | else => unreachable, | 3108 | else => unreachable, |
| 3107 | } | 3109 | } |
| 3108 | | 3110 | |
| ... | @@ -5427,7 +5429,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl | ... | @@ -5427,7 +5429,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl |
| 5427 | }); | 5429 | }); |
| 5428 | | 5430 | |
| 5429 | if (nearest_power_of_two > 1) { | 5431 | if (nearest_power_of_two > 1) { |
| 5430 | try self.genShiftBinOpMir(ty, tmp_reg, .{ .immediate = nearest_power_of_two * 8 }, .right); | 5432 | try self.genShiftBinOpMir(.shr, ty, tmp_reg, .{ .immediate = nearest_power_of_two * 8 }); |
| 5431 | } | 5433 | } |
| 5432 | | 5434 | |
| 5433 | remainder -= nearest_power_of_two; | 5435 | remainder -= nearest_power_of_two; |
| ... | @@ -6804,8 +6806,8 @@ fn truncateRegister(self: *Self, ty: Type, reg: Register) !void { | ... | @@ -6804,8 +6806,8 @@ fn truncateRegister(self: *Self, ty: Type, reg: Register) !void { |
| 6804 | switch (int_info.signedness) { | 6806 | switch (int_info.signedness) { |
| 6805 | .signed => { | 6807 | .signed => { |
| 6806 | const shift = @intCast(u6, max_reg_bit_width - int_info.bits); | 6808 | const shift = @intCast(u6, max_reg_bit_width - int_info.bits); |
| 6807 | try self.genShiftBinOpMir(Type.isize, reg, .{ .immediate = shift }, .left); | 6809 | try self.genShiftBinOpMir(.sal, Type.isize, reg, .{ .immediate = shift }); |
| 6808 | try self.genShiftBinOpMir(Type.isize, reg, .{ .immediate = shift }, .right); | 6810 | try self.genShiftBinOpMir(.sar, Type.isize, reg, .{ .immediate = shift }); |
| 6809 | }, | 6811 | }, |
| 6810 | .unsigned => { | 6812 | .unsigned => { |
| 6811 | const shift = @intCast(u6, max_reg_bit_width - int_info.bits); | 6813 | const shift = @intCast(u6, max_reg_bit_width - int_info.bits); |