authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-03-25 05:16:33-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-03-25 16:23:55-04:00
log77300c02d65af81da6019995e4f1a156ef364df4
tree3f71bb8b28f92e7fd44e31f43ff5fc0a028b4574
parent8f385e77caae676ad675ca13baea51751230f200

x86_64: implement large ptr_elem_val


1 files changed, 64 insertions(+), 78 deletions(-)

src/arch/x86_64/CodeGen.zig+64-78
......@@ -2386,8 +2386,8 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {
23862386
23872387 .stack_offset => |off| try self.asmMemoryImmediate(
23882388 .mov,
2389 Memory.sib(.byte, .{ .base = .rsp, .disp = pl_abi_size - off }),
2390 Immediate.u(0),
2389 Memory.sib(.byte, .{ .base = .rbp, .disp = pl_abi_size - off }),
2390 Immediate.u(1),
23912391 ),
23922392 }
23932393 }
......@@ -2606,10 +2606,9 @@ fn genSliceElemPtr(self: *Self, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue {
26062606}
26072607
26082608fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {
2609 const is_volatile = false; // TODO
26102609 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
2611 const result: MCValue = if (!is_volatile and self.liveness.isUnused(inst)) .dead else result: {
2612 const slice_ty = self.air.typeOf(bin_op.lhs);
2610 const slice_ty = self.air.typeOf(bin_op.lhs);
2611 const result = if (!slice_ty.isVolatilePtr() and self.liveness.isUnused(inst)) .dead else result: {
26132612 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
26142613 const slice_ptr_field_type = slice_ty.slicePtrFieldType(&buf);
26152614 const elem_ptr = try self.genSliceElemPtr(bin_op.lhs, bin_op.rhs);
......@@ -2696,54 +2695,44 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
26962695}
26972696
26982697fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void {
2699 const is_volatile = false; // TODO
27002698 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
2701
2702 if (!is_volatile and self.liveness.isUnused(inst)) {
2703 return self.finishAir(inst, .dead, .{ bin_op.lhs, bin_op.rhs, .none });
2704 }
2705
2706 // this is identical to the `airPtrElemPtr` codegen expect here an
2707 // additional `mov` is needed at the end to get the actual value
2708
27092699 const ptr_ty = self.air.typeOf(bin_op.lhs);
2710 const ptr = try self.resolveInst(bin_op.lhs);
2711 const ptr_lock: ?RegisterLock = switch (ptr) {
2712 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
2713 else => null,
2714 };
2715 defer if (ptr_lock) |lock| self.register_manager.unlockReg(lock);
2716
2717 const elem_ty = ptr_ty.elemType2();
2718 const elem_abi_size = @intCast(u32, elem_ty.abiSize(self.target.*));
2719 const index_ty = self.air.typeOf(bin_op.rhs);
2720 const index = try self.resolveInst(bin_op.rhs);
2721 const index_lock: ?RegisterLock = switch (index) {
2722 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
2723 else => null,
2724 };
2725 defer if (index_lock) |lock| self.register_manager.unlockReg(lock);
2700 const result = if (!ptr_ty.isVolatilePtr() and self.liveness.isUnused(inst)) .dead else result: {
2701 // this is identical to the `airPtrElemPtr` codegen expect here an
2702 // additional `mov` is needed at the end to get the actual value
2703
2704 const elem_ty = ptr_ty.elemType2();
2705 const elem_abi_size = @intCast(u32, elem_ty.abiSize(self.target.*));
2706 const index_ty = self.air.typeOf(bin_op.rhs);
2707 const index_mcv = try self.resolveInst(bin_op.rhs);
2708 const index_lock = switch (index_mcv) {
2709 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
2710 else => null,
2711 };
2712 defer if (index_lock) |lock| self.register_manager.unlockReg(lock);
27262713
2727 const offset_reg = try self.elemOffset(index_ty, index, elem_abi_size);
2728 const offset_reg_lock = self.register_manager.lockRegAssumeUnused(offset_reg);
2729 defer self.register_manager.unlockReg(offset_reg_lock);
2714 const offset_reg = try self.elemOffset(index_ty, index_mcv, elem_abi_size);
2715 const offset_lock = self.register_manager.lockRegAssumeUnused(offset_reg);
2716 defer self.register_manager.unlockReg(offset_lock);
27302717
2731 const dst_mcv = try self.copyToRegisterWithInstTracking(inst, ptr_ty, ptr);
2732 try self.genBinOpMir(.add, ptr_ty, dst_mcv, .{ .register = offset_reg });
2718 const ptr_mcv = try self.resolveInst(bin_op.lhs);
2719 const elem_ptr_reg = if (ptr_mcv.isRegister() and self.liveness.operandDies(inst, 0))
2720 ptr_mcv.register
2721 else
2722 try self.copyToTmpRegister(ptr_ty, ptr_mcv);
2723 const elem_ptr_lock = self.register_manager.lockRegAssumeUnused(elem_ptr_reg);
2724 defer self.register_manager.unlockReg(elem_ptr_lock);
2725 try self.asmRegisterRegister(.add, elem_ptr_reg, offset_reg);
27332726
2734 const result: MCValue = result: {
2735 if (elem_abi_size > 8) {
2736 return self.fail("TODO copy value with size {} from pointer", .{elem_abi_size});
2737 } else {
2738 try self.asmRegisterMemory(
2739 .mov,
2740 registerAlias(dst_mcv.register, elem_abi_size),
2741 Memory.sib(Memory.PtrSize.fromSize(elem_abi_size), .{ .base = dst_mcv.register }),
2742 );
2743 break :result .{ .register = registerAlias(dst_mcv.register, @intCast(u32, elem_abi_size)) };
2744 }
2727 const dst_mcv = try self.allocRegOrMem(inst, true);
2728 const dst_lock = switch (dst_mcv) {
2729 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
2730 else => null,
2731 };
2732 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
2733 try self.load(dst_mcv, .{ .register = elem_ptr_reg }, ptr_ty);
2734 break :result dst_mcv;
27452735 };
2746
27472736 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
27482737}
27492738
......@@ -2751,36 +2740,34 @@ fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void {
27512740 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
27522741 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
27532742
2754 if (self.liveness.isUnused(inst)) {
2755 return self.finishAir(inst, .dead, .{ extra.lhs, extra.rhs, .none });
2756 }
2757
2758 const ptr_ty = self.air.typeOf(extra.lhs);
2759 const ptr = try self.resolveInst(extra.lhs);
2760 const ptr_lock: ?RegisterLock = switch (ptr) {
2761 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
2762 else => null,
2763 };
2764 defer if (ptr_lock) |lock| self.register_manager.unlockReg(lock);
2765
2766 const elem_ty = ptr_ty.elemType2();
2767 const elem_abi_size = elem_ty.abiSize(self.target.*);
2768 const index_ty = self.air.typeOf(extra.rhs);
2769 const index = try self.resolveInst(extra.rhs);
2770 const index_lock: ?RegisterLock = switch (index) {
2771 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
2772 else => null,
2773 };
2774 defer if (index_lock) |lock| self.register_manager.unlockReg(lock);
2743 const result = if (self.liveness.isUnused(inst)) .dead else result: {
2744 const ptr_ty = self.air.typeOf(extra.lhs);
2745 const ptr = try self.resolveInst(extra.lhs);
2746 const ptr_lock: ?RegisterLock = switch (ptr) {
2747 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
2748 else => null,
2749 };
2750 defer if (ptr_lock) |lock| self.register_manager.unlockReg(lock);
27752751
2776 const offset_reg = try self.elemOffset(index_ty, index, elem_abi_size);
2777 const offset_reg_lock = self.register_manager.lockRegAssumeUnused(offset_reg);
2778 defer self.register_manager.unlockReg(offset_reg_lock);
2752 const elem_ty = ptr_ty.elemType2();
2753 const elem_abi_size = elem_ty.abiSize(self.target.*);
2754 const index_ty = self.air.typeOf(extra.rhs);
2755 const index = try self.resolveInst(extra.rhs);
2756 const index_lock: ?RegisterLock = switch (index) {
2757 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
2758 else => null,
2759 };
2760 defer if (index_lock) |lock| self.register_manager.unlockReg(lock);
27792761
2780 const dst_mcv = try self.copyToRegisterWithInstTracking(inst, ptr_ty, ptr);
2781 try self.genBinOpMir(.add, ptr_ty, dst_mcv, .{ .register = offset_reg });
2762 const offset_reg = try self.elemOffset(index_ty, index, elem_abi_size);
2763 const offset_reg_lock = self.register_manager.lockRegAssumeUnused(offset_reg);
2764 defer self.register_manager.unlockReg(offset_reg_lock);
27822765
2783 return self.finishAir(inst, dst_mcv, .{ extra.lhs, extra.rhs, .none });
2766 const dst_mcv = try self.copyToRegisterWithInstTracking(inst, ptr_ty, ptr);
2767 try self.genBinOpMir(.add, ptr_ty, dst_mcv, .{ .register = offset_reg });
2768 break :result dst_mcv;
2769 };
2770 return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none });
27842771}
27852772
27862773fn airSetUnionTag(self: *Self, inst: Air.Inst.Index) !void {
......@@ -2953,12 +2940,11 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void {
29532940 const extra_bits = self.regExtraBits(src_ty);
29542941 const masked_mcv = if (extra_bits > 0) masked: {
29552942 const mask_mcv = MCValue{
2956 .immediate = ((@as(u64, 1) << @intCast(u6, extra_bits)) - 1) << @intCast(u6, src_bits),
2943 .immediate = ((@as(u64, 1) << @intCast(u6, extra_bits)) - 1) <<
2944 @intCast(u6, src_bits),
29572945 };
29582946 const tmp_mcv = tmp: {
2959 if (src_mcv.isImmediate() or self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) {
2960 break :tmp src_mcv;
2961 }
2947 if (src_mcv.isImmediate() or self.liveness.operandDies(inst, 0)) break :tmp src_mcv;
29622948 try self.genSetReg(src_ty, dst_reg, src_mcv);
29632949 break :tmp dst_mcv;
29642950 };