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 {...@@ -2386,8 +2386,8 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {
23862386
2387 .stack_offset => |off| try self.asmMemoryImmediate(2387 .stack_offset => |off| try self.asmMemoryImmediate(
2388 .mov,2388 .mov,
2389 Memory.sib(.byte, .{ .base = .rsp, .disp = pl_abi_size - off }),2389 Memory.sib(.byte, .{ .base = .rbp, .disp = pl_abi_size - off }),
2390 Immediate.u(0),2390 Immediate.u(1),
2391 ),2391 ),
2392 }2392 }
2393 }2393 }
...@@ -2606,10 +2606,9 @@ fn genSliceElemPtr(self: *Self, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue {...@@ -2606,10 +2606,9 @@ fn genSliceElemPtr(self: *Self, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue {
2606}2606}
26072607
2608fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {2608fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {
2609 const is_volatile = false; // TODO
2610 const bin_op = self.air.instructions.items(.data)[inst].bin_op;2609 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: {2610 const slice_ty = self.air.typeOf(bin_op.lhs);
2612 const slice_ty = self.air.typeOf(bin_op.lhs);2611 const result = if (!slice_ty.isVolatilePtr() and self.liveness.isUnused(inst)) .dead else result: {
2613 var buf: Type.SlicePtrFieldTypeBuffer = undefined;2612 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
2614 const slice_ptr_field_type = slice_ty.slicePtrFieldType(&buf);2613 const slice_ptr_field_type = slice_ty.slicePtrFieldType(&buf);
2615 const elem_ptr = try self.genSliceElemPtr(bin_op.lhs, bin_op.rhs);2614 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 {...@@ -2696,54 +2695,44 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
2696}2695}
26972696
2698fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void {2697fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void {
2699 const is_volatile = false; // TODO
2700 const bin_op = self.air.instructions.items(.data)[inst].bin_op;2698 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
2709 const ptr_ty = self.air.typeOf(bin_op.lhs);2699 const ptr_ty = self.air.typeOf(bin_op.lhs);
2710 const ptr = try self.resolveInst(bin_op.lhs);2700 const result = if (!ptr_ty.isVolatilePtr() and self.liveness.isUnused(inst)) .dead else result: {
2711 const ptr_lock: ?RegisterLock = switch (ptr) {2701 // this is identical to the `airPtrElemPtr` codegen expect here an
2712 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),2702 // additional `mov` is needed at the end to get the actual value
2713 else => null,2703
2714 };2704 const elem_ty = ptr_ty.elemType2();
2715 defer if (ptr_lock) |lock| self.register_manager.unlockReg(lock);2705 const elem_abi_size = @intCast(u32, elem_ty.abiSize(self.target.*));
27162706 const index_ty = self.air.typeOf(bin_op.rhs);
2717 const elem_ty = ptr_ty.elemType2();2707 const index_mcv = try self.resolveInst(bin_op.rhs);
2718 const elem_abi_size = @intCast(u32, elem_ty.abiSize(self.target.*));2708 const index_lock = switch (index_mcv) {
2719 const index_ty = self.air.typeOf(bin_op.rhs);2709 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
2720 const index = try self.resolveInst(bin_op.rhs);2710 else => null,
2721 const index_lock: ?RegisterLock = switch (index) {2711 };
2722 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),2712 defer if (index_lock) |lock| self.register_manager.unlockReg(lock);
2723 else => null,
2724 };
2725 defer if (index_lock) |lock| self.register_manager.unlockReg(lock);
27262713
2727 const offset_reg = try self.elemOffset(index_ty, index, elem_abi_size);2714 const offset_reg = try self.elemOffset(index_ty, index_mcv, elem_abi_size);
2728 const offset_reg_lock = self.register_manager.lockRegAssumeUnused(offset_reg);2715 const offset_lock = self.register_manager.lockRegAssumeUnused(offset_reg);
2729 defer self.register_manager.unlockReg(offset_reg_lock);2716 defer self.register_manager.unlockReg(offset_lock);
27302717
2731 const dst_mcv = try self.copyToRegisterWithInstTracking(inst, ptr_ty, ptr);2718 const ptr_mcv = try self.resolveInst(bin_op.lhs);
2732 try self.genBinOpMir(.add, ptr_ty, dst_mcv, .{ .register = offset_reg });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: {2727 const dst_mcv = try self.allocRegOrMem(inst, true);
2735 if (elem_abi_size > 8) {2728 const dst_lock = switch (dst_mcv) {
2736 return self.fail("TODO copy value with size {} from pointer", .{elem_abi_size});2729 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
2737 } else {2730 else => null,
2738 try self.asmRegisterMemory(2731 };
2739 .mov,2732 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
2740 registerAlias(dst_mcv.register, elem_abi_size),2733 try self.load(dst_mcv, .{ .register = elem_ptr_reg }, ptr_ty);
2741 Memory.sib(Memory.PtrSize.fromSize(elem_abi_size), .{ .base = dst_mcv.register }),2734 break :result dst_mcv;
2742 );
2743 break :result .{ .register = registerAlias(dst_mcv.register, @intCast(u32, elem_abi_size)) };
2744 }
2745 };2735 };
2746
2747 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });2736 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2748}2737}
27492738
...@@ -2751,36 +2740,34 @@ fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -2751,36 +2740,34 @@ fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void {
2751 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;2740 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
2752 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;2741 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
27532742
2754 if (self.liveness.isUnused(inst)) {2743 const result = if (self.liveness.isUnused(inst)) .dead else result: {
2755 return self.finishAir(inst, .dead, .{ extra.lhs, extra.rhs, .none });2744 const ptr_ty = self.air.typeOf(extra.lhs);
2756 }2745 const ptr = try self.resolveInst(extra.lhs);
27572746 const ptr_lock: ?RegisterLock = switch (ptr) {
2758 const ptr_ty = self.air.typeOf(extra.lhs);2747 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
2759 const ptr = try self.resolveInst(extra.lhs);2748 else => null,
2760 const ptr_lock: ?RegisterLock = switch (ptr) {2749 };
2761 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),2750 defer if (ptr_lock) |lock| self.register_manager.unlockReg(lock);
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);
27752751
2776 const offset_reg = try self.elemOffset(index_ty, index, elem_abi_size);2752 const elem_ty = ptr_ty.elemType2();
2777 const offset_reg_lock = self.register_manager.lockRegAssumeUnused(offset_reg);2753 const elem_abi_size = elem_ty.abiSize(self.target.*);
2778 defer self.register_manager.unlockReg(offset_reg_lock);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);2762 const offset_reg = try self.elemOffset(index_ty, index, elem_abi_size);
2781 try self.genBinOpMir(.add, ptr_ty, dst_mcv, .{ .register = offset_reg });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 });
2784}2771}
27852772
2786fn airSetUnionTag(self: *Self, inst: Air.Inst.Index) !void {2773fn airSetUnionTag(self: *Self, inst: Air.Inst.Index) !void {
...@@ -2953,12 +2940,11 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void {...@@ -2953,12 +2940,11 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void {
2953 const extra_bits = self.regExtraBits(src_ty);2940 const extra_bits = self.regExtraBits(src_ty);
2954 const masked_mcv = if (extra_bits > 0) masked: {2941 const masked_mcv = if (extra_bits > 0) masked: {
2955 const mask_mcv = MCValue{2942 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),
2957 };2945 };
2958 const tmp_mcv = tmp: {2946 const tmp_mcv = tmp: {
2959 if (src_mcv.isImmediate() or self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) {2947 if (src_mcv.isImmediate() or self.liveness.operandDies(inst, 0)) break :tmp src_mcv;
2960 break :tmp src_mcv;
2961 }
2962 try self.genSetReg(src_ty, dst_reg, src_mcv);2948 try self.genSetReg(src_ty, dst_reg, src_mcv);
2963 break :tmp dst_mcv;2949 break :tmp dst_mcv;
2964 };2950 };