authorgravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2023-10-27 01:30:04-04:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2023-11-07 00:49:39+00:00
log35c86984a6c5e275c5c980ebb9d4b372291c9917
tree0e4c42a7cf8d7f440ea72c06b4dad8ff1f16f2c5
parentf10499be0a16ec58d98387b49189401f2af2094f
signaturelock-open Commit is signed but in an unrecognized format.

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.

1 files changed, 73 insertions(+), 44 deletions(-)

src/codegen/c.zig+73-44
......@@ -1499,56 +1499,85 @@ pub const DeclGen = struct {
14991499 else => unreachable,
15001500 },
15011501 .un => |un| {
1502 if (!location.isInitializer()) {
1503 try writer.writeByte('(');
1504 try dg.renderType(writer, ty);
1505 try writer.writeByte(')');
1506 }
1507
15081502 const union_obj = mod.typeToUnion(ty).?;
1509 const field_i = mod.unionTagFieldIndex(union_obj, un.tag.toValue()).?;
1510 const field_ty = union_obj.field_types.get(ip)[field_i].toType();
1511 const field_name = union_obj.field_names.get(ip)[field_i];
1512 if (union_obj.getLayout(ip) == .Packed) {
1513 if (field_ty.hasRuntimeBits(mod)) {
1514 if (field_ty.isPtrAtRuntime(mod)) {
1515 try writer.writeByte('(');
1516 try dg.renderType(writer, ty);
1517 try writer.writeByte(')');
1518 } else if (field_ty.zigTypeTag(mod) == .Float) {
1519 try writer.writeByte('(');
1520 try dg.renderType(writer, ty);
1521 try writer.writeByte(')');
1503 if (un.tag == .none) {
1504 const backing_ty = try ty.unionBackingType(mod);
1505 switch (union_obj.getLayout(ip)) {
1506 .Packed => {
1507 if (!location.isInitializer()) {
1508 try writer.writeByte('(');
1509 try dg.renderType(writer, backing_ty);
1510 try writer.writeByte(')');
1511 }
1512 try dg.renderValue(writer, backing_ty, un.val.toValue(), initializer_type);
1513 },
1514 .Extern => {
1515 if (location == .StaticInitializer) {
1516 return dg.fail("TODO: C backend: implement extern union backing type rendering in static initializers", .{});
1517 }
1518
1519 const ptr_ty = try mod.singleConstPtrType(ty);
1520 try writer.writeAll("*((");
1521 try dg.renderType(writer, ptr_ty);
1522 try writer.writeAll(")(");
1523 try dg.renderType(writer, backing_ty);
1524 try writer.writeAll("){");
1525 try dg.renderValue(writer, backing_ty, un.val.toValue(), initializer_type);
1526 try writer.writeAll("})");
1527 },
1528 else => unreachable,
1529 }
1530 } else {
1531 if (!location.isInitializer()) {
1532 try writer.writeByte('(');
1533 try dg.renderType(writer, ty);
1534 try writer.writeByte(')');
1535 }
1536
1537 const field_i = mod.unionTagFieldIndex(union_obj, un.tag.toValue()).?;
1538 const field_ty = union_obj.field_types.get(ip)[field_i].toType();
1539 const field_name = union_obj.field_names.get(ip)[field_i];
1540 if (union_obj.getLayout(ip) == .Packed) {
1541 if (field_ty.hasRuntimeBits(mod)) {
1542 if (field_ty.isPtrAtRuntime(mod)) {
1543 try writer.writeByte('(');
1544 try dg.renderType(writer, ty);
1545 try writer.writeByte(')');
1546 } else if (field_ty.zigTypeTag(mod) == .Float) {
1547 try writer.writeByte('(');
1548 try dg.renderType(writer, ty);
1549 try writer.writeByte(')');
1550 }
1551 try dg.renderValue(writer, field_ty, un.val.toValue(), initializer_type);
1552 } else {
1553 try writer.writeAll("0");
15221554 }
1523 try dg.renderValue(writer, field_ty, un.val.toValue(), initializer_type);
1524 } else {
1525 try writer.writeAll("0");
1555 return;
15261556 }
1527 return;
1528 }
15291557
1530 try writer.writeByte('{');
1531 if (ty.unionTagTypeSafety(mod)) |tag_ty| {
1532 const layout = mod.getUnionLayout(union_obj);
1533 if (layout.tag_size != 0) {
1534 try writer.writeAll(" .tag = ");
1535 try dg.renderValue(writer, tag_ty, un.tag.toValue(), initializer_type);
1558 try writer.writeByte('{');
1559 if (ty.unionTagTypeSafety(mod)) |tag_ty| {
1560 const layout = mod.getUnionLayout(union_obj);
1561 if (layout.tag_size != 0) {
1562 try writer.writeAll(" .tag = ");
1563 try dg.renderValue(writer, tag_ty, un.tag.toValue(), initializer_type);
1564 }
1565 if (ty.unionHasAllZeroBitFieldTypes(mod)) return try writer.writeByte('}');
1566 if (layout.tag_size != 0) try writer.writeByte(',');
1567 try writer.writeAll(" .payload = {");
15361568 }
1537 if (ty.unionHasAllZeroBitFieldTypes(mod)) return try writer.writeByte('}');
1538 if (layout.tag_size != 0) try writer.writeByte(',');
1539 try writer.writeAll(" .payload = {");
1540 }
1541 if (field_ty.hasRuntimeBits(mod)) {
1542 try writer.print(" .{ } = ", .{fmtIdent(ip.stringToSlice(field_name))});
1543 try dg.renderValue(writer, field_ty, un.val.toValue(), initializer_type);
1544 try writer.writeByte(' ');
1545 } else for (union_obj.field_types.get(ip)) |this_field_ty| {
1546 if (!this_field_ty.toType().hasRuntimeBits(mod)) continue;
1547 try dg.renderValue(writer, this_field_ty.toType(), Value.undef, initializer_type);
1548 break;
1569 if (field_ty.hasRuntimeBits(mod)) {
1570 try writer.print(" .{ } = ", .{fmtIdent(ip.stringToSlice(field_name))});
1571 try dg.renderValue(writer, field_ty, un.val.toValue(), initializer_type);
1572 try writer.writeByte(' ');
1573 } else for (union_obj.field_types.get(ip)) |this_field_ty| {
1574 if (!this_field_ty.toType().hasRuntimeBits(mod)) continue;
1575 try dg.renderValue(writer, this_field_ty.toType(), Value.undef, initializer_type);
1576 break;
1577 }
1578 if (ty.unionTagTypeSafety(mod)) |_| try writer.writeByte('}');
1579 try writer.writeByte('}');
15491580 }
1550 if (ty.unionTagTypeSafety(mod)) |_| try writer.writeByte('}');
1551 try writer.writeByte('}');
15521581 },
15531582 }
15541583 }