authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-06-07 19:10:26+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-06-07 19:33:43+02:00
log76ad7af4d87982ef62876df2a2df7bbb2ac312e8
tree728a86acc80780fc4e2af45121ace6b89049c679
parent03068ce6a67d2cf83954606dc96329b85bd4be1a

x64: pull common codepath between store and genSetStack into a helper


1 files changed, 63 insertions(+), 79 deletions(-)

src/arch/x86_64/CodeGen.zig+63-79
...@@ -2738,46 +2738,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type...@@ -2738,46 +2738,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
2738 }2738 }
2739 },2739 },
2740 .register => |src_reg| {2740 .register => |src_reg| {
2741 const src_reg_lock = self.register_manager.lockReg(src_reg);2741 try self.genInlineMemcpyRegisterRegister(value_ty, reg, src_reg, 0);
2742 defer if (src_reg_lock) |lock| self.register_manager.unlockReg(lock);
2743
2744 // TODO common code-path with genSetStack, refactor!
2745 if (!math.isPowerOfTwo(abi_size)) {
2746 const tmp_reg = try self.copyToTmpRegister(value_ty, value);
2747
2748 var next_offset: i32 = 0;
2749 var remainder = abi_size;
2750 while (remainder > 0) {
2751 const nearest_power_of_two = @as(u6, 1) << math.log2_int(u3, @intCast(u3, remainder));
2752
2753 _ = try self.addInst(.{
2754 .tag = .mov,
2755 .ops = Mir.Inst.Ops.encode(.{
2756 .reg1 = reg.to64(),
2757 .reg2 = registerAlias(tmp_reg, nearest_power_of_two),
2758 .flags = 0b10,
2759 }),
2760 .data = .{ .imm = @bitCast(u32, -next_offset) },
2761 });
2762
2763 if (nearest_power_of_two > 1) {
2764 try self.genShiftBinOpMir(.shr, value_ty, tmp_reg, .{ .immediate = nearest_power_of_two * 8 });
2765 }
2766
2767 remainder -= nearest_power_of_two;
2768 next_offset -= nearest_power_of_two;
2769 }
2770 } else {
2771 _ = try self.addInst(.{
2772 .tag = .mov,
2773 .ops = Mir.Inst.Ops.encode(.{
2774 .reg1 = reg.to64(),
2775 .reg2 = registerAlias(src_reg, @intCast(u32, abi_size)),
2776 .flags = 0b10,
2777 }),
2778 .data = .{ .imm = 0 },
2779 });
2780 }
2781 },2742 },
2782 .got_load,2743 .got_load,
2783 .direct_load,2744 .direct_load,
...@@ -5638,45 +5599,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl...@@ -5638,45 +5599,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl
5638 return self.fail("TODO genSetStack for register for type float with no intrinsics", .{});5599 return self.fail("TODO genSetStack for register for type float with no intrinsics", .{});
5639 },5600 },
5640 else => {5601 else => {
5641 if (!math.isPowerOfTwo(abi_size)) {5602 try self.genInlineMemcpyRegisterRegister(ty, base_reg, reg, stack_offset);
5642 const reg_lock = self.register_manager.lockReg(reg);
5643 defer if (reg_lock) |lock| self.register_manager.unlockReg(lock);
5644
5645 const tmp_reg = try self.copyToTmpRegister(ty, mcv);
5646
5647 var next_offset = stack_offset;
5648 var remainder = abi_size;
5649 while (remainder > 0) {
5650 const nearest_power_of_two = @as(u6, 1) << math.log2_int(u3, @intCast(u3, remainder));
5651
5652 _ = try self.addInst(.{
5653 .tag = .mov,
5654 .ops = Mir.Inst.Ops.encode(.{
5655 .reg1 = base_reg,
5656 .reg2 = registerAlias(tmp_reg, nearest_power_of_two),
5657 .flags = 0b10,
5658 }),
5659 .data = .{ .imm = @bitCast(u32, -next_offset) },
5660 });
5661
5662 if (nearest_power_of_two > 1) {
5663 try self.genShiftBinOpMir(.shr, ty, tmp_reg, .{ .immediate = nearest_power_of_two * 8 });
5664 }
5665
5666 remainder -= nearest_power_of_two;
5667 next_offset -= nearest_power_of_two;
5668 }
5669 } else {
5670 _ = try self.addInst(.{
5671 .tag = .mov,
5672 .ops = Mir.Inst.Ops.encode(.{
5673 .reg1 = base_reg,
5674 .reg2 = registerAlias(reg, @intCast(u32, abi_size)),
5675 .flags = 0b10,
5676 }),
5677 .data = .{ .imm = @bitCast(u32, -stack_offset) },
5678 });
5679 }
5680 },5603 },
5681 }5604 }
5682 },5605 },
...@@ -5711,6 +5634,67 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl...@@ -5711,6 +5634,67 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl
5711 }5634 }
5712}5635}
57135636
5637/// Like `genInlineMemcpy` but copies value from a register to an address via dereferencing
5638/// of destination register.
5639/// Boils down to MOV r/m64, r64.
5640fn genInlineMemcpyRegisterRegister(
5641 self: *Self,
5642 ty: Type,
5643 dst_reg: Register,
5644 src_reg: Register,
5645 offset: i32,
5646) InnerError!void {
5647 assert(dst_reg.size() == 64);
5648
5649 const dst_reg_lock = self.register_manager.lockReg(dst_reg);
5650 defer if (dst_reg_lock) |lock| self.register_manager.unlockReg(lock);
5651
5652 const src_reg_lock = self.register_manager.lockReg(src_reg);
5653 defer if (src_reg_lock) |lock| self.register_manager.unlockReg(lock);
5654
5655 const abi_size = @intCast(u32, ty.abiSize(self.target.*));
5656
5657 // TODO common code-path with genSetStack, refactor!
5658 if (!math.isPowerOfTwo(abi_size)) {
5659 const tmp_reg = try self.copyToTmpRegister(ty, .{ .register = src_reg });
5660
5661 var next_offset = offset;
5662 var remainder = abi_size;
5663 while (remainder > 0) {
5664 const nearest_power_of_two = @as(u6, 1) << math.log2_int(u3, @intCast(u3, remainder));
5665
5666 _ = try self.addInst(.{
5667 .tag = .mov,
5668 .ops = Mir.Inst.Ops.encode(.{
5669 .reg1 = dst_reg,
5670 .reg2 = registerAlias(tmp_reg, nearest_power_of_two),
5671 .flags = 0b10,
5672 }),
5673 .data = .{ .imm = @bitCast(u32, -next_offset) },
5674 });
5675
5676 if (nearest_power_of_two > 1) {
5677 try self.genShiftBinOpMir(.shr, ty, tmp_reg, .{
5678 .immediate = nearest_power_of_two * 8,
5679 });
5680 }
5681
5682 remainder -= nearest_power_of_two;
5683 next_offset -= nearest_power_of_two;
5684 }
5685 } else {
5686 _ = try self.addInst(.{
5687 .tag = .mov,
5688 .ops = Mir.Inst.Ops.encode(.{
5689 .reg1 = dst_reg,
5690 .reg2 = registerAlias(src_reg, @intCast(u32, abi_size)),
5691 .flags = 0b10,
5692 }),
5693 .data = .{ .imm = @bitCast(u32, -offset) },
5694 });
5695 }
5696}
5697
5714const InlineMemcpyOpts = struct {5698const InlineMemcpyOpts = struct {
5715 source_stack_base: ?Register = null,5699 source_stack_base: ?Register = null,
5716 dest_stack_base: ?Register = null,5700 dest_stack_base: ?Register = null,