authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-04-03 12:09:07-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-04-06 00:56:44-04:00
logcac0f56c03bd44f37944211c4801d93fd2ca8b1b
tree2fe5cede817dc83cca736df1ce58311adfb3fdb0
parenta2ea4b02bc35d0cbde1716705daad2e0a395fa12

x86_64: fix incorrect handling of unreusable operands

Closes #23448

2 files changed, 55 insertions(+), 4 deletions(-)

src/arch/x86_64/CodeGen.zig+12-3
......@@ -101177,8 +101177,9 @@ const Temp = struct {
101177101177 const result_temp: Temp = .{ .index = result_temp_index.toIndex() };
101178101178 assert(cg.reuseTemp(result_temp.index, first_temp.index, first_temp_tracking));
101179101179 assert(cg.reuseTemp(result_temp.index, second_temp.index, second_temp_tracking));
101180 cg.temp_type[@intFromEnum(result_temp_index)] = .slice_const_u8;
101181101180 result_temp_index.tracking(cg).* = .init(result);
101181 cg.temp_type[@intFromEnum(result_temp_index)] = .slice_const_u8;
101182 cg.next_temp_index = @enumFromInt(@intFromEnum(result_temp_index) + 1);
101182101183 first_temp.* = result_temp;
101183101184 second_temp.* = result_temp;
101184101185 }
......@@ -105837,7 +105838,8 @@ const Temp = struct {
105837105838 ) InnerError!void {
105838105839 const tomb_bits = cg.liveness.getTombBits(inst);
105839105840 for (0.., op_refs, op_temps) |op_index, op_ref, op_temp| {
105840 if (op_temp.index != temp.index) try op_temp.die(cg);
105841 if (op_temp.index == temp.index) continue;
105842 if (op_temp.tracking(cg).short != .dead) try op_temp.die(cg);
105841105843 if (tomb_bits & @as(Liveness.Bpi, 1) << @intCast(op_index) == 0) continue;
105842105844 if (cg.reused_operands.isSet(op_index)) continue;
105843105845 try cg.processDeath(op_ref.toIndexAllowNone() orelse continue);
......@@ -105856,6 +105858,12 @@ const Temp = struct {
105856105858 assert(cg.reuseTemp(inst, temp_index.toIndex(), temp_tracking));
105857105859 },
105858105860 }
105861 for (0.., op_refs, op_temps) |op_index, op_ref, op_temp| {
105862 if (op_temp.index != temp.index) continue;
105863 if (tomb_bits & @as(Liveness.Bpi, 1) << @intCast(op_index) == 0) continue;
105864 if (cg.reused_operands.isSet(op_index)) continue;
105865 try cg.processDeath(op_ref.toIndexAllowNone() orelse continue);
105866 }
105859105867 }
105860105868
105861105869 fn die(temp: Temp, cg: *CodeGen) InnerError!void {
......@@ -105881,7 +105889,8 @@ const Temp = struct {
105881105889 }
105882105890
105883105891 fn isValid(index: Index, cg: *CodeGen) bool {
105884 return index.tracking(cg).short != .dead;
105892 return @intFromEnum(index) < @intFromEnum(cg.next_temp_index) and
105893 index.tracking(cg).short != .dead;
105885105894 }
105886105895
105887105896 fn typeOf(index: Index, cg: *CodeGen) Type {
test/behavior/struct.zig+43-1
......@@ -1529,7 +1529,7 @@ test "optional generic function label struct field" {
15291529}
15301530
15311531test "struct fields get automatically reordered" {
1532 if (builtin.zig_backend != .stage2_llvm) return error.SkipZigTest; // TODO
1532 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
15331533
15341534 const S1 = struct {
15351535 a: u32,
......@@ -2140,3 +2140,45 @@ test "anonymous struct equivalence" {
21402140 comptime assert(A != C);
21412141 comptime assert(B != C);
21422142}
2143
2144test "field access through mem ptr arg" {
2145 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
2146
2147 const S = struct {
2148 fn nestedFieldAccess(
2149 _: usize,
2150 _: usize,
2151 _: usize,
2152 _: usize,
2153 _: usize,
2154 _: usize,
2155 _: usize,
2156 _: usize,
2157 ptr_struct: *const struct { field: u32 },
2158 ) u32 {
2159 return ptr_struct.field;
2160 }
2161 };
2162 try expect(S.nestedFieldAccess(
2163 undefined,
2164 undefined,
2165 undefined,
2166 undefined,
2167 undefined,
2168 undefined,
2169 undefined,
2170 undefined,
2171 &.{ .field = 0x6b00a2eb },
2172 ) == 0x6b00a2eb);
2173 comptime assert(S.nestedFieldAccess(
2174 undefined,
2175 undefined,
2176 undefined,
2177 undefined,
2178 undefined,
2179 undefined,
2180 undefined,
2181 undefined,
2182 &.{ .field = 0x0ced271f },
2183 ) == 0x0ced271f);
2184}