authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2022-12-03 07:20:42-05:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2022-12-03 08:40:08-05:00
logec3116f57375bac136d07c6c4d9f07cbcc58194c
tree788b85a9f468a03995bd6debe35de36bb39fc8d1
parent7fb6eb3d14c232d397a4737f9dbd24dbae3db60f

cbe: fix zero-bit struct field pointer


2 files changed, 32 insertions(+), 21 deletions(-)

src/codegen/c.zig+32-20
......@@ -4568,9 +4568,18 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc
45684568 else => .none,
45694569 };
45704570
4571 const field_name: CValue = switch (struct_ty.tag()) {
4571 const FieldLoc = union(enum) {
4572 begin: void,
4573 field: CValue,
4574 end: void,
4575 };
4576 const field_loc = switch (struct_ty.tag()) {
45724577 .@"struct" => switch (struct_ty.containerLayout()) {
4573 .Auto, .Extern => CValue{ .identifier = struct_ty.structFieldName(index) },
4578 .Auto, .Extern => for (struct_ty.structFields().values()[index..]) |field, offset| {
4579 if (field.ty.hasRuntimeBitsIgnoreComptime()) break FieldLoc{ .field = .{
4580 .identifier = struct_ty.structFieldName(index + offset),
4581 } };
4582 } else @as(FieldLoc, .end),
45744583 .Packed => if (field_ptr_info.data.host_size == 0) {
45754584 const target = f.object.dg.module.getTarget();
45764585
......@@ -4595,40 +4604,43 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc
45954604 try f.writeCValue(writer, struct_ptr, .Other);
45964605 try writer.print(")[{}];\n", .{try f.fmtIntLiteral(Type.usize, byte_offset_val)});
45974606 return local;
4598 } else @as(CValue, CValue.none), // this @as is needed because of a stage1 bug
4607 } else @as(FieldLoc, .begin),
45994608 },
46004609 .@"union", .union_safety_tagged, .union_tagged => if (struct_ty.containerLayout() == .Packed) {
46014610 try f.writeCValue(writer, struct_ptr, .Other);
46024611 try writer.writeAll(";\n");
46034612 return local;
4604 } else .{
4613 } else if (field_ty.hasRuntimeBitsIgnoreComptime()) FieldLoc{ .field = .{
46054614 .identifier = struct_ty.unionFields().keys()[index],
4606 },
4615 } } else @as(FieldLoc, .end),
46074616 .tuple, .anon_struct => field_name: {
46084617 const tuple = struct_ty.tupleFields();
46094618 if (tuple.values[index].tag() != .unreachable_value) return CValue.none;
46104619
46114620 var id: usize = 0;
4612 for (tuple.values[0..index]) |value|
4613 id += @boolToInt(value.tag() == .unreachable_value);
4614 break :field_name .{ .field = id };
4621 break :field_name for (tuple.values) |value, i| {
4622 if (value.tag() != .unreachable_value) continue;
4623 if (!tuple.types[i].hasRuntimeBitsIgnoreComptime()) continue;
4624 if (i >= index) break FieldLoc{ .field = .{ .field = id } };
4625 id += 1;
4626 } else @as(FieldLoc, .end);
46154627 },
46164628 else => unreachable,
46174629 };
46184630
4619 if (field_ty.hasRuntimeBitsIgnoreComptime()) {
4620 try writer.writeByte('&');
4621 if (extra_name != .none) {
4631 try writer.writeByte('&');
4632 switch (field_loc) {
4633 .begin, .end => {
4634 try writer.writeByte('(');
4635 try f.writeCValue(writer, struct_ptr, .Other);
4636 try writer.print(")[{}]", .{@boolToInt(field_loc == .end)});
4637 },
4638 .field => |field| if (extra_name != .none) {
46224639 try f.writeCValueDerefMember(writer, struct_ptr, extra_name);
4623 if (field_name != .none) {
4624 try writer.writeByte('.');
4625 try f.writeCValue(writer, field_name, .Other);
4626 }
4627 } else if (field_name != .none)
4628 try f.writeCValueDerefMember(writer, struct_ptr, field_name)
4629 else
4630 try f.writeCValueDeref(writer, struct_ptr);
4631 } else try f.writeCValue(writer, struct_ptr, .Other);
4640 try writer.writeByte('.');
4641 try f.writeCValue(writer, field, .Other);
4642 } else try f.writeCValueDerefMember(writer, struct_ptr, field),
4643 }
46324644 try writer.writeAll(";\n");
46334645 return local;
46344646}
test/behavior/struct.zig-1
......@@ -1390,7 +1390,6 @@ test "address of zero-bit field is equal to address of only field" {
13901390 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
13911391 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
13921392 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1393 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
13941393
13951394 {
13961395 const A = struct { b: void = {}, u: u8 };