From 35c86984a6c5e275c5c980ebb9d4b372291c9917 Mon Sep 17 00:00:00 2001 From: kcbanner Date: Fri, 27 Oct 2023 01:30:04 -0400 Subject: 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. --- src/codegen/c.zig | 117 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 73 insertions(+), 44 deletions(-) (limited to 'src/codegen') 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('}'); }, } } -- cgit v1.2.3