aboutsummaryrefslogtreecommitdiff
path: root/src/arch/x86_64/CodeGen.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2025-03-11 16:11:09 -0400
committerGitHub <noreply@github.com>2025-03-11 16:11:09 -0400
commit982c500be5285500a236ca01c2f66e8555647a52 (patch)
tree070417adb81d973df463dd7f4adb40d175af453f /src/arch/x86_64/CodeGen.zig
parentf66067546775a04ca0cda1c74cb9002d02dc49d5 (diff)
parentcff90e3ae0b14da5163ea0c3283557f402001c67 (diff)
downloadzig-982c500be5285500a236ca01c2f66e8555647a52.tar.gz
zig-982c500be5285500a236ca01c2f66e8555647a52.zip
Merge pull request #23188 from jacobly0/fix-23143
x86_64: fix crashes with symbols
Diffstat (limited to 'src/arch/x86_64/CodeGen.zig')
-rw-r--r--src/arch/x86_64/CodeGen.zig204
1 files changed, 159 insertions, 45 deletions
diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig
index 9141646e4d..2a9e25500c 100644
--- a/src/arch/x86_64/CodeGen.zig
+++ b/src/arch/x86_64/CodeGen.zig
@@ -97980,16 +97980,150 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {
switch (pred_mcv) {
.register => |pred_reg| switch (pred_reg.class()) {
.general_purpose => {},
- .sse => if (need_xmm0 and pred_reg.id() != comptime Register.xmm0.id()) {
- try self.register_manager.getKnownReg(.xmm0, null);
- try self.genSetReg(.xmm0, pred_ty, pred_mcv, .{});
- break :mask .xmm0;
- } else break :mask if (has_blend)
- pred_reg
+ .sse => if (elem_ty.toIntern() == .bool_type)
+ if (need_xmm0 and pred_reg.id() != comptime Register.xmm0.id()) {
+ try self.register_manager.getKnownReg(.xmm0, null);
+ try self.genSetReg(.xmm0, pred_ty, pred_mcv, .{});
+ break :mask .xmm0;
+ } else break :mask if (has_blend)
+ pred_reg
+ else
+ try self.copyToTmpRegister(pred_ty, pred_mcv)
else
- try self.copyToTmpRegister(pred_ty, pred_mcv),
+ return self.fail("TODO implement airSelect for {}", .{ty.fmt(pt)}),
else => unreachable,
},
+ .register_mask => |pred_reg_mask| {
+ if (pred_reg_mask.info.scalar.bitSize(self.target) != 8 * elem_abi_size)
+ return self.fail("TODO implement airSelect for {}", .{ty.fmt(pt)});
+
+ const mask_reg: Register = if (need_xmm0 and pred_reg_mask.reg.id() != comptime Register.xmm0.id()) mask_reg: {
+ try self.register_manager.getKnownReg(.xmm0, null);
+ try self.genSetReg(.xmm0, ty, .{ .register = pred_reg_mask.reg }, .{});
+ break :mask_reg .xmm0;
+ } else pred_reg_mask.reg;
+ const mask_alias = registerAlias(mask_reg, abi_size);
+ const mask_lock = self.register_manager.lockRegAssumeUnused(mask_reg);
+ defer self.register_manager.unlockReg(mask_lock);
+
+ const lhs_mcv = try self.resolveInst(extra.lhs);
+ const lhs_lock = switch (lhs_mcv) {
+ .register => |lhs_reg| self.register_manager.lockRegAssumeUnused(lhs_reg),
+ else => null,
+ };
+ defer if (lhs_lock) |lock| self.register_manager.unlockReg(lock);
+
+ const rhs_mcv = try self.resolveInst(extra.rhs);
+ const rhs_lock = switch (rhs_mcv) {
+ .register => |rhs_reg| self.register_manager.lockReg(rhs_reg),
+ else => null,
+ };
+ defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock);
+
+ const order = has_blend != pred_reg_mask.info.inverted;
+ const reuse_mcv, const other_mcv = if (order)
+ .{ rhs_mcv, lhs_mcv }
+ else
+ .{ lhs_mcv, rhs_mcv };
+ const dst_mcv: MCValue = if (reuse_mcv.isRegister() and self.reuseOperand(
+ inst,
+ if (order) extra.rhs else extra.lhs,
+ @intFromBool(order),
+ reuse_mcv,
+ )) reuse_mcv else if (has_avx)
+ .{ .register = try self.register_manager.allocReg(inst, abi.RegisterClass.sse) }
+ else
+ try self.copyToRegisterWithInstTracking(inst, ty, reuse_mcv);
+ const dst_reg = dst_mcv.getReg().?;
+ const dst_alias = registerAlias(dst_reg, abi_size);
+ const dst_lock = self.register_manager.lockReg(dst_reg);
+ defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
+
+ const mir_tag = @as(?Mir.Inst.FixedTag, if ((pred_reg_mask.info.kind == .all and
+ elem_ty.toIntern() != .f32_type and elem_ty.toIntern() != .f64_type) or pred_reg_mask.info.scalar == .byte)
+ if (has_avx)
+ .{ .vp_b, .blendv }
+ else if (has_blend)
+ .{ .p_b, .blendv }
+ else if (pred_reg_mask.info.kind == .all)
+ .{ .p_, undefined }
+ else
+ null
+ else if ((pred_reg_mask.info.kind == .all and (elem_ty.toIntern() != .f64_type or !self.hasFeature(.sse2))) or
+ pred_reg_mask.info.scalar == .dword)
+ if (has_avx)
+ .{ .v_ps, .blendv }
+ else if (has_blend)
+ .{ ._ps, .blendv }
+ else if (pred_reg_mask.info.kind == .all)
+ .{ ._ps, undefined }
+ else
+ null
+ else if (pred_reg_mask.info.kind == .all or pred_reg_mask.info.scalar == .qword)
+ if (has_avx)
+ .{ .v_pd, .blendv }
+ else if (has_blend)
+ .{ ._pd, .blendv }
+ else if (pred_reg_mask.info.kind == .all)
+ .{ ._pd, undefined }
+ else
+ null
+ else
+ null) orelse return self.fail("TODO implement airSelect for {}", .{ty.fmt(pt)});
+ if (has_avx) {
+ const rhs_alias = if (reuse_mcv.isRegister())
+ registerAlias(reuse_mcv.getReg().?, abi_size)
+ else rhs: {
+ try self.genSetReg(dst_reg, ty, reuse_mcv, .{});
+ break :rhs dst_alias;
+ };
+ if (other_mcv.isBase()) try self.asmRegisterRegisterMemoryRegister(
+ mir_tag,
+ dst_alias,
+ rhs_alias,
+ try other_mcv.mem(self, .{ .size = self.memSize(ty) }),
+ mask_alias,
+ ) else try self.asmRegisterRegisterRegisterRegister(
+ mir_tag,
+ dst_alias,
+ rhs_alias,
+ registerAlias(if (other_mcv.isRegister())
+ other_mcv.getReg().?
+ else
+ try self.copyToTmpRegister(ty, other_mcv), abi_size),
+ mask_alias,
+ );
+ } else if (has_blend) if (other_mcv.isBase()) try self.asmRegisterMemoryRegister(
+ mir_tag,
+ dst_alias,
+ try other_mcv.mem(self, .{ .size = self.memSize(ty) }),
+ mask_alias,
+ ) else try self.asmRegisterRegisterRegister(
+ mir_tag,
+ dst_alias,
+ registerAlias(if (other_mcv.isRegister())
+ other_mcv.getReg().?
+ else
+ try self.copyToTmpRegister(ty, other_mcv), abi_size),
+ mask_alias,
+ ) else {
+ try self.asmRegisterRegister(.{ mir_tag[0], .@"and" }, dst_alias, mask_alias);
+ if (other_mcv.isBase()) try self.asmRegisterMemory(
+ .{ mir_tag[0], .andn },
+ mask_alias,
+ try other_mcv.mem(self, .{ .size = .fromSize(abi_size) }),
+ ) else try self.asmRegisterRegister(
+ .{ mir_tag[0], .andn },
+ mask_alias,
+ if (other_mcv.isRegister())
+ other_mcv.getReg().?
+ else
+ try self.copyToTmpRegister(ty, other_mcv),
+ );
+ try self.asmRegisterRegister(.{ mir_tag[0], .@"or" }, dst_alias, mask_alias);
+ }
+ break :result dst_mcv;
+ },
else => {},
}
const mask_reg: Register = if (need_xmm0) mask_reg: {
@@ -98192,7 +98326,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {
const dst_lock = self.register_manager.lockReg(dst_reg);
defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
- const mir_tag = @as(?Mir.Inst.FixedTag, switch (ty.childType(zcu).zigTypeTag(zcu)) {
+ const mir_tag = @as(?Mir.Inst.FixedTag, switch (elem_ty.zigTypeTag(zcu)) {
else => null,
.int => switch (abi_size) {
0 => unreachable,
@@ -98208,7 +98342,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {
null,
else => null,
},
- .float => switch (ty.childType(zcu).floatBits(self.target.*)) {
+ .float => switch (elem_ty.floatBits(self.target.*)) {
else => unreachable,
16, 80, 128 => null,
32 => switch (vec_len) {
@@ -98262,30 +98396,20 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {
try self.copyToTmpRegister(ty, lhs_mcv), abi_size),
mask_alias,
) else {
- const mir_fixes = @as(?Mir.Inst.Fixes, switch (elem_ty.zigTypeTag(zcu)) {
- else => null,
- .int => .p_,
- .float => switch (elem_ty.floatBits(self.target.*)) {
- 32 => ._ps,
- 64 => ._pd,
- 16, 80, 128 => null,
- else => unreachable,
- },
- }) orelse return self.fail("TODO implement airSelect for {}", .{ty.fmt(pt)});
- try self.asmRegisterRegister(.{ mir_fixes, .@"and" }, dst_alias, mask_alias);
+ try self.asmRegisterRegister(.{ mir_tag[0], .@"and" }, dst_alias, mask_alias);
if (rhs_mcv.isBase()) try self.asmRegisterMemory(
- .{ mir_fixes, .andn },
+ .{ mir_tag[0], .andn },
mask_alias,
try rhs_mcv.mem(self, .{ .size = .fromSize(abi_size) }),
) else try self.asmRegisterRegister(
- .{ mir_fixes, .andn },
+ .{ mir_tag[0], .andn },
mask_alias,
if (rhs_mcv.isRegister())
rhs_mcv.getReg().?
else
try self.copyToTmpRegister(ty, rhs_mcv),
);
- try self.asmRegisterRegister(.{ mir_fixes, .@"or" }, dst_alias, mask_alias);
+ try self.asmRegisterRegister(.{ mir_tag[0], .@"or" }, dst_alias, mask_alias);
}
break :result dst_mcv;
};
@@ -100824,11 +100948,11 @@ const Temp = struct {
const new_temp_index = cg.next_temp_index;
cg.temp_type[@intFromEnum(new_temp_index)] = .usize;
cg.next_temp_index = @enumFromInt(@intFromEnum(new_temp_index) + 1);
- switch (temp.tracking(cg).short) {
- else => |mcv| std.debug.panic("{s}: {}\n", .{ @src().fn_name, mcv }),
+ const mcv = temp.tracking(cg).short;
+ switch (mcv) {
+ else => std.debug.panic("{s}: {}\n", .{ @src().fn_name, mcv }),
.register => |reg| {
- const new_reg =
- try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp);
+ const new_reg = try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp);
new_temp_index.tracking(cg).* = .init(.{ .register = new_reg });
try cg.asmRegisterMemory(.{ ._, .lea }, new_reg.to64(), .{
.base = .{ .reg = reg.to64() },
@@ -100836,33 +100960,22 @@ const Temp = struct {
});
},
.register_offset => |reg_off| {
- const new_reg =
- try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp);
+ const new_reg = try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp);
new_temp_index.tracking(cg).* = .init(.{ .register = new_reg });
try cg.asmRegisterMemory(.{ ._, .lea }, new_reg.to64(), .{
.base = .{ .reg = reg_off.reg.to64() },
.mod = .{ .rm = .{ .disp = reg_off.off + off } },
});
},
+ .load_symbol, .load_frame => {
+ const new_reg = try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp);
+ new_temp_index.tracking(cg).* = .init(.{ .register_offset = .{ .reg = new_reg, .off = off } });
+ try cg.genSetReg(new_reg, .usize, mcv, .{});
+ },
.lea_symbol => |sym_off| new_temp_index.tracking(cg).* = .init(.{ .lea_symbol = .{
.sym_index = sym_off.sym_index,
.off = sym_off.off + off,
} }),
- .load_frame => |frame_addr| {
- const new_reg =
- try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp);
- new_temp_index.tracking(cg).* = .init(.{ .register_offset = .{
- .reg = new_reg,
- .off = off,
- } });
- try cg.asmRegisterMemory(.{ ._, .mov }, new_reg.to64(), .{
- .base = .{ .frame = frame_addr.index },
- .mod = .{ .rm = .{
- .size = .qword,
- .disp = frame_addr.off,
- } },
- });
- },
.lea_frame => |frame_addr| new_temp_index.tracking(cg).* = .init(.{ .lea_frame = .{
.index = frame_addr.index,
.off = frame_addr.off + off,
@@ -101179,7 +101292,8 @@ const Temp = struct {
=> return temp.toRegClass(true, .general_purpose, cg),
.lea_symbol => |sym_off| {
const off = sym_off.off;
- if (off == 0) return false;
+ // hack around linker relocation bugs
+ if (false and off == 0) return false;
try temp.toOffset(-off, cg);
while (try temp.toRegClass(true, .general_purpose, cg)) {}
try temp.toOffset(off, cg);