x86_64: fix field_ptr nonsense

This commit is contained in:
Jacob Young 2023-05-08 23:13:23 -04:00
parent 81664f17d5
commit 1336619979
3 changed files with 14 additions and 62 deletions

View File

@ -5257,64 +5257,24 @@ fn airStructFieldPtrIndex(self: *Self, inst: Air.Inst.Index, index: u8) !void {
fn fieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32) !MCValue {
const ptr_field_ty = self.air.typeOfIndex(inst);
const mcv = try self.resolveInst(operand);
const ptr_container_ty = self.air.typeOf(operand);
const container_ty = ptr_container_ty.childType();
const field_offset = switch (container_ty.containerLayout()) {
.Auto, .Extern => @intCast(u32, container_ty.structFieldOffset(index, self.target.*)),
const field_offset = @intCast(i32, switch (container_ty.containerLayout()) {
.Auto, .Extern => container_ty.structFieldOffset(index, self.target.*),
.Packed => if (container_ty.zigTypeTag() == .Struct and
ptr_field_ty.ptrInfo().data.host_size == 0)
container_ty.packedStructFieldByteOffset(index, self.target.*)
else
0,
};
});
const result: MCValue = result: {
switch (mcv) {
.load_frame, .lea_tlv, .load_tlv => {
const offset_reg = try self.copyToTmpRegister(Type.usize, .{
.immediate = field_offset,
});
const offset_reg_lock = self.register_manager.lockRegAssumeUnused(offset_reg);
defer self.register_manager.unlockReg(offset_reg_lock);
const dst_mcv = try self.copyToRegisterWithInstTracking(inst, Type.usize, switch (mcv) {
.load_tlv => |sym_index| .{ .lea_tlv = sym_index },
else => mcv,
});
try self.genBinOpMir(.{ ._, .add }, Type.usize, dst_mcv, .{ .register = offset_reg });
break :result dst_mcv;
},
.indirect => |reg_off| break :result .{ .indirect = .{
.reg = reg_off.reg,
.off = reg_off.off + @intCast(i32, field_offset),
} },
.lea_frame => |frame_addr| break :result .{ .lea_frame = .{
.index = frame_addr.index,
.off = frame_addr.off + @intCast(i32, field_offset),
} },
.register, .register_offset => {
const src_reg = mcv.getReg().?;
const src_lock = self.register_manager.lockRegAssumeUnused(src_reg);
defer self.register_manager.unlockReg(src_lock);
const dst_mcv: MCValue = if (self.reuseOperand(inst, operand, 0, mcv))
mcv
else
.{ .register = try self.copyToTmpRegister(ptr_field_ty, mcv) };
break :result .{ .register_offset = .{
.reg = dst_mcv.getReg().?,
.off = switch (dst_mcv) {
.register => 0,
.register_offset => |reg_off| reg_off.off,
else => unreachable,
} + @intCast(i32, field_offset),
} };
},
else => return self.fail("TODO implement fieldPtr for {}", .{mcv}),
}
};
return result;
const src_mcv = try self.resolveInst(operand);
const dst_mcv = if (switch (src_mcv) {
.immediate, .lea_frame => true,
.register, .register_offset => self.reuseOperand(inst, operand, 0, src_mcv),
else => false,
}) src_mcv else try self.copyToRegisterWithInstTracking(inst, ptr_field_ty, src_mcv);
return dst_mcv.offset(field_offset);
}
fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
@ -6717,7 +6677,6 @@ fn genBinOpMir(
.dead,
.undef,
.immediate,
.register_offset,
.eflags,
.register_overflow,
.lea_direct,
@ -6726,7 +6685,9 @@ fn genBinOpMir(
.lea_frame,
.reserved_frame,
=> unreachable, // unmodifiable destination
.register => |dst_reg| {
.register, .register_offset => {
assert(dst_mcv.isRegister());
const dst_reg = dst_mcv.getReg().?;
const dst_alias = registerAlias(dst_reg, abi_size);
switch (src_mcv) {
.none,
@ -8625,11 +8586,7 @@ fn movMirTag(self: *Self, ty: Type, aligned: bool) !Mir.Inst.FixedTag {
}
fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) InnerError!void {
const src_lock = switch (src_mcv) {
.register => |reg| self.register_manager.lockReg(reg),
.register_overflow => |ro| self.register_manager.lockReg(ro.reg),
else => null,
};
const src_lock = if (src_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null;
defer if (src_lock) |lock| self.register_manager.unlockReg(lock);
switch (dst_mcv) {

View File

@ -11,7 +11,6 @@ test "@fieldParentPtr non-first field" {
}
test "@fieldParentPtr first field" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
@ -51,7 +50,6 @@ fn testParentFieldPtrFirst(a: *const bool) !void {
}
test "@fieldParentPtr untagged union" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
@ -79,7 +77,6 @@ fn testFieldParentPtrUnion(c: *const i32) !void {
}
test "@fieldParentPtr tagged union" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
@ -107,7 +104,6 @@ fn testFieldParentPtrTaggedUnion(c: *const i32) !void {
}
test "@fieldParentPtr extern union" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO

View File

@ -1164,7 +1164,6 @@ test "union enum type gets a separate scope" {
}
test "global variable struct contains union initialized to non-most-aligned field" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO