aboutsummaryrefslogtreecommitdiff
path: root/src/codegen
diff options
context:
space:
mode:
authorkcbanner <kcbanner@gmail.com>2023-10-27 01:30:04 -0400
committermlugg <mlugg@mlugg.co.uk>2023-11-07 00:49:39 +0000
commit35c86984a6c5e275c5c980ebb9d4b372291c9917 (patch)
tree0e4c42a7cf8d7f440ea72c06b4dad8ff1f16f2c5 /src/codegen
parentf10499be0a16ec58d98387b49189401f2af2094f (diff)
downloadzig-35c86984a6c5e275c5c980ebb9d4b372291c9917.tar.gz
zig-35c86984a6c5e275c5c980ebb9d4b372291c9917.zip
cbe: support rendering union values that have no defined tag type
This was regressed in d657b6c0e2ab7c47f5416dc4df1abb2bfbecd4b6, when the comptime memory model for unions was changed to allow them to have no defined tag type.
Diffstat (limited to 'src/codegen')
-rw-r--r--src/codegen/c.zig117
1 files changed, 73 insertions, 44 deletions
diff --git a/src/codegen/c.zig b/src/codegen/c.zig
index 0178ffef9a..f85f4b522b 100644
--- a/src/codegen/c.zig
+++ b/src/codegen/c.zig
@@ -1499,56 +1499,85 @@ pub const DeclGen = struct {
else => unreachable,
},
.un => |un| {
- if (!location.isInitializer()) {
- try writer.writeByte('(');
- try dg.renderType(writer, ty);
- try writer.writeByte(')');
- }
-
const union_obj = mod.typeToUnion(ty).?;
- const field_i = mod.unionTagFieldIndex(union_obj, un.tag.toValue()).?;
- const field_ty = union_obj.field_types.get(ip)[field_i].toType();
- const field_name = union_obj.field_names.get(ip)[field_i];
- if (union_obj.getLayout(ip) == .Packed) {
- if (field_ty.hasRuntimeBits(mod)) {
- if (field_ty.isPtrAtRuntime(mod)) {
- try writer.writeByte('(');
- try dg.renderType(writer, ty);
- try writer.writeByte(')');
- } else if (field_ty.zigTypeTag(mod) == .Float) {
- try writer.writeByte('(');
- try dg.renderType(writer, ty);
- try writer.writeByte(')');
+ if (un.tag == .none) {
+ const backing_ty = try ty.unionBackingType(mod);
+ switch (union_obj.getLayout(ip)) {
+ .Packed => {
+ if (!location.isInitializer()) {
+ try writer.writeByte('(');
+ try dg.renderType(writer, backing_ty);
+ try writer.writeByte(')');
+ }
+ try dg.renderValue(writer, backing_ty, un.val.toValue(), initializer_type);
+ },
+ .Extern => {
+ if (location == .StaticInitializer) {
+ return dg.fail("TODO: C backend: implement extern union backing type rendering in static initializers", .{});
+ }
+
+ const ptr_ty = try mod.singleConstPtrType(ty);
+ try writer.writeAll("*((");
+ try dg.renderType(writer, ptr_ty);
+ try writer.writeAll(")(");
+ try dg.renderType(writer, backing_ty);
+ try writer.writeAll("){");
+ try dg.renderValue(writer, backing_ty, un.val.toValue(), initializer_type);
+ try writer.writeAll("})");
+ },
+ else => unreachable,
+ }
+ } else {
+ if (!location.isInitializer()) {
+ try writer.writeByte('(');
+ try dg.renderType(writer, ty);
+ try writer.writeByte(')');
+ }
+
+ const field_i = mod.unionTagFieldIndex(union_obj, un.tag.toValue()).?;
+ const field_ty = union_obj.field_types.get(ip)[field_i].toType();
+ const field_name = union_obj.field_names.get(ip)[field_i];
+ if (union_obj.getLayout(ip) == .Packed) {
+ if (field_ty.hasRuntimeBits(mod)) {
+ if (field_ty.isPtrAtRuntime(mod)) {
+ try writer.writeByte('(');
+ try dg.renderType(writer, ty);
+ try writer.writeByte(')');
+ } else if (field_ty.zigTypeTag(mod) == .Float) {
+ try writer.writeByte('(');
+ try dg.renderType(writer, ty);
+ try writer.writeByte(')');
+ }
+ try dg.renderValue(writer, field_ty, un.val.toValue(), initializer_type);
+ } else {
+ try writer.writeAll("0");
}
- try dg.renderValue(writer, field_ty, un.val.toValue(), initializer_type);
- } else {
- try writer.writeAll("0");
+ return;
}
- return;
- }
- try writer.writeByte('{');
- if (ty.unionTagTypeSafety(mod)) |tag_ty| {
- const layout = mod.getUnionLayout(union_obj);
- if (layout.tag_size != 0) {
- try writer.writeAll(" .tag = ");
- try dg.renderValue(writer, tag_ty, un.tag.toValue(), initializer_type);
+ try writer.writeByte('{');
+ if (ty.unionTagTypeSafety(mod)) |tag_ty| {
+ const layout = mod.getUnionLayout(union_obj);
+ if (layout.tag_size != 0) {
+ try writer.writeAll(" .tag = ");
+ try dg.renderValue(writer, tag_ty, un.tag.toValue(), initializer_type);
+ }
+ if (ty.unionHasAllZeroBitFieldTypes(mod)) return try writer.writeByte('}');
+ if (layout.tag_size != 0) try writer.writeByte(',');
+ try writer.writeAll(" .payload = {");
}
- if (ty.unionHasAllZeroBitFieldTypes(mod)) return try writer.writeByte('}');
- if (layout.tag_size != 0) try writer.writeByte(',');
- try writer.writeAll(" .payload = {");
- }
- if (field_ty.hasRuntimeBits(mod)) {
- try writer.print(" .{ } = ", .{fmtIdent(ip.stringToSlice(field_name))});
- try dg.renderValue(writer, field_ty, un.val.toValue(), initializer_type);
- try writer.writeByte(' ');
- } else for (union_obj.field_types.get(ip)) |this_field_ty| {
- if (!this_field_ty.toType().hasRuntimeBits(mod)) continue;
- try dg.renderValue(writer, this_field_ty.toType(), Value.undef, initializer_type);
- break;
+ if (field_ty.hasRuntimeBits(mod)) {
+ try writer.print(" .{ } = ", .{fmtIdent(ip.stringToSlice(field_name))});
+ try dg.renderValue(writer, field_ty, un.val.toValue(), initializer_type);
+ try writer.writeByte(' ');
+ } else for (union_obj.field_types.get(ip)) |this_field_ty| {
+ if (!this_field_ty.toType().hasRuntimeBits(mod)) continue;
+ try dg.renderValue(writer, this_field_ty.toType(), Value.undef, initializer_type);
+ break;
+ }
+ if (ty.unionTagTypeSafety(mod)) |_| try writer.writeByte('}');
+ try writer.writeByte('}');
}
- if (ty.unionTagTypeSafety(mod)) |_| try writer.writeByte('}');
- try writer.writeByte('}');
},
}
}