| ... | @@ -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 { |
| 2386 | | 2386 | |
| 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 | } |
| 2607 | | 2607 | |
| 2608 | fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { | 2608 | fn 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 | } |
| 2697 | | 2696 | |
| 2698 | fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void { | 2697 | fn 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.*)); |
| 2716 | | 2706 | 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); | | |
| 2726 | | 2713 | |
| 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); |
| 2730 | | 2717 | |
| 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); |
| 2733 | | 2726 | |
| 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 | } |
| 2749 | | 2738 | |
| ... | @@ -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; |
| 2753 | | 2742 | |
| 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); |
| 2757 | | 2746 | 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); | | |
| 2775 | | 2751 | |
| 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); |
| 2779 | | 2761 | |
| 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); |
| 2782 | | 2765 | |
| 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 | } |
| 2785 | | 2772 | |
| 2786 | fn airSetUnionTag(self: *Self, inst: Air.Inst.Index) !void { | 2773 | fn 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 | }; |