diff options
Diffstat (limited to 'src/codegen/c.zig')
| -rw-r--r-- | src/codegen/c.zig | 117 |
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('}'); }, } } |
