diff options
| author | Jacob Young <jacobly0@users.noreply.github.com> | 2022-12-03 07:20:42 -0500 |
|---|---|---|
| committer | Jacob Young <jacobly0@users.noreply.github.com> | 2022-12-03 08:40:08 -0500 |
| commit | ec3116f57375bac136d07c6c4d9f07cbcc58194c (patch) | |
| tree | 788b85a9f468a03995bd6debe35de36bb39fc8d1 /src/codegen/c.zig | |
| parent | 7fb6eb3d14c232d397a4737f9dbd24dbae3db60f (diff) | |
| download | zig-ec3116f57375bac136d07c6c4d9f07cbcc58194c.tar.gz zig-ec3116f57375bac136d07c6c4d9f07cbcc58194c.zip | |
cbe: fix zero-bit struct field pointer
Diffstat (limited to 'src/codegen/c.zig')
| -rw-r--r-- | src/codegen/c.zig | 52 |
1 files changed, 32 insertions, 20 deletions
diff --git a/src/codegen/c.zig b/src/codegen/c.zig index 6a60065ba4..75d705003c 100644 --- 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; } |
