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...@@ -4568,9 +4568,18 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc
4568 else => .none,4568 else => .none,
4569 };4569 };
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()) {
4572 .@"struct" => switch (struct_ty.containerLayout()) {4577 .@"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),
4574 .Packed => if (field_ptr_info.data.host_size == 0) {4583 .Packed => if (field_ptr_info.data.host_size == 0) {
4575 const target = f.object.dg.module.getTarget();4584 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...@@ -4595,40 +4604,43 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc
4595 try f.writeCValue(writer, struct_ptr, .Other);4604 try f.writeCValue(writer, struct_ptr, .Other);
4596 try writer.print(")[{}];\n", .{try f.fmtIntLiteral(Type.usize, byte_offset_val)});4605 try writer.print(")[{}];\n", .{try f.fmtIntLiteral(Type.usize, byte_offset_val)});
4597 return local;4606 return local;
4598 } else @as(CValue, CValue.none), // this @as is needed because of a stage1 bug4607 } else @as(FieldLoc, .begin),
4599 },4608 },
4600 .@"union", .union_safety_tagged, .union_tagged => if (struct_ty.containerLayout() == .Packed) {4609 .@"union", .union_safety_tagged, .union_tagged => if (struct_ty.containerLayout() == .Packed) {
4601 try f.writeCValue(writer, struct_ptr, .Other);4610 try f.writeCValue(writer, struct_ptr, .Other);
4602 try writer.writeAll(";\n");4611 try writer.writeAll(";\n");
4603 return local;4612 return local;
4604 } else .{4613 } else if (field_ty.hasRuntimeBitsIgnoreComptime()) FieldLoc{ .field = .{
4605 .identifier = struct_ty.unionFields().keys()[index],4614 .identifier = struct_ty.unionFields().keys()[index],
4606 },4615 } } else @as(FieldLoc, .end),
4607 .tuple, .anon_struct => field_name: {4616 .tuple, .anon_struct => field_name: {
4608 const tuple = struct_ty.tupleFields();4617 const tuple = struct_ty.tupleFields();
4609 if (tuple.values[index].tag() != .unreachable_value) return CValue.none;4618 if (tuple.values[index].tag() != .unreachable_value) return CValue.none;
46104619
4611 var id: usize = 0;4620 var id: usize = 0;
4612 for (tuple.values[0..index]) |value|4621 break :field_name for (tuple.values) |value, i| {
4613 id += @boolToInt(value.tag() == .unreachable_value);4622 if (value.tag() != .unreachable_value) continue;
4614 break :field_name .{ .field = id };4623 if (!tuple.types[i].hasRuntimeBitsIgnoreComptime()) continue;
4624 if (i >= index) break FieldLoc{ .field = .{ .field = id } };
4625 id += 1;
4626 } else @as(FieldLoc, .end);
4615 },4627 },
4616 else => unreachable,4628 else => unreachable,
4617 };4629 };
46184630
4619 if (field_ty.hasRuntimeBitsIgnoreComptime()) {4631 try writer.writeByte('&');
4620 try writer.writeByte('&');4632 switch (field_loc) {
4621 if (extra_name != .none) {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) {
4622 try f.writeCValueDerefMember(writer, struct_ptr, extra_name);4639 try f.writeCValueDerefMember(writer, struct_ptr, extra_name);
4623 if (field_name != .none) {4640 try writer.writeByte('.');
4624 try writer.writeByte('.');4641 try f.writeCValue(writer, field, .Other);
4625 try f.writeCValue(writer, field_name, .Other);4642 } else try f.writeCValueDerefMember(writer, struct_ptr, field),
4626 }4643 }
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);
4632 try writer.writeAll(";\n");4644 try writer.writeAll(";\n");
4633 return local;4645 return local;
4634}4646}
test/behavior/struct.zig-1
...@@ -1390,7 +1390,6 @@ test "address of zero-bit field is equal to address of only field" {...@@ -1390,7 +1390,6 @@ test "address of zero-bit field is equal to address of only field" {
1390 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO1390 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1391 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1391 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1392 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1392 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1393 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
13941393
1395 {1394 {
1396 const A = struct { b: void = {}, u: u8 };1395 const A = struct { b: void = {}, u: u8 };