| ... | @@ -1488,29 +1488,42 @@ pub const DeclGen = struct { | ... | @@ -1488,29 +1488,42 @@ pub const DeclGen = struct { |
| 1488 | // The forward declaration for T is stored with a key of *const T. | 1488 | // The forward declaration for T is stored with a key of *const T. |
| 1489 | const child_ty = t.childType(); | 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 | var buffer = std.ArrayList(u8).init(dg.typedefs.allocator); | 1491 | var buffer = std.ArrayList(u8).init(dg.typedefs.allocator); |
| 1499 | defer buffer.deinit(); | 1492 | defer buffer.deinit(); |
| | 1493 | const bw = buffer.writer(); |
| 1500 | | 1494 | |
| 1501 | const tag = switch (child_ty.zigTypeTag()) { | 1495 | const tag = switch (child_ty.zigTypeTag()) { |
| 1502 | .Struct => "struct ", | 1496 | .Struct, .ErrorUnion, .Optional => "struct", |
| 1503 | .Union => if (child_ty.unionTagTypeSafety()) |_| "struct " else "union ", | 1497 | .Union => if (child_ty.unionTagTypeSafety()) |_| "struct" else "union", |
| 1504 | else => unreachable, | 1498 | else => unreachable, |
| 1505 | }; | 1499 | }; |
| 1506 | const name_begin = buffer.items.len + "typedef ".len + tag.len; | 1500 | try bw.writeAll("typedef "); |
| 1507 | try buffer.writer().print("typedef {s}zig_S_{}__{d} ", .{ | 1501 | try bw.writeAll(tag); |
| 1508 | tag, | 1502 | const name_begin = buffer.items.len + " ".len; |
| 1509 | fmtIdent(fqn_buf.items), | 1503 | try bw.writeAll(" zig_"); |
| 1510 | @enumToInt(owner_decl_index), | 1504 | switch (child_ty.zigTypeTag()) { |
| 1511 | }); | 1505 | .Struct, .Union => { |
| 1512 | const name_end = buffer.items.len - " ".len; | 1506 | var fqn_buf = std.ArrayList(u8).init(dg.typedefs.allocator); |
| 1513 | try buffer.ensureUnusedCapacity((name_end - name_begin) + ";\n".len); | 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 | buffer.appendSliceAssumeCapacity(buffer.items[name_begin..name_end]); | 1527 | buffer.appendSliceAssumeCapacity(buffer.items[name_begin..name_end]); |
| 1515 | buffer.appendSliceAssumeCapacity(";\n"); | 1528 | buffer.appendSliceAssumeCapacity(";\n"); |
| 1516 | | 1529 | |
| ... | @@ -1570,7 +1583,11 @@ pub const DeclGen = struct { | ... | @@ -1570,7 +1583,11 @@ pub const DeclGen = struct { |
| 1570 | return name; | 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 | var buffer = std.ArrayList(u8).init(dg.typedefs.allocator); | 1591 | var buffer = std.ArrayList(u8).init(dg.typedefs.allocator); |
| 1575 | defer buffer.deinit(); | 1592 | defer buffer.deinit(); |
| 1576 | | 1593 | |
| ... | @@ -1582,7 +1599,7 @@ pub const DeclGen = struct { | ... | @@ -1582,7 +1599,7 @@ pub const DeclGen = struct { |
| 1582 | if (!field_ty.hasRuntimeBits() or fields.values[i].tag() != .unreachable_value) continue; | 1599 | if (!field_ty.hasRuntimeBits() or fields.values[i].tag() != .unreachable_value) continue; |
| 1583 | | 1600 | |
| 1584 | try buffer.append(' '); | 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 | try buffer.appendSlice(";\n"); | 1603 | try buffer.appendSlice(";\n"); |
| 1587 | | 1604 | |
| 1588 | field_id += 1; | 1605 | field_id += 1; |
| ... | @@ -1670,6 +1687,11 @@ pub const DeclGen = struct { | ... | @@ -1670,6 +1687,11 @@ pub const DeclGen = struct { |
| 1670 | fn renderErrorUnionTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 { | 1687 | fn renderErrorUnionTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 { |
| 1671 | assert(t.errorUnionSet().tag() == .anyerror); | 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 | var buffer = std.ArrayList(u8).init(dg.typedefs.allocator); | 1695 | var buffer = std.ArrayList(u8).init(dg.typedefs.allocator); |
| 1674 | defer buffer.deinit(); | 1696 | defer buffer.deinit(); |
| 1675 | const bw = buffer.writer(); | 1697 | const bw = buffer.writer(); |
| ... | @@ -1682,7 +1704,9 @@ pub const DeclGen = struct { | ... | @@ -1682,7 +1704,9 @@ pub const DeclGen = struct { |
| 1682 | const target = dg.module.getTarget(); | 1704 | const target = dg.module.getTarget(); |
| 1683 | const payload_align = payload_ty.abiAlignment(target); | 1705 | const payload_align = payload_ty.abiAlignment(target); |
| 1684 | const error_align = error_ty.abiAlignment(target); | 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 | if (error_align > payload_align) { | 1710 | if (error_align > payload_align) { |
| 1687 | try dg.renderTypeAndName(bw, payload_ty, payload_name, .Mut, 0, .Complete); | 1711 | try dg.renderTypeAndName(bw, payload_ty, payload_name, .Mut, 0, .Complete); |
| 1688 | try bw.writeAll(";\n "); | 1712 | try bw.writeAll(";\n "); |
| ... | @@ -1692,15 +1716,10 @@ pub const DeclGen = struct { | ... | @@ -1692,15 +1716,10 @@ pub const DeclGen = struct { |
| 1692 | try bw.writeAll(";\n "); | 1716 | try bw.writeAll(";\n "); |
| 1693 | try dg.renderTypeAndName(bw, payload_ty, payload_name, .Mut, 0, .Complete); | 1717 | try dg.renderTypeAndName(bw, payload_ty, payload_name, .Mut, 0, .Complete); |
| 1694 | } | 1718 | } |
| 1695 | try bw.writeAll(";\n} "); | 1719 | try bw.writeAll(";\n};\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"); | | |
| 1700 | | 1720 | |
| 1701 | const rendered = try buffer.toOwnedSlice(); | 1721 | const rendered = try buffer.toOwnedSlice(); |
| 1702 | errdefer dg.typedefs.allocator.free(rendered); | 1722 | errdefer dg.typedefs.allocator.free(rendered); |
| 1703 | const name = rendered[name_begin..name_end]; | | |
| 1704 | | 1723 | |
| 1705 | try dg.typedefs.ensureUnusedCapacity(1); | 1724 | try dg.typedefs.ensureUnusedCapacity(1); |
| 1706 | dg.typedefs.putAssumeCapacityNoClobber( | 1725 | dg.typedefs.putAssumeCapacityNoClobber( |
| ... | @@ -1744,24 +1763,29 @@ pub const DeclGen = struct { | ... | @@ -1744,24 +1763,29 @@ pub const DeclGen = struct { |
| 1744 | return name; | 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 | var buffer = std.ArrayList(u8).init(dg.typedefs.allocator); | 1772 | var buffer = std.ArrayList(u8).init(dg.typedefs.allocator); |
| 1749 | defer buffer.deinit(); | 1773 | defer buffer.deinit(); |
| 1750 | const bw = buffer.writer(); | 1774 | const bw = buffer.writer(); |
| 1751 | | 1775 | |
| 1752 | try bw.writeAll("typedef struct {\n "); | 1776 | var opt_buf: Type.Payload.ElemType = undefined; |
| 1753 | try dg.renderTypeAndName(bw, child_type, .{ .identifier = "payload" }, .Mut, 0, .Complete); | 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 | try bw.writeAll(";\n "); | 1783 | try bw.writeAll(";\n "); |
| 1755 | try dg.renderTypeAndName(bw, Type.bool, .{ .identifier = "is_null" }, .Mut, 0, .Complete); | 1784 | try dg.renderTypeAndName(bw, Type.bool, .{ .identifier = "is_null" }, .Mut, 0, .Complete); |
| 1756 | try bw.writeAll(";\n} "); | 1785 | try bw.writeAll(";\n};\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"); | | |
| 1761 | | 1786 | |
| 1762 | const rendered = try buffer.toOwnedSlice(); | 1787 | const rendered = try buffer.toOwnedSlice(); |
| 1763 | errdefer dg.typedefs.allocator.free(rendered); | 1788 | errdefer dg.typedefs.allocator.free(rendered); |
| 1764 | const name = rendered[name_begin..name_end]; | | |
| 1765 | | 1789 | |
| 1766 | try dg.typedefs.ensureUnusedCapacity(1); | 1790 | try dg.typedefs.ensureUnusedCapacity(1); |
| 1767 | dg.typedefs.putAssumeCapacityNoClobber( | 1791 | dg.typedefs.putAssumeCapacityNoClobber( |
| ... | @@ -1900,18 +1924,34 @@ pub const DeclGen = struct { | ... | @@ -1900,18 +1924,34 @@ pub const DeclGen = struct { |
| 1900 | }, | 1924 | }, |
| 1901 | .Optional => { | 1925 | .Optional => { |
| 1902 | var opt_buf: Type.Payload.ElemType = undefined; | 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 | return dg.renderType(w, Type.bool, kind); | 1930 | return dg.renderType(w, Type.bool, kind); |
| 1907 | | 1931 | |
| 1908 | if (t.optionalReprIsPayload()) | 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 | 1935 | switch (kind) { |
| 1912 | try dg.renderOptionalTypedef(t, child_type); | 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 | .ErrorUnion => { | 1956 | .ErrorUnion => { |
| 1917 | const payload_ty = t.errorUnionPayload(); | 1957 | const payload_ty = t.errorUnionPayload(); |
| ... | @@ -1924,10 +1964,26 @@ pub const DeclGen = struct { | ... | @@ -1924,10 +1964,26 @@ pub const DeclGen = struct { |
| 1924 | }; | 1964 | }; |
| 1925 | const error_union_ty = Type.initPayload(&error_union_pl.base); | 1965 | const error_union_ty = Type.initPayload(&error_union_pl.base); |
| 1926 | | 1966 | |
| 1927 | const name = dg.getTypedefName(error_union_ty) orelse | 1967 | switch (kind) { |
| 1928 | try dg.renderErrorUnionTypedef(error_union_ty); | 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 | .Struct, .Union => |tag| if (t.containerLayout() == .Packed) { | 1988 | .Struct, .Union => |tag| if (t.containerLayout() == .Packed) { |
| 1933 | if (t.castTag(.@"struct")) |struct_obj| { | 1989 | if (t.castTag(.@"struct")) |struct_obj| { |
| ... | @@ -1965,28 +2021,31 @@ pub const DeclGen = struct { | ... | @@ -1965,28 +2021,31 @@ pub const DeclGen = struct { |
| 1965 | const tuple_ty = Type.initPayload(&tuple_pl.base); | 2021 | const tuple_ty = Type.initPayload(&tuple_pl.base); |
| 1966 | | 2022 | |
| 1967 | const name = dg.getTypedefName(tuple_ty) orelse | 2023 | const name = dg.getTypedefName(tuple_ty) orelse |
| 1968 | try dg.renderTupleTypedef(tuple_ty); | 2024 | try dg.renderTupleTypedef(tuple_ty, kind); |
| 1969 | | 2025 | |
| 1970 | try w.writeAll(name); | 2026 | try w.writeAll(name); |
| 1971 | } else if (kind == .Complete) { | 2027 | } else switch (kind) { |
| 1972 | const name = dg.getTypedefName(t) orelse switch (tag) { | 2028 | .Complete => { |
| 1973 | .Struct => try dg.renderStructTypedef(t), | 2029 | const name = dg.getTypedefName(t) orelse switch (tag) { |
| 1974 | .Union => try dg.renderUnionTypedef(t), | 2030 | .Struct => try dg.renderStructTypedef(t), |
| 1975 | else => unreachable, | 2031 | .Union => try dg.renderUnionTypedef(t), |
| 1976 | }; | 2032 | else => unreachable, |
| | 2033 | }; |
| 1977 | | 2034 | |
| 1978 | try w.writeAll(name); | 2035 | try w.writeAll(name); |
| 1979 | } else { | 2036 | }, |
| 1980 | var ptr_pl = Type.Payload.ElemType{ | 2037 | .Forward => { |
| 1981 | .base = .{ .tag = .single_const_pointer }, | 2038 | var ptr_pl = Type.Payload.ElemType{ |
| 1982 | .data = t, | 2039 | .base = .{ .tag = .single_const_pointer }, |
| 1983 | }; | 2040 | .data = t, |
| 1984 | const ptr_ty = Type.initPayload(&ptr_pl.base); | 2041 | }; |
| | 2042 | const ptr_ty = Type.initPayload(&ptr_pl.base); |
| 1985 | | 2043 | |
| 1986 | const name = dg.getTypedefName(ptr_ty) orelse | 2044 | const name = dg.getTypedefName(ptr_ty) orelse |
| 1987 | try dg.renderFwdTypedef(ptr_ty); | 2045 | try dg.renderFwdTypedef(ptr_ty); |
| 1988 | | 2046 | |
| 1989 | try w.writeAll(name); | 2047 | try w.writeAll(name); |
| | 2048 | }, |
| 1990 | }, | 2049 | }, |
| 1991 | .Enum => { | 2050 | .Enum => { |
| 1992 | // For enums, we simply use the integer tag type. | 2051 | // For enums, we simply use the integer tag type. |