| ... | ... | @@ -537,7 +537,7 @@ const InstTracking = struct { |
| 537 | 537 | else => unreachable, |
| 538 | 538 | } |
| 539 | 539 | tracking_log.debug("spill %{d} from {} to {}", .{ inst, self.short, self.long }); |
| 540 | | try function.genCopy(function.typeOfIndex(inst), self.long, self.short); |
| 540 | try function.genCopy(function.typeOfIndex(inst), self.long, self.short, .{}); |
| 541 | 541 | } |
| 542 | 542 | |
| 543 | 543 | fn reuseFrame(self: *InstTracking) void { |
| ... | ... | @@ -637,8 +637,8 @@ const InstTracking = struct { |
| 637 | 637 | ) !void { |
| 638 | 638 | const ty = function.typeOfIndex(inst); |
| 639 | 639 | if ((self.long == .none or self.long == .reserved_frame) and target.long == .load_frame) |
| 640 | | try function.genCopy(ty, target.long, self.short); |
| 641 | | try function.genCopy(ty, target.short, self.short); |
| 640 | try function.genCopy(ty, target.long, self.short, .{}); |
| 641 | try function.genCopy(ty, target.short, self.short, .{}); |
| 642 | 642 | } |
| 643 | 643 | |
| 644 | 644 | fn trackMaterialize(self: *InstTracking, inst: Air.Inst.Index, target: InstTracking) void { |
| ... | ... | @@ -1717,6 +1717,7 @@ fn gen(self: *Self) InnerError!void { |
| 1717 | 1717 | 0, |
| 1718 | 1718 | Type.usize, |
| 1719 | 1719 | self.ret_mcv.long.address().offset(-self.ret_mcv.short.indirect.off), |
| 1720 | .{}, |
| 1720 | 1721 | ); |
| 1721 | 1722 | self.ret_mcv.long = .{ .load_frame = .{ .index = frame_index } }; |
| 1722 | 1723 | tracking_log.debug("spill {} to {}", .{ self.ret_mcv.long, frame_index }); |
| ... | ... | @@ -1740,6 +1741,7 @@ fn gen(self: *Self) InnerError!void { |
| 1740 | 1741 | @intCast(reg_i * 8), |
| 1741 | 1742 | Type.usize, |
| 1742 | 1743 | .{ .register = reg }, |
| 1744 | .{}, |
| 1743 | 1745 | ); |
| 1744 | 1746 | |
| 1745 | 1747 | try self.asmRegisterImmediate(.{ ._, .cmp }, .al, Immediate.u(info.fp_count)); |
| ... | ... | @@ -1752,6 +1754,7 @@ fn gen(self: *Self) InnerError!void { |
| 1752 | 1754 | @intCast(abi.SysV.c_abi_int_param_regs.len * 8 + reg_i * 16), |
| 1753 | 1755 | vec_2_f64, |
| 1754 | 1756 | .{ .register = reg }, |
| 1757 | .{}, |
| 1755 | 1758 | ); |
| 1756 | 1759 | |
| 1757 | 1760 | try self.performReloc(skip_sse_reloc); |
| ... | ... | @@ -2006,8 +2009,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 2006 | 2009 | .load => try self.airLoad(inst), |
| 2007 | 2010 | .loop => try self.airLoop(inst), |
| 2008 | 2011 | .int_from_ptr => try self.airIntFromPtr(inst), |
| 2009 | | .ret => try self.airRet(inst), |
| 2010 | | .ret_safe => try self.airRet(inst), // TODO |
| 2012 | .ret => try self.airRet(inst, false), |
| 2013 | .ret_safe => try self.airRet(inst, true), |
| 2011 | 2014 | .ret_load => try self.airRetLoad(inst), |
| 2012 | 2015 | .store => try self.airStore(inst, false), |
| 2013 | 2016 | .store_safe => try self.airStore(inst, true), |
| ... | ... | @@ -2209,8 +2212,15 @@ fn genLazy(self: *Self, lazy_sym: link.File.LazySymbol) InnerError!void { |
| 2209 | 2212 | 0, |
| 2210 | 2213 | Type.usize, |
| 2211 | 2214 | .{ .register_offset = .{ .reg = data_reg, .off = data_off } }, |
| 2215 | .{}, |
| 2216 | ); |
| 2217 | try self.genSetMem( |
| 2218 | .{ .reg = ret_reg }, |
| 2219 | 8, |
| 2220 | Type.usize, |
| 2221 | .{ .immediate = tag_name.len }, |
| 2222 | .{}, |
| 2212 | 2223 | ); |
| 2213 | | try self.genSetMem(.{ .reg = ret_reg }, 8, Type.usize, .{ .immediate = tag_name.len }); |
| 2214 | 2224 | |
| 2215 | 2225 | exitlude_jump_reloc.* = try self.asmJmpReloc(undefined); |
| 2216 | 2226 | try self.performReloc(skip_reloc); |
| ... | ... | @@ -2651,7 +2661,7 @@ pub fn spillRegisters(self: *Self, comptime registers: []const Register) !void { |
| 2651 | 2661 | /// This can have a side effect of spilling instructions to the stack to free up a register. |
| 2652 | 2662 | fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register { |
| 2653 | 2663 | const reg = try self.register_manager.allocReg(null, self.regClassForType(ty)); |
| 2654 | | try self.genSetReg(reg, ty, mcv); |
| 2664 | try self.genSetReg(reg, ty, mcv, .{}); |
| 2655 | 2665 | return reg; |
| 2656 | 2666 | } |
| 2657 | 2667 | |
| ... | ... | @@ -2666,7 +2676,7 @@ fn copyToRegisterWithInstTracking( |
| 2666 | 2676 | mcv: MCValue, |
| 2667 | 2677 | ) !MCValue { |
| 2668 | 2678 | const reg: Register = try self.register_manager.allocReg(reg_owner, self.regClassForType(ty)); |
| 2669 | | try self.genSetReg(reg, ty, mcv); |
| 2679 | try self.genSetReg(reg, ty, mcv, .{}); |
| 2670 | 2680 | return MCValue{ .register = reg }; |
| 2671 | 2681 | } |
| 2672 | 2682 | |
| ... | ... | @@ -2919,7 +2929,7 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void { |
| 2919 | 2929 | math.divCeil(u32, src_storage_bits, 64) catch unreachable and |
| 2920 | 2930 | self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) src_mcv else dst: { |
| 2921 | 2931 | const dst_mcv = try self.allocRegOrMem(inst, true); |
| 2922 | | try self.genCopy(min_ty, dst_mcv, src_mcv); |
| 2932 | try self.genCopy(min_ty, dst_mcv, src_mcv, .{}); |
| 2923 | 2933 | break :dst dst_mcv; |
| 2924 | 2934 | }; |
| 2925 | 2935 | |
| ... | ... | @@ -2954,7 +2964,7 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void { |
| 2954 | 2964 | if (high_bits > 0) { |
| 2955 | 2965 | try self.truncateRegister(src_ty, high_reg); |
| 2956 | 2966 | const high_ty = if (dst_int_info.bits >= 64) Type.usize else dst_ty; |
| 2957 | | try self.genCopy(high_ty, high_mcv, .{ .register = high_reg }); |
| 2967 | try self.genCopy(high_ty, high_mcv, .{ .register = high_reg }, .{}); |
| 2958 | 2968 | } |
| 2959 | 2969 | |
| 2960 | 2970 | if (dst_limbs_len > src_limbs_len) try self.genInlineMemset( |
| ... | ... | @@ -2973,6 +2983,7 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void { |
| 2973 | 2983 | .unsigned => .{ .immediate = 0 }, |
| 2974 | 2984 | }, |
| 2975 | 2985 | .{ .immediate = (dst_limbs_len - src_limbs_len) * 8 }, |
| 2986 | .{}, |
| 2976 | 2987 | ); |
| 2977 | 2988 | |
| 2978 | 2989 | break :result dst_mcv; |
| ... | ... | @@ -3006,7 +3017,7 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void { |
| 3006 | 3017 | const dst_locks = self.register_manager.lockRegsAssumeUnused(2, dst_regs); |
| 3007 | 3018 | defer for (dst_locks) |lock| self.register_manager.unlockReg(lock); |
| 3008 | 3019 | |
| 3009 | | try self.genCopy(dst_ty, dst_mcv, src_mcv); |
| 3020 | try self.genCopy(dst_ty, dst_mcv, src_mcv, .{}); |
| 3010 | 3021 | break :dst dst_mcv; |
| 3011 | 3022 | } else try self.allocRegOrMem(inst, true); |
| 3012 | 3023 | |
| ... | ... | @@ -3082,11 +3093,15 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void { |
| 3082 | 3093 | // when truncating a `u16` to `u5`, for example, those top 3 bits in the result |
| 3083 | 3094 | // have to be removed. this only happens if the dst if not a power-of-two size. |
| 3084 | 3095 | if (dst_abi_size <= 8) { |
| 3085 | | if (self.regExtraBits(dst_ty) > 0) try self.truncateRegister(dst_ty, dst_mcv.register.to64()); |
| 3096 | if (self.regExtraBits(dst_ty) > 0) { |
| 3097 | try self.truncateRegister(dst_ty, dst_mcv.register.to64()); |
| 3098 | } |
| 3086 | 3099 | } else if (dst_abi_size <= 16) { |
| 3087 | 3100 | const dst_info = dst_ty.intInfo(mod); |
| 3088 | 3101 | const high_ty = try mod.intType(dst_info.signedness, dst_info.bits - 64); |
| 3089 | | if (self.regExtraBits(high_ty) > 0) try self.truncateRegister(high_ty, dst_mcv.register_pair[1].to64()); |
| 3102 | if (self.regExtraBits(high_ty) > 0) { |
| 3103 | try self.truncateRegister(high_ty, dst_mcv.register_pair[1].to64()); |
| 3104 | } |
| 3090 | 3105 | } |
| 3091 | 3106 | |
| 3092 | 3107 | break :result dst_mcv; |
| ... | ... | @@ -3116,7 +3131,7 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void { |
| 3116 | 3131 | const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(slice_ty, mod)); |
| 3117 | 3132 | |
| 3118 | 3133 | const ptr_ty = self.typeOf(bin_op.lhs); |
| 3119 | | try self.genSetMem(.{ .frame = frame_index }, 0, ptr_ty, .{ .air_ref = bin_op.lhs }); |
| 3134 | try self.genSetMem(.{ .frame = frame_index }, 0, ptr_ty, .{ .air_ref = bin_op.lhs }, .{}); |
| 3120 | 3135 | |
| 3121 | 3136 | const len_ty = self.typeOf(bin_op.rhs); |
| 3122 | 3137 | try self.genSetMem( |
| ... | ... | @@ -3124,6 +3139,7 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void { |
| 3124 | 3139 | @intCast(ptr_ty.abiSize(mod)), |
| 3125 | 3140 | len_ty, |
| 3126 | 3141 | .{ .air_ref = bin_op.rhs }, |
| 3142 | .{}, |
| 3127 | 3143 | ); |
| 3128 | 3144 | |
| 3129 | 3145 | const result = MCValue{ .load_frame = .{ .index = frame_index } }; |
| ... | ... | @@ -3161,9 +3177,9 @@ fn airBinOp(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void { |
| 3161 | 3177 | |
| 3162 | 3178 | const hi_ty = try mod.intType(.unsigned, @intCast((dst_ty.bitSize(mod) - 1) % 64 + 1)); |
| 3163 | 3179 | const hi_mcv = dst_mcv.address().offset(@intCast(bit_size / 64 * 8)).deref(); |
| 3164 | | try self.genSetReg(tmp_reg, hi_ty, hi_mcv); |
| 3180 | try self.genSetReg(tmp_reg, hi_ty, hi_mcv, .{}); |
| 3165 | 3181 | try self.truncateRegister(dst_ty, tmp_reg); |
| 3166 | | try self.genCopy(hi_ty, hi_mcv, .{ .register = tmp_reg }); |
| 3182 | try self.genCopy(hi_ty, hi_mcv, .{ .register = tmp_reg }, .{}); |
| 3167 | 3183 | } |
| 3168 | 3184 | } |
| 3169 | 3185 | } |
| ... | ... | @@ -3476,7 +3492,7 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void { |
| 3476 | 3492 | if (reg_extra_bits > 0) { |
| 3477 | 3493 | try self.genShiftBinOpMir(.{ ._l, .sa }, ty, dst_mcv, .{ .immediate = reg_extra_bits }); |
| 3478 | 3494 | } |
| 3479 | | try self.genSetReg(limit_reg, ty, dst_mcv); |
| 3495 | try self.genSetReg(limit_reg, ty, dst_mcv, .{}); |
| 3480 | 3496 | try self.genShiftBinOpMir(.{ ._r, .sa }, ty, limit_mcv, .{ .immediate = reg_bits - 1 }); |
| 3481 | 3497 | try self.genBinOpMir(.{ ._, .xor }, ty, limit_mcv, .{ |
| 3482 | 3498 | .immediate = (@as(u64, 1) << @intCast(reg_bits - 1)) - 1, |
| ... | ... | @@ -3499,7 +3515,7 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void { |
| 3499 | 3515 | } else cc: { |
| 3500 | 3516 | try self.genSetReg(limit_reg, ty, .{ |
| 3501 | 3517 | .immediate = @as(u64, math.maxInt(u64)) >> @intCast(64 - ty.bitSize(mod)), |
| 3502 | | }); |
| 3518 | }, .{}); |
| 3503 | 3519 | |
| 3504 | 3520 | try self.genBinOpMir(.{ ._, .add }, ty, dst_mcv, rhs_mcv); |
| 3505 | 3521 | if (reg_extra_bits > 0) { |
| ... | ... | @@ -3559,7 +3575,7 @@ fn airSubSat(self: *Self, inst: Air.Inst.Index) !void { |
| 3559 | 3575 | if (reg_extra_bits > 0) { |
| 3560 | 3576 | try self.genShiftBinOpMir(.{ ._l, .sa }, ty, dst_mcv, .{ .immediate = reg_extra_bits }); |
| 3561 | 3577 | } |
| 3562 | | try self.genSetReg(limit_reg, ty, dst_mcv); |
| 3578 | try self.genSetReg(limit_reg, ty, dst_mcv, .{}); |
| 3563 | 3579 | try self.genShiftBinOpMir(.{ ._r, .sa }, ty, limit_mcv, .{ .immediate = reg_bits - 1 }); |
| 3564 | 3580 | try self.genBinOpMir(.{ ._, .xor }, ty, limit_mcv, .{ |
| 3565 | 3581 | .immediate = (@as(u64, 1) << @intCast(reg_bits - 1)) - 1, |
| ... | ... | @@ -3580,7 +3596,7 @@ fn airSubSat(self: *Self, inst: Air.Inst.Index) !void { |
| 3580 | 3596 | } else try self.genBinOpMir(.{ ._, .sub }, ty, dst_mcv, rhs_mcv); |
| 3581 | 3597 | break :cc .o; |
| 3582 | 3598 | } else cc: { |
| 3583 | | try self.genSetReg(limit_reg, ty, .{ .immediate = 0 }); |
| 3599 | try self.genSetReg(limit_reg, ty, .{ .immediate = 0 }, .{}); |
| 3584 | 3600 | try self.genBinOpMir(.{ ._, .sub }, ty, dst_mcv, rhs_mcv); |
| 3585 | 3601 | break :cc .c; |
| 3586 | 3602 | }; |
| ... | ... | @@ -3713,7 +3729,7 @@ fn airMulSat(self: *Self, inst: Air.Inst.Index) !void { |
| 3713 | 3729 | |
| 3714 | 3730 | const reg_bits = self.regBitSize(ty); |
| 3715 | 3731 | const cc: Condition = if (ty.isSignedInt(mod)) cc: { |
| 3716 | | try self.genSetReg(limit_reg, ty, lhs_mcv); |
| 3732 | try self.genSetReg(limit_reg, ty, lhs_mcv, .{}); |
| 3717 | 3733 | try self.genBinOpMir(.{ ._, .xor }, ty, limit_mcv, rhs_mcv); |
| 3718 | 3734 | try self.genShiftBinOpMir(.{ ._r, .sa }, ty, limit_mcv, .{ .immediate = reg_bits - 1 }); |
| 3719 | 3735 | try self.genBinOpMir(.{ ._, .xor }, ty, limit_mcv, .{ |
| ... | ... | @@ -3723,7 +3739,7 @@ fn airMulSat(self: *Self, inst: Air.Inst.Index) !void { |
| 3723 | 3739 | } else cc: { |
| 3724 | 3740 | try self.genSetReg(limit_reg, ty, .{ |
| 3725 | 3741 | .immediate = @as(u64, math.maxInt(u64)) >> @intCast(64 - reg_bits), |
| 3726 | | }); |
| 3742 | }, .{}); |
| 3727 | 3743 | break :cc .c; |
| 3728 | 3744 | }; |
| 3729 | 3745 | |
| ... | ... | @@ -3779,12 +3795,14 @@ fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 3779 | 3795 | @intCast(tuple_ty.structFieldOffset(1, mod)), |
| 3780 | 3796 | Type.u1, |
| 3781 | 3797 | .{ .eflags = cc }, |
| 3798 | .{}, |
| 3782 | 3799 | ); |
| 3783 | 3800 | try self.genSetMem( |
| 3784 | 3801 | .{ .frame = frame_index }, |
| 3785 | 3802 | @intCast(tuple_ty.structFieldOffset(0, mod)), |
| 3786 | 3803 | ty, |
| 3787 | 3804 | partial_mcv, |
| 3805 | .{}, |
| 3788 | 3806 | ); |
| 3789 | 3807 | break :result .{ .load_frame = .{ .index = frame_index } }; |
| 3790 | 3808 | } |
| ... | ... | @@ -3852,12 +3870,14 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 3852 | 3870 | @intCast(tuple_ty.structFieldOffset(1, mod)), |
| 3853 | 3871 | tuple_ty.structFieldType(1, mod), |
| 3854 | 3872 | .{ .eflags = cc }, |
| 3873 | .{}, |
| 3855 | 3874 | ); |
| 3856 | 3875 | try self.genSetMem( |
| 3857 | 3876 | .{ .frame = frame_index }, |
| 3858 | 3877 | @intCast(tuple_ty.structFieldOffset(0, mod)), |
| 3859 | 3878 | tuple_ty.structFieldType(0, mod), |
| 3860 | 3879 | partial_mcv, |
| 3880 | .{}, |
| 3861 | 3881 | ); |
| 3862 | 3882 | break :result .{ .load_frame = .{ .index = frame_index } }; |
| 3863 | 3883 | } |
| ... | ... | @@ -3912,7 +3932,7 @@ fn genSetFrameTruncatedOverflowCompare( |
| 3912 | 3932 | src_mcv.address().offset(int_info.bits / 64 * 8).deref() |
| 3913 | 3933 | else |
| 3914 | 3934 | src_mcv; |
| 3915 | | try self.genSetReg(scratch_reg, limb_ty, hi_limb_mcv); |
| 3935 | try self.genSetReg(scratch_reg, limb_ty, hi_limb_mcv, .{}); |
| 3916 | 3936 | try self.truncateRegister(hi_ty, scratch_reg); |
| 3917 | 3937 | try self.genBinOpMir(.{ ._, .cmp }, limb_ty, .{ .register = scratch_reg }, hi_limb_mcv); |
| 3918 | 3938 | |
| ... | ... | @@ -3928,18 +3948,26 @@ fn genSetFrameTruncatedOverflowCompare( |
| 3928 | 3948 | } |
| 3929 | 3949 | |
| 3930 | 3950 | const payload_off: i32 = @intCast(tuple_ty.structFieldOffset(0, mod)); |
| 3931 | | if (hi_limb_off > 0) try self.genSetMem(.{ .frame = frame_index }, payload_off, rest_ty, src_mcv); |
| 3951 | if (hi_limb_off > 0) try self.genSetMem( |
| 3952 | .{ .frame = frame_index }, |
| 3953 | payload_off, |
| 3954 | rest_ty, |
| 3955 | src_mcv, |
| 3956 | .{}, |
| 3957 | ); |
| 3932 | 3958 | try self.genSetMem( |
| 3933 | 3959 | .{ .frame = frame_index }, |
| 3934 | 3960 | payload_off + hi_limb_off, |
| 3935 | 3961 | limb_ty, |
| 3936 | 3962 | .{ .register = scratch_reg }, |
| 3963 | .{}, |
| 3937 | 3964 | ); |
| 3938 | 3965 | try self.genSetMem( |
| 3939 | 3966 | .{ .frame = frame_index }, |
| 3940 | 3967 | @intCast(tuple_ty.structFieldOffset(1, mod)), |
| 3941 | 3968 | tuple_ty.structFieldType(1, mod), |
| 3942 | 3969 | if (overflow_cc) |_| .{ .register = overflow_reg.to8() } else .{ .eflags = .ne }, |
| 3970 | .{}, |
| 3943 | 3971 | ); |
| 3944 | 3972 | } |
| 3945 | 3973 | |
| ... | ... | @@ -3967,6 +3995,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 3967 | 3995 | dst_mcv.address(), |
| 3968 | 3996 | .{ .immediate = 0 }, |
| 3969 | 3997 | .{ .immediate = tuple_ty.abiSize(mod) }, |
| 3998 | .{}, |
| 3970 | 3999 | ); |
| 3971 | 4000 | const lhs_mcv = try self.resolveInst(bin_op.lhs); |
| 3972 | 4001 | const rhs_mcv = try self.resolveInst(bin_op.rhs); |
| ... | ... | @@ -4122,6 +4151,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 4122 | 4151 | @intCast(tuple_ty.structFieldOffset(0, mod)), |
| 4123 | 4152 | tuple_ty.structFieldType(0, mod), |
| 4124 | 4153 | result, |
| 4154 | .{}, |
| 4125 | 4155 | ); |
| 4126 | 4156 | try self.asmMemoryImmediate( |
| 4127 | 4157 | .{ ._, .cmp }, |
| ... | ... | @@ -4133,6 +4163,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 4133 | 4163 | @intCast(tuple_ty.structFieldOffset(1, mod)), |
| 4134 | 4164 | tuple_ty.structFieldType(1, mod), |
| 4135 | 4165 | .{ .eflags = .ne }, |
| 4166 | .{}, |
| 4136 | 4167 | ); |
| 4137 | 4168 | try self.freeValue(overflow); |
| 4138 | 4169 | break :result dst_mcv; |
| ... | ... | @@ -4244,12 +4275,14 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 4244 | 4275 | @intCast(tuple_ty.structFieldOffset(0, mod)), |
| 4245 | 4276 | tuple_ty.structFieldType(0, mod), |
| 4246 | 4277 | .{ .register_pair = .{ .rax, .rdx } }, |
| 4278 | .{}, |
| 4247 | 4279 | ); |
| 4248 | 4280 | try self.genSetMem( |
| 4249 | 4281 | .{ .frame = dst_mcv.load_frame.index }, |
| 4250 | 4282 | @intCast(tuple_ty.structFieldOffset(1, mod)), |
| 4251 | 4283 | tuple_ty.structFieldType(1, mod), |
| 4252 | 4284 | .{ .register = tmp_regs[1] }, |
| 4285 | .{}, |
| 4253 | 4286 | ); |
| 4254 | 4287 | break :result dst_mcv; |
| 4255 | 4288 | }, |
| ... | ... | @@ -4297,12 +4330,14 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 4297 | 4330 | @intCast(tuple_ty.structFieldOffset(0, mod)), |
| 4298 | 4331 | tuple_ty.structFieldType(0, mod), |
| 4299 | 4332 | partial_mcv, |
| 4333 | .{}, |
| 4300 | 4334 | ); |
| 4301 | 4335 | try self.genSetMem( |
| 4302 | 4336 | .{ .frame = frame_index }, |
| 4303 | 4337 | @intCast(tuple_ty.structFieldOffset(1, mod)), |
| 4304 | 4338 | tuple_ty.structFieldType(1, mod), |
| 4305 | 4339 | .{ .immediate = 0 }, // cc being set is impossible |
| 4340 | .{}, |
| 4306 | 4341 | ); |
| 4307 | 4342 | } else try self.genSetFrameTruncatedOverflowCompare( |
| 4308 | 4343 | tuple_ty, |
| ... | ... | @@ -4330,7 +4365,7 @@ fn genIntMulDivOpMir(self: *Self, tag: Mir.Inst.FixedTag, ty: Type, lhs: MCValue |
| 4330 | 4365 | return self.fail("TODO implement genIntMulDivOpMir for ABI size larger than 8", .{}); |
| 4331 | 4366 | } |
| 4332 | 4367 | |
| 4333 | | try self.genSetReg(.rax, ty, lhs); |
| 4368 | try self.genSetReg(.rax, ty, lhs, .{}); |
| 4334 | 4369 | switch (tag[1]) { |
| 4335 | 4370 | else => unreachable, |
| 4336 | 4371 | .mul => {}, |
| ... | ... | @@ -4459,6 +4494,7 @@ fn airShlShrBinOp(self: *Self, inst: Air.Inst.Index) !void { |
| 4459 | 4494 | tmp_reg, |
| 4460 | 4495 | tmp_ty, |
| 4461 | 4496 | .{ .load_frame = .{ .index = frame_addr.index, .off = off } }, |
| 4497 | .{}, |
| 4462 | 4498 | ); |
| 4463 | 4499 | try self.truncateRegister(lhs_ty, tmp_reg); |
| 4464 | 4500 | try self.genSetMem( |
| ... | ... | @@ -4466,6 +4502,7 @@ fn airShlShrBinOp(self: *Self, inst: Air.Inst.Index) !void { |
| 4466 | 4502 | off, |
| 4467 | 4503 | tmp_ty, |
| 4468 | 4504 | .{ .register = tmp_reg }, |
| 4505 | .{}, |
| 4469 | 4506 | ); |
| 4470 | 4507 | }, |
| 4471 | 4508 | else => {}, |
| ... | ... | @@ -4726,7 +4763,7 @@ fn airOptionalPayload(self: *Self, inst: Air.Inst.Index) !void { |
| 4726 | 4763 | try self.genCopy(pl_ty, pl_mcv, switch (opt_mcv) { |
| 4727 | 4764 | else => opt_mcv, |
| 4728 | 4765 | .register_overflow => |ro| .{ .register = ro.reg }, |
| 4729 | | }); |
| 4766 | }, .{}); |
| 4730 | 4767 | break :result pl_mcv; |
| 4731 | 4768 | }; |
| 4732 | 4769 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| ... | ... | @@ -4773,7 +4810,13 @@ fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void { |
| 4773 | 4810 | |
| 4774 | 4811 | const pl_ty = dst_ty.childType(mod); |
| 4775 | 4812 | const pl_abi_size: i32 = @intCast(pl_ty.abiSize(mod)); |
| 4776 | | try self.genSetMem(.{ .reg = dst_mcv.getReg().? }, pl_abi_size, Type.bool, .{ .immediate = 1 }); |
| 4813 | try self.genSetMem( |
| 4814 | .{ .reg = dst_mcv.getReg().? }, |
| 4815 | pl_abi_size, |
| 4816 | Type.bool, |
| 4817 | .{ .immediate = 1 }, |
| 4818 | .{}, |
| 4819 | ); |
| 4777 | 4820 | break :result if (self.liveness.isUnused(inst)) .unreach else dst_mcv; |
| 4778 | 4821 | }; |
| 4779 | 4822 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| ... | ... | @@ -5039,7 +5082,7 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { |
| 5039 | 5082 | defer if (pl_lock) |lock| self.register_manager.unlockReg(lock); |
| 5040 | 5083 | |
| 5041 | 5084 | const opt_mcv = try self.allocRegOrMem(inst, true); |
| 5042 | | try self.genCopy(pl_ty, opt_mcv, pl_mcv); |
| 5085 | try self.genCopy(pl_ty, opt_mcv, pl_mcv, .{}); |
| 5043 | 5086 | |
| 5044 | 5087 | if (!same_repr) { |
| 5045 | 5088 | const pl_abi_size: i32 = @intCast(pl_ty.abiSize(mod)); |
| ... | ... | @@ -5089,8 +5132,8 @@ fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void { |
| 5089 | 5132 | const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(eu_ty, mod)); |
| 5090 | 5133 | const pl_off: i32 = @intCast(errUnionPayloadOffset(pl_ty, mod)); |
| 5091 | 5134 | const err_off: i32 = @intCast(errUnionErrorOffset(pl_ty, mod)); |
| 5092 | | try self.genSetMem(.{ .frame = frame_index }, pl_off, pl_ty, operand); |
| 5093 | | try self.genSetMem(.{ .frame = frame_index }, err_off, err_ty, .{ .immediate = 0 }); |
| 5135 | try self.genSetMem(.{ .frame = frame_index }, pl_off, pl_ty, operand, .{}); |
| 5136 | try self.genSetMem(.{ .frame = frame_index }, err_off, err_ty, .{ .immediate = 0 }, .{}); |
| 5094 | 5137 | break :result .{ .load_frame = .{ .index = frame_index } }; |
| 5095 | 5138 | }; |
| 5096 | 5139 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| ... | ... | @@ -5111,9 +5154,9 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void { |
| 5111 | 5154 | const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(eu_ty, mod)); |
| 5112 | 5155 | const pl_off: i32 = @intCast(errUnionPayloadOffset(pl_ty, mod)); |
| 5113 | 5156 | const err_off: i32 = @intCast(errUnionErrorOffset(pl_ty, mod)); |
| 5114 | | try self.genSetMem(.{ .frame = frame_index }, pl_off, pl_ty, .undef); |
| 5157 | try self.genSetMem(.{ .frame = frame_index }, pl_off, pl_ty, .undef, .{}); |
| 5115 | 5158 | const operand = try self.resolveInst(ty_op.operand); |
| 5116 | | try self.genSetMem(.{ .frame = frame_index }, err_off, err_ty, operand); |
| 5159 | try self.genSetMem(.{ .frame = frame_index }, err_off, err_ty, operand, .{}); |
| 5117 | 5160 | break :result .{ .load_frame = .{ .index = frame_index } }; |
| 5118 | 5161 | }; |
| 5119 | 5162 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| ... | ... | @@ -5127,7 +5170,7 @@ fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void { |
| 5127 | 5170 | |
| 5128 | 5171 | const dst_mcv = try self.allocRegOrMem(inst, true); |
| 5129 | 5172 | const dst_ty = self.typeOfIndex(inst); |
| 5130 | | try self.genCopy(dst_ty, dst_mcv, src_mcv); |
| 5173 | try self.genCopy(dst_ty, dst_mcv, src_mcv, .{}); |
| 5131 | 5174 | break :result dst_mcv; |
| 5132 | 5175 | }; |
| 5133 | 5176 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| ... | ... | @@ -5147,7 +5190,7 @@ fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void { |
| 5147 | 5190 | if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result len_mcv; |
| 5148 | 5191 | |
| 5149 | 5192 | const dst_mcv = try self.allocRegOrMem(inst, true); |
| 5150 | | try self.genCopy(Type.usize, dst_mcv, len_mcv); |
| 5193 | try self.genCopy(Type.usize, dst_mcv, len_mcv, .{}); |
| 5151 | 5194 | break :result dst_mcv; |
| 5152 | 5195 | }, |
| 5153 | 5196 | else => return self.fail("TODO implement slice_len for {}", .{src_mcv}), |
| ... | ... | @@ -5211,7 +5254,7 @@ fn elemOffset(self: *Self, index_ty: Type, index: MCValue, elem_size: u64) !Regi |
| 5211 | 5254 | // Optimisation: if index MCValue is an immediate, we can multiply in `comptime` |
| 5212 | 5255 | // and set the register directly to the scaled offset as an immediate. |
| 5213 | 5256 | const reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp); |
| 5214 | | try self.genSetReg(reg, index_ty, .{ .immediate = imm * elem_size }); |
| 5257 | try self.genSetReg(reg, index_ty, .{ .immediate = imm * elem_size }, .{}); |
| 5215 | 5258 | break :blk reg; |
| 5216 | 5259 | }, |
| 5217 | 5260 | else => { |
| ... | ... | @@ -5251,7 +5294,7 @@ fn genSliceElemPtr(self: *Self, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue { |
| 5251 | 5294 | defer self.register_manager.unlockReg(offset_reg_lock); |
| 5252 | 5295 | |
| 5253 | 5296 | const addr_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp); |
| 5254 | | try self.genSetReg(addr_reg, Type.usize, slice_mcv); |
| 5297 | try self.genSetReg(addr_reg, Type.usize, slice_mcv, .{}); |
| 5255 | 5298 | // TODO we could allocate register here, but need to expect addr register and potentially |
| 5256 | 5299 | // offset register. |
| 5257 | 5300 | try self.genBinOpMir(.{ ._, .add }, slice_ptr_field_type, .{ .register = addr_reg }, .{ |
| ... | ... | @@ -5353,7 +5396,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 5353 | 5396 | switch (array_mcv) { |
| 5354 | 5397 | .register => { |
| 5355 | 5398 | const frame_index = try self.allocFrameIndex(FrameAlloc.initType(array_ty, mod)); |
| 5356 | | try self.genSetMem(.{ .frame = frame_index }, 0, array_ty, array_mcv); |
| 5399 | try self.genSetMem(.{ .frame = frame_index }, 0, array_ty, array_mcv, .{}); |
| 5357 | 5400 | try self.asmRegisterMemory( |
| 5358 | 5401 | .{ ._, .lea }, |
| 5359 | 5402 | addr_reg, |
| ... | ... | @@ -5373,7 +5416,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 5373 | 5416 | .load_direct, |
| 5374 | 5417 | .load_got, |
| 5375 | 5418 | .load_tlv, |
| 5376 | | => try self.genSetReg(addr_reg, Type.usize, array_mcv.address()), |
| 5419 | => try self.genSetReg(addr_reg, Type.usize, array_mcv.address(), .{}), |
| 5377 | 5420 | .lea_symbol, .lea_direct, .lea_tlv => unreachable, |
| 5378 | 5421 | else => return self.fail("TODO airArrayElemVal_val for {s} of {}", .{ |
| 5379 | 5422 | @tagName(array_mcv), array_ty.fmt(mod), |
| ... | ... | @@ -5393,7 +5436,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 5393 | 5436 | .{ .register = addr_reg }, |
| 5394 | 5437 | .{ .register = offset_reg }, |
| 5395 | 5438 | ); |
| 5396 | | try self.genCopy(elem_ty, dst_mcv, .{ .indirect = .{ .reg = addr_reg } }); |
| 5439 | try self.genCopy(elem_ty, dst_mcv, .{ .indirect = .{ .reg = addr_reg } }, .{}); |
| 5397 | 5440 | break :result dst_mcv; |
| 5398 | 5441 | }; |
| 5399 | 5442 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| ... | ... | @@ -5533,7 +5576,7 @@ fn airSetUnionTag(self: *Self, inst: Air.Inst.Index) !void { |
| 5533 | 5576 | } else ptr; |
| 5534 | 5577 | |
| 5535 | 5578 | const ptr_tag_ty = try mod.adjustPtrTypeChild(ptr_union_ty, tag_ty); |
| 5536 | | try self.store(ptr_tag_ty, adjusted_ptr, tag); |
| 5579 | try self.store(ptr_tag_ty, adjusted_ptr, tag, .{}); |
| 5537 | 5580 | |
| 5538 | 5581 | return self.finishAir(inst, .none, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 5539 | 5582 | } |
| ... | ... | @@ -5743,7 +5786,7 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void { |
| 5743 | 5786 | registerAlias(dst_reg, cmov_abi_size), |
| 5744 | 5787 | ); |
| 5745 | 5788 | |
| 5746 | | try self.genSetReg(dst_reg, dst_ty, .{ .immediate = src_bits - 1 }); |
| 5789 | try self.genSetReg(dst_reg, dst_ty, .{ .immediate = src_bits - 1 }, .{}); |
| 5747 | 5790 | try self.genBinOpMir(.{ ._, .sub }, dst_ty, dst_mcv, .{ .register = imm_reg }); |
| 5748 | 5791 | } |
| 5749 | 5792 | break :result dst_mcv; |
| ... | ... | @@ -5798,7 +5841,7 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void { |
| 5798 | 5841 | const tmp_mcv = tmp: { |
| 5799 | 5842 | if (src_mcv.isImmediate() or self.liveness.operandDies(inst, 0)) |
| 5800 | 5843 | break :tmp src_mcv; |
| 5801 | | try self.genSetReg(dst_reg, wide_ty, src_mcv); |
| 5844 | try self.genSetReg(dst_reg, wide_ty, src_mcv, .{}); |
| 5802 | 5845 | break :tmp dst_mcv; |
| 5803 | 5846 | }; |
| 5804 | 5847 | try self.genBinOpMir( |
| ... | ... | @@ -5826,7 +5869,7 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void { |
| 5826 | 5869 | else |
| 5827 | 5870 | .{ .register = mat_src_mcv.register_pair[1] }; |
| 5828 | 5871 | const masked_mcv = if (src_bits < 128) masked: { |
| 5829 | | try self.genCopy(Type.u64, dst_mcv, hi_mat_src_mcv); |
| 5872 | try self.genCopy(Type.u64, dst_mcv, hi_mat_src_mcv, .{}); |
| 5830 | 5873 | try self.genBinOpMir( |
| 5831 | 5874 | .{ ._, .@"or" }, |
| 5832 | 5875 | Type.u64, |
| ... | ... | @@ -5941,7 +5984,7 @@ fn genPopCount( |
| 5941 | 5984 | if (src_abi_size > 1) src_ty else Type.u32, |
| 5942 | 5985 | .{ .register = dst_reg }, |
| 5943 | 5986 | if (src_abi_size > 1) src_mcv else src: { |
| 5944 | | if (!dst_contains_src) try self.genSetReg(dst_reg, src_ty, src_mcv); |
| 5987 | if (!dst_contains_src) try self.genSetReg(dst_reg, src_ty, src_mcv, .{}); |
| 5945 | 5988 | try self.truncateRegister(try src_ty.toUnsigned(mod), dst_reg); |
| 5946 | 5989 | break :src .{ .register = dst_reg }; |
| 5947 | 5990 | }, |
| ... | ... | @@ -5964,7 +6007,7 @@ fn genPopCount( |
| 5964 | 6007 | else |
| 5965 | 6008 | undefined; |
| 5966 | 6009 | |
| 5967 | | if (!dst_contains_src) try self.genSetReg(dst, src_ty, src_mcv); |
| 6010 | if (!dst_contains_src) try self.genSetReg(dst, src_ty, src_mcv, .{}); |
| 5968 | 6011 | // dst = operand |
| 5969 | 6012 | try self.asmRegisterRegister(.{ ._, .mov }, tmp, dst); |
| 5970 | 6013 | // tmp = operand |
| ... | ... | @@ -6102,7 +6145,7 @@ fn genByteSwap( |
| 6102 | 6145 | const dst_lock = self.register_manager.lockRegAssumeUnused(dst_mcv.register); |
| 6103 | 6146 | defer self.register_manager.unlockReg(dst_lock); |
| 6104 | 6147 | |
| 6105 | | try self.genSetReg(dst_reg, src_ty, src_mcv); |
| 6148 | try self.genSetReg(dst_reg, src_ty, src_mcv, .{}); |
| 6106 | 6149 | switch (abi_size) { |
| 6107 | 6150 | else => unreachable, |
| 6108 | 6151 | 2 => try self.genBinOpMir(.{ ._l, .ro }, src_ty, dst_mcv, .{ .immediate = 8 }), |
| ... | ... | @@ -6275,7 +6318,7 @@ fn floatSign(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, ty: Type) |
| 6275 | 6318 | if (!std.meta.eql(src_mcv, dst_mcv) or !self.reuseOperand(inst, operand, 0, src_mcv)) |
| 6276 | 6319 | try self.register_manager.getReg(.st0, inst); |
| 6277 | 6320 | |
| 6278 | | try self.genCopy(ty, dst_mcv, src_mcv); |
| 6321 | try self.genCopy(ty, dst_mcv, src_mcv, .{}); |
| 6279 | 6322 | switch (tag) { |
| 6280 | 6323 | .neg => try self.asmOpOnly(.{ .f_, .chs }), |
| 6281 | 6324 | .abs => try self.asmOpOnly(.{ .f_, .abs }), |
| ... | ... | @@ -6492,7 +6535,7 @@ fn genRound(self: *Self, ty: Type, dst_reg: Register, src_mcv: MCValue, mode: Ro |
| 6492 | 6535 | const mod = self.bin_file.comp.module.?; |
| 6493 | 6536 | const mir_tag = self.getRoundTag(ty) orelse { |
| 6494 | 6537 | const result = try self.genRoundLibcall(ty, src_mcv, mode); |
| 6495 | | return self.genSetReg(dst_reg, ty, result); |
| 6538 | return self.genSetReg(dst_reg, ty, result, .{}); |
| 6496 | 6539 | }; |
| 6497 | 6540 | const abi_size: u32 = @intCast(ty.abiSize(mod)); |
| 6498 | 6541 | const dst_alias = registerAlias(dst_reg, abi_size); |
| ... | ... | @@ -6583,7 +6626,7 @@ fn airAbs(self: *Self, inst: Air.Inst.Index) !void { |
| 6583 | 6626 | const dst_locks = self.register_manager.lockRegsAssumeUnused(2, dst_regs); |
| 6584 | 6627 | defer for (dst_locks) |lock| self.register_manager.unlockReg(lock); |
| 6585 | 6628 | |
| 6586 | | try self.genCopy(ty, dst_mcv, src_mcv); |
| 6629 | try self.genCopy(ty, dst_mcv, src_mcv, .{}); |
| 6587 | 6630 | break :dst dst_mcv; |
| 6588 | 6631 | }; |
| 6589 | 6632 | const dst_regs = dst_mcv.register_pair; |
| ... | ... | @@ -6940,9 +6983,9 @@ fn packedLoad(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) Inn |
| 6940 | 6983 | defer self.register_manager.unlockReg(tmp_lock); |
| 6941 | 6984 | |
| 6942 | 6985 | const hi_mcv = dst_mcv.address().offset(@intCast(val_bit_size / 64 * 8)).deref(); |
| 6943 | | try self.genSetReg(tmp_reg, Type.usize, hi_mcv); |
| 6986 | try self.genSetReg(tmp_reg, Type.usize, hi_mcv, .{}); |
| 6944 | 6987 | try self.truncateRegister(val_ty, tmp_reg); |
| 6945 | | try self.genCopy(Type.usize, hi_mcv, .{ .register = tmp_reg }); |
| 6988 | try self.genCopy(Type.usize, hi_mcv, .{ .register = tmp_reg }, .{}); |
| 6946 | 6989 | } |
| 6947 | 6990 | } |
| 6948 | 6991 | return; |
| ... | ... | @@ -7011,7 +7054,7 @@ fn packedLoad(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) Inn |
| 7011 | 7054 | } |
| 7012 | 7055 | |
| 7013 | 7056 | if (val_extra_bits > 0) try self.truncateRegister(val_ty, dst_reg); |
| 7014 | | try self.genCopy(val_ty, dst_mcv, .{ .register = dst_reg }); |
| 7057 | try self.genCopy(val_ty, dst_mcv, .{ .register = dst_reg }, .{}); |
| 7015 | 7058 | } |
| 7016 | 7059 | |
| 7017 | 7060 | fn load(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) InnerError!void { |
| ... | ... | @@ -7036,7 +7079,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) InnerErro |
| 7036 | 7079 | .lea_got, |
| 7037 | 7080 | .lea_tlv, |
| 7038 | 7081 | .lea_frame, |
| 7039 | | => try self.genCopy(dst_ty, dst_mcv, ptr_mcv.deref()), |
| 7082 | => try self.genCopy(dst_ty, dst_mcv, ptr_mcv.deref(), .{}), |
| 7040 | 7083 | .memory, |
| 7041 | 7084 | .indirect, |
| 7042 | 7085 | .load_symbol, |
| ... | ... | @@ -7049,7 +7092,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) InnerErro |
| 7049 | 7092 | const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg); |
| 7050 | 7093 | defer self.register_manager.unlockReg(addr_lock); |
| 7051 | 7094 | |
| 7052 | | try self.genCopy(dst_ty, dst_mcv, .{ .indirect = .{ .reg = addr_reg } }); |
| 7095 | try self.genCopy(dst_ty, dst_mcv, .{ .indirect = .{ .reg = addr_reg } }, .{}); |
| 7053 | 7096 | }, |
| 7054 | 7097 | .air_ref => |ptr_ref| try self.load(dst_mcv, ptr_ty, try self.resolveInst(ptr_ref)), |
| 7055 | 7098 | } |
| ... | ... | @@ -7105,6 +7148,7 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 7105 | 7148 | if (elem_size <= 8) elem_ty else Type.usize, |
| 7106 | 7149 | high_mcv, |
| 7107 | 7150 | .{ .register = high_reg }, |
| 7151 | .{}, |
| 7108 | 7152 | ); |
| 7109 | 7153 | } |
| 7110 | 7154 | break :result dst_mcv; |
| ... | ... | @@ -7167,7 +7211,7 @@ fn packedStore(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) In |
| 7167 | 7211 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| 7168 | 7212 | defer self.register_manager.unlockReg(tmp_lock); |
| 7169 | 7213 | |
| 7170 | | try self.genSetReg(tmp_reg, limb_ty, src_mcv); |
| 7214 | try self.genSetReg(tmp_reg, limb_ty, src_mcv, .{}); |
| 7171 | 7215 | switch (limb_i) { |
| 7172 | 7216 | 0 => try self.genShiftBinOpMir( |
| 7173 | 7217 | .{ ._l, .sh }, |
| ... | ... | @@ -7198,7 +7242,7 @@ fn packedStore(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) In |
| 7198 | 7242 | try self.genSetReg(tmp_reg, limb_ty, switch (limb_i) { |
| 7199 | 7243 | 0 => src_mcv, |
| 7200 | 7244 | else => src_mcv.address().offset(limb_i * limb_abi_size).deref(), |
| 7201 | | }); |
| 7245 | }, .{}); |
| 7202 | 7246 | try self.genBinOpMir(.{ ._, .@"and" }, limb_ty, tmp_mcv, .{ .immediate = part_mask }); |
| 7203 | 7247 | try self.asmMemoryRegister( |
| 7204 | 7248 | .{ ._, .@"or" }, |
| ... | ... | @@ -7209,7 +7253,13 @@ fn packedStore(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) In |
| 7209 | 7253 | } |
| 7210 | 7254 | } |
| 7211 | 7255 | |
| 7212 | | fn store(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) InnerError!void { |
| 7256 | fn store( |
| 7257 | self: *Self, |
| 7258 | ptr_ty: Type, |
| 7259 | ptr_mcv: MCValue, |
| 7260 | src_mcv: MCValue, |
| 7261 | opts: CopyOptions, |
| 7262 | ) InnerError!void { |
| 7213 | 7263 | const mod = self.bin_file.comp.module.?; |
| 7214 | 7264 | const src_ty = ptr_ty.childType(mod); |
| 7215 | 7265 | if (!src_ty.hasRuntimeBitsIgnoreComptime(mod)) return; |
| ... | ... | @@ -7231,7 +7281,7 @@ fn store(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) InnerErr |
| 7231 | 7281 | .lea_got, |
| 7232 | 7282 | .lea_tlv, |
| 7233 | 7283 | .lea_frame, |
| 7234 | | => try self.genCopy(src_ty, ptr_mcv.deref(), src_mcv), |
| 7284 | => try self.genCopy(src_ty, ptr_mcv.deref(), src_mcv, opts), |
| 7235 | 7285 | .memory, |
| 7236 | 7286 | .indirect, |
| 7237 | 7287 | .load_symbol, |
| ... | ... | @@ -7244,9 +7294,9 @@ fn store(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) InnerErr |
| 7244 | 7294 | const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg); |
| 7245 | 7295 | defer self.register_manager.unlockReg(addr_lock); |
| 7246 | 7296 | |
| 7247 | | try self.genCopy(src_ty, .{ .indirect = .{ .reg = addr_reg } }, src_mcv); |
| 7297 | try self.genCopy(src_ty, .{ .indirect = .{ .reg = addr_reg } }, src_mcv, opts); |
| 7248 | 7298 | }, |
| 7249 | | .air_ref => |ptr_ref| try self.store(ptr_ty, try self.resolveInst(ptr_ref), src_mcv), |
| 7299 | .air_ref => |ptr_ref| try self.store(ptr_ty, try self.resolveInst(ptr_ref), src_mcv, opts), |
| 7250 | 7300 | } |
| 7251 | 7301 | } |
| 7252 | 7302 | |
| ... | ... | @@ -7269,7 +7319,7 @@ fn airStore(self: *Self, inst: Air.Inst.Index, safety: bool) !void { |
| 7269 | 7319 | if (ptr_info.flags.vector_index != .none or ptr_info.packed_offset.host_size > 0) { |
| 7270 | 7320 | try self.packedStore(ptr_ty, ptr_mcv, src_mcv); |
| 7271 | 7321 | } else { |
| 7272 | | try self.store(ptr_ty, ptr_mcv, src_mcv); |
| 7322 | try self.store(ptr_ty, ptr_mcv, src_mcv, .{ .safety = safety }); |
| 7273 | 7323 | } |
| 7274 | 7324 | } |
| 7275 | 7325 | return self.finishAir(inst, .none, .{ bin_op.lhs, bin_op.rhs, .none }); |
| ... | ... | @@ -7389,7 +7439,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 7389 | 7439 | const dst_locks = self.register_manager.lockRegsAssumeUnused(2, dst_regs); |
| 7390 | 7440 | defer for (dst_locks) |lock| self.register_manager.unlockReg(lock); |
| 7391 | 7441 | |
| 7392 | | try self.genCopy(container_ty, .{ .register_pair = dst_regs }, src_mcv); |
| 7442 | try self.genCopy(container_ty, .{ .register_pair = dst_regs }, src_mcv, .{}); |
| 7393 | 7443 | break :dst dst_regs; |
| 7394 | 7444 | }; |
| 7395 | 7445 | const dst_mcv = MCValue{ .register_pair = dst_regs }; |
| ... | ... | @@ -7493,7 +7543,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 7493 | 7543 | const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg); |
| 7494 | 7544 | defer self.register_manager.unlockReg(dst_lock); |
| 7495 | 7545 | |
| 7496 | | try self.genCopy(int_ty, dst_mcv, off_mcv); |
| 7546 | try self.genCopy(int_ty, dst_mcv, off_mcv, .{}); |
| 7497 | 7547 | if (self.regExtraBits(field_ty) > 0) try self.truncateRegister(int_ty, dst_reg); |
| 7498 | 7548 | break :result if (field_is_gp) |
| 7499 | 7549 | dst_mcv |
| ... | ... | @@ -7507,7 +7557,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 7507 | 7557 | off_mcv |
| 7508 | 7558 | else dst: { |
| 7509 | 7559 | const dst_mcv = try self.allocRegOrMem(inst, true); |
| 7510 | | try self.genCopy(field_ty, dst_mcv, off_mcv); |
| 7560 | try self.genCopy(field_ty, dst_mcv, off_mcv, .{}); |
| 7511 | 7561 | break :dst dst_mcv; |
| 7512 | 7562 | }; |
| 7513 | 7563 | if (field_abi_size * 8 > field_bit_size and dst_mcv.isMemory()) { |
| ... | ... | @@ -7517,9 +7567,9 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 7517 | 7567 | |
| 7518 | 7568 | const hi_mcv = |
| 7519 | 7569 | dst_mcv.address().offset(@intCast(field_bit_size / 64 * 8)).deref(); |
| 7520 | | try self.genSetReg(tmp_reg, Type.usize, hi_mcv); |
| 7570 | try self.genSetReg(tmp_reg, Type.usize, hi_mcv, .{}); |
| 7521 | 7571 | try self.truncateRegister(field_ty, tmp_reg); |
| 7522 | | try self.genCopy(Type.usize, hi_mcv, .{ .register = tmp_reg }); |
| 7572 | try self.genCopy(Type.usize, hi_mcv, .{ .register = tmp_reg }, .{}); |
| 7523 | 7573 | } |
| 7524 | 7574 | break :result dst_mcv; |
| 7525 | 7575 | } |
| ... | ... | @@ -7650,7 +7700,7 @@ fn genUnOp(self: *Self, maybe_inst: ?Air.Inst.Index, tag: Air.Inst.Tag, src_air: |
| 7650 | 7700 | if (maybe_inst) |inst| if (self.reuseOperand(inst, src_air, 0, src_mcv)) break :dst src_mcv; |
| 7651 | 7701 | |
| 7652 | 7702 | const dst_mcv = try self.allocRegOrMemAdvanced(src_ty, maybe_inst, true); |
| 7653 | | try self.genCopy(src_ty, dst_mcv, src_mcv); |
| 7703 | try self.genCopy(src_ty, dst_mcv, src_mcv, .{}); |
| 7654 | 7704 | break :dst dst_mcv; |
| 7655 | 7705 | }; |
| 7656 | 7706 | const dst_lock = switch (dst_mcv) { |
| ... | ... | @@ -7697,9 +7747,9 @@ fn genUnOp(self: *Self, maybe_inst: ?Air.Inst.Index, tag: Air.Inst.Tag, src_air: |
| 7697 | 7747 | defer self.register_manager.unlockReg(tmp_lock); |
| 7698 | 7748 | |
| 7699 | 7749 | const hi_mcv = dst_mcv.address().offset(@intCast(bit_size / 64 * 8)).deref(); |
| 7700 | | try self.genSetReg(tmp_reg, Type.usize, hi_mcv); |
| 7750 | try self.genSetReg(tmp_reg, Type.usize, hi_mcv, .{}); |
| 7701 | 7751 | try self.truncateRegister(src_ty, tmp_reg); |
| 7702 | | try self.genCopy(Type.usize, hi_mcv, .{ .register = tmp_reg }); |
| 7752 | try self.genCopy(Type.usize, hi_mcv, .{ .register = tmp_reg }, .{}); |
| 7703 | 7753 | } |
| 7704 | 7754 | } |
| 7705 | 7755 | }, |
| ... | ... | @@ -7736,7 +7786,7 @@ fn genUnOpMir(self: *Self, mir_tag: Mir.Inst.FixedTag, dst_ty: Type, dst_mcv: MC |
| 7736 | 7786 | const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg); |
| 7737 | 7787 | defer self.register_manager.unlockReg(addr_reg_lock); |
| 7738 | 7788 | |
| 7739 | | try self.genSetReg(addr_reg, Type.usize, dst_mcv.address()); |
| 7789 | try self.genSetReg(addr_reg, Type.usize, dst_mcv.address(), .{}); |
| 7740 | 7790 | try self.asmMemory(mir_tag, .{ .base = .{ .reg = addr_reg }, .mod = .{ .rm = .{ |
| 7741 | 7791 | .size = Memory.Size.fromSize(abi_size), |
| 7742 | 7792 | } } }); |
| ... | ... | @@ -7767,7 +7817,7 @@ fn genShiftBinOpMir( |
| 7767 | 7817 | else => {}, |
| 7768 | 7818 | } |
| 7769 | 7819 | self.register_manager.getRegAssumeFree(.rcx, null); |
| 7770 | | try self.genSetReg(.cl, Type.u8, shift_mcv); |
| 7820 | try self.genSetReg(.cl, Type.u8, shift_mcv, .{}); |
| 7771 | 7821 | break :rhs .{ .register = .rcx }; |
| 7772 | 7822 | }; |
| 7773 | 7823 | |
| ... | ... | @@ -8161,7 +8211,7 @@ fn genShiftBinOp( |
| 8161 | 8211 | if (self.reuseOperand(inst, bin_op.lhs, 0, lhs_mcv)) break :dst lhs_mcv; |
| 8162 | 8212 | } |
| 8163 | 8213 | const dst_mcv = try self.allocRegOrMemAdvanced(lhs_ty, maybe_inst, true); |
| 8164 | | try self.genCopy(lhs_ty, dst_mcv, lhs_mcv); |
| 8214 | try self.genCopy(lhs_ty, dst_mcv, lhs_mcv, .{}); |
| 8165 | 8215 | break :dst dst_mcv; |
| 8166 | 8216 | }; |
| 8167 | 8217 | |
| ... | ... | @@ -8290,6 +8340,7 @@ fn genMulDivBinOp( |
| 8290 | 8340 | dst_mcv.address(), |
| 8291 | 8341 | .{ .immediate = 0 }, |
| 8292 | 8342 | .{ .immediate = src_abi_size }, |
| 8343 | .{}, |
| 8293 | 8344 | ); |
| 8294 | 8345 | |
| 8295 | 8346 | const temp_regs = try self.register_manager.allocRegs( |
| ... | ... | @@ -8891,7 +8942,7 @@ fn genBinOp( |
| 8891 | 8942 | if (sse_op and lhs_mcv.isRegister() and self.hasFeature(.avx)) |
| 8892 | 8943 | copied_to_dst = false |
| 8893 | 8944 | else |
| 8894 | | try self.genCopy(lhs_ty, dst_mcv, lhs_mcv); |
| 8945 | try self.genCopy(lhs_ty, dst_mcv, lhs_mcv, .{}); |
| 8895 | 8946 | rhs_mcv = try self.resolveInst(ordered_air[1]); |
| 8896 | 8947 | break :dst dst_mcv; |
| 8897 | 8948 | }; |
| ... | ... | @@ -8906,7 +8957,7 @@ fn genBinOp( |
| 8906 | 8957 | const src_mcv: MCValue = if (maybe_mask_reg) |mask_reg| |
| 8907 | 8958 | if (self.hasFeature(.avx) and unmat_src_mcv.isRegister() and maybe_inst != null and |
| 8908 | 8959 | self.liveness.operandDies(maybe_inst.?, if (flipped) 0 else 1)) unmat_src_mcv else src: { |
| 8909 | | try self.genSetReg(mask_reg, rhs_ty, unmat_src_mcv); |
| 8960 | try self.genSetReg(mask_reg, rhs_ty, unmat_src_mcv, .{}); |
| 8910 | 8961 | break :src .{ .register = mask_reg }; |
| 8911 | 8962 | } |
| 8912 | 8963 | else |
| ... | ... | @@ -8981,7 +9032,7 @@ fn genBinOp( |
| 8981 | 9032 | defer for (dst_regs_locks) |dst_lock| if (dst_lock) |lock| |
| 8982 | 9033 | self.register_manager.unlockReg(lock); |
| 8983 | 9034 | |
| 8984 | | try self.genCopy(lhs_ty, .{ .register_pair = dst_regs }, dst_mcv); |
| 9035 | try self.genCopy(lhs_ty, .{ .register_pair = dst_regs }, dst_mcv, .{}); |
| 8985 | 9036 | break :dst dst_regs; |
| 8986 | 9037 | }, |
| 8987 | 9038 | }; |
| ... | ... | @@ -9036,7 +9087,7 @@ fn genBinOp( |
| 9036 | 9087 | try self.asmCmovccRegisterRegister(cc, dst_regs[0], src_mcv.register_pair[0]); |
| 9037 | 9088 | try self.asmCmovccRegisterRegister(cc, dst_regs[1], src_mcv.register_pair[1]); |
| 9038 | 9089 | } |
| 9039 | | try self.genCopy(lhs_ty, dst_mcv, .{ .register_pair = dst_regs }); |
| 9090 | try self.genCopy(lhs_ty, dst_mcv, .{ .register_pair = dst_regs }, .{}); |
| 9040 | 9091 | } else { |
| 9041 | 9092 | const mat_src_mcv: MCValue = if (switch (resolved_src_mcv) { |
| 9042 | 9093 | .immediate, |
| ... | ... | @@ -9146,7 +9197,7 @@ fn genBinOp( |
| 9146 | 9197 | }, |
| 9147 | 9198 | ), |
| 9148 | 9199 | } |
| 9149 | | try self.genCopy(lhs_ty, dst_mcv, .{ .register = tmp_reg }); |
| 9200 | try self.genCopy(lhs_ty, dst_mcv, .{ .register = tmp_reg }, .{}); |
| 9150 | 9201 | } |
| 9151 | 9202 | }, |
| 9152 | 9203 | |
| ... | ... | @@ -10519,7 +10570,7 @@ fn genBinOpMir( |
| 10519 | 10570 | const dst_addr_lock = self.register_manager.lockRegAssumeUnused(dst_addr_reg); |
| 10520 | 10571 | errdefer self.register_manager.unlockReg(dst_addr_lock); |
| 10521 | 10572 | |
| 10522 | | try self.genSetReg(dst_addr_reg, Type.usize, dst_mcv.address()); |
| 10573 | try self.genSetReg(dst_addr_reg, Type.usize, dst_mcv.address(), .{}); |
| 10523 | 10574 | break :dst .{ .addr_reg = dst_addr_reg, .addr_lock = dst_addr_lock }; |
| 10524 | 10575 | }, |
| 10525 | 10576 | .load_frame => null, |
| ... | ... | @@ -10566,7 +10617,7 @@ fn genBinOpMir( |
| 10566 | 10617 | const src_addr_lock = self.register_manager.lockRegAssumeUnused(src_addr_reg); |
| 10567 | 10618 | errdefer self.register_manager.unlockReg(src_addr_lock); |
| 10568 | 10619 | |
| 10569 | | try self.genSetReg(src_addr_reg, Type.usize, resolved_src_mcv.address()); |
| 10620 | try self.genSetReg(src_addr_reg, Type.usize, resolved_src_mcv.address(), .{}); |
| 10570 | 10621 | break :src .{ .addr_reg = src_addr_reg, .addr_lock = src_addr_lock }; |
| 10571 | 10622 | }, |
| 10572 | 10623 | }; |
| ... | ... | @@ -10867,7 +10918,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M |
| 10867 | 10918 | defer self.register_manager.unlockReg(tmp_lock); |
| 10868 | 10919 | |
| 10869 | 10920 | try self.genIntMulComplexOpMir(dst_ty, tmp_mcv, src_mcv); |
| 10870 | | try self.genCopy(dst_ty, dst_mcv, tmp_mcv); |
| 10921 | try self.genCopy(dst_ty, dst_mcv, tmp_mcv, .{}); |
| 10871 | 10922 | }, |
| 10872 | 10923 | } |
| 10873 | 10924 | } |
| ... | ... | @@ -10890,7 +10941,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { |
| 10890 | 10941 | .indirect => |reg_off| dst: { |
| 10891 | 10942 | self.register_manager.getRegAssumeFree(reg_off.reg, inst); |
| 10892 | 10943 | const dst_mcv = try self.allocRegOrMem(inst, false); |
| 10893 | | try self.genCopy(arg_ty, dst_mcv, src_mcv); |
| 10944 | try self.genCopy(arg_ty, dst_mcv, src_mcv, .{}); |
| 10894 | 10945 | break :dst dst_mcv; |
| 10895 | 10946 | }, |
| 10896 | 10947 | else => return self.fail("TODO implement arg for {}", .{src_mcv}), |
| ... | ... | @@ -10998,13 +11049,13 @@ fn airBreakpoint(self: *Self) !void { |
| 10998 | 11049 | |
| 10999 | 11050 | fn airRetAddr(self: *Self, inst: Air.Inst.Index) !void { |
| 11000 | 11051 | const dst_mcv = try self.allocRegOrMem(inst, true); |
| 11001 | | try self.genCopy(Type.usize, dst_mcv, .{ .load_frame = .{ .index = .ret_addr } }); |
| 11052 | try self.genCopy(Type.usize, dst_mcv, .{ .load_frame = .{ .index = .ret_addr } }, .{}); |
| 11002 | 11053 | return self.finishAir(inst, dst_mcv, .{ .none, .none, .none }); |
| 11003 | 11054 | } |
| 11004 | 11055 | |
| 11005 | 11056 | fn airFrameAddress(self: *Self, inst: Air.Inst.Index) !void { |
| 11006 | 11057 | const dst_mcv = try self.allocRegOrMem(inst, true); |
| 11007 | | try self.genCopy(Type.usize, dst_mcv, .{ .lea_frame = .{ .index = .base_ptr } }); |
| 11058 | try self.genCopy(Type.usize, dst_mcv, .{ .lea_frame = .{ .index = .base_ptr } }, .{}); |
| 11008 | 11059 | return self.finishAir(inst, dst_mcv, .{ .none, .none, .none }); |
| 11009 | 11060 | } |
| 11010 | 11061 | |
| ... | ... | @@ -11143,12 +11194,12 @@ fn genCall(self: *Self, info: union(enum) { |
| 11143 | 11194 | }, |
| 11144 | 11195 | .indirect => |reg_off| { |
| 11145 | 11196 | frame_index.* = try self.allocFrameIndex(FrameAlloc.initType(arg_ty, mod)); |
| 11146 | | try self.genSetMem(.{ .frame = frame_index.* }, 0, arg_ty, src_arg); |
| 11197 | try self.genSetMem(.{ .frame = frame_index.* }, 0, arg_ty, src_arg, .{}); |
| 11147 | 11198 | try self.register_manager.getReg(reg_off.reg, null); |
| 11148 | 11199 | try reg_locks.append(self.register_manager.lockReg(reg_off.reg)); |
| 11149 | 11200 | }, |
| 11150 | 11201 | .load_frame => { |
| 11151 | | try self.genCopy(arg_ty, dst_arg, src_arg); |
| 11202 | try self.genCopy(arg_ty, dst_arg, src_arg, .{}); |
| 11152 | 11203 | try self.freeValue(src_arg); |
| 11153 | 11204 | }, |
| 11154 | 11205 | else => unreachable, |
| ... | ... | @@ -11162,7 +11213,7 @@ fn genCall(self: *Self, info: union(enum) { |
| 11162 | 11213 | const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(ret_ty, mod)); |
| 11163 | 11214 | try self.genSetReg(reg_off.reg, Type.usize, .{ |
| 11164 | 11215 | .lea_frame = .{ .index = frame_index, .off = -reg_off.off }, |
| 11165 | | }); |
| 11216 | }, .{}); |
| 11166 | 11217 | call_info.return_value.short = .{ .load_frame = .{ .index = frame_index } }; |
| 11167 | 11218 | try reg_locks.append(self.register_manager.lockReg(reg_off.reg)); |
| 11168 | 11219 | }, |
| ... | ... | @@ -11177,20 +11228,21 @@ fn genCall(self: *Self, info: union(enum) { |
| 11177 | 11228 | registerAlias(dst_reg, @intCast(arg_ty.abiSize(mod))), |
| 11178 | 11229 | arg_ty, |
| 11179 | 11230 | src_arg, |
| 11231 | .{}, |
| 11180 | 11232 | ), |
| 11181 | 11233 | .C, .SysV, .Win64 => { |
| 11182 | 11234 | const promoted_ty = self.promoteInt(arg_ty); |
| 11183 | 11235 | const promoted_abi_size: u32 = @intCast(promoted_ty.abiSize(mod)); |
| 11184 | 11236 | const dst_alias = registerAlias(dst_reg, promoted_abi_size); |
| 11185 | | try self.genSetReg(dst_alias, promoted_ty, src_arg); |
| 11237 | try self.genSetReg(dst_alias, promoted_ty, src_arg, .{}); |
| 11186 | 11238 | if (promoted_ty.toIntern() != arg_ty.toIntern()) |
| 11187 | 11239 | try self.truncateRegister(arg_ty, dst_alias); |
| 11188 | 11240 | }, |
| 11189 | 11241 | }, |
| 11190 | | .register_pair => try self.genCopy(arg_ty, dst_arg, src_arg), |
| 11242 | .register_pair => try self.genCopy(arg_ty, dst_arg, src_arg, .{}), |
| 11191 | 11243 | .indirect => |reg_off| try self.genSetReg(reg_off.reg, Type.usize, .{ |
| 11192 | 11244 | .lea_frame = .{ .index = frame_index, .off = -reg_off.off }, |
| 11193 | | }), |
| 11245 | }, .{}), |
| 11194 | 11246 | else => unreachable, |
| 11195 | 11247 | }; |
| 11196 | 11248 | |
| ... | ... | @@ -11231,6 +11283,7 @@ fn genCall(self: *Self, info: union(enum) { |
| 11231 | 11283 | callee_reg, |
| 11232 | 11284 | Type.usize, |
| 11233 | 11285 | .{ .load_symbol = .{ .sym = sym.esym_index } }, |
| 11286 | .{}, |
| 11234 | 11287 | ); |
| 11235 | 11288 | try self.asmRegister(.{ ._, .call }, callee_reg); |
| 11236 | 11289 | } else try self.asmMemory(.{ ._, .call }, .{ |
| ... | ... | @@ -11243,12 +11296,17 @@ fn genCall(self: *Self, info: union(enum) { |
| 11243 | 11296 | } else if (self.bin_file.cast(link.File.Coff)) |coff_file| { |
| 11244 | 11297 | const atom = try coff_file.getOrCreateAtomForDecl(func.owner_decl); |
| 11245 | 11298 | const sym_index = coff_file.getAtom(atom).getSymbolIndex().?; |
| 11246 | | try self.genSetReg(.rax, Type.usize, .{ .lea_got = sym_index }); |
| 11299 | try self.genSetReg(.rax, Type.usize, .{ .lea_got = sym_index }, .{}); |
| 11247 | 11300 | try self.asmRegister(.{ ._, .call }, .rax); |
| 11248 | 11301 | } else if (self.bin_file.cast(link.File.MachO)) |macho_file| { |
| 11249 | 11302 | const sym_index = try macho_file.getZigObject().?.getOrCreateMetadataForDecl(macho_file, func.owner_decl); |
| 11250 | 11303 | const sym = macho_file.getSymbol(sym_index); |
| 11251 | | try self.genSetReg(.rax, Type.usize, .{ .load_symbol = .{ .sym = sym.nlist_idx } }); |
| 11304 | try self.genSetReg( |
| 11305 | .rax, |
| 11306 | Type.usize, |
| 11307 | .{ .load_symbol = .{ .sym = sym.nlist_idx } }, |
| 11308 | .{}, |
| 11309 | ); |
| 11252 | 11310 | try self.asmRegister(.{ ._, .call }, .rax); |
| 11253 | 11311 | } else if (self.bin_file.cast(link.File.Plan9)) |p9| { |
| 11254 | 11312 | const atom_index = try p9.seeDecl(func.owner_decl); |
| ... | ... | @@ -11273,7 +11331,7 @@ fn genCall(self: *Self, info: union(enum) { |
| 11273 | 11331 | } |
| 11274 | 11332 | } else { |
| 11275 | 11333 | assert(self.typeOf(callee).zigTypeTag(mod) == .Pointer); |
| 11276 | | try self.genSetReg(.rax, Type.usize, .{ .air_ref = callee }); |
| 11334 | try self.genSetReg(.rax, Type.usize, .{ .air_ref = callee }, .{}); |
| 11277 | 11335 | try self.asmRegister(.{ ._, .call }, .rax); |
| 11278 | 11336 | }, |
| 11279 | 11337 | .lib => |lib| try self.genExternSymbolRef(.call, lib.lib, lib.callee), |
| ... | ... | @@ -11281,7 +11339,7 @@ fn genCall(self: *Self, info: union(enum) { |
| 11281 | 11339 | return call_info.return_value.short; |
| 11282 | 11340 | } |
| 11283 | 11341 | |
| 11284 | | fn airRet(self: *Self, inst: Air.Inst.Index) !void { |
| 11342 | fn airRet(self: *Self, inst: Air.Inst.Index, safety: bool) !void { |
| 11285 | 11343 | const mod = self.bin_file.comp.module.?; |
| 11286 | 11344 | const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 11287 | 11345 | |
| ... | ... | @@ -11290,14 +11348,20 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void { |
| 11290 | 11348 | .none => {}, |
| 11291 | 11349 | .register, |
| 11292 | 11350 | .register_pair, |
| 11293 | | => try self.genCopy(ret_ty, self.ret_mcv.short, .{ .air_ref = un_op }), |
| 11351 | => try self.genCopy(ret_ty, self.ret_mcv.short, .{ .air_ref = un_op }, .{ .safety = safety }), |
| 11294 | 11352 | .indirect => |reg_off| { |
| 11295 | 11353 | try self.register_manager.getReg(reg_off.reg, null); |
| 11296 | 11354 | const lock = self.register_manager.lockRegAssumeUnused(reg_off.reg); |
| 11297 | 11355 | defer self.register_manager.unlockReg(lock); |
| 11298 | 11356 | |
| 11299 | | try self.genSetReg(reg_off.reg, Type.usize, self.ret_mcv.long); |
| 11300 | | try self.genSetMem(.{ .reg = reg_off.reg }, reg_off.off, ret_ty, .{ .air_ref = un_op }); |
| 11357 | try self.genSetReg(reg_off.reg, Type.usize, self.ret_mcv.long, .{}); |
| 11358 | try self.genSetMem( |
| 11359 | .{ .reg = reg_off.reg }, |
| 11360 | reg_off.off, |
| 11361 | ret_ty, |
| 11362 | .{ .air_ref = un_op }, |
| 11363 | .{ .safety = safety }, |
| 11364 | ); |
| 11301 | 11365 | }, |
| 11302 | 11366 | else => unreachable, |
| 11303 | 11367 | } |
| ... | ... | @@ -11318,7 +11382,7 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 11318 | 11382 | switch (self.ret_mcv.short) { |
| 11319 | 11383 | .none => {}, |
| 11320 | 11384 | .register, .register_pair => try self.load(self.ret_mcv.short, ptr_ty, ptr), |
| 11321 | | .indirect => |reg_off| try self.genSetReg(reg_off.reg, ptr_ty, ptr), |
| 11385 | .indirect => |reg_off| try self.genSetReg(reg_off.reg, ptr_ty, ptr, .{}), |
| 11322 | 11386 | else => unreachable, |
| 11323 | 11387 | } |
| 11324 | 11388 | self.ret_mcv.liveOut(self, inst); |
| ... | ... | @@ -11423,7 +11487,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { |
| 11423 | 11487 | const dst_mcv = if (unmat_dst_mcv.isRegister() or |
| 11424 | 11488 | (abi_size <= 8 and unmat_dst_mcv.isMemory())) unmat_dst_mcv else dst: { |
| 11425 | 11489 | const dst_mcv = try self.allocTempRegOrMem(ty, true); |
| 11426 | | try self.genCopy(ty, dst_mcv, unmat_dst_mcv); |
| 11490 | try self.genCopy(ty, dst_mcv, unmat_dst_mcv, .{}); |
| 11427 | 11491 | break :dst dst_mcv; |
| 11428 | 11492 | }; |
| 11429 | 11493 | const dst_lock = |
| ... | ... | @@ -11494,6 +11558,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { |
| 11494 | 11558 | dst_addr_reg, |
| 11495 | 11559 | Type.usize, |
| 11496 | 11560 | resolved_dst_mcv.address(), |
| 11561 | .{}, |
| 11497 | 11562 | ); |
| 11498 | 11563 | break :dst .{ |
| 11499 | 11564 | .addr_reg = dst_addr_reg, |
| ... | ... | @@ -11553,6 +11618,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { |
| 11553 | 11618 | src_addr_reg, |
| 11554 | 11619 | Type.usize, |
| 11555 | 11620 | resolved_src_mcv.address(), |
| 11621 | .{}, |
| 11556 | 11622 | ); |
| 11557 | 11623 | break :src .{ |
| 11558 | 11624 | .addr_reg = src_addr_reg, |
| ... | ... | @@ -11594,7 +11660,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { |
| 11594 | 11660 | .off = frame_addr.off + off, |
| 11595 | 11661 | } }, |
| 11596 | 11662 | else => unreachable, |
| 11597 | | }); |
| 11663 | }, .{}); |
| 11598 | 11664 | |
| 11599 | 11665 | try self.genBinOpMir( |
| 11600 | 11666 | .{ ._, .xor }, |
| ... | ... | @@ -12000,7 +12066,7 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC |
| 12000 | 12066 | const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg); |
| 12001 | 12067 | defer self.register_manager.unlockReg(addr_reg_lock); |
| 12002 | 12068 | |
| 12003 | | try self.genSetReg(addr_reg, Type.usize, opt_mcv.address()); |
| 12069 | try self.genSetReg(addr_reg, Type.usize, opt_mcv.address(), .{}); |
| 12004 | 12070 | const some_abi_size: u32 = @intCast(some_info.ty.abiSize(mod)); |
| 12005 | 12071 | try self.asmMemoryImmediate( |
| 12006 | 12072 | .{ ._, .cmp }, |
| ... | ... | @@ -12440,7 +12506,7 @@ fn airBr(self: *Self, inst: Air.Inst.Index) !void { |
| 12440 | 12506 | try self.getValue(block_tracking.short, br.block_inst); |
| 12441 | 12507 | break :dst block_tracking.short; |
| 12442 | 12508 | }; |
| 12443 | | try self.genCopy(block_ty, dst_mcv, try self.resolveInst(br.operand)); |
| 12509 | try self.genCopy(block_ty, dst_mcv, try self.resolveInst(br.operand), .{}); |
| 12444 | 12510 | break :result dst_mcv; |
| 12445 | 12511 | }; |
| 12446 | 12512 | |
| ... | ... | @@ -12604,7 +12670,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void { |
| 12604 | 12670 | rc.isSet(RegisterManager.indexOfRegIntoTracked(input_mcv.getReg().?).?)) |
| 12605 | 12671 | break :arg input_mcv; |
| 12606 | 12672 | const reg = try self.register_manager.allocReg(null, rc); |
| 12607 | | try self.genSetReg(reg, ty, input_mcv); |
| 12673 | try self.genSetReg(reg, ty, input_mcv, .{}); |
| 12608 | 12674 | break :arg .{ .register = registerAlias(reg, @intCast(ty.abiSize(mod))) }; |
| 12609 | 12675 | } else if (mem.eql(u8, constraint, "i") or mem.eql(u8, constraint, "n")) |
| 12610 | 12676 | switch (input_mcv) { |
| ... | ... | @@ -12621,16 +12687,16 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void { |
| 12621 | 12687 | .load_symbol, .load_direct, .load_got, .load_tlv => {}, |
| 12622 | 12688 | else => { |
| 12623 | 12689 | const temp_mcv = try self.allocTempRegOrMem(ty, false); |
| 12624 | | try self.genCopy(ty, temp_mcv, input_mcv); |
| 12690 | try self.genCopy(ty, temp_mcv, input_mcv, .{}); |
| 12625 | 12691 | break :arg temp_mcv; |
| 12626 | 12692 | }, |
| 12627 | 12693 | } |
| 12628 | 12694 | const addr_reg = self.register_manager.tryAllocReg(null, abi.RegisterClass.gp) orelse { |
| 12629 | 12695 | const temp_mcv = try self.allocTempRegOrMem(ty, false); |
| 12630 | | try self.genCopy(ty, temp_mcv, input_mcv); |
| 12696 | try self.genCopy(ty, temp_mcv, input_mcv, .{}); |
| 12631 | 12697 | break :arg temp_mcv; |
| 12632 | 12698 | }; |
| 12633 | | try self.genSetReg(addr_reg, Type.usize, input_mcv.address()); |
| 12699 | try self.genSetReg(addr_reg, Type.usize, input_mcv.address(), .{}); |
| 12634 | 12700 | break :arg .{ .indirect = .{ .reg = addr_reg } }; |
| 12635 | 12701 | } else if (mem.eql(u8, constraint, "g") or |
| 12636 | 12702 | mem.eql(u8, constraint, "rm") or mem.eql(u8, constraint, "mr") or |
| ... | ... | @@ -12643,7 +12709,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void { |
| 12643 | 12709 | else => {}, |
| 12644 | 12710 | } |
| 12645 | 12711 | const temp_mcv = try self.allocTempRegOrMem(ty, true); |
| 12646 | | try self.genCopy(ty, temp_mcv, input_mcv); |
| 12712 | try self.genCopy(ty, temp_mcv, input_mcv, .{}); |
| 12647 | 12713 | break :arg temp_mcv; |
| 12648 | 12714 | } else if (mem.eql(u8, constraint, "X")) |
| 12649 | 12715 | input_mcv |
| ... | ... | @@ -12651,7 +12717,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void { |
| 12651 | 12717 | const reg = parseRegName(constraint["{".len .. constraint.len - "}".len]) orelse |
| 12652 | 12718 | return self.fail("invalid register constraint: '{s}'", .{constraint}); |
| 12653 | 12719 | try self.register_manager.getReg(reg, null); |
| 12654 | | try self.genSetReg(reg, ty, input_mcv); |
| 12720 | try self.genSetReg(reg, ty, input_mcv, .{}); |
| 12655 | 12721 | break :arg .{ .register = reg }; |
| 12656 | 12722 | } else if (constraint.len == 1 and std.ascii.isDigit(constraint[0])) arg: { |
| 12657 | 12723 | const index = std.fmt.charToDigit(constraint[0], 10) catch unreachable; |
| ... | ... | @@ -13105,7 +13171,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void { |
| 13105 | 13171 | if (output == .none) continue; |
| 13106 | 13172 | if (arg_mcv != .register) continue; |
| 13107 | 13173 | if (constraint.len == 2 and std.ascii.isDigit(constraint[1])) continue; |
| 13108 | | try self.store(self.typeOf(output), .{ .air_ref = output }, arg_mcv); |
| 13174 | try self.store(self.typeOf(output), .{ .air_ref = output }, arg_mcv, .{}); |
| 13109 | 13175 | } |
| 13110 | 13176 | |
| 13111 | 13177 | simple: { |
| ... | ... | @@ -13477,7 +13543,11 @@ fn moveStrategy(self: *Self, ty: Type, class: Register.Class, aligned: bool) !Mo |
| 13477 | 13543 | return self.fail("TODO moveStrategy for {}", .{ty.fmt(mod)}); |
| 13478 | 13544 | } |
| 13479 | 13545 | |
| 13480 | | fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) InnerError!void { |
| 13546 | const CopyOptions = struct { |
| 13547 | safety: bool = false, |
| 13548 | }; |
| 13549 | |
| 13550 | fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue, opts: CopyOptions) InnerError!void { |
| 13481 | 13551 | const mod = self.bin_file.comp.module.?; |
| 13482 | 13552 | |
| 13483 | 13553 | const src_lock = if (src_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null; |
| ... | ... | @@ -13499,7 +13569,7 @@ fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) InnerError |
| 13499 | 13569 | .reserved_frame, |
| 13500 | 13570 | .air_ref, |
| 13501 | 13571 | => unreachable, // unmodifiable destination |
| 13502 | | .register => |reg| try self.genSetReg(reg, ty, src_mcv), |
| 13572 | .register => |reg| try self.genSetReg(reg, ty, src_mcv, opts), |
| 13503 | 13573 | .register_offset => |dst_reg_off| try self.genSetReg(dst_reg_off.reg, ty, switch (src_mcv) { |
| 13504 | 13574 | .none, |
| 13505 | 13575 | .unreach, |
| ... | ... | @@ -13517,7 +13587,7 @@ fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) InnerError |
| 13517 | 13587 | .reg = try self.copyToTmpRegister(ty, src_mcv), |
| 13518 | 13588 | .off = -dst_reg_off.off, |
| 13519 | 13589 | } }, |
| 13520 | | }), |
| 13590 | }, opts), |
| 13521 | 13591 | .register_pair => |dst_regs| { |
| 13522 | 13592 | const src_info: ?struct { addr_reg: Register, addr_lock: RegisterLock } = switch (src_mcv) { |
| 13523 | 13593 | .register_pair, .memory, .indirect, .load_frame => null, |
| ... | ... | @@ -13527,10 +13597,15 @@ fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) InnerError |
| 13527 | 13597 | const src_addr_lock = self.register_manager.lockRegAssumeUnused(src_addr_reg); |
| 13528 | 13598 | errdefer self.register_manager.unlockReg(src_addr_lock); |
| 13529 | 13599 | |
| 13530 | | try self.genSetReg(src_addr_reg, Type.usize, src_mcv.address()); |
| 13600 | try self.genSetReg(src_addr_reg, Type.usize, src_mcv.address(), opts); |
| 13531 | 13601 | break :src .{ .addr_reg = src_addr_reg, .addr_lock = src_addr_lock }; |
| 13532 | 13602 | }, |
| 13533 | | .air_ref => |src_ref| return self.genCopy(ty, dst_mcv, try self.resolveInst(src_ref)), |
| 13603 | .air_ref => |src_ref| return self.genCopy( |
| 13604 | ty, |
| 13605 | dst_mcv, |
| 13606 | try self.resolveInst(src_ref), |
| 13607 | opts, |
| 13608 | ), |
| 13534 | 13609 | else => return self.fail("TODO implement genCopy for {s} of {}", .{ |
| 13535 | 13610 | @tagName(src_mcv), ty.fmt(mod), |
| 13536 | 13611 | }), |
| ... | ... | @@ -13547,15 +13622,21 @@ fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) InnerError |
| 13547 | 13622 | .off = part_disp, |
| 13548 | 13623 | } }, |
| 13549 | 13624 | else => unreachable, |
| 13550 | | }); |
| 13625 | }, opts); |
| 13551 | 13626 | part_disp += @intCast(dst_ty.abiSize(mod)); |
| 13552 | 13627 | } |
| 13553 | 13628 | }, |
| 13554 | | .indirect => |reg_off| try self.genSetMem(.{ .reg = reg_off.reg }, reg_off.off, ty, src_mcv), |
| 13629 | .indirect => |reg_off| try self.genSetMem( |
| 13630 | .{ .reg = reg_off.reg }, |
| 13631 | reg_off.off, |
| 13632 | ty, |
| 13633 | src_mcv, |
| 13634 | opts, |
| 13635 | ), |
| 13555 | 13636 | .memory, .load_symbol, .load_direct, .load_got, .load_tlv => { |
| 13556 | 13637 | switch (dst_mcv) { |
| 13557 | 13638 | .memory => |addr| if (math.cast(i32, @as(i64, @bitCast(addr)))) |small_addr| |
| 13558 | | return self.genSetMem(.{ .reg = .ds }, small_addr, ty, src_mcv), |
| 13639 | return self.genSetMem(.{ .reg = .ds }, small_addr, ty, src_mcv, opts), |
| 13559 | 13640 | .load_symbol, .load_direct, .load_got, .load_tlv => {}, |
| 13560 | 13641 | else => unreachable, |
| 13561 | 13642 | } |
| ... | ... | @@ -13564,18 +13645,25 @@ fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) InnerError |
| 13564 | 13645 | const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg); |
| 13565 | 13646 | defer self.register_manager.unlockReg(addr_lock); |
| 13566 | 13647 | |
| 13567 | | try self.genSetMem(.{ .reg = addr_reg }, 0, ty, src_mcv); |
| 13648 | try self.genSetMem(.{ .reg = addr_reg }, 0, ty, src_mcv, opts); |
| 13568 | 13649 | }, |
| 13569 | 13650 | .load_frame => |frame_addr| try self.genSetMem( |
| 13570 | 13651 | .{ .frame = frame_addr.index }, |
| 13571 | 13652 | frame_addr.off, |
| 13572 | 13653 | ty, |
| 13573 | 13654 | src_mcv, |
| 13655 | opts, |
| 13574 | 13656 | ), |
| 13575 | 13657 | } |
| 13576 | 13658 | } |
| 13577 | 13659 | |
| 13578 | | fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerError!void { |
| 13660 | fn genSetReg( |
| 13661 | self: *Self, |
| 13662 | dst_reg: Register, |
| 13663 | ty: Type, |
| 13664 | src_mcv: MCValue, |
| 13665 | opts: CopyOptions, |
| 13666 | ) InnerError!void { |
| 13579 | 13667 | const mod = self.bin_file.comp.module.?; |
| 13580 | 13668 | const abi_size: u32 = @intCast(ty.abiSize(mod)); |
| 13581 | 13669 | if (ty.bitSize(mod) > dst_reg.bitSize()) |
| ... | ... | @@ -13587,7 +13675,27 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr |
| 13587 | 13675 | .register_overflow, |
| 13588 | 13676 | .reserved_frame, |
| 13589 | 13677 | => unreachable, |
| 13590 | | .undef => {}, |
| 13678 | .undef => if (opts.safety) switch (dst_reg.class()) { |
| 13679 | .general_purpose => switch (abi_size) { |
| 13680 | 1 => try self.asmRegisterImmediate(.{ ._, .mov }, dst_reg.to8(), Immediate.u(0xAA)), |
| 13681 | 2 => try self.asmRegisterImmediate(.{ ._, .mov }, dst_reg.to16(), Immediate.u(0xAAAA)), |
| 13682 | 3...4 => try self.asmRegisterImmediate( |
| 13683 | .{ ._, .mov }, |
| 13684 | dst_reg.to32(), |
| 13685 | Immediate.s(@as(i32, @bitCast(@as(u32, 0xAAAAAAAA)))), |
| 13686 | ), |
| 13687 | 5...8 => try self.asmRegisterImmediate( |
| 13688 | .{ ._, .mov }, |
| 13689 | dst_reg.to64(), |
| 13690 | Immediate.u(0xAAAAAAAAAAAAAAAA), |
| 13691 | ), |
| 13692 | else => unreachable, |
| 13693 | }, |
| 13694 | .segment, .x87, .mmx, .sse => try self.genSetReg(dst_reg, ty, try self.genTypedValue(.{ |
| 13695 | .ty = ty, |
| 13696 | .val = try mod.undefValue(ty), |
| 13697 | }), opts), |
| 13698 | }, |
| 13591 | 13699 | .eflags => |cc| try self.asmSetccRegister(cc, dst_reg.to8()), |
| 13592 | 13700 | .immediate => |imm| { |
| 13593 | 13701 | if (imm == 0) { |
| ... | ... | @@ -13672,6 +13780,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr |
| 13672 | 13780 | dst_reg, |
| 13673 | 13781 | ty, |
| 13674 | 13782 | .{ .register = try self.copyToTmpRegister(ty, src_mcv) }, |
| 13783 | opts, |
| 13675 | 13784 | ), |
| 13676 | 13785 | .x87, .mmx => unreachable, |
| 13677 | 13786 | .sse => try self.asmRegisterRegister( |
| ... | ... | @@ -13701,14 +13810,14 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr |
| 13701 | 13810 | ), |
| 13702 | 13811 | }, |
| 13703 | 13812 | }, |
| 13704 | | .register_pair => |src_regs| try self.genSetReg(dst_reg, ty, .{ .register = src_regs[0] }), |
| 13813 | .register_pair => |src_regs| try self.genSetReg(dst_reg, ty, .{ .register = src_regs[0] }, opts), |
| 13705 | 13814 | .register_offset, |
| 13706 | 13815 | .indirect, |
| 13707 | 13816 | .load_frame, |
| 13708 | 13817 | .lea_frame, |
| 13709 | 13818 | => try @as(MoveStrategy, switch (src_mcv) { |
| 13710 | 13819 | .register_offset => |reg_off| switch (reg_off.off) { |
| 13711 | | 0 => return self.genSetReg(dst_reg, ty, .{ .register = reg_off.reg }), |
| 13820 | 0 => return self.genSetReg(dst_reg, ty, .{ .register = reg_off.reg }, opts), |
| 13712 | 13821 | else => .{ .move = .{ ._, .lea } }, |
| 13713 | 13822 | }, |
| 13714 | 13823 | .indirect => try self.moveStrategy(ty, dst_reg.class(), false), |
| ... | ... | @@ -13852,11 +13961,18 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr |
| 13852 | 13961 | }); |
| 13853 | 13962 | }, |
| 13854 | 13963 | .lea_tlv => unreachable, // TODO: remove this |
| 13855 | | .air_ref => |src_ref| try self.genSetReg(dst_reg, ty, try self.resolveInst(src_ref)), |
| 13964 | .air_ref => |src_ref| try self.genSetReg(dst_reg, ty, try self.resolveInst(src_ref), opts), |
| 13856 | 13965 | } |
| 13857 | 13966 | } |
| 13858 | 13967 | |
| 13859 | | fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCValue) InnerError!void { |
| 13968 | fn genSetMem( |
| 13969 | self: *Self, |
| 13970 | base: Memory.Base, |
| 13971 | disp: i32, |
| 13972 | ty: Type, |
| 13973 | src_mcv: MCValue, |
| 13974 | opts: CopyOptions, |
| 13975 | ) InnerError!void { |
| 13860 | 13976 | const mod = self.bin_file.comp.module.?; |
| 13861 | 13977 | const abi_size: u32 = @intCast(ty.abiSize(mod)); |
| 13862 | 13978 | const dst_ptr_mcv: MCValue = switch (base) { |
| ... | ... | @@ -13867,10 +13983,11 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal |
| 13867 | 13983 | }; |
| 13868 | 13984 | switch (src_mcv) { |
| 13869 | 13985 | .none, .unreach, .dead, .reserved_frame => unreachable, |
| 13870 | | .undef => try self.genInlineMemset( |
| 13986 | .undef => if (opts.safety) try self.genInlineMemset( |
| 13871 | 13987 | dst_ptr_mcv, |
| 13872 | | .{ .immediate = 0xaa }, |
| 13988 | src_mcv, |
| 13873 | 13989 | .{ .immediate = abi_size }, |
| 13990 | opts, |
| 13874 | 13991 | ), |
| 13875 | 13992 | .immediate => |imm| switch (abi_size) { |
| 13876 | 13993 | 1, 2, 4 => { |
| ... | ... | @@ -13951,7 +14068,7 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal |
| 13951 | 14068 | } } }, |
| 13952 | 14069 | src_alias, |
| 13953 | 14070 | ); |
| 13954 | | try self.genSetMem(base, disp, ty, frame_mcv); |
| 14071 | try self.genSetMem(base, disp, ty, frame_mcv, opts); |
| 13955 | 14072 | try self.freeValue(frame_mcv); |
| 13956 | 14073 | } else try (try self.moveStrategy(ty, src_alias.class(), switch (base) { |
| 13957 | 14074 | .none => ty.abiAlignment(mod).check(@as(u32, @bitCast(disp))), |
| ... | ... | @@ -13975,7 +14092,7 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal |
| 13975 | 14092 | .register_pair => |src_regs| { |
| 13976 | 14093 | var part_disp: i32 = disp; |
| 13977 | 14094 | for (try self.splitType(ty), src_regs) |src_ty, src_reg| { |
| 13978 | | try self.genSetMem(base, part_disp, src_ty, .{ .register = src_reg }); |
| 14095 | try self.genSetMem(base, part_disp, src_ty, .{ .register = src_reg }, opts); |
| 13979 | 14096 | part_disp += @intCast(src_ty.abiSize(mod)); |
| 13980 | 14097 | } |
| 13981 | 14098 | }, |
| ... | ... | @@ -13986,23 +14103,26 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal |
| 13986 | 14103 | disp + @as(i32, @intCast(ty.structFieldOffset(0, mod))), |
| 13987 | 14104 | ty.structFieldType(0, mod), |
| 13988 | 14105 | .{ .register = ro.reg }, |
| 14106 | opts, |
| 13989 | 14107 | ); |
| 13990 | 14108 | try self.genSetMem( |
| 13991 | 14109 | base, |
| 13992 | 14110 | disp + @as(i32, @intCast(ty.structFieldOffset(1, mod))), |
| 13993 | 14111 | ty.structFieldType(1, mod), |
| 13994 | 14112 | .{ .eflags = ro.eflags }, |
| 14113 | opts, |
| 13995 | 14114 | ); |
| 13996 | 14115 | }, |
| 13997 | 14116 | .Optional => { |
| 13998 | 14117 | assert(!ty.optionalReprIsPayload(mod)); |
| 13999 | 14118 | const child_ty = ty.optionalChild(mod); |
| 14000 | | try self.genSetMem(base, disp, child_ty, .{ .register = ro.reg }); |
| 14119 | try self.genSetMem(base, disp, child_ty, .{ .register = ro.reg }, opts); |
| 14001 | 14120 | try self.genSetMem( |
| 14002 | 14121 | base, |
| 14003 | 14122 | disp + @as(i32, @intCast(child_ty.abiSize(mod))), |
| 14004 | 14123 | Type.bool, |
| 14005 | 14124 | .{ .eflags = ro.eflags }, |
| 14125 | opts, |
| 14006 | 14126 | ); |
| 14007 | 14127 | }, |
| 14008 | 14128 | else => return self.fail("TODO implement genSetMem for {s} of {}", .{ |
| ... | ... | @@ -14029,27 +14149,37 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal |
| 14029 | 14149 | const src_lock = self.register_manager.lockRegAssumeUnused(src_reg); |
| 14030 | 14150 | defer self.register_manager.unlockReg(src_lock); |
| 14031 | 14151 | |
| 14032 | | try self.genSetMem(base, disp, ty, .{ .register = src_reg }); |
| 14152 | try self.genSetMem(base, disp, ty, .{ .register = src_reg }, opts); |
| 14033 | 14153 | }, |
| 14034 | | else => try self.genInlineMemcpy(dst_ptr_mcv, src_mcv.address(), .{ .immediate = abi_size }), |
| 14154 | else => try self.genInlineMemcpy( |
| 14155 | dst_ptr_mcv, |
| 14156 | src_mcv.address(), |
| 14157 | .{ .immediate = abi_size }, |
| 14158 | ), |
| 14035 | 14159 | }, |
| 14036 | | .air_ref => |src_ref| try self.genSetMem(base, disp, ty, try self.resolveInst(src_ref)), |
| 14160 | .air_ref => |src_ref| try self.genSetMem(base, disp, ty, try self.resolveInst(src_ref), opts), |
| 14037 | 14161 | } |
| 14038 | 14162 | } |
| 14039 | 14163 | |
| 14040 | 14164 | fn genInlineMemcpy(self: *Self, dst_ptr: MCValue, src_ptr: MCValue, len: MCValue) InnerError!void { |
| 14041 | 14165 | try self.spillRegisters(&.{ .rsi, .rdi, .rcx }); |
| 14042 | | try self.genSetReg(.rsi, Type.usize, src_ptr); |
| 14043 | | try self.genSetReg(.rdi, Type.usize, dst_ptr); |
| 14044 | | try self.genSetReg(.rcx, Type.usize, len); |
| 14166 | try self.genSetReg(.rsi, Type.usize, src_ptr, .{}); |
| 14167 | try self.genSetReg(.rdi, Type.usize, dst_ptr, .{}); |
| 14168 | try self.genSetReg(.rcx, Type.usize, len, .{}); |
| 14045 | 14169 | try self.asmOpOnly(.{ .@"rep _sb", .mov }); |
| 14046 | 14170 | } |
| 14047 | 14171 | |
| 14048 | | fn genInlineMemset(self: *Self, dst_ptr: MCValue, value: MCValue, len: MCValue) InnerError!void { |
| 14172 | fn genInlineMemset( |
| 14173 | self: *Self, |
| 14174 | dst_ptr: MCValue, |
| 14175 | value: MCValue, |
| 14176 | len: MCValue, |
| 14177 | opts: CopyOptions, |
| 14178 | ) InnerError!void { |
| 14049 | 14179 | try self.spillRegisters(&.{ .rdi, .al, .rcx }); |
| 14050 | | try self.genSetReg(.rdi, Type.usize, dst_ptr); |
| 14051 | | try self.genSetReg(.al, Type.u8, value); |
| 14052 | | try self.genSetReg(.rcx, Type.usize, len); |
| 14180 | try self.genSetReg(.rdi, Type.usize, dst_ptr, .{}); |
| 14181 | try self.genSetReg(.al, Type.u8, value, opts); |
| 14182 | try self.genSetReg(.rcx, Type.usize, len, .{}); |
| 14053 | 14183 | try self.asmOpOnly(.{ .@"rep _sb", .sto }); |
| 14054 | 14184 | } |
| 14055 | 14185 | |
| ... | ... | @@ -14113,10 +14243,10 @@ fn genLazySymbolRef( |
| 14113 | 14243 | switch (tag) { |
| 14114 | 14244 | .lea, .call => try self.genSetReg(reg, Type.usize, .{ |
| 14115 | 14245 | .load_symbol = .{ .sym = sym.esym_index }, |
| 14116 | | }), |
| 14246 | }, .{}), |
| 14117 | 14247 | .mov => try self.genSetReg(reg, Type.usize, .{ |
| 14118 | 14248 | .load_symbol = .{ .sym = sym.esym_index }, |
| 14119 | | }), |
| 14249 | }, .{}), |
| 14120 | 14250 | else => unreachable, |
| 14121 | 14251 | } |
| 14122 | 14252 | switch (tag) { |
| ... | ... | @@ -14173,8 +14303,8 @@ fn genLazySymbolRef( |
| 14173 | 14303 | return self.fail("{s} creating lazy symbol", .{@errorName(err)}); |
| 14174 | 14304 | const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?; |
| 14175 | 14305 | switch (tag) { |
| 14176 | | .lea, .call => try self.genSetReg(reg, Type.usize, .{ .lea_got = sym_index }), |
| 14177 | | .mov => try self.genSetReg(reg, Type.usize, .{ .load_got = sym_index }), |
| 14306 | .lea, .call => try self.genSetReg(reg, Type.usize, .{ .lea_got = sym_index }, .{}), |
| 14307 | .mov => try self.genSetReg(reg, Type.usize, .{ .load_got = sym_index }, .{}), |
| 14178 | 14308 | else => unreachable, |
| 14179 | 14309 | } |
| 14180 | 14310 | switch (tag) { |
| ... | ... | @@ -14187,8 +14317,13 @@ fn genLazySymbolRef( |
| 14187 | 14317 | return self.fail("{s} creating lazy symbol", .{@errorName(err)}); |
| 14188 | 14318 | const sym = macho_file.getSymbol(sym_index); |
| 14189 | 14319 | switch (tag) { |
| 14190 | | .lea, .call => try self.genSetReg(reg, Type.usize, .{ .load_symbol = .{ .sym = sym.nlist_idx } }), |
| 14191 | | .mov => try self.genSetReg(reg, Type.usize, .{ .load_symbol = .{ .sym = sym.nlist_idx } }), |
| 14320 | .lea, .call => try self.genSetReg( |
| 14321 | reg, |
| 14322 | Type.usize, |
| 14323 | .{ .load_symbol = .{ .sym = sym.nlist_idx } }, |
| 14324 | .{}, |
| 14325 | ), |
| 14326 | .mov => try self.genSetReg(reg, Type.usize, .{ .load_symbol = .{ .sym = sym.nlist_idx } }, .{}), |
| 14192 | 14327 | else => unreachable, |
| 14193 | 14328 | } |
| 14194 | 14329 | switch (tag) { |
| ... | ... | @@ -14210,7 +14345,7 @@ fn airIntFromPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 14210 | 14345 | |
| 14211 | 14346 | const dst_mcv = try self.allocRegOrMem(inst, true); |
| 14212 | 14347 | const dst_ty = self.typeOfIndex(inst); |
| 14213 | | try self.genCopy(dst_ty, dst_mcv, src_mcv); |
| 14348 | try self.genCopy(dst_ty, dst_mcv, src_mcv, .{}); |
| 14214 | 14349 | break :result dst_mcv; |
| 14215 | 14350 | }; |
| 14216 | 14351 | return self.finishAir(inst, result, .{ un_op, .none, .none }); |
| ... | ... | @@ -14237,7 +14372,7 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void { |
| 14237 | 14372 | .lt => dst_ty, |
| 14238 | 14373 | .eq => if (!dst_mcv.isMemory() or src_mcv.isMemory()) dst_ty else src_ty, |
| 14239 | 14374 | .gt => src_ty, |
| 14240 | | }, dst_mcv, src_mcv); |
| 14375 | }, dst_mcv, src_mcv, .{}); |
| 14241 | 14376 | break :dst dst_mcv; |
| 14242 | 14377 | }; |
| 14243 | 14378 | |
| ... | ... | @@ -14268,6 +14403,7 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void { |
| 14268 | 14403 | if (abi_size <= 8) dst_ty else Type.usize, |
| 14269 | 14404 | high_mcv, |
| 14270 | 14405 | .{ .register = high_reg }, |
| 14406 | .{}, |
| 14271 | 14407 | ); |
| 14272 | 14408 | break :result dst_mcv; |
| 14273 | 14409 | }; |
| ... | ... | @@ -14285,12 +14421,13 @@ fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void { |
| 14285 | 14421 | const array_len = array_ty.arrayLen(mod); |
| 14286 | 14422 | |
| 14287 | 14423 | const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(slice_ty, mod)); |
| 14288 | | try self.genSetMem(.{ .frame = frame_index }, 0, ptr_ty, ptr); |
| 14424 | try self.genSetMem(.{ .frame = frame_index }, 0, ptr_ty, ptr, .{}); |
| 14289 | 14425 | try self.genSetMem( |
| 14290 | 14426 | .{ .frame = frame_index }, |
| 14291 | 14427 | @intCast(ptr_ty.abiSize(mod)), |
| 14292 | 14428 | Type.usize, |
| 14293 | 14429 | .{ .immediate = array_len }, |
| 14430 | .{}, |
| 14294 | 14431 | ); |
| 14295 | 14432 | |
| 14296 | 14433 | const result = MCValue{ .load_frame = .{ .index = frame_index } }; |
| ... | ... | @@ -14470,9 +14607,9 @@ fn airCmpxchg(self: *Self, inst: Air.Inst.Index) !void { |
| 14470 | 14607 | if (exp_addr_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null; |
| 14471 | 14608 | defer if (exp_addr_lock) |lock| self.register_manager.unlockReg(lock); |
| 14472 | 14609 | |
| 14473 | | try self.genSetReg(.rax, Type.usize, exp_addr_mcv.deref()); |
| 14474 | | try self.genSetReg(.rdx, Type.usize, exp_addr_mcv.offset(8).deref()); |
| 14475 | | } else try self.genSetReg(.rax, val_ty, exp_mcv); |
| 14610 | try self.genSetReg(.rax, Type.usize, exp_addr_mcv.deref(), .{}); |
| 14611 | try self.genSetReg(.rdx, Type.usize, exp_addr_mcv.offset(8).deref(), .{}); |
| 14612 | } else try self.genSetReg(.rax, val_ty, exp_mcv, .{}); |
| 14476 | 14613 | |
| 14477 | 14614 | const new_mcv = try self.resolveInst(extra.new_value); |
| 14478 | 14615 | const new_reg = if (val_abi_size > 8) new: { |
| ... | ... | @@ -14484,8 +14621,8 @@ fn airCmpxchg(self: *Self, inst: Air.Inst.Index) !void { |
| 14484 | 14621 | if (new_addr_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null; |
| 14485 | 14622 | defer if (new_addr_lock) |lock| self.register_manager.unlockReg(lock); |
| 14486 | 14623 | |
| 14487 | | try self.genSetReg(.rbx, Type.usize, new_addr_mcv.deref()); |
| 14488 | | try self.genSetReg(.rcx, Type.usize, new_addr_mcv.offset(8).deref()); |
| 14624 | try self.genSetReg(.rbx, Type.usize, new_addr_mcv.deref(), .{}); |
| 14625 | try self.genSetReg(.rcx, Type.usize, new_addr_mcv.offset(8).deref(), .{}); |
| 14489 | 14626 | break :new null; |
| 14490 | 14627 | } else try self.copyToTmpRegister(val_ty, new_mcv); |
| 14491 | 14628 | const new_lock = if (new_reg) |reg| self.register_manager.lockRegAssumeUnused(reg) else null; |
| ... | ... | @@ -14526,9 +14663,9 @@ fn airCmpxchg(self: *Self, inst: Air.Inst.Index) !void { |
| 14526 | 14663 | } |
| 14527 | 14664 | |
| 14528 | 14665 | const dst_mcv = try self.allocRegOrMem(inst, false); |
| 14529 | | try self.genCopy(Type.usize, dst_mcv, .{ .register = .rax }); |
| 14530 | | try self.genCopy(Type.usize, dst_mcv.address().offset(8).deref(), .{ .register = .rdx }); |
| 14531 | | try self.genCopy(Type.bool, dst_mcv.address().offset(16).deref(), .{ .eflags = .ne }); |
| 14666 | try self.genCopy(Type.usize, dst_mcv, .{ .register = .rax }, .{}); |
| 14667 | try self.genCopy(Type.usize, dst_mcv.address().offset(8).deref(), .{ .register = .rdx }, .{}); |
| 14668 | try self.genCopy(Type.bool, dst_mcv.address().offset(16).deref(), .{ .eflags = .ne }, .{}); |
| 14532 | 14669 | break :result dst_mcv; |
| 14533 | 14670 | }; |
| 14534 | 14671 | return self.finishAir(inst, result, .{ extra.ptr, extra.expected_value, extra.new_value }); |
| ... | ... | @@ -14612,7 +14749,7 @@ fn atomicOp( |
| 14612 | 14749 | const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg); |
| 14613 | 14750 | defer self.register_manager.unlockReg(dst_lock); |
| 14614 | 14751 | |
| 14615 | | try self.genSetReg(dst_reg, val_ty, val_mcv); |
| 14752 | try self.genSetReg(dst_reg, val_ty, val_mcv, .{}); |
| 14616 | 14753 | if (rmw_op == std.builtin.AtomicRmwOp.Sub and tag == .xadd) { |
| 14617 | 14754 | try self.genUnOpMir(.{ ._, .neg }, val_ty, dst_mcv); |
| 14618 | 14755 | } |
| ... | ... | @@ -14645,7 +14782,7 @@ fn atomicOp( |
| 14645 | 14782 | try self.asmRegisterMemory(.{ ._, .mov }, registerAlias(.rax, val_abi_size), ptr_mem); |
| 14646 | 14783 | const loop: Mir.Inst.Index = @intCast(self.mir_instructions.len); |
| 14647 | 14784 | if (!use_sse and rmw_op orelse .Xchg != .Xchg) { |
| 14648 | | try self.genSetReg(tmp_reg, val_ty, .{ .register = .rax }); |
| 14785 | try self.genSetReg(tmp_reg, val_ty, .{ .register = .rax }, .{}); |
| 14649 | 14786 | } |
| 14650 | 14787 | if (rmw_op) |op| if (use_sse) { |
| 14651 | 14788 | const mir_tag = @as(?Mir.Inst.FixedTag, switch (op) { |
| ... | ... | @@ -14673,7 +14810,7 @@ fn atomicOp( |
| 14673 | 14810 | }) orelse return self.fail("TODO implement atomicOp of {s} for {}", .{ |
| 14674 | 14811 | @tagName(op), val_ty.fmt(mod), |
| 14675 | 14812 | }); |
| 14676 | | try self.genSetReg(sse_reg, val_ty, .{ .register = .rax }); |
| 14813 | try self.genSetReg(sse_reg, val_ty, .{ .register = .rax }, .{}); |
| 14677 | 14814 | switch (mir_tag[0]) { |
| 14678 | 14815 | .v_ss, .v_sd => if (val_mcv.isMemory()) try self.asmRegisterRegisterMemory( |
| 14679 | 14816 | mir_tag, |
| ... | ... | @@ -14703,9 +14840,9 @@ fn atomicOp( |
| 14703 | 14840 | ), |
| 14704 | 14841 | else => unreachable, |
| 14705 | 14842 | } |
| 14706 | | try self.genSetReg(tmp_reg, val_ty, .{ .register = sse_reg }); |
| 14843 | try self.genSetReg(tmp_reg, val_ty, .{ .register = sse_reg }, .{}); |
| 14707 | 14844 | } else switch (op) { |
| 14708 | | .Xchg => try self.genSetReg(tmp_reg, val_ty, val_mcv), |
| 14845 | .Xchg => try self.genSetReg(tmp_reg, val_ty, val_mcv, .{}), |
| 14709 | 14846 | .Add => try self.genBinOpMir(.{ ._, .add }, val_ty, tmp_mcv, val_mcv), |
| 14710 | 14847 | .Sub => try self.genBinOpMir(.{ ._, .sub }, val_ty, tmp_mcv, val_mcv), |
| 14711 | 14848 | .And => try self.genBinOpMir(.{ ._, .@"and" }, val_ty, tmp_mcv, val_mcv), |
| ... | ... | @@ -14995,7 +15132,7 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void { |
| 14995 | 15132 | }; |
| 14996 | 15133 | defer if (len_lock) |lock| self.register_manager.unlockReg(lock); |
| 14997 | 15134 | |
| 14998 | | try self.genInlineMemset(ptr, src_val, len); |
| 15135 | try self.genInlineMemset(ptr, src_val, len, .{ .safety = safety }); |
| 14999 | 15136 | break :result; |
| 15000 | 15137 | } |
| 15001 | 15138 | |
| ... | ... | @@ -15017,11 +15154,11 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void { |
| 15017 | 15154 | const len_lock = self.register_manager.lockRegAssumeUnused(len_reg); |
| 15018 | 15155 | defer self.register_manager.unlockReg(len_lock); |
| 15019 | 15156 | |
| 15020 | | try self.genSetReg(len_reg, Type.usize, len); |
| 15157 | try self.genSetReg(len_reg, Type.usize, len, .{}); |
| 15021 | 15158 | try self.asmRegisterRegister(.{ ._, .@"test" }, len_reg, len_reg); |
| 15022 | 15159 | |
| 15023 | 15160 | const skip_reloc = try self.asmJccReloc(.z, undefined); |
| 15024 | | try self.store(slice_ptr_ty, ptr, src_val); |
| 15161 | try self.store(slice_ptr_ty, ptr, src_val, .{ .safety = safety }); |
| 15025 | 15162 | |
| 15026 | 15163 | const second_elem_ptr_reg = |
| 15027 | 15164 | try self.register_manager.allocReg(null, abi.RegisterClass.gp); |
| ... | ... | @@ -15033,7 +15170,7 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void { |
| 15033 | 15170 | try self.genSetReg(second_elem_ptr_reg, Type.usize, .{ .register_offset = .{ |
| 15034 | 15171 | .reg = try self.copyToTmpRegister(Type.usize, ptr), |
| 15035 | 15172 | .off = elem_abi_size, |
| 15036 | | } }); |
| 15173 | } }, .{}); |
| 15037 | 15174 | |
| 15038 | 15175 | try self.genBinOpMir(.{ ._, .sub }, Type.usize, len_mcv, .{ .immediate = 1 }); |
| 15039 | 15176 | try self.asmRegisterRegisterImmediate( |
| ... | ... | @@ -15052,7 +15189,7 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void { |
| 15052 | 15189 | const len = dst_ptr_ty.childType(mod).arrayLen(mod); |
| 15053 | 15190 | |
| 15054 | 15191 | assert(len != 0); // prevented by Sema |
| 15055 | | try self.store(elem_ptr_ty, dst_ptr, src_val); |
| 15192 | try self.store(elem_ptr_ty, dst_ptr, src_val, .{ .safety = safety }); |
| 15056 | 15193 | |
| 15057 | 15194 | const second_elem_ptr_reg = |
| 15058 | 15195 | try self.register_manager.allocReg(null, abi.RegisterClass.gp); |
| ... | ... | @@ -15064,7 +15201,7 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void { |
| 15064 | 15201 | try self.genSetReg(second_elem_ptr_reg, Type.usize, .{ .register_offset = .{ |
| 15065 | 15202 | .reg = try self.copyToTmpRegister(Type.usize, dst_ptr), |
| 15066 | 15203 | .off = elem_abi_size, |
| 15067 | | } }); |
| 15204 | } }, .{}); |
| 15068 | 15205 | |
| 15069 | 15206 | const bytes_to_copy: MCValue = .{ .immediate = elem_abi_size * (len - 1) }; |
| 15070 | 15207 | try self.genInlineMemcpy(second_elem_ptr_mcv, dst_ptr, bytes_to_copy); |
| ... | ... | @@ -15158,10 +15295,10 @@ fn airTagName(self: *Self, inst: Air.Inst.Index) !void { |
| 15158 | 15295 | const param_regs = abi.getCAbiIntParamRegs(resolved_cc); |
| 15159 | 15296 | |
| 15160 | 15297 | const dst_mcv = try self.allocRegOrMem(inst, false); |
| 15161 | | try self.genSetReg(param_regs[0], Type.usize, dst_mcv.address()); |
| 15298 | try self.genSetReg(param_regs[0], Type.usize, dst_mcv.address(), .{}); |
| 15162 | 15299 | |
| 15163 | 15300 | const operand = try self.resolveInst(un_op); |
| 15164 | | try self.genSetReg(param_regs[1], enum_ty, operand); |
| 15301 | try self.genSetReg(param_regs[1], enum_ty, operand, .{}); |
| 15165 | 15302 | |
| 15166 | 15303 | try self.genLazySymbolRef( |
| 15167 | 15304 | .call, |
| ... | ... | @@ -15291,11 +15428,12 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void { |
| 15291 | 15428 | const reg_locks = self.register_manager.lockRegsAssumeUnused(2, regs); |
| 15292 | 15429 | defer for (reg_locks) |lock| self.register_manager.unlockReg(lock); |
| 15293 | 15430 | |
| 15294 | | try self.genSetReg(regs[1], vector_ty, .{ .immediate = 0 }); |
| 15431 | try self.genSetReg(regs[1], vector_ty, .{ .immediate = 0 }, .{}); |
| 15295 | 15432 | try self.genSetReg( |
| 15296 | 15433 | regs[1], |
| 15297 | 15434 | vector_ty, |
| 15298 | 15435 | .{ .immediate = @as(u64, math.maxInt(u64)) >> @intCast(64 - vector_len) }, |
| 15436 | .{}, |
| 15299 | 15437 | ); |
| 15300 | 15438 | const src_mcv = try self.resolveInst(ty_op.operand); |
| 15301 | 15439 | const abi_size = @max(math.divCeil(u32, vector_len, 8) catch unreachable, 4); |
| ... | ... | @@ -15360,7 +15498,7 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void { |
| 15360 | 15498 | try src_mcv.mem(self, self.memSize(scalar_ty)), |
| 15361 | 15499 | ) else { |
| 15362 | 15500 | if (mir_tag[0] == .vp_i128) break :avx2; |
| 15363 | | try self.genSetReg(dst_reg, scalar_ty, src_mcv); |
| 15501 | try self.genSetReg(dst_reg, scalar_ty, src_mcv, .{}); |
| 15364 | 15502 | try self.asmRegisterRegister( |
| 15365 | 15503 | mir_tag, |
| 15366 | 15504 | registerAlias(dst_reg, @intCast(vector_ty.abiSize(mod))), |
| ... | ... | @@ -15373,7 +15511,7 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void { |
| 15373 | 15511 | const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg); |
| 15374 | 15512 | defer self.register_manager.unlockReg(dst_lock); |
| 15375 | 15513 | |
| 15376 | | try self.genSetReg(dst_reg, scalar_ty, .{ .air_ref = ty_op.operand }); |
| 15514 | try self.genSetReg(dst_reg, scalar_ty, .{ .air_ref = ty_op.operand }, .{}); |
| 15377 | 15515 | if (vector_len == 1) break :result .{ .register = dst_reg }; |
| 15378 | 15516 | |
| 15379 | 15517 | const dst_alias = registerAlias(dst_reg, @intCast(vector_ty.abiSize(mod))); |
| ... | ... | @@ -15423,7 +15561,7 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void { |
| 15423 | 15561 | const src_mcv = try self.resolveInst(ty_op.operand); |
| 15424 | 15562 | if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result src_mcv; |
| 15425 | 15563 | const dst_reg = try self.register_manager.allocReg(inst, dst_rc); |
| 15426 | | try self.genSetReg(dst_reg, scalar_ty, src_mcv); |
| 15564 | try self.genSetReg(dst_reg, scalar_ty, src_mcv, .{}); |
| 15427 | 15565 | break :result .{ .register = dst_reg }; |
| 15428 | 15566 | }, |
| 15429 | 15567 | 2...4 => { |
| ... | ... | @@ -15506,7 +15644,7 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void { |
| 15506 | 15644 | const src_mcv = try self.resolveInst(ty_op.operand); |
| 15507 | 15645 | if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result src_mcv; |
| 15508 | 15646 | const dst_reg = try self.register_manager.allocReg(inst, dst_rc); |
| 15509 | | try self.genSetReg(dst_reg, scalar_ty, src_mcv); |
| 15647 | try self.genSetReg(dst_reg, scalar_ty, src_mcv, .{}); |
| 15510 | 15648 | break :result .{ .register = dst_reg }; |
| 15511 | 15649 | }, |
| 15512 | 15650 | 2 => { |
| ... | ... | @@ -15575,7 +15713,7 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void { |
| 15575 | 15713 | const src_mcv = try self.resolveInst(ty_op.operand); |
| 15576 | 15714 | if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result src_mcv; |
| 15577 | 15715 | const dst_reg = try self.register_manager.allocReg(inst, dst_rc); |
| 15578 | | try self.genSetReg(dst_reg, scalar_ty, src_mcv); |
| 15716 | try self.genSetReg(dst_reg, scalar_ty, src_mcv, .{}); |
| 15579 | 15717 | break :result .{ .register = dst_reg }; |
| 15580 | 15718 | }, |
| 15581 | 15719 | 2 => if (self.hasFeature(.avx)) { |
| ... | ... | @@ -15699,6 +15837,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { |
| 15699 | 15837 | .{ .lea_frame = .{ .index = frame_index } }, |
| 15700 | 15838 | .{ .immediate = 0 }, |
| 15701 | 15839 | .{ .immediate = result_ty.abiSize(mod) }, |
| 15840 | .{}, |
| 15702 | 15841 | ); |
| 15703 | 15842 | for (elements, 0..) |elem, elem_i_usize| { |
| 15704 | 15843 | const elem_i: u32 = @intCast(elem_i_usize); |
| ... | ... | @@ -15783,7 +15922,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { |
| 15783 | 15922 | .load_tlv => |sym_index| MCValue{ .lea_tlv = sym_index }, |
| 15784 | 15923 | else => elem_mcv, |
| 15785 | 15924 | }; |
| 15786 | | try self.genSetMem(.{ .frame = frame_index }, elem_off, elem_ty, mat_elem_mcv); |
| 15925 | try self.genSetMem(.{ .frame = frame_index }, elem_off, elem_ty, mat_elem_mcv, .{}); |
| 15787 | 15926 | } |
| 15788 | 15927 | break :result .{ .load_frame = .{ .index = frame_index } }; |
| 15789 | 15928 | }, |
| ... | ... | @@ -15831,13 +15970,20 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { |
| 15831 | 15970 | else => elem_mcv, |
| 15832 | 15971 | }; |
| 15833 | 15972 | const elem_off: i32 = @intCast(elem_size * elem_i); |
| 15834 | | try self.genSetMem(.{ .frame = frame_index }, elem_off, elem_ty, mat_elem_mcv); |
| 15973 | try self.genSetMem( |
| 15974 | .{ .frame = frame_index }, |
| 15975 | elem_off, |
| 15976 | elem_ty, |
| 15977 | mat_elem_mcv, |
| 15978 | .{}, |
| 15979 | ); |
| 15835 | 15980 | } |
| 15836 | 15981 | if (result_ty.sentinel(mod)) |sentinel| try self.genSetMem( |
| 15837 | 15982 | .{ .frame = frame_index }, |
| 15838 | 15983 | @intCast(elem_size * elements.len), |
| 15839 | 15984 | elem_ty, |
| 15840 | 15985 | try self.genTypedValue(.{ .ty = elem_ty, .val = sentinel }), |
| 15986 | .{}, |
| 15841 | 15987 | ); |
| 15842 | 15988 | break :result .{ .load_frame = .{ .index = frame_index } }; |
| 15843 | 15989 | } |
| ... | ... | @@ -15872,7 +16018,7 @@ fn airUnionInit(self: *Self, inst: Air.Inst.Index) !void { |
| 15872 | 16018 | self.reuseOperand(inst, extra.init, 0, src_mcv)) break :result src_mcv; |
| 15873 | 16019 | |
| 15874 | 16020 | const dst_mcv = try self.allocRegOrMem(inst, true); |
| 15875 | | try self.genCopy(src_ty, dst_mcv, src_mcv); |
| 16021 | try self.genCopy(src_ty, dst_mcv, src_mcv, .{}); |
| 15876 | 16022 | break :result dst_mcv; |
| 15877 | 16023 | } |
| 15878 | 16024 | |
| ... | ... | @@ -15889,13 +16035,18 @@ fn airUnionInit(self: *Self, inst: Air.Inst.Index) !void { |
| 15889 | 16035 | @intCast(layout.payload_size) |
| 15890 | 16036 | else |
| 15891 | 16037 | 0; |
| 15892 | | try self.genCopy(tag_ty, dst_mcv.address().offset(tag_off).deref(), .{ .immediate = tag_int }); |
| 16038 | try self.genCopy( |
| 16039 | tag_ty, |
| 16040 | dst_mcv.address().offset(tag_off).deref(), |
| 16041 | .{ .immediate = tag_int }, |
| 16042 | .{}, |
| 16043 | ); |
| 15893 | 16044 | |
| 15894 | 16045 | const pl_off: i32 = if (layout.tag_align.compare(.lt, layout.payload_align)) |
| 15895 | 16046 | 0 |
| 15896 | 16047 | else |
| 15897 | 16048 | @intCast(layout.tag_size); |
| 15898 | | try self.genCopy(src_ty, dst_mcv.address().offset(pl_off).deref(), src_mcv); |
| 16049 | try self.genCopy(src_ty, dst_mcv.address().offset(pl_off).deref(), src_mcv, .{}); |
| 15899 | 16050 | |
| 15900 | 16051 | break :result dst_mcv; |
| 15901 | 16052 | }; |
| ... | ... | @@ -16093,6 +16244,7 @@ fn airVaStart(self: *Self, inst: Air.Inst.Index) !void { |
| 16093 | 16244 | field_off, |
| 16094 | 16245 | Type.c_uint, |
| 16095 | 16246 | .{ .immediate = info.gp_count * 8 }, |
| 16247 | .{}, |
| 16096 | 16248 | ); |
| 16097 | 16249 | field_off += @intCast(Type.c_uint.abiSize(mod)); |
| 16098 | 16250 | // fp_offset: c_uint, |
| ... | ... | @@ -16101,6 +16253,7 @@ fn airVaStart(self: *Self, inst: Air.Inst.Index) !void { |
| 16101 | 16253 | field_off, |
| 16102 | 16254 | Type.c_uint, |
| 16103 | 16255 | .{ .immediate = abi.SysV.c_abi_int_param_regs.len * 8 + info.fp_count * 16 }, |
| 16256 | .{}, |
| 16104 | 16257 | ); |
| 16105 | 16258 | field_off += @intCast(Type.c_uint.abiSize(mod)); |
| 16106 | 16259 | // overflow_arg_area: *anyopaque, |
| ... | ... | @@ -16109,6 +16262,7 @@ fn airVaStart(self: *Self, inst: Air.Inst.Index) !void { |
| 16109 | 16262 | field_off, |
| 16110 | 16263 | ptr_anyopaque_ty, |
| 16111 | 16264 | .{ .lea_frame = info.overflow_arg_area }, |
| 16265 | .{}, |
| 16112 | 16266 | ); |
| 16113 | 16267 | field_off += @intCast(ptr_anyopaque_ty.abiSize(mod)); |
| 16114 | 16268 | // reg_save_area: *anyopaque, |
| ... | ... | @@ -16117,6 +16271,7 @@ fn airVaStart(self: *Self, inst: Air.Inst.Index) !void { |
| 16117 | 16271 | field_off, |
| 16118 | 16272 | ptr_anyopaque_ty, |
| 16119 | 16273 | .{ .lea_frame = info.reg_save_area }, |
| 16274 | .{}, |
| 16120 | 16275 | ); |
| 16121 | 16276 | field_off += @intCast(ptr_anyopaque_ty.abiSize(mod)); |
| 16122 | 16277 | break :result .{ .load_frame = .{ .index = dst_fi } }; |
| ... | ... | @@ -16171,13 +16326,13 @@ fn airVaArg(self: *Self, inst: Air.Inst.Index) !void { |
| 16171 | 16326 | .integer => { |
| 16172 | 16327 | assert(classes.len == 1); |
| 16173 | 16328 | |
| 16174 | | try self.genSetReg(offset_reg, Type.c_uint, gp_offset); |
| 16329 | try self.genSetReg(offset_reg, Type.c_uint, gp_offset, .{}); |
| 16175 | 16330 | try self.asmRegisterImmediate(.{ ._, .cmp }, offset_reg, Immediate.u( |
| 16176 | 16331 | abi.SysV.c_abi_int_param_regs.len * 8, |
| 16177 | 16332 | )); |
| 16178 | 16333 | const mem_reloc = try self.asmJccReloc(.ae, undefined); |
| 16179 | 16334 | |
| 16180 | | try self.genSetReg(addr_reg, ptr_anyopaque_ty, reg_save_area); |
| 16335 | try self.genSetReg(addr_reg, ptr_anyopaque_ty, reg_save_area, .{}); |
| 16181 | 16336 | if (!unused) try self.asmRegisterMemory(.{ ._, .lea }, addr_reg, .{ |
| 16182 | 16337 | .base = .{ .reg = addr_reg }, |
| 16183 | 16338 | .mod = .{ .rm = .{ |
| ... | ... | @@ -16192,11 +16347,11 @@ fn airVaArg(self: *Self, inst: Air.Inst.Index) !void { |
| 16192 | 16347 | .disp = 8, |
| 16193 | 16348 | } }, |
| 16194 | 16349 | }); |
| 16195 | | try self.genCopy(Type.c_uint, gp_offset, .{ .register = offset_reg }); |
| 16350 | try self.genCopy(Type.c_uint, gp_offset, .{ .register = offset_reg }, .{}); |
| 16196 | 16351 | const done_reloc = try self.asmJmpReloc(undefined); |
| 16197 | 16352 | |
| 16198 | 16353 | try self.performReloc(mem_reloc); |
| 16199 | | try self.genSetReg(addr_reg, ptr_anyopaque_ty, overflow_arg_area); |
| 16354 | try self.genSetReg(addr_reg, ptr_anyopaque_ty, overflow_arg_area, .{}); |
| 16200 | 16355 | try self.asmRegisterMemory(.{ ._, .lea }, offset_reg.to64(), .{ |
| 16201 | 16356 | .base = .{ .reg = addr_reg }, |
| 16202 | 16357 | .mod = .{ .rm = .{ |
| ... | ... | @@ -16208,23 +16363,24 @@ fn airVaArg(self: *Self, inst: Air.Inst.Index) !void { |
| 16208 | 16363 | ptr_anyopaque_ty, |
| 16209 | 16364 | overflow_arg_area, |
| 16210 | 16365 | .{ .register = offset_reg.to64() }, |
| 16366 | .{}, |
| 16211 | 16367 | ); |
| 16212 | 16368 | |
| 16213 | 16369 | try self.performReloc(done_reloc); |
| 16214 | 16370 | if (!unused) try self.genCopy(promote_ty, promote_mcv, .{ |
| 16215 | 16371 | .indirect = .{ .reg = addr_reg }, |
| 16216 | | }); |
| 16372 | }, .{}); |
| 16217 | 16373 | }, |
| 16218 | 16374 | .sse => { |
| 16219 | 16375 | assert(classes.len == 1); |
| 16220 | 16376 | |
| 16221 | | try self.genSetReg(offset_reg, Type.c_uint, fp_offset); |
| 16377 | try self.genSetReg(offset_reg, Type.c_uint, fp_offset, .{}); |
| 16222 | 16378 | try self.asmRegisterImmediate(.{ ._, .cmp }, offset_reg, Immediate.u( |
| 16223 | 16379 | abi.SysV.c_abi_int_param_regs.len * 8 + abi.SysV.c_abi_sse_param_regs.len * 16, |
| 16224 | 16380 | )); |
| 16225 | 16381 | const mem_reloc = try self.asmJccReloc(.ae, undefined); |
| 16226 | 16382 | |
| 16227 | | try self.genSetReg(addr_reg, ptr_anyopaque_ty, reg_save_area); |
| 16383 | try self.genSetReg(addr_reg, ptr_anyopaque_ty, reg_save_area, .{}); |
| 16228 | 16384 | if (!unused) try self.asmRegisterMemory(.{ ._, .lea }, addr_reg, .{ |
| 16229 | 16385 | .base = .{ .reg = addr_reg }, |
| 16230 | 16386 | .mod = .{ .rm = .{ |
| ... | ... | @@ -16239,11 +16395,11 @@ fn airVaArg(self: *Self, inst: Air.Inst.Index) !void { |
| 16239 | 16395 | .disp = 16, |
| 16240 | 16396 | } }, |
| 16241 | 16397 | }); |
| 16242 | | try self.genCopy(Type.c_uint, fp_offset, .{ .register = offset_reg }); |
| 16398 | try self.genCopy(Type.c_uint, fp_offset, .{ .register = offset_reg }, .{}); |
| 16243 | 16399 | const done_reloc = try self.asmJmpReloc(undefined); |
| 16244 | 16400 | |
| 16245 | 16401 | try self.performReloc(mem_reloc); |
| 16246 | | try self.genSetReg(addr_reg, ptr_anyopaque_ty, overflow_arg_area); |
| 16402 | try self.genSetReg(addr_reg, ptr_anyopaque_ty, overflow_arg_area, .{}); |
| 16247 | 16403 | try self.asmRegisterMemory(.{ ._, .lea }, offset_reg.to64(), .{ |
| 16248 | 16404 | .base = .{ .reg = addr_reg }, |
| 16249 | 16405 | .mod = .{ .rm = .{ |
| ... | ... | @@ -16255,12 +16411,13 @@ fn airVaArg(self: *Self, inst: Air.Inst.Index) !void { |
| 16255 | 16411 | ptr_anyopaque_ty, |
| 16256 | 16412 | overflow_arg_area, |
| 16257 | 16413 | .{ .register = offset_reg.to64() }, |
| 16414 | .{}, |
| 16258 | 16415 | ); |
| 16259 | 16416 | |
| 16260 | 16417 | try self.performReloc(done_reloc); |
| 16261 | 16418 | if (!unused) try self.genCopy(promote_ty, promote_mcv, .{ |
| 16262 | 16419 | .indirect = .{ .reg = addr_reg }, |
| 16263 | | }); |
| 16420 | }, .{}); |
| 16264 | 16421 | }, |
| 16265 | 16422 | .memory => { |
| 16266 | 16423 | assert(classes.len == 1); |
| ... | ... | @@ -16276,7 +16433,7 @@ fn airVaArg(self: *Self, inst: Air.Inst.Index) !void { |
| 16276 | 16433 | |
| 16277 | 16434 | if (!promote_ty.isRuntimeFloat()) { |
| 16278 | 16435 | const dst_mcv = try self.allocRegOrMem(inst, true); |
| 16279 | | try self.genCopy(ty, dst_mcv, promote_mcv); |
| 16436 | try self.genCopy(ty, dst_mcv, promote_mcv, .{}); |
| 16280 | 16437 | break :result dst_mcv; |
| 16281 | 16438 | } |
| 16282 | 16439 | |
| ... | ... | @@ -16367,6 +16524,7 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue { |
| 16367 | 16524 | 0, |
| 16368 | 16525 | Type.usize, |
| 16369 | 16526 | .{ .lea_symbol = .{ .sym = tlv_sym } }, |
| 16527 | .{}, |
| 16370 | 16528 | ); |
| 16371 | 16529 | break :init .{ .load_frame = .{ .index = frame_index } }; |
| 16372 | 16530 | }, |