zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit ec3116f57375bac136d07c6c4d9f07cbcc58194c (tree)
parent 7fb6eb3d14c232d397a4737f9dbd24dbae3db60f
Author: Jacob Young <jacobly0@users.noreply.github.com>
Date:   Sat,  3 Dec 2022 07:20:42 -0500

cbe: fix zero-bit struct field pointer

Diffstat:
Msrc/codegen/c.zig | 52++++++++++++++++++++++++++++++++--------------------
Mtest/behavior/struct.zig | 1-
2 files changed, 32 insertions(+), 21 deletions(-)

diff --git a/src/codegen/c.zig b/src/codegen/c.zig @@ -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; } diff --git a/test/behavior/struct.zig b/test/behavior/struct.zig @@ -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 };