authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-02-06 02:06:03+01:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-02-12 05:25:07+01:00
logf2a62d25fc722da9dd4fb09ec614e278271442b9
tree839cb80844e4c97e5c3c68ac2103dc7f91e35017
parentc619551f7d0aae794d628fc7d2f34cfc70f1cba3

x86_64: implement `ret_safe`


2 files changed, 348 insertions(+), 191 deletions(-)

src/arch/x86_64/CodeGen.zig+348-190
...@@ -537,7 +537,7 @@ const InstTracking = struct {...@@ -537,7 +537,7 @@ const InstTracking = struct {
537 else => unreachable,537 else => unreachable,
538 }538 }
539 tracking_log.debug("spill %{d} from {} to {}", .{ inst, self.short, self.long });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 }
542542
543 fn reuseFrame(self: *InstTracking) void {543 fn reuseFrame(self: *InstTracking) void {
...@@ -637,8 +637,8 @@ const InstTracking = struct {...@@ -637,8 +637,8 @@ const InstTracking = struct {
637 ) !void {637 ) !void {
638 const ty = function.typeOfIndex(inst);638 const ty = function.typeOfIndex(inst);
639 if ((self.long == .none or self.long == .reserved_frame) and target.long == .load_frame)639 if ((self.long == .none or self.long == .reserved_frame) and target.long == .load_frame)
640 try function.genCopy(ty, target.long, self.short);640 try function.genCopy(ty, target.long, self.short, .{});
641 try function.genCopy(ty, target.short, self.short);641 try function.genCopy(ty, target.short, self.short, .{});
642 }642 }
643643
644 fn trackMaterialize(self: *InstTracking, inst: Air.Inst.Index, target: InstTracking) void {644 fn trackMaterialize(self: *InstTracking, inst: Air.Inst.Index, target: InstTracking) void {
...@@ -1717,6 +1717,7 @@ fn gen(self: *Self) InnerError!void {...@@ -1717,6 +1717,7 @@ fn gen(self: *Self) InnerError!void {
1717 0,1717 0,
1718 Type.usize,1718 Type.usize,
1719 self.ret_mcv.long.address().offset(-self.ret_mcv.short.indirect.off),1719 self.ret_mcv.long.address().offset(-self.ret_mcv.short.indirect.off),
1720 .{},
1720 );1721 );
1721 self.ret_mcv.long = .{ .load_frame = .{ .index = frame_index } };1722 self.ret_mcv.long = .{ .load_frame = .{ .index = frame_index } };
1722 tracking_log.debug("spill {} to {}", .{ self.ret_mcv.long, frame_index });1723 tracking_log.debug("spill {} to {}", .{ self.ret_mcv.long, frame_index });
...@@ -1740,6 +1741,7 @@ fn gen(self: *Self) InnerError!void {...@@ -1740,6 +1741,7 @@ fn gen(self: *Self) InnerError!void {
1740 @intCast(reg_i * 8),1741 @intCast(reg_i * 8),
1741 Type.usize,1742 Type.usize,
1742 .{ .register = reg },1743 .{ .register = reg },
1744 .{},
1743 );1745 );
17441746
1745 try self.asmRegisterImmediate(.{ ._, .cmp }, .al, Immediate.u(info.fp_count));1747 try self.asmRegisterImmediate(.{ ._, .cmp }, .al, Immediate.u(info.fp_count));
...@@ -1752,6 +1754,7 @@ fn gen(self: *Self) InnerError!void {...@@ -1752,6 +1754,7 @@ fn gen(self: *Self) InnerError!void {
1752 @intCast(abi.SysV.c_abi_int_param_regs.len * 8 + reg_i * 16),1754 @intCast(abi.SysV.c_abi_int_param_regs.len * 8 + reg_i * 16),
1753 vec_2_f64,1755 vec_2_f64,
1754 .{ .register = reg },1756 .{ .register = reg },
1757 .{},
1755 );1758 );
17561759
1757 try self.performReloc(skip_sse_reloc);1760 try self.performReloc(skip_sse_reloc);
...@@ -2006,8 +2009,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -2006,8 +2009,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
2006 .load => try self.airLoad(inst),2009 .load => try self.airLoad(inst),
2007 .loop => try self.airLoop(inst),2010 .loop => try self.airLoop(inst),
2008 .int_from_ptr => try self.airIntFromPtr(inst),2011 .int_from_ptr => try self.airIntFromPtr(inst),
2009 .ret => try self.airRet(inst),2012 .ret => try self.airRet(inst, false),
2010 .ret_safe => try self.airRet(inst), // TODO2013 .ret_safe => try self.airRet(inst, true),
2011 .ret_load => try self.airRetLoad(inst),2014 .ret_load => try self.airRetLoad(inst),
2012 .store => try self.airStore(inst, false),2015 .store => try self.airStore(inst, false),
2013 .store_safe => try self.airStore(inst, true),2016 .store_safe => try self.airStore(inst, true),
...@@ -2209,8 +2212,15 @@ fn genLazy(self: *Self, lazy_sym: link.File.LazySymbol) InnerError!void {...@@ -2209,8 +2212,15 @@ fn genLazy(self: *Self, lazy_sym: link.File.LazySymbol) InnerError!void {
2209 0,2212 0,
2210 Type.usize,2213 Type.usize,
2211 .{ .register_offset = .{ .reg = data_reg, .off = data_off } },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 });
22142224
2215 exitlude_jump_reloc.* = try self.asmJmpReloc(undefined);2225 exitlude_jump_reloc.* = try self.asmJmpReloc(undefined);
2216 try self.performReloc(skip_reloc);2226 try self.performReloc(skip_reloc);
...@@ -2651,7 +2661,7 @@ pub fn spillRegisters(self: *Self, comptime registers: []const Register) !void {...@@ -2651,7 +2661,7 @@ pub fn spillRegisters(self: *Self, comptime registers: []const Register) !void {
2651/// This can have a side effect of spilling instructions to the stack to free up a register.2661/// This can have a side effect of spilling instructions to the stack to free up a register.
2652fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register {2662fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register {
2653 const reg = try self.register_manager.allocReg(null, self.regClassForType(ty));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 return reg;2665 return reg;
2656}2666}
26572667
...@@ -2666,7 +2676,7 @@ fn copyToRegisterWithInstTracking(...@@ -2666,7 +2676,7 @@ fn copyToRegisterWithInstTracking(
2666 mcv: MCValue,2676 mcv: MCValue,
2667) !MCValue {2677) !MCValue {
2668 const reg: Register = try self.register_manager.allocReg(reg_owner, self.regClassForType(ty));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 return MCValue{ .register = reg };2680 return MCValue{ .register = reg };
2671}2681}
26722682
...@@ -2919,7 +2929,7 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {...@@ -2919,7 +2929,7 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
2919 math.divCeil(u32, src_storage_bits, 64) catch unreachable and2929 math.divCeil(u32, src_storage_bits, 64) catch unreachable and
2920 self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) src_mcv else dst: {2930 self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) src_mcv else dst: {
2921 const dst_mcv = try self.allocRegOrMem(inst, true);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 break :dst dst_mcv;2933 break :dst dst_mcv;
2924 };2934 };
29252935
...@@ -2954,7 +2964,7 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {...@@ -2954,7 +2964,7 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
2954 if (high_bits > 0) {2964 if (high_bits > 0) {
2955 try self.truncateRegister(src_ty, high_reg);2965 try self.truncateRegister(src_ty, high_reg);
2956 const high_ty = if (dst_int_info.bits >= 64) Type.usize else dst_ty;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 }
29592969
2960 if (dst_limbs_len > src_limbs_len) try self.genInlineMemset(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,6 +2983,7 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
2973 .unsigned => .{ .immediate = 0 },2983 .unsigned => .{ .immediate = 0 },
2974 },2984 },
2975 .{ .immediate = (dst_limbs_len - src_limbs_len) * 8 },2985 .{ .immediate = (dst_limbs_len - src_limbs_len) * 8 },
2986 .{},
2976 );2987 );
29772988
2978 break :result dst_mcv;2989 break :result dst_mcv;
...@@ -3006,7 +3017,7 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {...@@ -3006,7 +3017,7 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {
3006 const dst_locks = self.register_manager.lockRegsAssumeUnused(2, dst_regs);3017 const dst_locks = self.register_manager.lockRegsAssumeUnused(2, dst_regs);
3007 defer for (dst_locks) |lock| self.register_manager.unlockReg(lock);3018 defer for (dst_locks) |lock| self.register_manager.unlockReg(lock);
30083019
3009 try self.genCopy(dst_ty, dst_mcv, src_mcv);3020 try self.genCopy(dst_ty, dst_mcv, src_mcv, .{});
3010 break :dst dst_mcv;3021 break :dst dst_mcv;
3011 } else try self.allocRegOrMem(inst, true);3022 } else try self.allocRegOrMem(inst, true);
30123023
...@@ -3082,11 +3093,15 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {...@@ -3082,11 +3093,15 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {
3082 // when truncating a `u16` to `u5`, for example, those top 3 bits in the result3093 // when truncating a `u16` to `u5`, for example, those top 3 bits in the result
3083 // have to be removed. this only happens if the dst if not a power-of-two size.3094 // have to be removed. this only happens if the dst if not a power-of-two size.
3084 if (dst_abi_size <= 8) {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 } else if (dst_abi_size <= 16) {3099 } else if (dst_abi_size <= 16) {
3087 const dst_info = dst_ty.intInfo(mod);3100 const dst_info = dst_ty.intInfo(mod);
3088 const high_ty = try mod.intType(dst_info.signedness, dst_info.bits - 64);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 }
30913106
3092 break :result dst_mcv;3107 break :result dst_mcv;
...@@ -3116,7 +3131,7 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void {...@@ -3116,7 +3131,7 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void {
3116 const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(slice_ty, mod));3131 const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(slice_ty, mod));
31173132
3118 const ptr_ty = self.typeOf(bin_op.lhs);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 }, .{});
31203135
3121 const len_ty = self.typeOf(bin_op.rhs);3136 const len_ty = self.typeOf(bin_op.rhs);
3122 try self.genSetMem(3137 try self.genSetMem(
...@@ -3124,6 +3139,7 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void {...@@ -3124,6 +3139,7 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void {
3124 @intCast(ptr_ty.abiSize(mod)),3139 @intCast(ptr_ty.abiSize(mod)),
3125 len_ty,3140 len_ty,
3126 .{ .air_ref = bin_op.rhs },3141 .{ .air_ref = bin_op.rhs },
3142 .{},
3127 );3143 );
31283144
3129 const result = MCValue{ .load_frame = .{ .index = frame_index } };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,9 +3177,9 @@ fn airBinOp(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {
31613177
3162 const hi_ty = try mod.intType(.unsigned, @intCast((dst_ty.bitSize(mod) - 1) % 64 + 1));3178 const hi_ty = try mod.intType(.unsigned, @intCast((dst_ty.bitSize(mod) - 1) % 64 + 1));
3163 const hi_mcv = dst_mcv.address().offset(@intCast(bit_size / 64 * 8)).deref();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 try self.truncateRegister(dst_ty, tmp_reg);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,7 +3492,7 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void {
3476 if (reg_extra_bits > 0) {3492 if (reg_extra_bits > 0) {
3477 try self.genShiftBinOpMir(.{ ._l, .sa }, ty, dst_mcv, .{ .immediate = reg_extra_bits });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 try self.genShiftBinOpMir(.{ ._r, .sa }, ty, limit_mcv, .{ .immediate = reg_bits - 1 });3496 try self.genShiftBinOpMir(.{ ._r, .sa }, ty, limit_mcv, .{ .immediate = reg_bits - 1 });
3481 try self.genBinOpMir(.{ ._, .xor }, ty, limit_mcv, .{3497 try self.genBinOpMir(.{ ._, .xor }, ty, limit_mcv, .{
3482 .immediate = (@as(u64, 1) << @intCast(reg_bits - 1)) - 1,3498 .immediate = (@as(u64, 1) << @intCast(reg_bits - 1)) - 1,
...@@ -3499,7 +3515,7 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void {...@@ -3499,7 +3515,7 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void {
3499 } else cc: {3515 } else cc: {
3500 try self.genSetReg(limit_reg, ty, .{3516 try self.genSetReg(limit_reg, ty, .{
3501 .immediate = @as(u64, math.maxInt(u64)) >> @intCast(64 - ty.bitSize(mod)),3517 .immediate = @as(u64, math.maxInt(u64)) >> @intCast(64 - ty.bitSize(mod)),
3502 });3518 }, .{});
35033519
3504 try self.genBinOpMir(.{ ._, .add }, ty, dst_mcv, rhs_mcv);3520 try self.genBinOpMir(.{ ._, .add }, ty, dst_mcv, rhs_mcv);
3505 if (reg_extra_bits > 0) {3521 if (reg_extra_bits > 0) {
...@@ -3559,7 +3575,7 @@ fn airSubSat(self: *Self, inst: Air.Inst.Index) !void {...@@ -3559,7 +3575,7 @@ fn airSubSat(self: *Self, inst: Air.Inst.Index) !void {
3559 if (reg_extra_bits > 0) {3575 if (reg_extra_bits > 0) {
3560 try self.genShiftBinOpMir(.{ ._l, .sa }, ty, dst_mcv, .{ .immediate = reg_extra_bits });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 try self.genShiftBinOpMir(.{ ._r, .sa }, ty, limit_mcv, .{ .immediate = reg_bits - 1 });3579 try self.genShiftBinOpMir(.{ ._r, .sa }, ty, limit_mcv, .{ .immediate = reg_bits - 1 });
3564 try self.genBinOpMir(.{ ._, .xor }, ty, limit_mcv, .{3580 try self.genBinOpMir(.{ ._, .xor }, ty, limit_mcv, .{
3565 .immediate = (@as(u64, 1) << @intCast(reg_bits - 1)) - 1,3581 .immediate = (@as(u64, 1) << @intCast(reg_bits - 1)) - 1,
...@@ -3580,7 +3596,7 @@ fn airSubSat(self: *Self, inst: Air.Inst.Index) !void {...@@ -3580,7 +3596,7 @@ fn airSubSat(self: *Self, inst: Air.Inst.Index) !void {
3580 } else try self.genBinOpMir(.{ ._, .sub }, ty, dst_mcv, rhs_mcv);3596 } else try self.genBinOpMir(.{ ._, .sub }, ty, dst_mcv, rhs_mcv);
3581 break :cc .o;3597 break :cc .o;
3582 } else cc: {3598 } else cc: {
3583 try self.genSetReg(limit_reg, ty, .{ .immediate = 0 });3599 try self.genSetReg(limit_reg, ty, .{ .immediate = 0 }, .{});
3584 try self.genBinOpMir(.{ ._, .sub }, ty, dst_mcv, rhs_mcv);3600 try self.genBinOpMir(.{ ._, .sub }, ty, dst_mcv, rhs_mcv);
3585 break :cc .c;3601 break :cc .c;
3586 };3602 };
...@@ -3713,7 +3729,7 @@ fn airMulSat(self: *Self, inst: Air.Inst.Index) !void {...@@ -3713,7 +3729,7 @@ fn airMulSat(self: *Self, inst: Air.Inst.Index) !void {
37133729
3714 const reg_bits = self.regBitSize(ty);3730 const reg_bits = self.regBitSize(ty);
3715 const cc: Condition = if (ty.isSignedInt(mod)) cc: {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 try self.genBinOpMir(.{ ._, .xor }, ty, limit_mcv, rhs_mcv);3733 try self.genBinOpMir(.{ ._, .xor }, ty, limit_mcv, rhs_mcv);
3718 try self.genShiftBinOpMir(.{ ._r, .sa }, ty, limit_mcv, .{ .immediate = reg_bits - 1 });3734 try self.genShiftBinOpMir(.{ ._r, .sa }, ty, limit_mcv, .{ .immediate = reg_bits - 1 });
3719 try self.genBinOpMir(.{ ._, .xor }, ty, limit_mcv, .{3735 try self.genBinOpMir(.{ ._, .xor }, ty, limit_mcv, .{
...@@ -3723,7 +3739,7 @@ fn airMulSat(self: *Self, inst: Air.Inst.Index) !void {...@@ -3723,7 +3739,7 @@ fn airMulSat(self: *Self, inst: Air.Inst.Index) !void {
3723 } else cc: {3739 } else cc: {
3724 try self.genSetReg(limit_reg, ty, .{3740 try self.genSetReg(limit_reg, ty, .{
3725 .immediate = @as(u64, math.maxInt(u64)) >> @intCast(64 - reg_bits),3741 .immediate = @as(u64, math.maxInt(u64)) >> @intCast(64 - reg_bits),
3726 });3742 }, .{});
3727 break :cc .c;3743 break :cc .c;
3728 };3744 };
37293745
...@@ -3779,12 +3795,14 @@ fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -3779,12 +3795,14 @@ fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
3779 @intCast(tuple_ty.structFieldOffset(1, mod)),3795 @intCast(tuple_ty.structFieldOffset(1, mod)),
3780 Type.u1,3796 Type.u1,
3781 .{ .eflags = cc },3797 .{ .eflags = cc },
3798 .{},
3782 );3799 );
3783 try self.genSetMem(3800 try self.genSetMem(
3784 .{ .frame = frame_index },3801 .{ .frame = frame_index },
3785 @intCast(tuple_ty.structFieldOffset(0, mod)),3802 @intCast(tuple_ty.structFieldOffset(0, mod)),
3786 ty,3803 ty,
3787 partial_mcv,3804 partial_mcv,
3805 .{},
3788 );3806 );
3789 break :result .{ .load_frame = .{ .index = frame_index } };3807 break :result .{ .load_frame = .{ .index = frame_index } };
3790 }3808 }
...@@ -3852,12 +3870,14 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -3852,12 +3870,14 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
3852 @intCast(tuple_ty.structFieldOffset(1, mod)),3870 @intCast(tuple_ty.structFieldOffset(1, mod)),
3853 tuple_ty.structFieldType(1, mod),3871 tuple_ty.structFieldType(1, mod),
3854 .{ .eflags = cc },3872 .{ .eflags = cc },
3873 .{},
3855 );3874 );
3856 try self.genSetMem(3875 try self.genSetMem(
3857 .{ .frame = frame_index },3876 .{ .frame = frame_index },
3858 @intCast(tuple_ty.structFieldOffset(0, mod)),3877 @intCast(tuple_ty.structFieldOffset(0, mod)),
3859 tuple_ty.structFieldType(0, mod),3878 tuple_ty.structFieldType(0, mod),
3860 partial_mcv,3879 partial_mcv,
3880 .{},
3861 );3881 );
3862 break :result .{ .load_frame = .{ .index = frame_index } };3882 break :result .{ .load_frame = .{ .index = frame_index } };
3863 }3883 }
...@@ -3912,7 +3932,7 @@ fn genSetFrameTruncatedOverflowCompare(...@@ -3912,7 +3932,7 @@ fn genSetFrameTruncatedOverflowCompare(
3912 src_mcv.address().offset(int_info.bits / 64 * 8).deref()3932 src_mcv.address().offset(int_info.bits / 64 * 8).deref()
3913 else3933 else
3914 src_mcv;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 try self.truncateRegister(hi_ty, scratch_reg);3936 try self.truncateRegister(hi_ty, scratch_reg);
3917 try self.genBinOpMir(.{ ._, .cmp }, limb_ty, .{ .register = scratch_reg }, hi_limb_mcv);3937 try self.genBinOpMir(.{ ._, .cmp }, limb_ty, .{ .register = scratch_reg }, hi_limb_mcv);
39183938
...@@ -3928,18 +3948,26 @@ fn genSetFrameTruncatedOverflowCompare(...@@ -3928,18 +3948,26 @@ fn genSetFrameTruncatedOverflowCompare(
3928 }3948 }
39293949
3930 const payload_off: i32 = @intCast(tuple_ty.structFieldOffset(0, mod));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 try self.genSetMem(3958 try self.genSetMem(
3933 .{ .frame = frame_index },3959 .{ .frame = frame_index },
3934 payload_off + hi_limb_off,3960 payload_off + hi_limb_off,
3935 limb_ty,3961 limb_ty,
3936 .{ .register = scratch_reg },3962 .{ .register = scratch_reg },
3963 .{},
3937 );3964 );
3938 try self.genSetMem(3965 try self.genSetMem(
3939 .{ .frame = frame_index },3966 .{ .frame = frame_index },
3940 @intCast(tuple_ty.structFieldOffset(1, mod)),3967 @intCast(tuple_ty.structFieldOffset(1, mod)),
3941 tuple_ty.structFieldType(1, mod),3968 tuple_ty.structFieldType(1, mod),
3942 if (overflow_cc) |_| .{ .register = overflow_reg.to8() } else .{ .eflags = .ne },3969 if (overflow_cc) |_| .{ .register = overflow_reg.to8() } else .{ .eflags = .ne },
3970 .{},
3943 );3971 );
3944}3972}
39453973
...@@ -3967,6 +3995,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -3967,6 +3995,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
3967 dst_mcv.address(),3995 dst_mcv.address(),
3968 .{ .immediate = 0 },3996 .{ .immediate = 0 },
3969 .{ .immediate = tuple_ty.abiSize(mod) },3997 .{ .immediate = tuple_ty.abiSize(mod) },
3998 .{},
3970 );3999 );
3971 const lhs_mcv = try self.resolveInst(bin_op.lhs);4000 const lhs_mcv = try self.resolveInst(bin_op.lhs);
3972 const rhs_mcv = try self.resolveInst(bin_op.rhs);4001 const rhs_mcv = try self.resolveInst(bin_op.rhs);
...@@ -4122,6 +4151,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -4122,6 +4151,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
4122 @intCast(tuple_ty.structFieldOffset(0, mod)),4151 @intCast(tuple_ty.structFieldOffset(0, mod)),
4123 tuple_ty.structFieldType(0, mod),4152 tuple_ty.structFieldType(0, mod),
4124 result,4153 result,
4154 .{},
4125 );4155 );
4126 try self.asmMemoryImmediate(4156 try self.asmMemoryImmediate(
4127 .{ ._, .cmp },4157 .{ ._, .cmp },
...@@ -4133,6 +4163,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -4133,6 +4163,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
4133 @intCast(tuple_ty.structFieldOffset(1, mod)),4163 @intCast(tuple_ty.structFieldOffset(1, mod)),
4134 tuple_ty.structFieldType(1, mod),4164 tuple_ty.structFieldType(1, mod),
4135 .{ .eflags = .ne },4165 .{ .eflags = .ne },
4166 .{},
4136 );4167 );
4137 try self.freeValue(overflow);4168 try self.freeValue(overflow);
4138 break :result dst_mcv;4169 break :result dst_mcv;
...@@ -4244,12 +4275,14 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -4244,12 +4275,14 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
4244 @intCast(tuple_ty.structFieldOffset(0, mod)),4275 @intCast(tuple_ty.structFieldOffset(0, mod)),
4245 tuple_ty.structFieldType(0, mod),4276 tuple_ty.structFieldType(0, mod),
4246 .{ .register_pair = .{ .rax, .rdx } },4277 .{ .register_pair = .{ .rax, .rdx } },
4278 .{},
4247 );4279 );
4248 try self.genSetMem(4280 try self.genSetMem(
4249 .{ .frame = dst_mcv.load_frame.index },4281 .{ .frame = dst_mcv.load_frame.index },
4250 @intCast(tuple_ty.structFieldOffset(1, mod)),4282 @intCast(tuple_ty.structFieldOffset(1, mod)),
4251 tuple_ty.structFieldType(1, mod),4283 tuple_ty.structFieldType(1, mod),
4252 .{ .register = tmp_regs[1] },4284 .{ .register = tmp_regs[1] },
4285 .{},
4253 );4286 );
4254 break :result dst_mcv;4287 break :result dst_mcv;
4255 },4288 },
...@@ -4297,12 +4330,14 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -4297,12 +4330,14 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
4297 @intCast(tuple_ty.structFieldOffset(0, mod)),4330 @intCast(tuple_ty.structFieldOffset(0, mod)),
4298 tuple_ty.structFieldType(0, mod),4331 tuple_ty.structFieldType(0, mod),
4299 partial_mcv,4332 partial_mcv,
4333 .{},
4300 );4334 );
4301 try self.genSetMem(4335 try self.genSetMem(
4302 .{ .frame = frame_index },4336 .{ .frame = frame_index },
4303 @intCast(tuple_ty.structFieldOffset(1, mod)),4337 @intCast(tuple_ty.structFieldOffset(1, mod)),
4304 tuple_ty.structFieldType(1, mod),4338 tuple_ty.structFieldType(1, mod),
4305 .{ .immediate = 0 }, // cc being set is impossible4339 .{ .immediate = 0 }, // cc being set is impossible
4340 .{},
4306 );4341 );
4307 } else try self.genSetFrameTruncatedOverflowCompare(4342 } else try self.genSetFrameTruncatedOverflowCompare(
4308 tuple_ty,4343 tuple_ty,
...@@ -4330,7 +4365,7 @@ fn genIntMulDivOpMir(self: *Self, tag: Mir.Inst.FixedTag, ty: Type, lhs: MCValue...@@ -4330,7 +4365,7 @@ fn genIntMulDivOpMir(self: *Self, tag: Mir.Inst.FixedTag, ty: Type, lhs: MCValue
4330 return self.fail("TODO implement genIntMulDivOpMir for ABI size larger than 8", .{});4365 return self.fail("TODO implement genIntMulDivOpMir for ABI size larger than 8", .{});
4331 }4366 }
43324367
4333 try self.genSetReg(.rax, ty, lhs);4368 try self.genSetReg(.rax, ty, lhs, .{});
4334 switch (tag[1]) {4369 switch (tag[1]) {
4335 else => unreachable,4370 else => unreachable,
4336 .mul => {},4371 .mul => {},
...@@ -4459,6 +4494,7 @@ fn airShlShrBinOp(self: *Self, inst: Air.Inst.Index) !void {...@@ -4459,6 +4494,7 @@ fn airShlShrBinOp(self: *Self, inst: Air.Inst.Index) !void {
4459 tmp_reg,4494 tmp_reg,
4460 tmp_ty,4495 tmp_ty,
4461 .{ .load_frame = .{ .index = frame_addr.index, .off = off } },4496 .{ .load_frame = .{ .index = frame_addr.index, .off = off } },
4497 .{},
4462 );4498 );
4463 try self.truncateRegister(lhs_ty, tmp_reg);4499 try self.truncateRegister(lhs_ty, tmp_reg);
4464 try self.genSetMem(4500 try self.genSetMem(
...@@ -4466,6 +4502,7 @@ fn airShlShrBinOp(self: *Self, inst: Air.Inst.Index) !void {...@@ -4466,6 +4502,7 @@ fn airShlShrBinOp(self: *Self, inst: Air.Inst.Index) !void {
4466 off,4502 off,
4467 tmp_ty,4503 tmp_ty,
4468 .{ .register = tmp_reg },4504 .{ .register = tmp_reg },
4505 .{},
4469 );4506 );
4470 },4507 },
4471 else => {},4508 else => {},
...@@ -4726,7 +4763,7 @@ fn airOptionalPayload(self: *Self, inst: Air.Inst.Index) !void {...@@ -4726,7 +4763,7 @@ fn airOptionalPayload(self: *Self, inst: Air.Inst.Index) !void {
4726 try self.genCopy(pl_ty, pl_mcv, switch (opt_mcv) {4763 try self.genCopy(pl_ty, pl_mcv, switch (opt_mcv) {
4727 else => opt_mcv,4764 else => opt_mcv,
4728 .register_overflow => |ro| .{ .register = ro.reg },4765 .register_overflow => |ro| .{ .register = ro.reg },
4729 });4766 }, .{});
4730 break :result pl_mcv;4767 break :result pl_mcv;
4731 };4768 };
4732 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });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,7 +4810,13 @@ fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {
47734810
4774 const pl_ty = dst_ty.childType(mod);4811 const pl_ty = dst_ty.childType(mod);
4775 const pl_abi_size: i32 = @intCast(pl_ty.abiSize(mod));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 break :result if (self.liveness.isUnused(inst)) .unreach else dst_mcv;4820 break :result if (self.liveness.isUnused(inst)) .unreach else dst_mcv;
4778 };4821 };
4779 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });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,7 +5082,7 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {
5039 defer if (pl_lock) |lock| self.register_manager.unlockReg(lock);5082 defer if (pl_lock) |lock| self.register_manager.unlockReg(lock);
50405083
5041 const opt_mcv = try self.allocRegOrMem(inst, true);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, .{});
50435086
5044 if (!same_repr) {5087 if (!same_repr) {
5045 const pl_abi_size: i32 = @intCast(pl_ty.abiSize(mod));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,8 +5132,8 @@ fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void {
5089 const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(eu_ty, mod));5132 const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(eu_ty, mod));
5090 const pl_off: i32 = @intCast(errUnionPayloadOffset(pl_ty, mod));5133 const pl_off: i32 = @intCast(errUnionPayloadOffset(pl_ty, mod));
5091 const err_off: i32 = @intCast(errUnionErrorOffset(pl_ty, mod));5134 const err_off: i32 = @intCast(errUnionErrorOffset(pl_ty, mod));
5092 try self.genSetMem(.{ .frame = frame_index }, pl_off, pl_ty, operand);5135 try self.genSetMem(.{ .frame = frame_index }, pl_off, pl_ty, operand, .{});
5093 try self.genSetMem(.{ .frame = frame_index }, err_off, err_ty, .{ .immediate = 0 });5136 try self.genSetMem(.{ .frame = frame_index }, err_off, err_ty, .{ .immediate = 0 }, .{});
5094 break :result .{ .load_frame = .{ .index = frame_index } };5137 break :result .{ .load_frame = .{ .index = frame_index } };
5095 };5138 };
5096 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });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,9 +5154,9 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {
5111 const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(eu_ty, mod));5154 const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(eu_ty, mod));
5112 const pl_off: i32 = @intCast(errUnionPayloadOffset(pl_ty, mod));5155 const pl_off: i32 = @intCast(errUnionPayloadOffset(pl_ty, mod));
5113 const err_off: i32 = @intCast(errUnionErrorOffset(pl_ty, mod));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 const operand = try self.resolveInst(ty_op.operand);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 break :result .{ .load_frame = .{ .index = frame_index } };5160 break :result .{ .load_frame = .{ .index = frame_index } };
5118 };5161 };
5119 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });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,7 +5170,7 @@ fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void {
51275170
5128 const dst_mcv = try self.allocRegOrMem(inst, true);5171 const dst_mcv = try self.allocRegOrMem(inst, true);
5129 const dst_ty = self.typeOfIndex(inst);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 break :result dst_mcv;5174 break :result dst_mcv;
5132 };5175 };
5133 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });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,7 +5190,7 @@ fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void {
5147 if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result len_mcv;5190 if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result len_mcv;
51485191
5149 const dst_mcv = try self.allocRegOrMem(inst, true);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 break :result dst_mcv;5194 break :result dst_mcv;
5152 },5195 },
5153 else => return self.fail("TODO implement slice_len for {}", .{src_mcv}),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,7 +5254,7 @@ fn elemOffset(self: *Self, index_ty: Type, index: MCValue, elem_size: u64) !Regi
5211 // Optimisation: if index MCValue is an immediate, we can multiply in `comptime`5254 // Optimisation: if index MCValue is an immediate, we can multiply in `comptime`
5212 // and set the register directly to the scaled offset as an immediate.5255 // and set the register directly to the scaled offset as an immediate.
5213 const reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);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 break :blk reg;5258 break :blk reg;
5216 },5259 },
5217 else => {5260 else => {
...@@ -5251,7 +5294,7 @@ fn genSliceElemPtr(self: *Self, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue {...@@ -5251,7 +5294,7 @@ fn genSliceElemPtr(self: *Self, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue {
5251 defer self.register_manager.unlockReg(offset_reg_lock);5294 defer self.register_manager.unlockReg(offset_reg_lock);
52525295
5253 const addr_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);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 // TODO we could allocate register here, but need to expect addr register and potentially5298 // TODO we could allocate register here, but need to expect addr register and potentially
5256 // offset register.5299 // offset register.
5257 try self.genBinOpMir(.{ ._, .add }, slice_ptr_field_type, .{ .register = addr_reg }, .{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,7 +5396,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
5353 switch (array_mcv) {5396 switch (array_mcv) {
5354 .register => {5397 .register => {
5355 const frame_index = try self.allocFrameIndex(FrameAlloc.initType(array_ty, mod));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 try self.asmRegisterMemory(5400 try self.asmRegisterMemory(
5358 .{ ._, .lea },5401 .{ ._, .lea },
5359 addr_reg,5402 addr_reg,
...@@ -5373,7 +5416,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -5373,7 +5416,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
5373 .load_direct,5416 .load_direct,
5374 .load_got,5417 .load_got,
5375 .load_tlv,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 .lea_symbol, .lea_direct, .lea_tlv => unreachable,5420 .lea_symbol, .lea_direct, .lea_tlv => unreachable,
5378 else => return self.fail("TODO airArrayElemVal_val for {s} of {}", .{5421 else => return self.fail("TODO airArrayElemVal_val for {s} of {}", .{
5379 @tagName(array_mcv), array_ty.fmt(mod),5422 @tagName(array_mcv), array_ty.fmt(mod),
...@@ -5393,7 +5436,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -5393,7 +5436,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
5393 .{ .register = addr_reg },5436 .{ .register = addr_reg },
5394 .{ .register = offset_reg },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 break :result dst_mcv;5440 break :result dst_mcv;
5398 };5441 };
5399 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });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,7 +5576,7 @@ fn airSetUnionTag(self: *Self, inst: Air.Inst.Index) !void {
5533 } else ptr;5576 } else ptr;
55345577
5535 const ptr_tag_ty = try mod.adjustPtrTypeChild(ptr_union_ty, tag_ty);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, .{});
55375580
5538 return self.finishAir(inst, .none, .{ bin_op.lhs, bin_op.rhs, .none });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,7 +5786,7 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void {
5743 registerAlias(dst_reg, cmov_abi_size),5786 registerAlias(dst_reg, cmov_abi_size),
5744 );5787 );
57455788
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 try self.genBinOpMir(.{ ._, .sub }, dst_ty, dst_mcv, .{ .register = imm_reg });5790 try self.genBinOpMir(.{ ._, .sub }, dst_ty, dst_mcv, .{ .register = imm_reg });
5748 }5791 }
5749 break :result dst_mcv;5792 break :result dst_mcv;
...@@ -5798,7 +5841,7 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void {...@@ -5798,7 +5841,7 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void {
5798 const tmp_mcv = tmp: {5841 const tmp_mcv = tmp: {
5799 if (src_mcv.isImmediate() or self.liveness.operandDies(inst, 0))5842 if (src_mcv.isImmediate() or self.liveness.operandDies(inst, 0))
5800 break :tmp src_mcv;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 break :tmp dst_mcv;5845 break :tmp dst_mcv;
5803 };5846 };
5804 try self.genBinOpMir(5847 try self.genBinOpMir(
...@@ -5826,7 +5869,7 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void {...@@ -5826,7 +5869,7 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void {
5826 else5869 else
5827 .{ .register = mat_src_mcv.register_pair[1] };5870 .{ .register = mat_src_mcv.register_pair[1] };
5828 const masked_mcv = if (src_bits < 128) masked: {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 try self.genBinOpMir(5873 try self.genBinOpMir(
5831 .{ ._, .@"or" },5874 .{ ._, .@"or" },
5832 Type.u64,5875 Type.u64,
...@@ -5941,7 +5984,7 @@ fn genPopCount(...@@ -5941,7 +5984,7 @@ fn genPopCount(
5941 if (src_abi_size > 1) src_ty else Type.u32,5984 if (src_abi_size > 1) src_ty else Type.u32,
5942 .{ .register = dst_reg },5985 .{ .register = dst_reg },
5943 if (src_abi_size > 1) src_mcv else src: {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 try self.truncateRegister(try src_ty.toUnsigned(mod), dst_reg);5988 try self.truncateRegister(try src_ty.toUnsigned(mod), dst_reg);
5946 break :src .{ .register = dst_reg };5989 break :src .{ .register = dst_reg };
5947 },5990 },
...@@ -5964,7 +6007,7 @@ fn genPopCount(...@@ -5964,7 +6007,7 @@ fn genPopCount(
5964 else6007 else
5965 undefined;6008 undefined;
59666009
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 // dst = operand6011 // dst = operand
5969 try self.asmRegisterRegister(.{ ._, .mov }, tmp, dst);6012 try self.asmRegisterRegister(.{ ._, .mov }, tmp, dst);
5970 // tmp = operand6013 // tmp = operand
...@@ -6102,7 +6145,7 @@ fn genByteSwap(...@@ -6102,7 +6145,7 @@ fn genByteSwap(
6102 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_mcv.register);6145 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_mcv.register);
6103 defer self.register_manager.unlockReg(dst_lock);6146 defer self.register_manager.unlockReg(dst_lock);
61046147
6105 try self.genSetReg(dst_reg, src_ty, src_mcv);6148 try self.genSetReg(dst_reg, src_ty, src_mcv, .{});
6106 switch (abi_size) {6149 switch (abi_size) {
6107 else => unreachable,6150 else => unreachable,
6108 2 => try self.genBinOpMir(.{ ._l, .ro }, src_ty, dst_mcv, .{ .immediate = 8 }),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,7 +6318,7 @@ fn floatSign(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, ty: Type)
6275 if (!std.meta.eql(src_mcv, dst_mcv) or !self.reuseOperand(inst, operand, 0, src_mcv))6318 if (!std.meta.eql(src_mcv, dst_mcv) or !self.reuseOperand(inst, operand, 0, src_mcv))
6276 try self.register_manager.getReg(.st0, inst);6319 try self.register_manager.getReg(.st0, inst);
62776320
6278 try self.genCopy(ty, dst_mcv, src_mcv);6321 try self.genCopy(ty, dst_mcv, src_mcv, .{});
6279 switch (tag) {6322 switch (tag) {
6280 .neg => try self.asmOpOnly(.{ .f_, .chs }),6323 .neg => try self.asmOpOnly(.{ .f_, .chs }),
6281 .abs => try self.asmOpOnly(.{ .f_, .abs }),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,7 +6535,7 @@ fn genRound(self: *Self, ty: Type, dst_reg: Register, src_mcv: MCValue, mode: Ro
6492 const mod = self.bin_file.comp.module.?;6535 const mod = self.bin_file.comp.module.?;
6493 const mir_tag = self.getRoundTag(ty) orelse {6536 const mir_tag = self.getRoundTag(ty) orelse {
6494 const result = try self.genRoundLibcall(ty, src_mcv, mode);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 const abi_size: u32 = @intCast(ty.abiSize(mod));6540 const abi_size: u32 = @intCast(ty.abiSize(mod));
6498 const dst_alias = registerAlias(dst_reg, abi_size);6541 const dst_alias = registerAlias(dst_reg, abi_size);
...@@ -6583,7 +6626,7 @@ fn airAbs(self: *Self, inst: Air.Inst.Index) !void {...@@ -6583,7 +6626,7 @@ fn airAbs(self: *Self, inst: Air.Inst.Index) !void {
6583 const dst_locks = self.register_manager.lockRegsAssumeUnused(2, dst_regs);6626 const dst_locks = self.register_manager.lockRegsAssumeUnused(2, dst_regs);
6584 defer for (dst_locks) |lock| self.register_manager.unlockReg(lock);6627 defer for (dst_locks) |lock| self.register_manager.unlockReg(lock);
65856628
6586 try self.genCopy(ty, dst_mcv, src_mcv);6629 try self.genCopy(ty, dst_mcv, src_mcv, .{});
6587 break :dst dst_mcv;6630 break :dst dst_mcv;
6588 };6631 };
6589 const dst_regs = dst_mcv.register_pair;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,9 +6983,9 @@ fn packedLoad(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) Inn
6940 defer self.register_manager.unlockReg(tmp_lock);6983 defer self.register_manager.unlockReg(tmp_lock);
69416984
6942 const hi_mcv = dst_mcv.address().offset(@intCast(val_bit_size / 64 * 8)).deref();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 try self.truncateRegister(val_ty, tmp_reg);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 return;6991 return;
...@@ -7011,7 +7054,7 @@ fn packedLoad(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) Inn...@@ -7011,7 +7054,7 @@ fn packedLoad(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) Inn
7011 }7054 }
70127055
7013 if (val_extra_bits > 0) try self.truncateRegister(val_ty, dst_reg);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}
70167059
7017fn load(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) InnerError!void {7060fn 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,7 +7079,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) InnerErro
7036 .lea_got,7079 .lea_got,
7037 .lea_tlv,7080 .lea_tlv,
7038 .lea_frame,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 .memory,7083 .memory,
7041 .indirect,7084 .indirect,
7042 .load_symbol,7085 .load_symbol,
...@@ -7049,7 +7092,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) InnerErro...@@ -7049,7 +7092,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) InnerErro
7049 const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg);7092 const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
7050 defer self.register_manager.unlockReg(addr_lock);7093 defer self.register_manager.unlockReg(addr_lock);
70517094
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 .air_ref => |ptr_ref| try self.load(dst_mcv, ptr_ty, try self.resolveInst(ptr_ref)),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,6 +7148,7 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {
7105 if (elem_size <= 8) elem_ty else Type.usize,7148 if (elem_size <= 8) elem_ty else Type.usize,
7106 high_mcv,7149 high_mcv,
7107 .{ .register = high_reg },7150 .{ .register = high_reg },
7151 .{},
7108 );7152 );
7109 }7153 }
7110 break :result dst_mcv;7154 break :result dst_mcv;
...@@ -7167,7 +7211,7 @@ fn packedStore(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) In...@@ -7167,7 +7211,7 @@ fn packedStore(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) In
7167 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);7211 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
7168 defer self.register_manager.unlockReg(tmp_lock);7212 defer self.register_manager.unlockReg(tmp_lock);
71697213
7170 try self.genSetReg(tmp_reg, limb_ty, src_mcv);7214 try self.genSetReg(tmp_reg, limb_ty, src_mcv, .{});
7171 switch (limb_i) {7215 switch (limb_i) {
7172 0 => try self.genShiftBinOpMir(7216 0 => try self.genShiftBinOpMir(
7173 .{ ._l, .sh },7217 .{ ._l, .sh },
...@@ -7198,7 +7242,7 @@ fn packedStore(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) In...@@ -7198,7 +7242,7 @@ fn packedStore(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) In
7198 try self.genSetReg(tmp_reg, limb_ty, switch (limb_i) {7242 try self.genSetReg(tmp_reg, limb_ty, switch (limb_i) {
7199 0 => src_mcv,7243 0 => src_mcv,
7200 else => src_mcv.address().offset(limb_i * limb_abi_size).deref(),7244 else => src_mcv.address().offset(limb_i * limb_abi_size).deref(),
7201 });7245 }, .{});
7202 try self.genBinOpMir(.{ ._, .@"and" }, limb_ty, tmp_mcv, .{ .immediate = part_mask });7246 try self.genBinOpMir(.{ ._, .@"and" }, limb_ty, tmp_mcv, .{ .immediate = part_mask });
7203 try self.asmMemoryRegister(7247 try self.asmMemoryRegister(
7204 .{ ._, .@"or" },7248 .{ ._, .@"or" },
...@@ -7209,7 +7253,13 @@ fn packedStore(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) In...@@ -7209,7 +7253,13 @@ fn packedStore(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) In
7209 }7253 }
7210}7254}
72117255
7212fn store(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) InnerError!void {7256fn store(
7257 self: *Self,
7258 ptr_ty: Type,
7259 ptr_mcv: MCValue,
7260 src_mcv: MCValue,
7261 opts: CopyOptions,
7262) InnerError!void {
7213 const mod = self.bin_file.comp.module.?;7263 const mod = self.bin_file.comp.module.?;
7214 const src_ty = ptr_ty.childType(mod);7264 const src_ty = ptr_ty.childType(mod);
7215 if (!src_ty.hasRuntimeBitsIgnoreComptime(mod)) return;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,7 +7281,7 @@ fn store(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) InnerErr
7231 .lea_got,7281 .lea_got,
7232 .lea_tlv,7282 .lea_tlv,
7233 .lea_frame,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 .memory,7285 .memory,
7236 .indirect,7286 .indirect,
7237 .load_symbol,7287 .load_symbol,
...@@ -7244,9 +7294,9 @@ fn store(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) InnerErr...@@ -7244,9 +7294,9 @@ fn store(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) InnerErr
7244 const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg);7294 const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
7245 defer self.register_manager.unlockReg(addr_lock);7295 defer self.register_manager.unlockReg(addr_lock);
72467296
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}
72527302
...@@ -7269,7 +7319,7 @@ fn airStore(self: *Self, inst: Air.Inst.Index, safety: bool) !void {...@@ -7269,7 +7319,7 @@ fn airStore(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
7269 if (ptr_info.flags.vector_index != .none or ptr_info.packed_offset.host_size > 0) {7319 if (ptr_info.flags.vector_index != .none or ptr_info.packed_offset.host_size > 0) {
7270 try self.packedStore(ptr_ty, ptr_mcv, src_mcv);7320 try self.packedStore(ptr_ty, ptr_mcv, src_mcv);
7271 } else {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 return self.finishAir(inst, .none, .{ bin_op.lhs, bin_op.rhs, .none });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,7 +7439,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
7389 const dst_locks = self.register_manager.lockRegsAssumeUnused(2, dst_regs);7439 const dst_locks = self.register_manager.lockRegsAssumeUnused(2, dst_regs);
7390 defer for (dst_locks) |lock| self.register_manager.unlockReg(lock);7440 defer for (dst_locks) |lock| self.register_manager.unlockReg(lock);
73917441
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 break :dst dst_regs;7443 break :dst dst_regs;
7394 };7444 };
7395 const dst_mcv = MCValue{ .register_pair = dst_regs };7445 const dst_mcv = MCValue{ .register_pair = dst_regs };
...@@ -7493,7 +7543,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -7493,7 +7543,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
7493 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);7543 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);
7494 defer self.register_manager.unlockReg(dst_lock);7544 defer self.register_manager.unlockReg(dst_lock);
74957545
7496 try self.genCopy(int_ty, dst_mcv, off_mcv);7546 try self.genCopy(int_ty, dst_mcv, off_mcv, .{});
7497 if (self.regExtraBits(field_ty) > 0) try self.truncateRegister(int_ty, dst_reg);7547 if (self.regExtraBits(field_ty) > 0) try self.truncateRegister(int_ty, dst_reg);
7498 break :result if (field_is_gp)7548 break :result if (field_is_gp)
7499 dst_mcv7549 dst_mcv
...@@ -7507,7 +7557,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -7507,7 +7557,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
7507 off_mcv7557 off_mcv
7508 else dst: {7558 else dst: {
7509 const dst_mcv = try self.allocRegOrMem(inst, true);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 break :dst dst_mcv;7561 break :dst dst_mcv;
7512 };7562 };
7513 if (field_abi_size * 8 > field_bit_size and dst_mcv.isMemory()) {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,9 +7567,9 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
75177567
7518 const hi_mcv =7568 const hi_mcv =
7519 dst_mcv.address().offset(@intCast(field_bit_size / 64 * 8)).deref();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 try self.truncateRegister(field_ty, tmp_reg);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 break :result dst_mcv;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,7 +7700,7 @@ fn genUnOp(self: *Self, maybe_inst: ?Air.Inst.Index, tag: Air.Inst.Tag, src_air:
7650 if (maybe_inst) |inst| if (self.reuseOperand(inst, src_air, 0, src_mcv)) break :dst src_mcv;7700 if (maybe_inst) |inst| if (self.reuseOperand(inst, src_air, 0, src_mcv)) break :dst src_mcv;
76517701
7652 const dst_mcv = try self.allocRegOrMemAdvanced(src_ty, maybe_inst, true);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 break :dst dst_mcv;7704 break :dst dst_mcv;
7655 };7705 };
7656 const dst_lock = switch (dst_mcv) {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,9 +7747,9 @@ fn genUnOp(self: *Self, maybe_inst: ?Air.Inst.Index, tag: Air.Inst.Tag, src_air:
7697 defer self.register_manager.unlockReg(tmp_lock);7747 defer self.register_manager.unlockReg(tmp_lock);
76987748
7699 const hi_mcv = dst_mcv.address().offset(@intCast(bit_size / 64 * 8)).deref();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 try self.truncateRegister(src_ty, tmp_reg);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,7 +7786,7 @@ fn genUnOpMir(self: *Self, mir_tag: Mir.Inst.FixedTag, dst_ty: Type, dst_mcv: MC
7736 const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg);7786 const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
7737 defer self.register_manager.unlockReg(addr_reg_lock);7787 defer self.register_manager.unlockReg(addr_reg_lock);
77387788
7739 try self.genSetReg(addr_reg, Type.usize, dst_mcv.address());7789 try self.genSetReg(addr_reg, Type.usize, dst_mcv.address(), .{});
7740 try self.asmMemory(mir_tag, .{ .base = .{ .reg = addr_reg }, .mod = .{ .rm = .{7790 try self.asmMemory(mir_tag, .{ .base = .{ .reg = addr_reg }, .mod = .{ .rm = .{
7741 .size = Memory.Size.fromSize(abi_size),7791 .size = Memory.Size.fromSize(abi_size),
7742 } } });7792 } } });
...@@ -7767,7 +7817,7 @@ fn genShiftBinOpMir(...@@ -7767,7 +7817,7 @@ fn genShiftBinOpMir(
7767 else => {},7817 else => {},
7768 }7818 }
7769 self.register_manager.getRegAssumeFree(.rcx, null);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 break :rhs .{ .register = .rcx };7821 break :rhs .{ .register = .rcx };
7772 };7822 };
77737823
...@@ -8161,7 +8211,7 @@ fn genShiftBinOp(...@@ -8161,7 +8211,7 @@ fn genShiftBinOp(
8161 if (self.reuseOperand(inst, bin_op.lhs, 0, lhs_mcv)) break :dst lhs_mcv;8211 if (self.reuseOperand(inst, bin_op.lhs, 0, lhs_mcv)) break :dst lhs_mcv;
8162 }8212 }
8163 const dst_mcv = try self.allocRegOrMemAdvanced(lhs_ty, maybe_inst, true);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 break :dst dst_mcv;8215 break :dst dst_mcv;
8166 };8216 };
81678217
...@@ -8290,6 +8340,7 @@ fn genMulDivBinOp(...@@ -8290,6 +8340,7 @@ fn genMulDivBinOp(
8290 dst_mcv.address(),8340 dst_mcv.address(),
8291 .{ .immediate = 0 },8341 .{ .immediate = 0 },
8292 .{ .immediate = src_abi_size },8342 .{ .immediate = src_abi_size },
8343 .{},
8293 );8344 );
82948345
8295 const temp_regs = try self.register_manager.allocRegs(8346 const temp_regs = try self.register_manager.allocRegs(
...@@ -8891,7 +8942,7 @@ fn genBinOp(...@@ -8891,7 +8942,7 @@ fn genBinOp(
8891 if (sse_op and lhs_mcv.isRegister() and self.hasFeature(.avx))8942 if (sse_op and lhs_mcv.isRegister() and self.hasFeature(.avx))
8892 copied_to_dst = false8943 copied_to_dst = false
8893 else8944 else
8894 try self.genCopy(lhs_ty, dst_mcv, lhs_mcv);8945 try self.genCopy(lhs_ty, dst_mcv, lhs_mcv, .{});
8895 rhs_mcv = try self.resolveInst(ordered_air[1]);8946 rhs_mcv = try self.resolveInst(ordered_air[1]);
8896 break :dst dst_mcv;8947 break :dst dst_mcv;
8897 };8948 };
...@@ -8906,7 +8957,7 @@ fn genBinOp(...@@ -8906,7 +8957,7 @@ fn genBinOp(
8906 const src_mcv: MCValue = if (maybe_mask_reg) |mask_reg|8957 const src_mcv: MCValue = if (maybe_mask_reg) |mask_reg|
8907 if (self.hasFeature(.avx) and unmat_src_mcv.isRegister() and maybe_inst != null and8958 if (self.hasFeature(.avx) and unmat_src_mcv.isRegister() and maybe_inst != null and
8908 self.liveness.operandDies(maybe_inst.?, if (flipped) 0 else 1)) unmat_src_mcv else src: {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 break :src .{ .register = mask_reg };8961 break :src .{ .register = mask_reg };
8911 }8962 }
8912 else8963 else
...@@ -8981,7 +9032,7 @@ fn genBinOp(...@@ -8981,7 +9032,7 @@ fn genBinOp(
8981 defer for (dst_regs_locks) |dst_lock| if (dst_lock) |lock|9032 defer for (dst_regs_locks) |dst_lock| if (dst_lock) |lock|
8982 self.register_manager.unlockReg(lock);9033 self.register_manager.unlockReg(lock);
89839034
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 break :dst dst_regs;9036 break :dst dst_regs;
8986 },9037 },
8987 };9038 };
...@@ -9036,7 +9087,7 @@ fn genBinOp(...@@ -9036,7 +9087,7 @@ fn genBinOp(
9036 try self.asmCmovccRegisterRegister(cc, dst_regs[0], src_mcv.register_pair[0]);9087 try self.asmCmovccRegisterRegister(cc, dst_regs[0], src_mcv.register_pair[0]);
9037 try self.asmCmovccRegisterRegister(cc, dst_regs[1], src_mcv.register_pair[1]);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 } else {9091 } else {
9041 const mat_src_mcv: MCValue = if (switch (resolved_src_mcv) {9092 const mat_src_mcv: MCValue = if (switch (resolved_src_mcv) {
9042 .immediate,9093 .immediate,
...@@ -9146,7 +9197,7 @@ fn genBinOp(...@@ -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 },
91529203
...@@ -10519,7 +10570,7 @@ fn genBinOpMir(...@@ -10519,7 +10570,7 @@ fn genBinOpMir(
10519 const dst_addr_lock = self.register_manager.lockRegAssumeUnused(dst_addr_reg);10570 const dst_addr_lock = self.register_manager.lockRegAssumeUnused(dst_addr_reg);
10520 errdefer self.register_manager.unlockReg(dst_addr_lock);10571 errdefer self.register_manager.unlockReg(dst_addr_lock);
1052110572
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 break :dst .{ .addr_reg = dst_addr_reg, .addr_lock = dst_addr_lock };10574 break :dst .{ .addr_reg = dst_addr_reg, .addr_lock = dst_addr_lock };
10524 },10575 },
10525 .load_frame => null,10576 .load_frame => null,
...@@ -10566,7 +10617,7 @@ fn genBinOpMir(...@@ -10566,7 +10617,7 @@ fn genBinOpMir(
10566 const src_addr_lock = self.register_manager.lockRegAssumeUnused(src_addr_reg);10617 const src_addr_lock = self.register_manager.lockRegAssumeUnused(src_addr_reg);
10567 errdefer self.register_manager.unlockReg(src_addr_lock);10618 errdefer self.register_manager.unlockReg(src_addr_lock);
1056810619
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 break :src .{ .addr_reg = src_addr_reg, .addr_lock = src_addr_lock };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,7 +10918,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
10867 defer self.register_manager.unlockReg(tmp_lock);10918 defer self.register_manager.unlockReg(tmp_lock);
1086810919
10869 try self.genIntMulComplexOpMir(dst_ty, tmp_mcv, src_mcv);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,7 +10941,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
10890 .indirect => |reg_off| dst: {10941 .indirect => |reg_off| dst: {
10891 self.register_manager.getRegAssumeFree(reg_off.reg, inst);10942 self.register_manager.getRegAssumeFree(reg_off.reg, inst);
10892 const dst_mcv = try self.allocRegOrMem(inst, false);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 break :dst dst_mcv;10945 break :dst dst_mcv;
10895 },10946 },
10896 else => return self.fail("TODO implement arg for {}", .{src_mcv}),10947 else => return self.fail("TODO implement arg for {}", .{src_mcv}),
...@@ -10998,13 +11049,13 @@ fn airBreakpoint(self: *Self) !void {...@@ -10998,13 +11049,13 @@ fn airBreakpoint(self: *Self) !void {
1099811049
10999fn airRetAddr(self: *Self, inst: Air.Inst.Index) !void {11050fn airRetAddr(self: *Self, inst: Air.Inst.Index) !void {
11000 const dst_mcv = try self.allocRegOrMem(inst, true);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 return self.finishAir(inst, dst_mcv, .{ .none, .none, .none });11053 return self.finishAir(inst, dst_mcv, .{ .none, .none, .none });
11003}11054}
1100411055
11005fn airFrameAddress(self: *Self, inst: Air.Inst.Index) !void {11056fn airFrameAddress(self: *Self, inst: Air.Inst.Index) !void {
11006 const dst_mcv = try self.allocRegOrMem(inst, true);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 return self.finishAir(inst, dst_mcv, .{ .none, .none, .none });11059 return self.finishAir(inst, dst_mcv, .{ .none, .none, .none });
11009}11060}
1101011061
...@@ -11143,12 +11194,12 @@ fn genCall(self: *Self, info: union(enum) {...@@ -11143,12 +11194,12 @@ fn genCall(self: *Self, info: union(enum) {
11143 },11194 },
11144 .indirect => |reg_off| {11195 .indirect => |reg_off| {
11145 frame_index.* = try self.allocFrameIndex(FrameAlloc.initType(arg_ty, mod));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 try self.register_manager.getReg(reg_off.reg, null);11198 try self.register_manager.getReg(reg_off.reg, null);
11148 try reg_locks.append(self.register_manager.lockReg(reg_off.reg));11199 try reg_locks.append(self.register_manager.lockReg(reg_off.reg));
11149 },11200 },
11150 .load_frame => {11201 .load_frame => {
11151 try self.genCopy(arg_ty, dst_arg, src_arg);11202 try self.genCopy(arg_ty, dst_arg, src_arg, .{});
11152 try self.freeValue(src_arg);11203 try self.freeValue(src_arg);
11153 },11204 },
11154 else => unreachable,11205 else => unreachable,
...@@ -11162,7 +11213,7 @@ fn genCall(self: *Self, info: union(enum) {...@@ -11162,7 +11213,7 @@ fn genCall(self: *Self, info: union(enum) {
11162 const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(ret_ty, mod));11213 const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(ret_ty, mod));
11163 try self.genSetReg(reg_off.reg, Type.usize, .{11214 try self.genSetReg(reg_off.reg, Type.usize, .{
11164 .lea_frame = .{ .index = frame_index, .off = -reg_off.off },11215 .lea_frame = .{ .index = frame_index, .off = -reg_off.off },
11165 });11216 }, .{});
11166 call_info.return_value.short = .{ .load_frame = .{ .index = frame_index } };11217 call_info.return_value.short = .{ .load_frame = .{ .index = frame_index } };
11167 try reg_locks.append(self.register_manager.lockReg(reg_off.reg));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,20 +11228,21 @@ fn genCall(self: *Self, info: union(enum) {
11177 registerAlias(dst_reg, @intCast(arg_ty.abiSize(mod))),11228 registerAlias(dst_reg, @intCast(arg_ty.abiSize(mod))),
11178 arg_ty,11229 arg_ty,
11179 src_arg,11230 src_arg,
11231 .{},
11180 ),11232 ),
11181 .C, .SysV, .Win64 => {11233 .C, .SysV, .Win64 => {
11182 const promoted_ty = self.promoteInt(arg_ty);11234 const promoted_ty = self.promoteInt(arg_ty);
11183 const promoted_abi_size: u32 = @intCast(promoted_ty.abiSize(mod));11235 const promoted_abi_size: u32 = @intCast(promoted_ty.abiSize(mod));
11184 const dst_alias = registerAlias(dst_reg, promoted_abi_size);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 if (promoted_ty.toIntern() != arg_ty.toIntern())11238 if (promoted_ty.toIntern() != arg_ty.toIntern())
11187 try self.truncateRegister(arg_ty, dst_alias);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 .indirect => |reg_off| try self.genSetReg(reg_off.reg, Type.usize, .{11243 .indirect => |reg_off| try self.genSetReg(reg_off.reg, Type.usize, .{
11192 .lea_frame = .{ .index = frame_index, .off = -reg_off.off },11244 .lea_frame = .{ .index = frame_index, .off = -reg_off.off },
11193 }),11245 }, .{}),
11194 else => unreachable,11246 else => unreachable,
11195 };11247 };
1119611248
...@@ -11231,6 +11283,7 @@ fn genCall(self: *Self, info: union(enum) {...@@ -11231,6 +11283,7 @@ fn genCall(self: *Self, info: union(enum) {
11231 callee_reg,11283 callee_reg,
11232 Type.usize,11284 Type.usize,
11233 .{ .load_symbol = .{ .sym = sym.esym_index } },11285 .{ .load_symbol = .{ .sym = sym.esym_index } },
11286 .{},
11234 );11287 );
11235 try self.asmRegister(.{ ._, .call }, callee_reg);11288 try self.asmRegister(.{ ._, .call }, callee_reg);
11236 } else try self.asmMemory(.{ ._, .call }, .{11289 } else try self.asmMemory(.{ ._, .call }, .{
...@@ -11243,12 +11296,17 @@ fn genCall(self: *Self, info: union(enum) {...@@ -11243,12 +11296,17 @@ fn genCall(self: *Self, info: union(enum) {
11243 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {11296 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
11244 const atom = try coff_file.getOrCreateAtomForDecl(func.owner_decl);11297 const atom = try coff_file.getOrCreateAtomForDecl(func.owner_decl);
11245 const sym_index = coff_file.getAtom(atom).getSymbolIndex().?;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 try self.asmRegister(.{ ._, .call }, .rax);11300 try self.asmRegister(.{ ._, .call }, .rax);
11248 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {11301 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
11249 const sym_index = try macho_file.getZigObject().?.getOrCreateMetadataForDecl(macho_file, func.owner_decl);11302 const sym_index = try macho_file.getZigObject().?.getOrCreateMetadataForDecl(macho_file, func.owner_decl);
11250 const sym = macho_file.getSymbol(sym_index);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 try self.asmRegister(.{ ._, .call }, .rax);11310 try self.asmRegister(.{ ._, .call }, .rax);
11253 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {11311 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {
11254 const atom_index = try p9.seeDecl(func.owner_decl);11312 const atom_index = try p9.seeDecl(func.owner_decl);
...@@ -11273,7 +11331,7 @@ fn genCall(self: *Self, info: union(enum) {...@@ -11273,7 +11331,7 @@ fn genCall(self: *Self, info: union(enum) {
11273 }11331 }
11274 } else {11332 } else {
11275 assert(self.typeOf(callee).zigTypeTag(mod) == .Pointer);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 try self.asmRegister(.{ ._, .call }, .rax);11335 try self.asmRegister(.{ ._, .call }, .rax);
11278 },11336 },
11279 .lib => |lib| try self.genExternSymbolRef(.call, lib.lib, lib.callee),11337 .lib => |lib| try self.genExternSymbolRef(.call, lib.lib, lib.callee),
...@@ -11281,7 +11339,7 @@ fn genCall(self: *Self, info: union(enum) {...@@ -11281,7 +11339,7 @@ fn genCall(self: *Self, info: union(enum) {
11281 return call_info.return_value.short;11339 return call_info.return_value.short;
11282}11340}
1128311341
11284fn airRet(self: *Self, inst: Air.Inst.Index) !void {11342fn airRet(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
11285 const mod = self.bin_file.comp.module.?;11343 const mod = self.bin_file.comp.module.?;
11286 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;11344 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
1128711345
...@@ -11290,14 +11348,20 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void {...@@ -11290,14 +11348,20 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void {
11290 .none => {},11348 .none => {},
11291 .register,11349 .register,
11292 .register_pair,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 .indirect => |reg_off| {11352 .indirect => |reg_off| {
11295 try self.register_manager.getReg(reg_off.reg, null);11353 try self.register_manager.getReg(reg_off.reg, null);
11296 const lock = self.register_manager.lockRegAssumeUnused(reg_off.reg);11354 const lock = self.register_manager.lockRegAssumeUnused(reg_off.reg);
11297 defer self.register_manager.unlockReg(lock);11355 defer self.register_manager.unlockReg(lock);
1129811356
11299 try self.genSetReg(reg_off.reg, Type.usize, self.ret_mcv.long);11357 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 });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 else => unreachable,11366 else => unreachable,
11303 }11367 }
...@@ -11318,7 +11382,7 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {...@@ -11318,7 +11382,7 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {
11318 switch (self.ret_mcv.short) {11382 switch (self.ret_mcv.short) {
11319 .none => {},11383 .none => {},
11320 .register, .register_pair => try self.load(self.ret_mcv.short, ptr_ty, ptr),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 else => unreachable,11386 else => unreachable,
11323 }11387 }
11324 self.ret_mcv.liveOut(self, inst);11388 self.ret_mcv.liveOut(self, inst);
...@@ -11423,7 +11487,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {...@@ -11423,7 +11487,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
11423 const dst_mcv = if (unmat_dst_mcv.isRegister() or11487 const dst_mcv = if (unmat_dst_mcv.isRegister() or
11424 (abi_size <= 8 and unmat_dst_mcv.isMemory())) unmat_dst_mcv else dst: {11488 (abi_size <= 8 and unmat_dst_mcv.isMemory())) unmat_dst_mcv else dst: {
11425 const dst_mcv = try self.allocTempRegOrMem(ty, true);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 break :dst dst_mcv;11491 break :dst dst_mcv;
11428 };11492 };
11429 const dst_lock =11493 const dst_lock =
...@@ -11494,6 +11558,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {...@@ -11494,6 +11558,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
11494 dst_addr_reg,11558 dst_addr_reg,
11495 Type.usize,11559 Type.usize,
11496 resolved_dst_mcv.address(),11560 resolved_dst_mcv.address(),
11561 .{},
11497 );11562 );
11498 break :dst .{11563 break :dst .{
11499 .addr_reg = dst_addr_reg,11564 .addr_reg = dst_addr_reg,
...@@ -11553,6 +11618,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {...@@ -11553,6 +11618,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
11553 src_addr_reg,11618 src_addr_reg,
11554 Type.usize,11619 Type.usize,
11555 resolved_src_mcv.address(),11620 resolved_src_mcv.address(),
11621 .{},
11556 );11622 );
11557 break :src .{11623 break :src .{
11558 .addr_reg = src_addr_reg,11624 .addr_reg = src_addr_reg,
...@@ -11594,7 +11660,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {...@@ -11594,7 +11660,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
11594 .off = frame_addr.off + off,11660 .off = frame_addr.off + off,
11595 } },11661 } },
11596 else => unreachable,11662 else => unreachable,
11597 });11663 }, .{});
1159811664
11599 try self.genBinOpMir(11665 try self.genBinOpMir(
11600 .{ ._, .xor },11666 .{ ._, .xor },
...@@ -12000,7 +12066,7 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC...@@ -12000,7 +12066,7 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC
12000 const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg);12066 const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
12001 defer self.register_manager.unlockReg(addr_reg_lock);12067 defer self.register_manager.unlockReg(addr_reg_lock);
1200212068
12003 try self.genSetReg(addr_reg, Type.usize, opt_mcv.address());12069 try self.genSetReg(addr_reg, Type.usize, opt_mcv.address(), .{});
12004 const some_abi_size: u32 = @intCast(some_info.ty.abiSize(mod));12070 const some_abi_size: u32 = @intCast(some_info.ty.abiSize(mod));
12005 try self.asmMemoryImmediate(12071 try self.asmMemoryImmediate(
12006 .{ ._, .cmp },12072 .{ ._, .cmp },
...@@ -12440,7 +12506,7 @@ fn airBr(self: *Self, inst: Air.Inst.Index) !void {...@@ -12440,7 +12506,7 @@ fn airBr(self: *Self, inst: Air.Inst.Index) !void {
12440 try self.getValue(block_tracking.short, br.block_inst);12506 try self.getValue(block_tracking.short, br.block_inst);
12441 break :dst block_tracking.short;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 break :result dst_mcv;12510 break :result dst_mcv;
12445 };12511 };
1244612512
...@@ -12604,7 +12670,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {...@@ -12604,7 +12670,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
12604 rc.isSet(RegisterManager.indexOfRegIntoTracked(input_mcv.getReg().?).?))12670 rc.isSet(RegisterManager.indexOfRegIntoTracked(input_mcv.getReg().?).?))
12605 break :arg input_mcv;12671 break :arg input_mcv;
12606 const reg = try self.register_manager.allocReg(null, rc);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 break :arg .{ .register = registerAlias(reg, @intCast(ty.abiSize(mod))) };12674 break :arg .{ .register = registerAlias(reg, @intCast(ty.abiSize(mod))) };
12609 } else if (mem.eql(u8, constraint, "i") or mem.eql(u8, constraint, "n"))12675 } else if (mem.eql(u8, constraint, "i") or mem.eql(u8, constraint, "n"))
12610 switch (input_mcv) {12676 switch (input_mcv) {
...@@ -12621,16 +12687,16 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {...@@ -12621,16 +12687,16 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
12621 .load_symbol, .load_direct, .load_got, .load_tlv => {},12687 .load_symbol, .load_direct, .load_got, .load_tlv => {},
12622 else => {12688 else => {
12623 const temp_mcv = try self.allocTempRegOrMem(ty, false);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 break :arg temp_mcv;12691 break :arg temp_mcv;
12626 },12692 },
12627 }12693 }
12628 const addr_reg = self.register_manager.tryAllocReg(null, abi.RegisterClass.gp) orelse {12694 const addr_reg = self.register_manager.tryAllocReg(null, abi.RegisterClass.gp) orelse {
12629 const temp_mcv = try self.allocTempRegOrMem(ty, false);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 break :arg temp_mcv;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 break :arg .{ .indirect = .{ .reg = addr_reg } };12700 break :arg .{ .indirect = .{ .reg = addr_reg } };
12635 } else if (mem.eql(u8, constraint, "g") or12701 } else if (mem.eql(u8, constraint, "g") or
12636 mem.eql(u8, constraint, "rm") or mem.eql(u8, constraint, "mr") or12702 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,7 +12709,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
12643 else => {},12709 else => {},
12644 }12710 }
12645 const temp_mcv = try self.allocTempRegOrMem(ty, true);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 break :arg temp_mcv;12713 break :arg temp_mcv;
12648 } else if (mem.eql(u8, constraint, "X"))12714 } else if (mem.eql(u8, constraint, "X"))
12649 input_mcv12715 input_mcv
...@@ -12651,7 +12717,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {...@@ -12651,7 +12717,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
12651 const reg = parseRegName(constraint["{".len .. constraint.len - "}".len]) orelse12717 const reg = parseRegName(constraint["{".len .. constraint.len - "}".len]) orelse
12652 return self.fail("invalid register constraint: '{s}'", .{constraint});12718 return self.fail("invalid register constraint: '{s}'", .{constraint});
12653 try self.register_manager.getReg(reg, null);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 break :arg .{ .register = reg };12721 break :arg .{ .register = reg };
12656 } else if (constraint.len == 1 and std.ascii.isDigit(constraint[0])) arg: {12722 } else if (constraint.len == 1 and std.ascii.isDigit(constraint[0])) arg: {
12657 const index = std.fmt.charToDigit(constraint[0], 10) catch unreachable;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,7 +13171,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
13105 if (output == .none) continue;13171 if (output == .none) continue;
13106 if (arg_mcv != .register) continue;13172 if (arg_mcv != .register) continue;
13107 if (constraint.len == 2 and std.ascii.isDigit(constraint[1])) continue;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 }
1311013176
13111 simple: {13177 simple: {
...@@ -13477,7 +13543,11 @@ fn moveStrategy(self: *Self, ty: Type, class: Register.Class, aligned: bool) !Mo...@@ -13477,7 +13543,11 @@ fn moveStrategy(self: *Self, ty: Type, class: Register.Class, aligned: bool) !Mo
13477 return self.fail("TODO moveStrategy for {}", .{ty.fmt(mod)});13543 return self.fail("TODO moveStrategy for {}", .{ty.fmt(mod)});
13478}13544}
1347913545
13480fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) InnerError!void {13546const CopyOptions = struct {
13547 safety: bool = false,
13548};
13549
13550fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue, opts: CopyOptions) InnerError!void {
13481 const mod = self.bin_file.comp.module.?;13551 const mod = self.bin_file.comp.module.?;
1348213552
13483 const src_lock = if (src_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null;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,7 +13569,7 @@ fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) InnerError
13499 .reserved_frame,13569 .reserved_frame,
13500 .air_ref,13570 .air_ref,
13501 => unreachable, // unmodifiable destination13571 => 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 .register_offset => |dst_reg_off| try self.genSetReg(dst_reg_off.reg, ty, switch (src_mcv) {13573 .register_offset => |dst_reg_off| try self.genSetReg(dst_reg_off.reg, ty, switch (src_mcv) {
13504 .none,13574 .none,
13505 .unreach,13575 .unreach,
...@@ -13517,7 +13587,7 @@ fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) InnerError...@@ -13517,7 +13587,7 @@ fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) InnerError
13517 .reg = try self.copyToTmpRegister(ty, src_mcv),13587 .reg = try self.copyToTmpRegister(ty, src_mcv),
13518 .off = -dst_reg_off.off,13588 .off = -dst_reg_off.off,
13519 } },13589 } },
13520 }),13590 }, opts),
13521 .register_pair => |dst_regs| {13591 .register_pair => |dst_regs| {
13522 const src_info: ?struct { addr_reg: Register, addr_lock: RegisterLock } = switch (src_mcv) {13592 const src_info: ?struct { addr_reg: Register, addr_lock: RegisterLock } = switch (src_mcv) {
13523 .register_pair, .memory, .indirect, .load_frame => null,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,10 +13597,15 @@ fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) InnerError
13527 const src_addr_lock = self.register_manager.lockRegAssumeUnused(src_addr_reg);13597 const src_addr_lock = self.register_manager.lockRegAssumeUnused(src_addr_reg);
13528 errdefer self.register_manager.unlockReg(src_addr_lock);13598 errdefer self.register_manager.unlockReg(src_addr_lock);
1352913599
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 break :src .{ .addr_reg = src_addr_reg, .addr_lock = src_addr_lock };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 else => return self.fail("TODO implement genCopy for {s} of {}", .{13609 else => return self.fail("TODO implement genCopy for {s} of {}", .{
13535 @tagName(src_mcv), ty.fmt(mod),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,15 +13622,21 @@ fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) InnerError
13547 .off = part_disp,13622 .off = part_disp,
13548 } },13623 } },
13549 else => unreachable,13624 else => unreachable,
13550 });13625 }, opts);
13551 part_disp += @intCast(dst_ty.abiSize(mod));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 .memory, .load_symbol, .load_direct, .load_got, .load_tlv => {13636 .memory, .load_symbol, .load_direct, .load_got, .load_tlv => {
13556 switch (dst_mcv) {13637 switch (dst_mcv) {
13557 .memory => |addr| if (math.cast(i32, @as(i64, @bitCast(addr)))) |small_addr|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 .load_symbol, .load_direct, .load_got, .load_tlv => {},13640 .load_symbol, .load_direct, .load_got, .load_tlv => {},
13560 else => unreachable,13641 else => unreachable,
13561 }13642 }
...@@ -13564,18 +13645,25 @@ fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) InnerError...@@ -13564,18 +13645,25 @@ fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) InnerError
13564 const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg);13645 const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
13565 defer self.register_manager.unlockReg(addr_lock);13646 defer self.register_manager.unlockReg(addr_lock);
1356613647
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 .load_frame => |frame_addr| try self.genSetMem(13650 .load_frame => |frame_addr| try self.genSetMem(
13570 .{ .frame = frame_addr.index },13651 .{ .frame = frame_addr.index },
13571 frame_addr.off,13652 frame_addr.off,
13572 ty,13653 ty,
13573 src_mcv,13654 src_mcv,
13655 opts,
13574 ),13656 ),
13575 }13657 }
13576}13658}
1357713659
13578fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerError!void {13660fn genSetReg(
13661 self: *Self,
13662 dst_reg: Register,
13663 ty: Type,
13664 src_mcv: MCValue,
13665 opts: CopyOptions,
13666) InnerError!void {
13579 const mod = self.bin_file.comp.module.?;13667 const mod = self.bin_file.comp.module.?;
13580 const abi_size: u32 = @intCast(ty.abiSize(mod));13668 const abi_size: u32 = @intCast(ty.abiSize(mod));
13581 if (ty.bitSize(mod) > dst_reg.bitSize())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,7 +13675,27 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
13587 .register_overflow,13675 .register_overflow,
13588 .reserved_frame,13676 .reserved_frame,
13589 => unreachable,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 .eflags => |cc| try self.asmSetccRegister(cc, dst_reg.to8()),13699 .eflags => |cc| try self.asmSetccRegister(cc, dst_reg.to8()),
13592 .immediate => |imm| {13700 .immediate => |imm| {
13593 if (imm == 0) {13701 if (imm == 0) {
...@@ -13672,6 +13780,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr...@@ -13672,6 +13780,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
13672 dst_reg,13780 dst_reg,
13673 ty,13781 ty,
13674 .{ .register = try self.copyToTmpRegister(ty, src_mcv) },13782 .{ .register = try self.copyToTmpRegister(ty, src_mcv) },
13783 opts,
13675 ),13784 ),
13676 .x87, .mmx => unreachable,13785 .x87, .mmx => unreachable,
13677 .sse => try self.asmRegisterRegister(13786 .sse => try self.asmRegisterRegister(
...@@ -13701,14 +13810,14 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr...@@ -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 .register_offset,13814 .register_offset,
13706 .indirect,13815 .indirect,
13707 .load_frame,13816 .load_frame,
13708 .lea_frame,13817 .lea_frame,
13709 => try @as(MoveStrategy, switch (src_mcv) {13818 => try @as(MoveStrategy, switch (src_mcv) {
13710 .register_offset => |reg_off| switch (reg_off.off) {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 else => .{ .move = .{ ._, .lea } },13821 else => .{ .move = .{ ._, .lea } },
13713 },13822 },
13714 .indirect => try self.moveStrategy(ty, dst_reg.class(), false),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,11 +13961,18 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
13852 });13961 });
13853 },13962 },
13854 .lea_tlv => unreachable, // TODO: remove this13963 .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}
1385813967
13859fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCValue) InnerError!void {13968fn 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 const mod = self.bin_file.comp.module.?;13976 const mod = self.bin_file.comp.module.?;
13861 const abi_size: u32 = @intCast(ty.abiSize(mod));13977 const abi_size: u32 = @intCast(ty.abiSize(mod));
13862 const dst_ptr_mcv: MCValue = switch (base) {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,10 +13983,11 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal
13867 };13983 };
13868 switch (src_mcv) {13984 switch (src_mcv) {
13869 .none, .unreach, .dead, .reserved_frame => unreachable,13985 .none, .unreach, .dead, .reserved_frame => unreachable,
13870 .undef => try self.genInlineMemset(13986 .undef => if (opts.safety) try self.genInlineMemset(
13871 dst_ptr_mcv,13987 dst_ptr_mcv,
13872 .{ .immediate = 0xaa },13988 src_mcv,
13873 .{ .immediate = abi_size },13989 .{ .immediate = abi_size },
13990 opts,
13874 ),13991 ),
13875 .immediate => |imm| switch (abi_size) {13992 .immediate => |imm| switch (abi_size) {
13876 1, 2, 4 => {13993 1, 2, 4 => {
...@@ -13951,7 +14068,7 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal...@@ -13951,7 +14068,7 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal
13951 } } },14068 } } },
13952 src_alias,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 try self.freeValue(frame_mcv);14072 try self.freeValue(frame_mcv);
13956 } else try (try self.moveStrategy(ty, src_alias.class(), switch (base) {14073 } else try (try self.moveStrategy(ty, src_alias.class(), switch (base) {
13957 .none => ty.abiAlignment(mod).check(@as(u32, @bitCast(disp))),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,7 +14092,7 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal
13975 .register_pair => |src_regs| {14092 .register_pair => |src_regs| {
13976 var part_disp: i32 = disp;14093 var part_disp: i32 = disp;
13977 for (try self.splitType(ty), src_regs) |src_ty, src_reg| {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 part_disp += @intCast(src_ty.abiSize(mod));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,23 +14103,26 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal
13986 disp + @as(i32, @intCast(ty.structFieldOffset(0, mod))),14103 disp + @as(i32, @intCast(ty.structFieldOffset(0, mod))),
13987 ty.structFieldType(0, mod),14104 ty.structFieldType(0, mod),
13988 .{ .register = ro.reg },14105 .{ .register = ro.reg },
14106 opts,
13989 );14107 );
13990 try self.genSetMem(14108 try self.genSetMem(
13991 base,14109 base,
13992 disp + @as(i32, @intCast(ty.structFieldOffset(1, mod))),14110 disp + @as(i32, @intCast(ty.structFieldOffset(1, mod))),
13993 ty.structFieldType(1, mod),14111 ty.structFieldType(1, mod),
13994 .{ .eflags = ro.eflags },14112 .{ .eflags = ro.eflags },
14113 opts,
13995 );14114 );
13996 },14115 },
13997 .Optional => {14116 .Optional => {
13998 assert(!ty.optionalReprIsPayload(mod));14117 assert(!ty.optionalReprIsPayload(mod));
13999 const child_ty = ty.optionalChild(mod);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 try self.genSetMem(14120 try self.genSetMem(
14002 base,14121 base,
14003 disp + @as(i32, @intCast(child_ty.abiSize(mod))),14122 disp + @as(i32, @intCast(child_ty.abiSize(mod))),
14004 Type.bool,14123 Type.bool,
14005 .{ .eflags = ro.eflags },14124 .{ .eflags = ro.eflags },
14125 opts,
14006 );14126 );
14007 },14127 },
14008 else => return self.fail("TODO implement genSetMem for {s} of {}", .{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,27 +14149,37 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal
14029 const src_lock = self.register_manager.lockRegAssumeUnused(src_reg);14149 const src_lock = self.register_manager.lockRegAssumeUnused(src_reg);
14030 defer self.register_manager.unlockReg(src_lock);14150 defer self.register_manager.unlockReg(src_lock);
1403114151
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}
1403914163
14040fn genInlineMemcpy(self: *Self, dst_ptr: MCValue, src_ptr: MCValue, len: MCValue) InnerError!void {14164fn genInlineMemcpy(self: *Self, dst_ptr: MCValue, src_ptr: MCValue, len: MCValue) InnerError!void {
14041 try self.spillRegisters(&.{ .rsi, .rdi, .rcx });14165 try self.spillRegisters(&.{ .rsi, .rdi, .rcx });
14042 try self.genSetReg(.rsi, Type.usize, src_ptr);14166 try self.genSetReg(.rsi, Type.usize, src_ptr, .{});
14043 try self.genSetReg(.rdi, Type.usize, dst_ptr);14167 try self.genSetReg(.rdi, Type.usize, dst_ptr, .{});
14044 try self.genSetReg(.rcx, Type.usize, len);14168 try self.genSetReg(.rcx, Type.usize, len, .{});
14045 try self.asmOpOnly(.{ .@"rep _sb", .mov });14169 try self.asmOpOnly(.{ .@"rep _sb", .mov });
14046}14170}
1404714171
14048fn genInlineMemset(self: *Self, dst_ptr: MCValue, value: MCValue, len: MCValue) InnerError!void {14172fn genInlineMemset(
14173 self: *Self,
14174 dst_ptr: MCValue,
14175 value: MCValue,
14176 len: MCValue,
14177 opts: CopyOptions,
14178) InnerError!void {
14049 try self.spillRegisters(&.{ .rdi, .al, .rcx });14179 try self.spillRegisters(&.{ .rdi, .al, .rcx });
14050 try self.genSetReg(.rdi, Type.usize, dst_ptr);14180 try self.genSetReg(.rdi, Type.usize, dst_ptr, .{});
14051 try self.genSetReg(.al, Type.u8, value);14181 try self.genSetReg(.al, Type.u8, value, opts);
14052 try self.genSetReg(.rcx, Type.usize, len);14182 try self.genSetReg(.rcx, Type.usize, len, .{});
14053 try self.asmOpOnly(.{ .@"rep _sb", .sto });14183 try self.asmOpOnly(.{ .@"rep _sb", .sto });
14054}14184}
1405514185
...@@ -14113,10 +14243,10 @@ fn genLazySymbolRef(...@@ -14113,10 +14243,10 @@ fn genLazySymbolRef(
14113 switch (tag) {14243 switch (tag) {
14114 .lea, .call => try self.genSetReg(reg, Type.usize, .{14244 .lea, .call => try self.genSetReg(reg, Type.usize, .{
14115 .load_symbol = .{ .sym = sym.esym_index },14245 .load_symbol = .{ .sym = sym.esym_index },
14116 }),14246 }, .{}),
14117 .mov => try self.genSetReg(reg, Type.usize, .{14247 .mov => try self.genSetReg(reg, Type.usize, .{
14118 .load_symbol = .{ .sym = sym.esym_index },14248 .load_symbol = .{ .sym = sym.esym_index },
14119 }),14249 }, .{}),
14120 else => unreachable,14250 else => unreachable,
14121 }14251 }
14122 switch (tag) {14252 switch (tag) {
...@@ -14173,8 +14303,8 @@ fn genLazySymbolRef(...@@ -14173,8 +14303,8 @@ fn genLazySymbolRef(
14173 return self.fail("{s} creating lazy symbol", .{@errorName(err)});14303 return self.fail("{s} creating lazy symbol", .{@errorName(err)});
14174 const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?;14304 const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?;
14175 switch (tag) {14305 switch (tag) {
14176 .lea, .call => try self.genSetReg(reg, Type.usize, .{ .lea_got = sym_index }),14306 .lea, .call => try self.genSetReg(reg, Type.usize, .{ .lea_got = sym_index }, .{}),
14177 .mov => try self.genSetReg(reg, Type.usize, .{ .load_got = sym_index }),14307 .mov => try self.genSetReg(reg, Type.usize, .{ .load_got = sym_index }, .{}),
14178 else => unreachable,14308 else => unreachable,
14179 }14309 }
14180 switch (tag) {14310 switch (tag) {
...@@ -14187,8 +14317,13 @@ fn genLazySymbolRef(...@@ -14187,8 +14317,13 @@ fn genLazySymbolRef(
14187 return self.fail("{s} creating lazy symbol", .{@errorName(err)});14317 return self.fail("{s} creating lazy symbol", .{@errorName(err)});
14188 const sym = macho_file.getSymbol(sym_index);14318 const sym = macho_file.getSymbol(sym_index);
14189 switch (tag) {14319 switch (tag) {
14190 .lea, .call => try self.genSetReg(reg, Type.usize, .{ .load_symbol = .{ .sym = sym.nlist_idx } }),14320 .lea, .call => try self.genSetReg(
14191 .mov => try self.genSetReg(reg, Type.usize, .{ .load_symbol = .{ .sym = sym.nlist_idx } }),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 else => unreachable,14327 else => unreachable,
14193 }14328 }
14194 switch (tag) {14329 switch (tag) {
...@@ -14210,7 +14345,7 @@ fn airIntFromPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -14210,7 +14345,7 @@ fn airIntFromPtr(self: *Self, inst: Air.Inst.Index) !void {
1421014345
14211 const dst_mcv = try self.allocRegOrMem(inst, true);14346 const dst_mcv = try self.allocRegOrMem(inst, true);
14212 const dst_ty = self.typeOfIndex(inst);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 break :result dst_mcv;14349 break :result dst_mcv;
14215 };14350 };
14216 return self.finishAir(inst, result, .{ un_op, .none, .none });14351 return self.finishAir(inst, result, .{ un_op, .none, .none });
...@@ -14237,7 +14372,7 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void {...@@ -14237,7 +14372,7 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void {
14237 .lt => dst_ty,14372 .lt => dst_ty,
14238 .eq => if (!dst_mcv.isMemory() or src_mcv.isMemory()) dst_ty else src_ty,14373 .eq => if (!dst_mcv.isMemory() or src_mcv.isMemory()) dst_ty else src_ty,
14239 .gt => src_ty,14374 .gt => src_ty,
14240 }, dst_mcv, src_mcv);14375 }, dst_mcv, src_mcv, .{});
14241 break :dst dst_mcv;14376 break :dst dst_mcv;
14242 };14377 };
1424314378
...@@ -14268,6 +14403,7 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void {...@@ -14268,6 +14403,7 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void {
14268 if (abi_size <= 8) dst_ty else Type.usize,14403 if (abi_size <= 8) dst_ty else Type.usize,
14269 high_mcv,14404 high_mcv,
14270 .{ .register = high_reg },14405 .{ .register = high_reg },
14406 .{},
14271 );14407 );
14272 break :result dst_mcv;14408 break :result dst_mcv;
14273 };14409 };
...@@ -14285,12 +14421,13 @@ fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void {...@@ -14285,12 +14421,13 @@ fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void {
14285 const array_len = array_ty.arrayLen(mod);14421 const array_len = array_ty.arrayLen(mod);
1428614422
14287 const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(slice_ty, mod));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 try self.genSetMem(14425 try self.genSetMem(
14290 .{ .frame = frame_index },14426 .{ .frame = frame_index },
14291 @intCast(ptr_ty.abiSize(mod)),14427 @intCast(ptr_ty.abiSize(mod)),
14292 Type.usize,14428 Type.usize,
14293 .{ .immediate = array_len },14429 .{ .immediate = array_len },
14430 .{},
14294 );14431 );
1429514432
14296 const result = MCValue{ .load_frame = .{ .index = frame_index } };14433 const result = MCValue{ .load_frame = .{ .index = frame_index } };
...@@ -14470,9 +14607,9 @@ fn airCmpxchg(self: *Self, inst: Air.Inst.Index) !void {...@@ -14470,9 +14607,9 @@ fn airCmpxchg(self: *Self, inst: Air.Inst.Index) !void {
14470 if (exp_addr_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null;14607 if (exp_addr_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null;
14471 defer if (exp_addr_lock) |lock| self.register_manager.unlockReg(lock);14608 defer if (exp_addr_lock) |lock| self.register_manager.unlockReg(lock);
1447214609
14473 try self.genSetReg(.rax, Type.usize, exp_addr_mcv.deref());14610 try self.genSetReg(.rax, Type.usize, exp_addr_mcv.deref(), .{});
14474 try self.genSetReg(.rdx, Type.usize, exp_addr_mcv.offset(8).deref());14611 try self.genSetReg(.rdx, Type.usize, exp_addr_mcv.offset(8).deref(), .{});
14475 } else try self.genSetReg(.rax, val_ty, exp_mcv);14612 } else try self.genSetReg(.rax, val_ty, exp_mcv, .{});
1447614613
14477 const new_mcv = try self.resolveInst(extra.new_value);14614 const new_mcv = try self.resolveInst(extra.new_value);
14478 const new_reg = if (val_abi_size > 8) new: {14615 const new_reg = if (val_abi_size > 8) new: {
...@@ -14484,8 +14621,8 @@ fn airCmpxchg(self: *Self, inst: Air.Inst.Index) !void {...@@ -14484,8 +14621,8 @@ fn airCmpxchg(self: *Self, inst: Air.Inst.Index) !void {
14484 if (new_addr_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null;14621 if (new_addr_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null;
14485 defer if (new_addr_lock) |lock| self.register_manager.unlockReg(lock);14622 defer if (new_addr_lock) |lock| self.register_manager.unlockReg(lock);
1448614623
14487 try self.genSetReg(.rbx, Type.usize, new_addr_mcv.deref());14624 try self.genSetReg(.rbx, Type.usize, new_addr_mcv.deref(), .{});
14488 try self.genSetReg(.rcx, Type.usize, new_addr_mcv.offset(8).deref());14625 try self.genSetReg(.rcx, Type.usize, new_addr_mcv.offset(8).deref(), .{});
14489 break :new null;14626 break :new null;
14490 } else try self.copyToTmpRegister(val_ty, new_mcv);14627 } else try self.copyToTmpRegister(val_ty, new_mcv);
14491 const new_lock = if (new_reg) |reg| self.register_manager.lockRegAssumeUnused(reg) else null;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,9 +14663,9 @@ fn airCmpxchg(self: *Self, inst: Air.Inst.Index) !void {
14526 }14663 }
1452714664
14528 const dst_mcv = try self.allocRegOrMem(inst, false);14665 const dst_mcv = try self.allocRegOrMem(inst, false);
14529 try self.genCopy(Type.usize, dst_mcv, .{ .register = .rax });14666 try self.genCopy(Type.usize, dst_mcv, .{ .register = .rax }, .{});
14530 try self.genCopy(Type.usize, dst_mcv.address().offset(8).deref(), .{ .register = .rdx });14667 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 });14668 try self.genCopy(Type.bool, dst_mcv.address().offset(16).deref(), .{ .eflags = .ne }, .{});
14532 break :result dst_mcv;14669 break :result dst_mcv;
14533 };14670 };
14534 return self.finishAir(inst, result, .{ extra.ptr, extra.expected_value, extra.new_value });14671 return self.finishAir(inst, result, .{ extra.ptr, extra.expected_value, extra.new_value });
...@@ -14612,7 +14749,7 @@ fn atomicOp(...@@ -14612,7 +14749,7 @@ fn atomicOp(
14612 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);14749 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);
14613 defer self.register_manager.unlockReg(dst_lock);14750 defer self.register_manager.unlockReg(dst_lock);
1461414751
14615 try self.genSetReg(dst_reg, val_ty, val_mcv);14752 try self.genSetReg(dst_reg, val_ty, val_mcv, .{});
14616 if (rmw_op == std.builtin.AtomicRmwOp.Sub and tag == .xadd) {14753 if (rmw_op == std.builtin.AtomicRmwOp.Sub and tag == .xadd) {
14617 try self.genUnOpMir(.{ ._, .neg }, val_ty, dst_mcv);14754 try self.genUnOpMir(.{ ._, .neg }, val_ty, dst_mcv);
14618 }14755 }
...@@ -14645,7 +14782,7 @@ fn atomicOp(...@@ -14645,7 +14782,7 @@ fn atomicOp(
14645 try self.asmRegisterMemory(.{ ._, .mov }, registerAlias(.rax, val_abi_size), ptr_mem);14782 try self.asmRegisterMemory(.{ ._, .mov }, registerAlias(.rax, val_abi_size), ptr_mem);
14646 const loop: Mir.Inst.Index = @intCast(self.mir_instructions.len);14783 const loop: Mir.Inst.Index = @intCast(self.mir_instructions.len);
14647 if (!use_sse and rmw_op orelse .Xchg != .Xchg) {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 if (rmw_op) |op| if (use_sse) {14787 if (rmw_op) |op| if (use_sse) {
14651 const mir_tag = @as(?Mir.Inst.FixedTag, switch (op) {14788 const mir_tag = @as(?Mir.Inst.FixedTag, switch (op) {
...@@ -14673,7 +14810,7 @@ fn atomicOp(...@@ -14673,7 +14810,7 @@ fn atomicOp(
14673 }) orelse return self.fail("TODO implement atomicOp of {s} for {}", .{14810 }) orelse return self.fail("TODO implement atomicOp of {s} for {}", .{
14674 @tagName(op), val_ty.fmt(mod),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 switch (mir_tag[0]) {14814 switch (mir_tag[0]) {
14678 .v_ss, .v_sd => if (val_mcv.isMemory()) try self.asmRegisterRegisterMemory(14815 .v_ss, .v_sd => if (val_mcv.isMemory()) try self.asmRegisterRegisterMemory(
14679 mir_tag,14816 mir_tag,
...@@ -14703,9 +14840,9 @@ fn atomicOp(...@@ -14703,9 +14840,9 @@ fn atomicOp(
14703 ),14840 ),
14704 else => unreachable,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 } else switch (op) {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 .Add => try self.genBinOpMir(.{ ._, .add }, val_ty, tmp_mcv, val_mcv),14846 .Add => try self.genBinOpMir(.{ ._, .add }, val_ty, tmp_mcv, val_mcv),
14710 .Sub => try self.genBinOpMir(.{ ._, .sub }, val_ty, tmp_mcv, val_mcv),14847 .Sub => try self.genBinOpMir(.{ ._, .sub }, val_ty, tmp_mcv, val_mcv),
14711 .And => try self.genBinOpMir(.{ ._, .@"and" }, val_ty, tmp_mcv, val_mcv),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,7 +15132,7 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
14995 };15132 };
14996 defer if (len_lock) |lock| self.register_manager.unlockReg(lock);15133 defer if (len_lock) |lock| self.register_manager.unlockReg(lock);
1499715134
14998 try self.genInlineMemset(ptr, src_val, len);15135 try self.genInlineMemset(ptr, src_val, len, .{ .safety = safety });
14999 break :result;15136 break :result;
15000 }15137 }
1500115138
...@@ -15017,11 +15154,11 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void {...@@ -15017,11 +15154,11 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
15017 const len_lock = self.register_manager.lockRegAssumeUnused(len_reg);15154 const len_lock = self.register_manager.lockRegAssumeUnused(len_reg);
15018 defer self.register_manager.unlockReg(len_lock);15155 defer self.register_manager.unlockReg(len_lock);
1501915156
15020 try self.genSetReg(len_reg, Type.usize, len);15157 try self.genSetReg(len_reg, Type.usize, len, .{});
15021 try self.asmRegisterRegister(.{ ._, .@"test" }, len_reg, len_reg);15158 try self.asmRegisterRegister(.{ ._, .@"test" }, len_reg, len_reg);
1502215159
15023 const skip_reloc = try self.asmJccReloc(.z, undefined);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 });
1502515162
15026 const second_elem_ptr_reg =15163 const second_elem_ptr_reg =
15027 try self.register_manager.allocReg(null, abi.RegisterClass.gp);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,7 +15170,7 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
15033 try self.genSetReg(second_elem_ptr_reg, Type.usize, .{ .register_offset = .{15170 try self.genSetReg(second_elem_ptr_reg, Type.usize, .{ .register_offset = .{
15034 .reg = try self.copyToTmpRegister(Type.usize, ptr),15171 .reg = try self.copyToTmpRegister(Type.usize, ptr),
15035 .off = elem_abi_size,15172 .off = elem_abi_size,
15036 } });15173 } }, .{});
1503715174
15038 try self.genBinOpMir(.{ ._, .sub }, Type.usize, len_mcv, .{ .immediate = 1 });15175 try self.genBinOpMir(.{ ._, .sub }, Type.usize, len_mcv, .{ .immediate = 1 });
15039 try self.asmRegisterRegisterImmediate(15176 try self.asmRegisterRegisterImmediate(
...@@ -15052,7 +15189,7 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void {...@@ -15052,7 +15189,7 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
15052 const len = dst_ptr_ty.childType(mod).arrayLen(mod);15189 const len = dst_ptr_ty.childType(mod).arrayLen(mod);
1505315190
15054 assert(len != 0); // prevented by Sema15191 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 });
1505615193
15057 const second_elem_ptr_reg =15194 const second_elem_ptr_reg =
15058 try self.register_manager.allocReg(null, abi.RegisterClass.gp);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,7 +15201,7 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
15064 try self.genSetReg(second_elem_ptr_reg, Type.usize, .{ .register_offset = .{15201 try self.genSetReg(second_elem_ptr_reg, Type.usize, .{ .register_offset = .{
15065 .reg = try self.copyToTmpRegister(Type.usize, dst_ptr),15202 .reg = try self.copyToTmpRegister(Type.usize, dst_ptr),
15066 .off = elem_abi_size,15203 .off = elem_abi_size,
15067 } });15204 } }, .{});
1506815205
15069 const bytes_to_copy: MCValue = .{ .immediate = elem_abi_size * (len - 1) };15206 const bytes_to_copy: MCValue = .{ .immediate = elem_abi_size * (len - 1) };
15070 try self.genInlineMemcpy(second_elem_ptr_mcv, dst_ptr, bytes_to_copy);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,10 +15295,10 @@ fn airTagName(self: *Self, inst: Air.Inst.Index) !void {
15158 const param_regs = abi.getCAbiIntParamRegs(resolved_cc);15295 const param_regs = abi.getCAbiIntParamRegs(resolved_cc);
1515915296
15160 const dst_mcv = try self.allocRegOrMem(inst, false);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(), .{});
1516215299
15163 const operand = try self.resolveInst(un_op);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, .{});
1516515302
15166 try self.genLazySymbolRef(15303 try self.genLazySymbolRef(
15167 .call,15304 .call,
...@@ -15291,11 +15428,12 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void {...@@ -15291,11 +15428,12 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void {
15291 const reg_locks = self.register_manager.lockRegsAssumeUnused(2, regs);15428 const reg_locks = self.register_manager.lockRegsAssumeUnused(2, regs);
15292 defer for (reg_locks) |lock| self.register_manager.unlockReg(lock);15429 defer for (reg_locks) |lock| self.register_manager.unlockReg(lock);
1529315430
15294 try self.genSetReg(regs[1], vector_ty, .{ .immediate = 0 });15431 try self.genSetReg(regs[1], vector_ty, .{ .immediate = 0 }, .{});
15295 try self.genSetReg(15432 try self.genSetReg(
15296 regs[1],15433 regs[1],
15297 vector_ty,15434 vector_ty,
15298 .{ .immediate = @as(u64, math.maxInt(u64)) >> @intCast(64 - vector_len) },15435 .{ .immediate = @as(u64, math.maxInt(u64)) >> @intCast(64 - vector_len) },
15436 .{},
15299 );15437 );
15300 const src_mcv = try self.resolveInst(ty_op.operand);15438 const src_mcv = try self.resolveInst(ty_op.operand);
15301 const abi_size = @max(math.divCeil(u32, vector_len, 8) catch unreachable, 4);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,7 +15498,7 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void {
15360 try src_mcv.mem(self, self.memSize(scalar_ty)),15498 try src_mcv.mem(self, self.memSize(scalar_ty)),
15361 ) else {15499 ) else {
15362 if (mir_tag[0] == .vp_i128) break :avx2;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 try self.asmRegisterRegister(15502 try self.asmRegisterRegister(
15365 mir_tag,15503 mir_tag,
15366 registerAlias(dst_reg, @intCast(vector_ty.abiSize(mod))),15504 registerAlias(dst_reg, @intCast(vector_ty.abiSize(mod))),
...@@ -15373,7 +15511,7 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void {...@@ -15373,7 +15511,7 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void {
15373 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);15511 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);
15374 defer self.register_manager.unlockReg(dst_lock);15512 defer self.register_manager.unlockReg(dst_lock);
1537515513
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 if (vector_len == 1) break :result .{ .register = dst_reg };15515 if (vector_len == 1) break :result .{ .register = dst_reg };
1537815516
15379 const dst_alias = registerAlias(dst_reg, @intCast(vector_ty.abiSize(mod)));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,7 +15561,7 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void {
15423 const src_mcv = try self.resolveInst(ty_op.operand);15561 const src_mcv = try self.resolveInst(ty_op.operand);
15424 if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result src_mcv;15562 if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result src_mcv;
15425 const dst_reg = try self.register_manager.allocReg(inst, dst_rc);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 break :result .{ .register = dst_reg };15565 break :result .{ .register = dst_reg };
15428 },15566 },
15429 2...4 => {15567 2...4 => {
...@@ -15506,7 +15644,7 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void {...@@ -15506,7 +15644,7 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void {
15506 const src_mcv = try self.resolveInst(ty_op.operand);15644 const src_mcv = try self.resolveInst(ty_op.operand);
15507 if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result src_mcv;15645 if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result src_mcv;
15508 const dst_reg = try self.register_manager.allocReg(inst, dst_rc);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 break :result .{ .register = dst_reg };15648 break :result .{ .register = dst_reg };
15511 },15649 },
15512 2 => {15650 2 => {
...@@ -15575,7 +15713,7 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void {...@@ -15575,7 +15713,7 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void {
15575 const src_mcv = try self.resolveInst(ty_op.operand);15713 const src_mcv = try self.resolveInst(ty_op.operand);
15576 if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result src_mcv;15714 if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result src_mcv;
15577 const dst_reg = try self.register_manager.allocReg(inst, dst_rc);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 break :result .{ .register = dst_reg };15717 break :result .{ .register = dst_reg };
15580 },15718 },
15581 2 => if (self.hasFeature(.avx)) {15719 2 => if (self.hasFeature(.avx)) {
...@@ -15699,6 +15837,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {...@@ -15699,6 +15837,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
15699 .{ .lea_frame = .{ .index = frame_index } },15837 .{ .lea_frame = .{ .index = frame_index } },
15700 .{ .immediate = 0 },15838 .{ .immediate = 0 },
15701 .{ .immediate = result_ty.abiSize(mod) },15839 .{ .immediate = result_ty.abiSize(mod) },
15840 .{},
15702 );15841 );
15703 for (elements, 0..) |elem, elem_i_usize| {15842 for (elements, 0..) |elem, elem_i_usize| {
15704 const elem_i: u32 = @intCast(elem_i_usize);15843 const elem_i: u32 = @intCast(elem_i_usize);
...@@ -15783,7 +15922,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {...@@ -15783,7 +15922,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
15783 .load_tlv => |sym_index| MCValue{ .lea_tlv = sym_index },15922 .load_tlv => |sym_index| MCValue{ .lea_tlv = sym_index },
15784 else => elem_mcv,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 break :result .{ .load_frame = .{ .index = frame_index } };15927 break :result .{ .load_frame = .{ .index = frame_index } };
15789 },15928 },
...@@ -15831,13 +15970,20 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {...@@ -15831,13 +15970,20 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
15831 else => elem_mcv,15970 else => elem_mcv,
15832 };15971 };
15833 const elem_off: i32 = @intCast(elem_size * elem_i);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 if (result_ty.sentinel(mod)) |sentinel| try self.genSetMem(15981 if (result_ty.sentinel(mod)) |sentinel| try self.genSetMem(
15837 .{ .frame = frame_index },15982 .{ .frame = frame_index },
15838 @intCast(elem_size * elements.len),15983 @intCast(elem_size * elements.len),
15839 elem_ty,15984 elem_ty,
15840 try self.genTypedValue(.{ .ty = elem_ty, .val = sentinel }),15985 try self.genTypedValue(.{ .ty = elem_ty, .val = sentinel }),
15986 .{},
15841 );15987 );
15842 break :result .{ .load_frame = .{ .index = frame_index } };15988 break :result .{ .load_frame = .{ .index = frame_index } };
15843 }15989 }
...@@ -15872,7 +16018,7 @@ fn airUnionInit(self: *Self, inst: Air.Inst.Index) !void {...@@ -15872,7 +16018,7 @@ fn airUnionInit(self: *Self, inst: Air.Inst.Index) !void {
15872 self.reuseOperand(inst, extra.init, 0, src_mcv)) break :result src_mcv;16018 self.reuseOperand(inst, extra.init, 0, src_mcv)) break :result src_mcv;
1587316019
15874 const dst_mcv = try self.allocRegOrMem(inst, true);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 break :result dst_mcv;16022 break :result dst_mcv;
15877 }16023 }
1587816024
...@@ -15889,13 +16035,18 @@ fn airUnionInit(self: *Self, inst: Air.Inst.Index) !void {...@@ -15889,13 +16035,18 @@ fn airUnionInit(self: *Self, inst: Air.Inst.Index) !void {
15889 @intCast(layout.payload_size)16035 @intCast(layout.payload_size)
15890 else16036 else
15891 0;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 );
1589316044
15894 const pl_off: i32 = if (layout.tag_align.compare(.lt, layout.payload_align))16045 const pl_off: i32 = if (layout.tag_align.compare(.lt, layout.payload_align))
15895 016046 0
15896 else16047 else
15897 @intCast(layout.tag_size);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, .{});
1589916050
15900 break :result dst_mcv;16051 break :result dst_mcv;
15901 };16052 };
...@@ -16093,6 +16244,7 @@ fn airVaStart(self: *Self, inst: Air.Inst.Index) !void {...@@ -16093,6 +16244,7 @@ fn airVaStart(self: *Self, inst: Air.Inst.Index) !void {
16093 field_off,16244 field_off,
16094 Type.c_uint,16245 Type.c_uint,
16095 .{ .immediate = info.gp_count * 8 },16246 .{ .immediate = info.gp_count * 8 },
16247 .{},
16096 );16248 );
16097 field_off += @intCast(Type.c_uint.abiSize(mod));16249 field_off += @intCast(Type.c_uint.abiSize(mod));
16098 // fp_offset: c_uint,16250 // fp_offset: c_uint,
...@@ -16101,6 +16253,7 @@ fn airVaStart(self: *Self, inst: Air.Inst.Index) !void {...@@ -16101,6 +16253,7 @@ fn airVaStart(self: *Self, inst: Air.Inst.Index) !void {
16101 field_off,16253 field_off,
16102 Type.c_uint,16254 Type.c_uint,
16103 .{ .immediate = abi.SysV.c_abi_int_param_regs.len * 8 + info.fp_count * 16 },16255 .{ .immediate = abi.SysV.c_abi_int_param_regs.len * 8 + info.fp_count * 16 },
16256 .{},
16104 );16257 );
16105 field_off += @intCast(Type.c_uint.abiSize(mod));16258 field_off += @intCast(Type.c_uint.abiSize(mod));
16106 // overflow_arg_area: *anyopaque,16259 // overflow_arg_area: *anyopaque,
...@@ -16109,6 +16262,7 @@ fn airVaStart(self: *Self, inst: Air.Inst.Index) !void {...@@ -16109,6 +16262,7 @@ fn airVaStart(self: *Self, inst: Air.Inst.Index) !void {
16109 field_off,16262 field_off,
16110 ptr_anyopaque_ty,16263 ptr_anyopaque_ty,
16111 .{ .lea_frame = info.overflow_arg_area },16264 .{ .lea_frame = info.overflow_arg_area },
16265 .{},
16112 );16266 );
16113 field_off += @intCast(ptr_anyopaque_ty.abiSize(mod));16267 field_off += @intCast(ptr_anyopaque_ty.abiSize(mod));
16114 // reg_save_area: *anyopaque,16268 // reg_save_area: *anyopaque,
...@@ -16117,6 +16271,7 @@ fn airVaStart(self: *Self, inst: Air.Inst.Index) !void {...@@ -16117,6 +16271,7 @@ fn airVaStart(self: *Self, inst: Air.Inst.Index) !void {
16117 field_off,16271 field_off,
16118 ptr_anyopaque_ty,16272 ptr_anyopaque_ty,
16119 .{ .lea_frame = info.reg_save_area },16273 .{ .lea_frame = info.reg_save_area },
16274 .{},
16120 );16275 );
16121 field_off += @intCast(ptr_anyopaque_ty.abiSize(mod));16276 field_off += @intCast(ptr_anyopaque_ty.abiSize(mod));
16122 break :result .{ .load_frame = .{ .index = dst_fi } };16277 break :result .{ .load_frame = .{ .index = dst_fi } };
...@@ -16171,13 +16326,13 @@ fn airVaArg(self: *Self, inst: Air.Inst.Index) !void {...@@ -16171,13 +16326,13 @@ fn airVaArg(self: *Self, inst: Air.Inst.Index) !void {
16171 .integer => {16326 .integer => {
16172 assert(classes.len == 1);16327 assert(classes.len == 1);
1617316328
16174 try self.genSetReg(offset_reg, Type.c_uint, gp_offset);16329 try self.genSetReg(offset_reg, Type.c_uint, gp_offset, .{});
16175 try self.asmRegisterImmediate(.{ ._, .cmp }, offset_reg, Immediate.u(16330 try self.asmRegisterImmediate(.{ ._, .cmp }, offset_reg, Immediate.u(
16176 abi.SysV.c_abi_int_param_regs.len * 8,16331 abi.SysV.c_abi_int_param_regs.len * 8,
16177 ));16332 ));
16178 const mem_reloc = try self.asmJccReloc(.ae, undefined);16333 const mem_reloc = try self.asmJccReloc(.ae, undefined);
1617916334
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 if (!unused) try self.asmRegisterMemory(.{ ._, .lea }, addr_reg, .{16336 if (!unused) try self.asmRegisterMemory(.{ ._, .lea }, addr_reg, .{
16182 .base = .{ .reg = addr_reg },16337 .base = .{ .reg = addr_reg },
16183 .mod = .{ .rm = .{16338 .mod = .{ .rm = .{
...@@ -16192,11 +16347,11 @@ fn airVaArg(self: *Self, inst: Air.Inst.Index) !void {...@@ -16192,11 +16347,11 @@ fn airVaArg(self: *Self, inst: Air.Inst.Index) !void {
16192 .disp = 8,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 const done_reloc = try self.asmJmpReloc(undefined);16351 const done_reloc = try self.asmJmpReloc(undefined);
1619716352
16198 try self.performReloc(mem_reloc);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 try self.asmRegisterMemory(.{ ._, .lea }, offset_reg.to64(), .{16355 try self.asmRegisterMemory(.{ ._, .lea }, offset_reg.to64(), .{
16201 .base = .{ .reg = addr_reg },16356 .base = .{ .reg = addr_reg },
16202 .mod = .{ .rm = .{16357 .mod = .{ .rm = .{
...@@ -16208,23 +16363,24 @@ fn airVaArg(self: *Self, inst: Air.Inst.Index) !void {...@@ -16208,23 +16363,24 @@ fn airVaArg(self: *Self, inst: Air.Inst.Index) !void {
16208 ptr_anyopaque_ty,16363 ptr_anyopaque_ty,
16209 overflow_arg_area,16364 overflow_arg_area,
16210 .{ .register = offset_reg.to64() },16365 .{ .register = offset_reg.to64() },
16366 .{},
16211 );16367 );
1621216368
16213 try self.performReloc(done_reloc);16369 try self.performReloc(done_reloc);
16214 if (!unused) try self.genCopy(promote_ty, promote_mcv, .{16370 if (!unused) try self.genCopy(promote_ty, promote_mcv, .{
16215 .indirect = .{ .reg = addr_reg },16371 .indirect = .{ .reg = addr_reg },
16216 });16372 }, .{});
16217 },16373 },
16218 .sse => {16374 .sse => {
16219 assert(classes.len == 1);16375 assert(classes.len == 1);
1622016376
16221 try self.genSetReg(offset_reg, Type.c_uint, fp_offset);16377 try self.genSetReg(offset_reg, Type.c_uint, fp_offset, .{});
16222 try self.asmRegisterImmediate(.{ ._, .cmp }, offset_reg, Immediate.u(16378 try self.asmRegisterImmediate(.{ ._, .cmp }, offset_reg, Immediate.u(
16223 abi.SysV.c_abi_int_param_regs.len * 8 + abi.SysV.c_abi_sse_param_regs.len * 16,16379 abi.SysV.c_abi_int_param_regs.len * 8 + abi.SysV.c_abi_sse_param_regs.len * 16,
16224 ));16380 ));
16225 const mem_reloc = try self.asmJccReloc(.ae, undefined);16381 const mem_reloc = try self.asmJccReloc(.ae, undefined);
1622616382
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 if (!unused) try self.asmRegisterMemory(.{ ._, .lea }, addr_reg, .{16384 if (!unused) try self.asmRegisterMemory(.{ ._, .lea }, addr_reg, .{
16229 .base = .{ .reg = addr_reg },16385 .base = .{ .reg = addr_reg },
16230 .mod = .{ .rm = .{16386 .mod = .{ .rm = .{
...@@ -16239,11 +16395,11 @@ fn airVaArg(self: *Self, inst: Air.Inst.Index) !void {...@@ -16239,11 +16395,11 @@ fn airVaArg(self: *Self, inst: Air.Inst.Index) !void {
16239 .disp = 16,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 const done_reloc = try self.asmJmpReloc(undefined);16399 const done_reloc = try self.asmJmpReloc(undefined);
1624416400
16245 try self.performReloc(mem_reloc);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 try self.asmRegisterMemory(.{ ._, .lea }, offset_reg.to64(), .{16403 try self.asmRegisterMemory(.{ ._, .lea }, offset_reg.to64(), .{
16248 .base = .{ .reg = addr_reg },16404 .base = .{ .reg = addr_reg },
16249 .mod = .{ .rm = .{16405 .mod = .{ .rm = .{
...@@ -16255,12 +16411,13 @@ fn airVaArg(self: *Self, inst: Air.Inst.Index) !void {...@@ -16255,12 +16411,13 @@ fn airVaArg(self: *Self, inst: Air.Inst.Index) !void {
16255 ptr_anyopaque_ty,16411 ptr_anyopaque_ty,
16256 overflow_arg_area,16412 overflow_arg_area,
16257 .{ .register = offset_reg.to64() },16413 .{ .register = offset_reg.to64() },
16414 .{},
16258 );16415 );
1625916416
16260 try self.performReloc(done_reloc);16417 try self.performReloc(done_reloc);
16261 if (!unused) try self.genCopy(promote_ty, promote_mcv, .{16418 if (!unused) try self.genCopy(promote_ty, promote_mcv, .{
16262 .indirect = .{ .reg = addr_reg },16419 .indirect = .{ .reg = addr_reg },
16263 });16420 }, .{});
16264 },16421 },
16265 .memory => {16422 .memory => {
16266 assert(classes.len == 1);16423 assert(classes.len == 1);
...@@ -16276,7 +16433,7 @@ fn airVaArg(self: *Self, inst: Air.Inst.Index) !void {...@@ -16276,7 +16433,7 @@ fn airVaArg(self: *Self, inst: Air.Inst.Index) !void {
1627616433
16277 if (!promote_ty.isRuntimeFloat()) {16434 if (!promote_ty.isRuntimeFloat()) {
16278 const dst_mcv = try self.allocRegOrMem(inst, true);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 break :result dst_mcv;16437 break :result dst_mcv;
16281 }16438 }
1628216439
...@@ -16367,6 +16524,7 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue {...@@ -16367,6 +16524,7 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue {
16367 0,16524 0,
16368 Type.usize,16525 Type.usize,
16369 .{ .lea_symbol = .{ .sym = tlv_sym } },16526 .{ .lea_symbol = .{ .sym = tlv_sym } },
16527 .{},
16370 );16528 );
16371 break :init .{ .load_frame = .{ .index = frame_index } };16529 break :init .{ .load_frame = .{ .index = frame_index } };
16372 },16530 },
test/behavior/undefined.zig-1
...@@ -99,7 +99,6 @@ test "reslice of undefined global var slice" {...@@ -99,7 +99,6 @@ test "reslice of undefined global var slice" {
99}99}
100100
101test "returned undef is 0xaa bytes when runtime safety is enabled" {101test "returned undef is 0xaa bytes when runtime safety is enabled" {
102 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
103 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO102 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
104 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO103 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
105 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO104 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO