aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacob Young <jacobly0@users.noreply.github.com>2023-05-02 01:27:21 -0400
committerJacob Young <jacobly0@users.noreply.github.com>2023-05-03 04:25:14 -0400
commit3a30b827414926dceccf606d6557e00f1cc6458d (patch)
tree7c824b5d6d1e09f3ae2becd3a3e2db6596528e68
parent3f5592c114ffbc28e7ffb9e9e411870b31d81dd8 (diff)
downloadzig-3a30b827414926dceccf606d6557e00f1cc6458d.tar.gz
zig-3a30b827414926dceccf606d6557e00f1cc6458d.zip
x86_64: implement fieldParentPtr
-rw-r--r--src/arch/x86_64/CodeGen.zig26
-rw-r--r--test/behavior/struct.zig1
-rw-r--r--test/behavior/tuple.zig2
3 files changed, 22 insertions, 7 deletions
diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig
index 51518485e4..521307ed6b 100644
--- a/src/arch/x86_64/CodeGen.zig
+++ b/src/arch/x86_64/CodeGen.zig
@@ -233,6 +233,13 @@ pub const MCValue = union(enum) {
};
}
+ fn isRegisterOffset(mcv: MCValue) bool {
+ return switch (mcv) {
+ .register, .register_offset => true,
+ else => false,
+ };
+ }
+
fn getReg(mcv: MCValue) ?Register {
return switch (mcv) {
.register => |reg| reg,
@@ -4772,10 +4779,21 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
}
fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void {
- const ty_op = self.air.instructions.items(.data)[inst].ty_op;
- _ = ty_op;
- return self.fail("TODO implement airFieldParentPtr for {}", .{self.target.cpu.arch});
- //return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
+ const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
+ const extra = self.air.extraData(Air.FieldParentPtr, ty_pl.payload).data;
+
+ const inst_ty = self.air.typeOfIndex(inst);
+ const parent_ty = inst_ty.childType();
+ const field_offset = @intCast(i32, parent_ty.structFieldOffset(extra.field_index, self.target.*));
+
+ const src_mcv = try self.resolveInst(extra.field_ptr);
+ const dst_mcv = if (src_mcv.isRegisterOffset() and
+ self.reuseOperand(inst, extra.field_ptr, 0, src_mcv))
+ src_mcv
+ else
+ try self.copyToRegisterWithInstTracking(inst, inst_ty, src_mcv);
+ const result = dst_mcv.offset(-field_offset);
+ return self.finishAir(inst, result, .{ extra.field_ptr, .none, .none });
}
fn genUnOp(self: *Self, maybe_inst: ?Air.Inst.Index, tag: Air.Inst.Tag, src_air: Air.Inst.Ref) !MCValue {
diff --git a/test/behavior/struct.zig b/test/behavior/struct.zig
index e533e34cc3..d5972b9161 100644
--- a/test/behavior/struct.zig
+++ b/test/behavior/struct.zig
@@ -1333,7 +1333,6 @@ test "under-aligned struct field" {
}
test "fieldParentPtr of a zero-bit 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
diff --git a/test/behavior/tuple.zig b/test/behavior/tuple.zig
index 11cc8b2dce..c1e5f40a46 100644
--- a/test/behavior/tuple.zig
+++ b/test/behavior/tuple.zig
@@ -209,7 +209,6 @@ test "initializing anon struct with explicit type" {
}
test "fieldParentPtr of tuple" {
- if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
@@ -220,7 +219,6 @@ test "fieldParentPtr of tuple" {
}
test "fieldParentPtr of anon struct" {
- if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO