| ... | ... | @@ -1488,29 +1488,42 @@ pub const DeclGen = struct { |
| 1488 | 1488 | // The forward declaration for T is stored with a key of *const T. |
| 1489 | 1489 | const child_ty = t.childType(); |
| 1490 | 1490 | |
| 1491 | | var fqn_buf = std.ArrayList(u8).init(dg.typedefs.allocator); |
| 1492 | | defer fqn_buf.deinit(); |
| 1493 | | |
| 1494 | | const owner_decl_index = child_ty.getOwnerDecl(); |
| 1495 | | const owner_decl = dg.module.declPtr(owner_decl_index); |
| 1496 | | try owner_decl.renderFullyQualifiedName(dg.module, fqn_buf.writer()); |
| 1497 | | |
| 1498 | 1491 | var buffer = std.ArrayList(u8).init(dg.typedefs.allocator); |
| 1499 | 1492 | defer buffer.deinit(); |
| 1493 | const bw = buffer.writer(); |
| 1500 | 1494 | |
| 1501 | 1495 | const tag = switch (child_ty.zigTypeTag()) { |
| 1502 | | .Struct => "struct ", |
| 1503 | | .Union => if (child_ty.unionTagTypeSafety()) |_| "struct " else "union ", |
| 1496 | .Struct, .ErrorUnion, .Optional => "struct", |
| 1497 | .Union => if (child_ty.unionTagTypeSafety()) |_| "struct" else "union", |
| 1504 | 1498 | else => unreachable, |
| 1505 | 1499 | }; |
| 1506 | | const name_begin = buffer.items.len + "typedef ".len + tag.len; |
| 1507 | | try buffer.writer().print("typedef {s}zig_S_{}__{d} ", .{ |
| 1508 | | tag, |
| 1509 | | fmtIdent(fqn_buf.items), |
| 1510 | | @enumToInt(owner_decl_index), |
| 1511 | | }); |
| 1512 | | const name_end = buffer.items.len - " ".len; |
| 1513 | | try buffer.ensureUnusedCapacity((name_end - name_begin) + ";\n".len); |
| 1500 | try bw.writeAll("typedef "); |
| 1501 | try bw.writeAll(tag); |
| 1502 | const name_begin = buffer.items.len + " ".len; |
| 1503 | try bw.writeAll(" zig_"); |
| 1504 | switch (child_ty.zigTypeTag()) { |
| 1505 | .Struct, .Union => { |
| 1506 | var fqn_buf = std.ArrayList(u8).init(dg.typedefs.allocator); |
| 1507 | defer fqn_buf.deinit(); |
| 1508 | |
| 1509 | const owner_decl_index = child_ty.getOwnerDecl(); |
| 1510 | const owner_decl = dg.module.declPtr(owner_decl_index); |
| 1511 | try owner_decl.renderFullyQualifiedName(dg.module, fqn_buf.writer()); |
| 1512 | |
| 1513 | try bw.print("S_{}__{d}", .{ fmtIdent(fqn_buf.items), @enumToInt(owner_decl_index) }); |
| 1514 | }, |
| 1515 | .ErrorUnion => { |
| 1516 | try bw.print("E_{}", .{typeToCIdentifier(child_ty.errorUnionPayload(), dg.module)}); |
| 1517 | }, |
| 1518 | .Optional => { |
| 1519 | var opt_buf: Type.Payload.ElemType = undefined; |
| 1520 | try bw.print("Q_{}", .{typeToCIdentifier(child_ty.optionalChild(&opt_buf), dg.module)}); |
| 1521 | }, |
| 1522 | else => unreachable, |
| 1523 | } |
| 1524 | const name_end = buffer.items.len; |
| 1525 | try buffer.ensureUnusedCapacity(" ".len + (name_end - name_begin) + ";\n".len); |
| 1526 | buffer.appendAssumeCapacity(' '); |
| 1514 | 1527 | buffer.appendSliceAssumeCapacity(buffer.items[name_begin..name_end]); |
| 1515 | 1528 | buffer.appendSliceAssumeCapacity(";\n"); |
| 1516 | 1529 | |
| ... | ... | @@ -1570,7 +1583,11 @@ pub const DeclGen = struct { |
| 1570 | 1583 | return name; |
| 1571 | 1584 | } |
| 1572 | 1585 | |
| 1573 | | fn renderTupleTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 { |
| 1586 | fn renderTupleTypedef( |
| 1587 | dg: *DeclGen, |
| 1588 | t: Type, |
| 1589 | kind: TypedefKind, |
| 1590 | ) error{ OutOfMemory, AnalysisFail }![]const u8 { |
| 1574 | 1591 | var buffer = std.ArrayList(u8).init(dg.typedefs.allocator); |
| 1575 | 1592 | defer buffer.deinit(); |
| 1576 | 1593 | |
| ... | ... | @@ -1582,7 +1599,7 @@ pub const DeclGen = struct { |
| 1582 | 1599 | if (!field_ty.hasRuntimeBits() or fields.values[i].tag() != .unreachable_value) continue; |
| 1583 | 1600 | |
| 1584 | 1601 | try buffer.append(' '); |
| 1585 | | try dg.renderTypeAndName(buffer.writer(), field_ty, .{ .field = field_id }, .Mut, 0, .Complete); |
| 1602 | try dg.renderTypeAndName(buffer.writer(), field_ty, .{ .field = field_id }, .Mut, 0, kind); |
| 1586 | 1603 | try buffer.appendSlice(";\n"); |
| 1587 | 1604 | |
| 1588 | 1605 | field_id += 1; |
| ... | ... | @@ -1670,6 +1687,11 @@ pub const DeclGen = struct { |
| 1670 | 1687 | fn renderErrorUnionTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 { |
| 1671 | 1688 | assert(t.errorUnionSet().tag() == .anyerror); |
| 1672 | 1689 | |
| 1690 | var ptr_pl = Type.Payload.ElemType{ .base = .{ .tag = .single_const_pointer }, .data = t }; |
| 1691 | const ptr_ty = Type.initPayload(&ptr_pl.base); |
| 1692 | const name = dg.getTypedefName(ptr_ty) orelse |
| 1693 | try dg.renderFwdTypedef(ptr_ty); |
| 1694 | |
| 1673 | 1695 | var buffer = std.ArrayList(u8).init(dg.typedefs.allocator); |
| 1674 | 1696 | defer buffer.deinit(); |
| 1675 | 1697 | const bw = buffer.writer(); |
| ... | ... | @@ -1682,7 +1704,9 @@ pub const DeclGen = struct { |
| 1682 | 1704 | const target = dg.module.getTarget(); |
| 1683 | 1705 | const payload_align = payload_ty.abiAlignment(target); |
| 1684 | 1706 | const error_align = error_ty.abiAlignment(target); |
| 1685 | | try bw.writeAll("typedef struct {\n "); |
| 1707 | try bw.writeAll("struct "); |
| 1708 | try bw.writeAll(name); |
| 1709 | try bw.writeAll(" {\n "); |
| 1686 | 1710 | if (error_align > payload_align) { |
| 1687 | 1711 | try dg.renderTypeAndName(bw, payload_ty, payload_name, .Mut, 0, .Complete); |
| 1688 | 1712 | try bw.writeAll(";\n "); |
| ... | ... | @@ -1692,15 +1716,10 @@ pub const DeclGen = struct { |
| 1692 | 1716 | try bw.writeAll(";\n "); |
| 1693 | 1717 | try dg.renderTypeAndName(bw, payload_ty, payload_name, .Mut, 0, .Complete); |
| 1694 | 1718 | } |
| 1695 | | try bw.writeAll(";\n} "); |
| 1696 | | const name_begin = buffer.items.len; |
| 1697 | | try bw.print("zig_E_{}", .{typeToCIdentifier(payload_ty, dg.module)}); |
| 1698 | | const name_end = buffer.items.len; |
| 1699 | | try bw.writeAll(";\n"); |
| 1719 | try bw.writeAll(";\n};\n"); |
| 1700 | 1720 | |
| 1701 | 1721 | const rendered = try buffer.toOwnedSlice(); |
| 1702 | 1722 | errdefer dg.typedefs.allocator.free(rendered); |
| 1703 | | const name = rendered[name_begin..name_end]; |
| 1704 | 1723 | |
| 1705 | 1724 | try dg.typedefs.ensureUnusedCapacity(1); |
| 1706 | 1725 | dg.typedefs.putAssumeCapacityNoClobber( |
| ... | ... | @@ -1744,24 +1763,29 @@ pub const DeclGen = struct { |
| 1744 | 1763 | return name; |
| 1745 | 1764 | } |
| 1746 | 1765 | |
| 1747 | | fn renderOptionalTypedef(dg: *DeclGen, t: Type, child_type: Type) error{ OutOfMemory, AnalysisFail }![]const u8 { |
| 1766 | fn renderOptionalTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 { |
| 1767 | var ptr_pl = Type.Payload.ElemType{ .base = .{ .tag = .single_const_pointer }, .data = t }; |
| 1768 | const ptr_ty = Type.initPayload(&ptr_pl.base); |
| 1769 | const name = dg.getTypedefName(ptr_ty) orelse |
| 1770 | try dg.renderFwdTypedef(ptr_ty); |
| 1771 | |
| 1748 | 1772 | var buffer = std.ArrayList(u8).init(dg.typedefs.allocator); |
| 1749 | 1773 | defer buffer.deinit(); |
| 1750 | 1774 | const bw = buffer.writer(); |
| 1751 | 1775 | |
| 1752 | | try bw.writeAll("typedef struct {\n "); |
| 1753 | | try dg.renderTypeAndName(bw, child_type, .{ .identifier = "payload" }, .Mut, 0, .Complete); |
| 1776 | var opt_buf: Type.Payload.ElemType = undefined; |
| 1777 | const child_ty = t.optionalChild(&opt_buf); |
| 1778 | |
| 1779 | try bw.writeAll("struct "); |
| 1780 | try bw.writeAll(name); |
| 1781 | try bw.writeAll(" {\n"); |
| 1782 | try dg.renderTypeAndName(bw, child_ty, .{ .identifier = "payload" }, .Mut, 0, .Complete); |
| 1754 | 1783 | try bw.writeAll(";\n "); |
| 1755 | 1784 | try dg.renderTypeAndName(bw, Type.bool, .{ .identifier = "is_null" }, .Mut, 0, .Complete); |
| 1756 | | try bw.writeAll(";\n} "); |
| 1757 | | const name_begin = buffer.items.len; |
| 1758 | | try bw.print("zig_Q_{}", .{typeToCIdentifier(child_type, dg.module)}); |
| 1759 | | const name_end = buffer.items.len; |
| 1760 | | try bw.writeAll(";\n"); |
| 1785 | try bw.writeAll(";\n};\n"); |
| 1761 | 1786 | |
| 1762 | 1787 | const rendered = try buffer.toOwnedSlice(); |
| 1763 | 1788 | errdefer dg.typedefs.allocator.free(rendered); |
| 1764 | | const name = rendered[name_begin..name_end]; |
| 1765 | 1789 | |
| 1766 | 1790 | try dg.typedefs.ensureUnusedCapacity(1); |
| 1767 | 1791 | dg.typedefs.putAssumeCapacityNoClobber( |
| ... | ... | @@ -1900,18 +1924,34 @@ pub const DeclGen = struct { |
| 1900 | 1924 | }, |
| 1901 | 1925 | .Optional => { |
| 1902 | 1926 | var opt_buf: Type.Payload.ElemType = undefined; |
| 1903 | | const child_type = t.optionalChild(&opt_buf); |
| 1927 | const child_ty = t.optionalChild(&opt_buf); |
| 1904 | 1928 | |
| 1905 | | if (!child_type.hasRuntimeBitsIgnoreComptime()) |
| 1929 | if (!child_ty.hasRuntimeBitsIgnoreComptime()) |
| 1906 | 1930 | return dg.renderType(w, Type.bool, kind); |
| 1907 | 1931 | |
| 1908 | 1932 | if (t.optionalReprIsPayload()) |
| 1909 | | return dg.renderType(w, child_type, kind); |
| 1933 | return dg.renderType(w, child_ty, kind); |
| 1910 | 1934 | |
| 1911 | | const name = dg.getTypedefName(t) orelse |
| 1912 | | try dg.renderOptionalTypedef(t, child_type); |
| 1935 | switch (kind) { |
| 1936 | .Complete => { |
| 1937 | const name = dg.getTypedefName(t) orelse |
| 1938 | try dg.renderOptionalTypedef(t); |
| 1913 | 1939 | |
| 1914 | | return w.writeAll(name); |
| 1940 | try w.writeAll(name); |
| 1941 | }, |
| 1942 | .Forward => { |
| 1943 | var ptr_pl = Type.Payload.ElemType{ |
| 1944 | .base = .{ .tag = .single_const_pointer }, |
| 1945 | .data = t, |
| 1946 | }; |
| 1947 | const ptr_ty = Type.initPayload(&ptr_pl.base); |
| 1948 | |
| 1949 | const name = dg.getTypedefName(ptr_ty) orelse |
| 1950 | try dg.renderFwdTypedef(ptr_ty); |
| 1951 | |
| 1952 | try w.writeAll(name); |
| 1953 | }, |
| 1954 | } |
| 1915 | 1955 | }, |
| 1916 | 1956 | .ErrorUnion => { |
| 1917 | 1957 | const payload_ty = t.errorUnionPayload(); |
| ... | ... | @@ -1924,10 +1964,26 @@ pub const DeclGen = struct { |
| 1924 | 1964 | }; |
| 1925 | 1965 | const error_union_ty = Type.initPayload(&error_union_pl.base); |
| 1926 | 1966 | |
| 1927 | | const name = dg.getTypedefName(error_union_ty) orelse |
| 1928 | | try dg.renderErrorUnionTypedef(error_union_ty); |
| 1967 | switch (kind) { |
| 1968 | .Complete => { |
| 1969 | const name = dg.getTypedefName(error_union_ty) orelse |
| 1970 | try dg.renderErrorUnionTypedef(error_union_ty); |
| 1929 | 1971 | |
| 1930 | | return w.writeAll(name); |
| 1972 | try w.writeAll(name); |
| 1973 | }, |
| 1974 | .Forward => { |
| 1975 | var ptr_pl = Type.Payload.ElemType{ |
| 1976 | .base = .{ .tag = .single_const_pointer }, |
| 1977 | .data = error_union_ty, |
| 1978 | }; |
| 1979 | const ptr_ty = Type.initPayload(&ptr_pl.base); |
| 1980 | |
| 1981 | const name = dg.getTypedefName(ptr_ty) orelse |
| 1982 | try dg.renderFwdTypedef(ptr_ty); |
| 1983 | |
| 1984 | try w.writeAll(name); |
| 1985 | }, |
| 1986 | } |
| 1931 | 1987 | }, |
| 1932 | 1988 | .Struct, .Union => |tag| if (t.containerLayout() == .Packed) { |
| 1933 | 1989 | if (t.castTag(.@"struct")) |struct_obj| { |
| ... | ... | @@ -1965,28 +2021,31 @@ pub const DeclGen = struct { |
| 1965 | 2021 | const tuple_ty = Type.initPayload(&tuple_pl.base); |
| 1966 | 2022 | |
| 1967 | 2023 | const name = dg.getTypedefName(tuple_ty) orelse |
| 1968 | | try dg.renderTupleTypedef(tuple_ty); |
| 2024 | try dg.renderTupleTypedef(tuple_ty, kind); |
| 1969 | 2025 | |
| 1970 | 2026 | try w.writeAll(name); |
| 1971 | | } else if (kind == .Complete) { |
| 1972 | | const name = dg.getTypedefName(t) orelse switch (tag) { |
| 1973 | | .Struct => try dg.renderStructTypedef(t), |
| 1974 | | .Union => try dg.renderUnionTypedef(t), |
| 1975 | | else => unreachable, |
| 1976 | | }; |
| 2027 | } else switch (kind) { |
| 2028 | .Complete => { |
| 2029 | const name = dg.getTypedefName(t) orelse switch (tag) { |
| 2030 | .Struct => try dg.renderStructTypedef(t), |
| 2031 | .Union => try dg.renderUnionTypedef(t), |
| 2032 | else => unreachable, |
| 2033 | }; |
| 1977 | 2034 | |
| 1978 | | try w.writeAll(name); |
| 1979 | | } else { |
| 1980 | | var ptr_pl = Type.Payload.ElemType{ |
| 1981 | | .base = .{ .tag = .single_const_pointer }, |
| 1982 | | .data = t, |
| 1983 | | }; |
| 1984 | | const ptr_ty = Type.initPayload(&ptr_pl.base); |
| 2035 | try w.writeAll(name); |
| 2036 | }, |
| 2037 | .Forward => { |
| 2038 | var ptr_pl = Type.Payload.ElemType{ |
| 2039 | .base = .{ .tag = .single_const_pointer }, |
| 2040 | .data = t, |
| 2041 | }; |
| 2042 | const ptr_ty = Type.initPayload(&ptr_pl.base); |
| 1985 | 2043 | |
| 1986 | | const name = dg.getTypedefName(ptr_ty) orelse |
| 1987 | | try dg.renderFwdTypedef(ptr_ty); |
| 2044 | const name = dg.getTypedefName(ptr_ty) orelse |
| 2045 | try dg.renderFwdTypedef(ptr_ty); |
| 1988 | 2046 | |
| 1989 | | try w.writeAll(name); |
| 2047 | try w.writeAll(name); |
| 2048 | }, |
| 1990 | 2049 | }, |
| 1991 | 2050 | .Enum => { |
| 1992 | 2051 | // For enums, we simply use the integer tag type. |