| ... | ... | @@ -2386,8 +2386,8 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { |
| 2386 | 2386 | |
| 2387 | 2387 | .stack_offset => |off| try self.asmMemoryImmediate( |
| 2388 | 2388 | .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), |
| 2391 | 2391 | ), |
| 2392 | 2392 | } |
| 2393 | 2393 | } |
| ... | ... | @@ -2606,10 +2606,9 @@ fn genSliceElemPtr(self: *Self, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue { |
| 2606 | 2606 | } |
| 2607 | 2607 | |
| 2608 | 2608 | fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 2609 | | const is_volatile = false; // TODO |
| 2610 | 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: { |
| 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: { |
| 2613 | 2612 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| 2614 | 2613 | const slice_ptr_field_type = slice_ty.slicePtrFieldType(&buf); |
| 2615 | 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 | 2695 | } |
| 2697 | 2696 | |
| 2698 | 2697 | fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 2699 | | const is_volatile = false; // TODO |
| 2700 | 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 | 2699 | 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); |
| 2726 | 2713 | |
| 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); |
| 2730 | 2717 | |
| 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); |
| 2733 | 2726 | |
| 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; |
| 2745 | 2735 | }; |
| 2746 | | |
| 2747 | 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 | 2740 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 2752 | 2741 | const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| 2753 | 2742 | |
| 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); |
| 2775 | 2751 | |
| 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); |
| 2779 | 2761 | |
| 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); |
| 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 | 2773 | fn airSetUnionTag(self: *Self, inst: Air.Inst.Index) !void { |
| ... | ... | @@ -2953,12 +2940,11 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void { |
| 2953 | 2940 | const extra_bits = self.regExtraBits(src_ty); |
| 2954 | 2941 | const masked_mcv = if (extra_bits > 0) masked: { |
| 2955 | 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 | 2946 | 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; |
| 2962 | 2948 | try self.genSetReg(src_ty, dst_reg, src_mcv); |
| 2963 | 2949 | break :tmp dst_mcv; |
| 2964 | 2950 | }; |