cbe: fix zero-bit struct field pointer

This commit is contained in:
Jacob Young 2022-12-03 07:20:42 -05:00
parent 7fb6eb3d14
commit ec3116f573
2 changed files with 32 additions and 21 deletions

View File

@ -4568,9 +4568,18 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc
else => .none,
};
const field_name: CValue = switch (struct_ty.tag()) {
const FieldLoc = union(enum) {
begin: void,
field: CValue,
end: void,
};
const field_loc = switch (struct_ty.tag()) {
.@"struct" => switch (struct_ty.containerLayout()) {
.Auto, .Extern => CValue{ .identifier = struct_ty.structFieldName(index) },
.Auto, .Extern => for (struct_ty.structFields().values()[index..]) |field, offset| {
if (field.ty.hasRuntimeBitsIgnoreComptime()) break FieldLoc{ .field = .{
.identifier = struct_ty.structFieldName(index + offset),
} };
} else @as(FieldLoc, .end),
.Packed => if (field_ptr_info.data.host_size == 0) {
const target = f.object.dg.module.getTarget();
@ -4595,40 +4604,43 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc
try f.writeCValue(writer, struct_ptr, .Other);
try writer.print(")[{}];\n", .{try f.fmtIntLiteral(Type.usize, byte_offset_val)});
return local;
} else @as(CValue, CValue.none), // this @as is needed because of a stage1 bug
} else @as(FieldLoc, .begin),
},
.@"union", .union_safety_tagged, .union_tagged => if (struct_ty.containerLayout() == .Packed) {
try f.writeCValue(writer, struct_ptr, .Other);
try writer.writeAll(";\n");
return local;
} else .{
} else if (field_ty.hasRuntimeBitsIgnoreComptime()) FieldLoc{ .field = .{
.identifier = struct_ty.unionFields().keys()[index],
},
} } else @as(FieldLoc, .end),
.tuple, .anon_struct => field_name: {
const tuple = struct_ty.tupleFields();
if (tuple.values[index].tag() != .unreachable_value) return CValue.none;
var id: usize = 0;
for (tuple.values[0..index]) |value|
id += @boolToInt(value.tag() == .unreachable_value);
break :field_name .{ .field = id };
break :field_name for (tuple.values) |value, i| {
if (value.tag() != .unreachable_value) continue;
if (!tuple.types[i].hasRuntimeBitsIgnoreComptime()) continue;
if (i >= index) break FieldLoc{ .field = .{ .field = id } };
id += 1;
} else @as(FieldLoc, .end);
},
else => unreachable,
};
if (field_ty.hasRuntimeBitsIgnoreComptime()) {
try writer.writeByte('&');
if (extra_name != .none) {
try writer.writeByte('&');
switch (field_loc) {
.begin, .end => {
try writer.writeByte('(');
try f.writeCValue(writer, struct_ptr, .Other);
try writer.print(")[{}]", .{@boolToInt(field_loc == .end)});
},
.field => |field| if (extra_name != .none) {
try f.writeCValueDerefMember(writer, struct_ptr, extra_name);
if (field_name != .none) {
try writer.writeByte('.');
try f.writeCValue(writer, field_name, .Other);
}
} else if (field_name != .none)
try f.writeCValueDerefMember(writer, struct_ptr, field_name)
else
try f.writeCValueDeref(writer, struct_ptr);
} else try f.writeCValue(writer, struct_ptr, .Other);
try writer.writeByte('.');
try f.writeCValue(writer, field, .Other);
} else try f.writeCValueDerefMember(writer, struct_ptr, field),
}
try writer.writeAll(";\n");
return local;
}

View File

@ -1390,7 +1390,6 @@ test "address of zero-bit field is equal to address of only 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_c) return error.SkipZigTest; // TODO
{
const A = struct { b: void = {}, u: u8 };