| ... | @@ -569,7 +569,7 @@ pub const DeclGen = struct { | ... | @@ -569,7 +569,7 @@ pub const DeclGen = struct { |
| 569 | try writer.writeByte(')'); | 569 | try writer.writeByte(')'); |
| 570 | } | 570 | } |
| 571 | try writer.writeByte('&'); | 571 | try writer.writeByte('&'); |
| 572 | try dg.renderDeclName(writer, decl_index); | 572 | try dg.renderDeclName(writer, decl_index, 0); |
| 573 | if (need_typecast) try writer.writeByte(')'); | 573 | if (need_typecast) try writer.writeByte(')'); |
| 574 | } | 574 | } |
| 575 | | 575 | |
| ... | @@ -1026,11 +1026,11 @@ pub const DeclGen = struct { | ... | @@ -1026,11 +1026,11 @@ pub const DeclGen = struct { |
| 1026 | }, | 1026 | }, |
| 1027 | .function => { | 1027 | .function => { |
| 1028 | const func = val.castTag(.function).?.data; | 1028 | const func = val.castTag(.function).?.data; |
| 1029 | try dg.renderDeclName(writer, func.owner_decl); | 1029 | try dg.renderDeclName(writer, func.owner_decl, 0); |
| 1030 | }, | 1030 | }, |
| 1031 | .extern_fn => { | 1031 | .extern_fn => { |
| 1032 | const extern_fn = val.castTag(.extern_fn).?.data; | 1032 | const extern_fn = val.castTag(.extern_fn).?.data; |
| 1033 | try dg.renderDeclName(writer, extern_fn.owner_decl); | 1033 | try dg.renderDeclName(writer, extern_fn.owner_decl, 0); |
| 1034 | }, | 1034 | }, |
| 1035 | .int_u64, .one => { | 1035 | .int_u64, .one => { |
| 1036 | try writer.writeAll("(("); | 1036 | try writer.writeAll("(("); |
| ... | @@ -1356,7 +1356,7 @@ pub const DeclGen = struct { | ... | @@ -1356,7 +1356,7 @@ pub const DeclGen = struct { |
| 1356 | } | 1356 | } |
| 1357 | } | 1357 | } |
| 1358 | | 1358 | |
| 1359 | fn renderFunctionSignature(dg: *DeclGen, w: anytype, kind: TypedefKind) !void { | 1359 | fn renderFunctionSignature(dg: *DeclGen, w: anytype, kind: TypedefKind, export_index: u32) !void { |
| 1360 | const fn_info = dg.decl.ty.fnInfo(); | 1360 | const fn_info = dg.decl.ty.fnInfo(); |
| 1361 | if (fn_info.cc == .Naked) try w.writeAll("zig_naked "); | 1361 | if (fn_info.cc == .Naked) try w.writeAll("zig_naked "); |
| 1362 | if (dg.decl.val.castTag(.function)) |func_payload| | 1362 | if (dg.decl.val.castTag(.function)) |func_payload| |
| ... | @@ -1368,7 +1368,7 @@ pub const DeclGen = struct { | ... | @@ -1368,7 +1368,7 @@ pub const DeclGen = struct { |
| 1368 | | 1368 | |
| 1369 | try dg.renderType(w, ret_ty, kind); | 1369 | try dg.renderType(w, ret_ty, kind); |
| 1370 | try w.writeByte(' '); | 1370 | try w.writeByte(' '); |
| 1371 | try dg.renderDeclName(w, dg.decl_index); | 1371 | try dg.renderDeclName(w, dg.decl_index, export_index); |
| 1372 | try w.writeByte('('); | 1372 | try w.writeByte('('); |
| 1373 | | 1373 | |
| 1374 | var index: usize = 0; | 1374 | var index: usize = 0; |
| ... | @@ -1387,6 +1387,7 @@ pub const DeclGen = struct { | ... | @@ -1387,6 +1387,7 @@ pub const DeclGen = struct { |
| 1387 | try dg.renderType(w, Type.void, kind); | 1387 | try dg.renderType(w, Type.void, kind); |
| 1388 | } | 1388 | } |
| 1389 | try w.writeByte(')'); | 1389 | try w.writeByte(')'); |
| | 1390 | if (fn_info.alignment > 0) try w.print(" zig_align_fn({})", .{fn_info.alignment}); |
| 1390 | } | 1391 | } |
| 1391 | | 1392 | |
| 1392 | fn renderPtrToFnTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 { | 1393 | fn renderPtrToFnTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 { |
| ... | @@ -1487,29 +1488,42 @@ pub const DeclGen = struct { | ... | @@ -1487,29 +1488,42 @@ pub const DeclGen = struct { |
| 1487 | // 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. |
| 1488 | const child_ty = t.childType(); | 1489 | const child_ty = t.childType(); |
| 1489 | | 1490 | |
| 1490 | var fqn_buf = std.ArrayList(u8).init(dg.typedefs.allocator); | | |
| 1491 | defer fqn_buf.deinit(); | | |
| 1492 | | | |
| 1493 | const owner_decl_index = child_ty.getOwnerDecl(); | | |
| 1494 | const owner_decl = dg.module.declPtr(owner_decl_index); | | |
| 1495 | try owner_decl.renderFullyQualifiedName(dg.module, fqn_buf.writer()); | | |
| 1496 | | | |
| 1497 | var buffer = std.ArrayList(u8).init(dg.typedefs.allocator); | 1491 | var buffer = std.ArrayList(u8).init(dg.typedefs.allocator); |
| 1498 | defer buffer.deinit(); | 1492 | defer buffer.deinit(); |
| | 1493 | const bw = buffer.writer(); |
| 1499 | | 1494 | |
| 1500 | const tag = switch (child_ty.zigTypeTag()) { | 1495 | const tag = switch (child_ty.zigTypeTag()) { |
| 1501 | .Struct => "struct ", | 1496 | .Struct, .ErrorUnion, .Optional => "struct", |
| 1502 | .Union => if (child_ty.unionTagTypeSafety()) |_| "struct " else "union ", | 1497 | .Union => if (child_ty.unionTagTypeSafety()) |_| "struct" else "union", |
| 1503 | else => unreachable, | 1498 | else => unreachable, |
| 1504 | }; | 1499 | }; |
| 1505 | const name_begin = buffer.items.len + "typedef ".len + tag.len; | 1500 | try bw.writeAll("typedef "); |
| 1506 | try buffer.writer().print("typedef {s}zig_S_{}__{d} ", .{ | 1501 | try bw.writeAll(tag); |
| 1507 | tag, | 1502 | const name_begin = buffer.items.len + " ".len; |
| 1508 | fmtIdent(fqn_buf.items), | 1503 | try bw.writeAll(" zig_"); |
| 1509 | @enumToInt(owner_decl_index), | 1504 | switch (child_ty.zigTypeTag()) { |
| 1510 | }); | 1505 | .Struct, .Union => { |
| 1511 | const name_end = buffer.items.len - " ".len; | 1506 | var fqn_buf = std.ArrayList(u8).init(dg.typedefs.allocator); |
| 1512 | 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(' '); |
| 1513 | buffer.appendSliceAssumeCapacity(buffer.items[name_begin..name_end]); | 1527 | buffer.appendSliceAssumeCapacity(buffer.items[name_begin..name_end]); |
| 1514 | buffer.appendSliceAssumeCapacity(";\n"); | 1528 | buffer.appendSliceAssumeCapacity(";\n"); |
| 1515 | | 1529 | |
| ... | @@ -1569,7 +1583,11 @@ pub const DeclGen = struct { | ... | @@ -1569,7 +1583,11 @@ pub const DeclGen = struct { |
| 1569 | return name; | 1583 | return name; |
| 1570 | } | 1584 | } |
| 1571 | | 1585 | |
| 1572 | 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 { |
| 1573 | var buffer = std.ArrayList(u8).init(dg.typedefs.allocator); | 1591 | var buffer = std.ArrayList(u8).init(dg.typedefs.allocator); |
| 1574 | defer buffer.deinit(); | 1592 | defer buffer.deinit(); |
| 1575 | | 1593 | |
| ... | @@ -1581,7 +1599,7 @@ pub const DeclGen = struct { | ... | @@ -1581,7 +1599,7 @@ pub const DeclGen = struct { |
| 1581 | 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; |
| 1582 | | 1600 | |
| 1583 | try buffer.append(' '); | 1601 | try buffer.append(' '); |
| 1584 | 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); |
| 1585 | try buffer.appendSlice(";\n"); | 1603 | try buffer.appendSlice(";\n"); |
| 1586 | | 1604 | |
| 1587 | field_id += 1; | 1605 | field_id += 1; |
| ... | @@ -1669,6 +1687,11 @@ pub const DeclGen = struct { | ... | @@ -1669,6 +1687,11 @@ pub const DeclGen = struct { |
| 1669 | fn renderErrorUnionTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 { | 1687 | fn renderErrorUnionTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 { |
| 1670 | assert(t.errorUnionSet().tag() == .anyerror); | 1688 | assert(t.errorUnionSet().tag() == .anyerror); |
| 1671 | | 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 | |
| 1672 | var buffer = std.ArrayList(u8).init(dg.typedefs.allocator); | 1695 | var buffer = std.ArrayList(u8).init(dg.typedefs.allocator); |
| 1673 | defer buffer.deinit(); | 1696 | defer buffer.deinit(); |
| 1674 | const bw = buffer.writer(); | 1697 | const bw = buffer.writer(); |
| ... | @@ -1681,7 +1704,9 @@ pub const DeclGen = struct { | ... | @@ -1681,7 +1704,9 @@ pub const DeclGen = struct { |
| 1681 | const target = dg.module.getTarget(); | 1704 | const target = dg.module.getTarget(); |
| 1682 | const payload_align = payload_ty.abiAlignment(target); | 1705 | const payload_align = payload_ty.abiAlignment(target); |
| 1683 | const error_align = error_ty.abiAlignment(target); | 1706 | const error_align = error_ty.abiAlignment(target); |
| 1684 | try bw.writeAll("typedef struct {\n "); | 1707 | try bw.writeAll("struct "); |
| | 1708 | try bw.writeAll(name); |
| | 1709 | try bw.writeAll(" {\n "); |
| 1685 | if (error_align > payload_align) { | 1710 | if (error_align > payload_align) { |
| 1686 | try dg.renderTypeAndName(bw, payload_ty, payload_name, .Mut, 0, .Complete); | 1711 | try dg.renderTypeAndName(bw, payload_ty, payload_name, .Mut, 0, .Complete); |
| 1687 | try bw.writeAll(";\n "); | 1712 | try bw.writeAll(";\n "); |
| ... | @@ -1691,15 +1716,10 @@ pub const DeclGen = struct { | ... | @@ -1691,15 +1716,10 @@ pub const DeclGen = struct { |
| 1691 | try bw.writeAll(";\n "); | 1716 | try bw.writeAll(";\n "); |
| 1692 | try dg.renderTypeAndName(bw, payload_ty, payload_name, .Mut, 0, .Complete); | 1717 | try dg.renderTypeAndName(bw, payload_ty, payload_name, .Mut, 0, .Complete); |
| 1693 | } | 1718 | } |
| 1694 | try bw.writeAll(";\n} "); | 1719 | try bw.writeAll(";\n};\n"); |
| 1695 | const name_begin = buffer.items.len; | | |
| 1696 | try bw.print("zig_E_{}", .{typeToCIdentifier(payload_ty, dg.module)}); | | |
| 1697 | const name_end = buffer.items.len; | | |
| 1698 | try bw.writeAll(";\n"); | | |
| 1699 | | 1720 | |
| 1700 | const rendered = try buffer.toOwnedSlice(); | 1721 | const rendered = try buffer.toOwnedSlice(); |
| 1701 | errdefer dg.typedefs.allocator.free(rendered); | 1722 | errdefer dg.typedefs.allocator.free(rendered); |
| 1702 | const name = rendered[name_begin..name_end]; | | |
| 1703 | | 1723 | |
| 1704 | try dg.typedefs.ensureUnusedCapacity(1); | 1724 | try dg.typedefs.ensureUnusedCapacity(1); |
| 1705 | dg.typedefs.putAssumeCapacityNoClobber( | 1725 | dg.typedefs.putAssumeCapacityNoClobber( |
| ... | @@ -1743,24 +1763,29 @@ pub const DeclGen = struct { | ... | @@ -1743,24 +1763,29 @@ pub const DeclGen = struct { |
| 1743 | return name; | 1763 | return name; |
| 1744 | } | 1764 | } |
| 1745 | | 1765 | |
| 1746 | 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 | |
| 1747 | var buffer = std.ArrayList(u8).init(dg.typedefs.allocator); | 1772 | var buffer = std.ArrayList(u8).init(dg.typedefs.allocator); |
| 1748 | defer buffer.deinit(); | 1773 | defer buffer.deinit(); |
| 1749 | const bw = buffer.writer(); | 1774 | const bw = buffer.writer(); |
| 1750 | | 1775 | |
| 1751 | try bw.writeAll("typedef struct {\n "); | 1776 | var opt_buf: Type.Payload.ElemType = undefined; |
| 1752 | 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); |
| 1753 | try bw.writeAll(";\n "); | 1783 | try bw.writeAll(";\n "); |
| 1754 | 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); |
| 1755 | try bw.writeAll(";\n} "); | 1785 | try bw.writeAll(";\n};\n"); |
| 1756 | const name_begin = buffer.items.len; | | |
| 1757 | try bw.print("zig_Q_{}", .{typeToCIdentifier(child_type, dg.module)}); | | |
| 1758 | const name_end = buffer.items.len; | | |
| 1759 | try bw.writeAll(";\n"); | | |
| 1760 | | 1786 | |
| 1761 | const rendered = try buffer.toOwnedSlice(); | 1787 | const rendered = try buffer.toOwnedSlice(); |
| 1762 | errdefer dg.typedefs.allocator.free(rendered); | 1788 | errdefer dg.typedefs.allocator.free(rendered); |
| 1763 | const name = rendered[name_begin..name_end]; | | |
| 1764 | | 1789 | |
| 1765 | try dg.typedefs.ensureUnusedCapacity(1); | 1790 | try dg.typedefs.ensureUnusedCapacity(1); |
| 1766 | dg.typedefs.putAssumeCapacityNoClobber( | 1791 | dg.typedefs.putAssumeCapacityNoClobber( |
| ... | @@ -1899,18 +1924,34 @@ pub const DeclGen = struct { | ... | @@ -1899,18 +1924,34 @@ pub const DeclGen = struct { |
| 1899 | }, | 1924 | }, |
| 1900 | .Optional => { | 1925 | .Optional => { |
| 1901 | var opt_buf: Type.Payload.ElemType = undefined; | 1926 | var opt_buf: Type.Payload.ElemType = undefined; |
| 1902 | const child_type = t.optionalChild(&opt_buf); | 1927 | const child_ty = t.optionalChild(&opt_buf); |
| 1903 | | 1928 | |
| 1904 | if (!child_type.hasRuntimeBitsIgnoreComptime()) | 1929 | if (!child_ty.hasRuntimeBitsIgnoreComptime()) |
| 1905 | return dg.renderType(w, Type.bool, kind); | 1930 | return dg.renderType(w, Type.bool, kind); |
| 1906 | | 1931 | |
| 1907 | if (t.optionalReprIsPayload()) | 1932 | if (t.optionalReprIsPayload()) |
| 1908 | return dg.renderType(w, child_type, kind); | 1933 | return dg.renderType(w, child_ty, kind); |
| 1909 | | 1934 | |
| 1910 | const name = dg.getTypedefName(t) orelse | 1935 | switch (kind) { |
| 1911 | try dg.renderOptionalTypedef(t, child_type); | 1936 | .Complete => { |
| | 1937 | const name = dg.getTypedefName(t) orelse |
| | 1938 | try dg.renderOptionalTypedef(t); |
| 1912 | | 1939 | |
| 1913 | 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 | } |
| 1914 | }, | 1955 | }, |
| 1915 | .ErrorUnion => { | 1956 | .ErrorUnion => { |
| 1916 | const payload_ty = t.errorUnionPayload(); | 1957 | const payload_ty = t.errorUnionPayload(); |
| ... | @@ -1923,10 +1964,26 @@ pub const DeclGen = struct { | ... | @@ -1923,10 +1964,26 @@ pub const DeclGen = struct { |
| 1923 | }; | 1964 | }; |
| 1924 | const error_union_ty = Type.initPayload(&error_union_pl.base); | 1965 | const error_union_ty = Type.initPayload(&error_union_pl.base); |
| 1925 | | 1966 | |
| 1926 | const name = dg.getTypedefName(error_union_ty) orelse | 1967 | switch (kind) { |
| 1927 | try dg.renderErrorUnionTypedef(error_union_ty); | 1968 | .Complete => { |
| | 1969 | const name = dg.getTypedefName(error_union_ty) orelse |
| | 1970 | try dg.renderErrorUnionTypedef(error_union_ty); |
| 1928 | | 1971 | |
| 1929 | 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 | } |
| 1930 | }, | 1987 | }, |
| 1931 | .Struct, .Union => |tag| if (t.containerLayout() == .Packed) { | 1988 | .Struct, .Union => |tag| if (t.containerLayout() == .Packed) { |
| 1932 | if (t.castTag(.@"struct")) |struct_obj| { | 1989 | if (t.castTag(.@"struct")) |struct_obj| { |
| ... | @@ -1964,28 +2021,31 @@ pub const DeclGen = struct { | ... | @@ -1964,28 +2021,31 @@ pub const DeclGen = struct { |
| 1964 | const tuple_ty = Type.initPayload(&tuple_pl.base); | 2021 | const tuple_ty = Type.initPayload(&tuple_pl.base); |
| 1965 | | 2022 | |
| 1966 | const name = dg.getTypedefName(tuple_ty) orelse | 2023 | const name = dg.getTypedefName(tuple_ty) orelse |
| 1967 | try dg.renderTupleTypedef(tuple_ty); | 2024 | try dg.renderTupleTypedef(tuple_ty, kind); |
| 1968 | | 2025 | |
| 1969 | try w.writeAll(name); | 2026 | try w.writeAll(name); |
| 1970 | } else if (kind == .Complete) { | 2027 | } else switch (kind) { |
| 1971 | const name = dg.getTypedefName(t) orelse switch (tag) { | 2028 | .Complete => { |
| 1972 | .Struct => try dg.renderStructTypedef(t), | 2029 | const name = dg.getTypedefName(t) orelse switch (tag) { |
| 1973 | .Union => try dg.renderUnionTypedef(t), | 2030 | .Struct => try dg.renderStructTypedef(t), |
| 1974 | else => unreachable, | 2031 | .Union => try dg.renderUnionTypedef(t), |
| 1975 | }; | 2032 | else => unreachable, |
| | 2033 | }; |
| 1976 | | 2034 | |
| 1977 | try w.writeAll(name); | 2035 | try w.writeAll(name); |
| 1978 | } else { | 2036 | }, |
| 1979 | var ptr_pl = Type.Payload.ElemType{ | 2037 | .Forward => { |
| 1980 | .base = .{ .tag = .single_const_pointer }, | 2038 | var ptr_pl = Type.Payload.ElemType{ |
| 1981 | .data = t, | 2039 | .base = .{ .tag = .single_const_pointer }, |
| 1982 | }; | 2040 | .data = t, |
| 1983 | const ptr_ty = Type.initPayload(&ptr_pl.base); | 2041 | }; |
| | 2042 | const ptr_ty = Type.initPayload(&ptr_pl.base); |
| 1984 | | 2043 | |
| 1985 | const name = dg.getTypedefName(ptr_ty) orelse | 2044 | const name = dg.getTypedefName(ptr_ty) orelse |
| 1986 | try dg.renderFwdTypedef(ptr_ty); | 2045 | try dg.renderFwdTypedef(ptr_ty); |
| 1987 | | 2046 | |
| 1988 | try w.writeAll(name); | 2047 | try w.writeAll(name); |
| | 2048 | }, |
| 1989 | }, | 2049 | }, |
| 1990 | .Enum => { | 2050 | .Enum => { |
| 1991 | // For enums, we simply use the integer tag type. | 2051 | // For enums, we simply use the integer tag type. |
| ... | @@ -2213,10 +2273,10 @@ pub const DeclGen = struct { | ... | @@ -2213,10 +2273,10 @@ pub const DeclGen = struct { |
| 2213 | .constant => unreachable, | 2273 | .constant => unreachable, |
| 2214 | .arg => |i| return w.print("a{d}", .{i}), | 2274 | .arg => |i| return w.print("a{d}", .{i}), |
| 2215 | .field => |i| return w.print("f{d}", .{i}), | 2275 | .field => |i| return w.print("f{d}", .{i}), |
| 2216 | .decl => |decl| return dg.renderDeclName(w, decl), | 2276 | .decl => |decl| return dg.renderDeclName(w, decl, 0), |
| 2217 | .decl_ref => |decl| { | 2277 | .decl_ref => |decl| { |
| 2218 | try w.writeByte('&'); | 2278 | try w.writeByte('&'); |
| 2219 | return dg.renderDeclName(w, decl); | 2279 | return dg.renderDeclName(w, decl, 0); |
| 2220 | }, | 2280 | }, |
| 2221 | .undef => |ty| return dg.renderValue(w, ty, Value.undef, .Other), | 2281 | .undef => |ty| return dg.renderValue(w, ty, Value.undef, .Other), |
| 2222 | .identifier => |ident| return w.print("{ }", .{fmtIdent(ident)}), | 2282 | .identifier => |ident| return w.print("{ }", .{fmtIdent(ident)}), |
| ... | @@ -2234,10 +2294,10 @@ pub const DeclGen = struct { | ... | @@ -2234,10 +2294,10 @@ pub const DeclGen = struct { |
| 2234 | .field => |i| return w.print("f{d}", .{i}), | 2294 | .field => |i| return w.print("f{d}", .{i}), |
| 2235 | .decl => |decl| { | 2295 | .decl => |decl| { |
| 2236 | try w.writeAll("(*"); | 2296 | try w.writeAll("(*"); |
| 2237 | try dg.renderDeclName(w, decl); | 2297 | try dg.renderDeclName(w, decl, 0); |
| 2238 | return w.writeByte(')'); | 2298 | return w.writeByte(')'); |
| 2239 | }, | 2299 | }, |
| 2240 | .decl_ref => |decl| return dg.renderDeclName(w, decl), | 2300 | .decl_ref => |decl| return dg.renderDeclName(w, decl, 0), |
| 2241 | .undef => unreachable, | 2301 | .undef => unreachable, |
| 2242 | .identifier => |ident| return w.print("(*{ })", .{fmtIdent(ident)}), | 2302 | .identifier => |ident| return w.print("(*{ })", .{fmtIdent(ident)}), |
| 2243 | .bytes => |bytes| { | 2303 | .bytes => |bytes| { |
| ... | @@ -2269,12 +2329,12 @@ pub const DeclGen = struct { | ... | @@ -2269,12 +2329,12 @@ pub const DeclGen = struct { |
| 2269 | try dg.writeCValue(writer, member); | 2329 | try dg.writeCValue(writer, member); |
| 2270 | } | 2330 | } |
| 2271 | | 2331 | |
| 2272 | fn renderDeclName(dg: *DeclGen, writer: anytype, decl_index: Decl.Index) !void { | 2332 | fn renderDeclName(dg: *DeclGen, writer: anytype, decl_index: Decl.Index, export_index: u32) !void { |
| 2273 | const decl = dg.module.declPtr(decl_index); | 2333 | const decl = dg.module.declPtr(decl_index); |
| 2274 | dg.module.markDeclAlive(decl); | 2334 | dg.module.markDeclAlive(decl); |
| 2275 | | 2335 | |
| 2276 | if (dg.module.decl_exports.get(decl_index)) |exports| { | 2336 | if (dg.module.decl_exports.get(decl_index)) |exports| { |
| 2277 | return writer.writeAll(exports.items[0].options.name); | 2337 | return writer.writeAll(exports.items[export_index].options.name); |
| 2278 | } else if (decl.isExtern()) { | 2338 | } else if (decl.isExtern()) { |
| 2279 | return writer.writeAll(mem.sliceTo(decl.name, 0)); | 2339 | return writer.writeAll(mem.sliceTo(decl.name, 0)); |
| 2280 | } else if (dg.module.test_functions.get(decl_index)) |_| { | 2340 | } else if (dg.module.test_functions.get(decl_index)) |_| { |
| ... | @@ -2422,24 +2482,44 @@ pub fn genErrDecls(o: *Object) !void { | ... | @@ -2422,24 +2482,44 @@ pub fn genErrDecls(o: *Object) !void { |
| 2422 | try writer.writeAll("};\n"); | 2482 | try writer.writeAll("};\n"); |
| 2423 | } | 2483 | } |
| 2424 | | 2484 | |
| | 2485 | fn genExports(o: *Object) !void { |
| | 2486 | const tracy = trace(@src()); |
| | 2487 | defer tracy.end(); |
| | 2488 | |
| | 2489 | const fwd_decl_writer = o.dg.fwd_decl.writer(); |
| | 2490 | if (o.dg.module.decl_exports.get(o.dg.decl_index)) |exports| for (exports.items[1..]) |@"export", i| { |
| | 2491 | try fwd_decl_writer.writeAll("zig_export("); |
| | 2492 | try o.dg.renderFunctionSignature(fwd_decl_writer, .Forward, @intCast(u32, 1 + i)); |
| | 2493 | try fwd_decl_writer.print(", {s}, {s});\n", .{ |
| | 2494 | fmtStringLiteral(exports.items[0].options.name), |
| | 2495 | fmtStringLiteral(@"export".options.name), |
| | 2496 | }); |
| | 2497 | }; |
| | 2498 | } |
| | 2499 | |
| 2425 | pub fn genFunc(f: *Function) !void { | 2500 | pub fn genFunc(f: *Function) !void { |
| 2426 | const tracy = trace(@src()); | 2501 | const tracy = trace(@src()); |
| 2427 | defer tracy.end(); | 2502 | defer tracy.end(); |
| 2428 | | 2503 | |
| 2429 | const o = &f.object; | 2504 | const o = &f.object; |
| | 2505 | const tv: TypedValue = .{ |
| | 2506 | .ty = o.dg.decl.ty, |
| | 2507 | .val = o.dg.decl.val, |
| | 2508 | }; |
| 2430 | | 2509 | |
| 2431 | o.code_header = std.ArrayList(u8).init(f.object.dg.gpa); | 2510 | o.code_header = std.ArrayList(u8).init(f.object.dg.gpa); |
| 2432 | defer o.code_header.deinit(); | 2511 | defer o.code_header.deinit(); |
| 2433 | | 2512 | |
| 2434 | const is_global = o.dg.module.decl_exports.contains(f.func.owner_decl); | 2513 | const is_global = o.dg.declIsGlobal(tv); |
| 2435 | const fwd_decl_writer = o.dg.fwd_decl.writer(); | 2514 | const fwd_decl_writer = o.dg.fwd_decl.writer(); |
| 2436 | try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static "); | 2515 | try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static "); |
| 2437 | try o.dg.renderFunctionSignature(fwd_decl_writer, .Forward); | 2516 | try o.dg.renderFunctionSignature(fwd_decl_writer, .Forward, 0); |
| 2438 | try fwd_decl_writer.writeAll(";\n"); | 2517 | try fwd_decl_writer.writeAll(";\n"); |
| | 2518 | try genExports(o); |
| 2439 | | 2519 | |
| 2440 | try o.indent_writer.insertNewline(); | 2520 | try o.indent_writer.insertNewline(); |
| 2441 | if (!is_global) try o.writer().writeAll("static "); | 2521 | if (!is_global) try o.writer().writeAll("static "); |
| 2442 | try o.dg.renderFunctionSignature(o.writer(), .Complete); | 2522 | try o.dg.renderFunctionSignature(o.writer(), .Complete, 0); |
| 2443 | try o.writer().writeByte(' '); | 2523 | try o.writer().writeByte(' '); |
| 2444 | | 2524 | |
| 2445 | // In case we need to use the header, populate it with a copy of the function | 2525 | // In case we need to use the header, populate it with a copy of the function |
| ... | @@ -2474,23 +2554,22 @@ pub fn genDecl(o: *Object) !void { | ... | @@ -2474,23 +2554,22 @@ pub fn genDecl(o: *Object) !void { |
| 2474 | if (tv.val.tag() == .extern_fn) { | 2554 | if (tv.val.tag() == .extern_fn) { |
| 2475 | const fwd_decl_writer = o.dg.fwd_decl.writer(); | 2555 | const fwd_decl_writer = o.dg.fwd_decl.writer(); |
| 2476 | try fwd_decl_writer.writeAll("zig_extern "); | 2556 | try fwd_decl_writer.writeAll("zig_extern "); |
| 2477 | try o.dg.renderFunctionSignature(fwd_decl_writer, .Forward); | 2557 | try o.dg.renderFunctionSignature(fwd_decl_writer, .Forward, 0); |
| 2478 | try fwd_decl_writer.writeAll(";\n"); | 2558 | try fwd_decl_writer.writeAll(";\n"); |
| | 2559 | try genExports(o); |
| 2479 | } else if (tv.val.castTag(.variable)) |var_payload| { | 2560 | } else if (tv.val.castTag(.variable)) |var_payload| { |
| 2480 | const variable: *Module.Var = var_payload.data; | 2561 | const variable: *Module.Var = var_payload.data; |
| | 2562 | |
| 2481 | const is_global = o.dg.declIsGlobal(tv) or variable.is_extern; | 2563 | const is_global = o.dg.declIsGlobal(tv) or variable.is_extern; |
| 2482 | const fwd_decl_writer = o.dg.fwd_decl.writer(); | 2564 | const fwd_decl_writer = o.dg.fwd_decl.writer(); |
| 2483 | | 2565 | |
| 2484 | const decl_c_value: CValue = if (is_global) .{ | 2566 | const decl_c_value = CValue{ .decl = o.dg.decl_index }; |
| 2485 | .bytes = mem.span(o.dg.decl.name), | | |
| 2486 | } else .{ | | |
| 2487 | .decl = o.dg.decl_index, | | |
| 2488 | }; | | |
| 2489 | | 2567 | |
| 2490 | try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static "); | 2568 | try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static "); |
| 2491 | if (variable.is_threadlocal) try fwd_decl_writer.writeAll("zig_threadlocal "); | 2569 | if (variable.is_threadlocal) try fwd_decl_writer.writeAll("zig_threadlocal "); |
| 2492 | try o.dg.renderTypeAndName(fwd_decl_writer, o.dg.decl.ty, decl_c_value, .Mut, o.dg.decl.@"align", .Complete); | 2570 | try o.dg.renderTypeAndName(fwd_decl_writer, o.dg.decl.ty, decl_c_value, .Mut, o.dg.decl.@"align", .Complete); |
| 2493 | try fwd_decl_writer.writeAll(";\n"); | 2571 | try fwd_decl_writer.writeAll(";\n"); |
| | 2572 | try genExports(o); |
| 2494 | | 2573 | |
| 2495 | if (variable.is_extern) return; | 2574 | if (variable.is_extern) return; |
| 2496 | | 2575 | |
| ... | @@ -2536,7 +2615,7 @@ pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void { | ... | @@ -2536,7 +2615,7 @@ pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void { |
| 2536 | const is_global = dg.declIsGlobal(tv); | 2615 | const is_global = dg.declIsGlobal(tv); |
| 2537 | if (is_global) { | 2616 | if (is_global) { |
| 2538 | try writer.writeAll("zig_extern "); | 2617 | try writer.writeAll("zig_extern "); |
| 2539 | try dg.renderFunctionSignature(writer, .Complete); | 2618 | try dg.renderFunctionSignature(writer, .Complete, 0); |
| 2540 | try dg.fwd_decl.appendSlice(";\n"); | 2619 | try dg.fwd_decl.appendSlice(";\n"); |
| 2541 | } | 2620 | } |
| 2542 | }, | 2621 | }, |
| ... | @@ -3676,7 +3755,7 @@ fn airCall( | ... | @@ -3676,7 +3755,7 @@ fn airCall( |
| 3676 | }; | 3755 | }; |
| 3677 | }; | 3756 | }; |
| 3678 | name = f.object.dg.module.declPtr(fn_decl).name; | 3757 | name = f.object.dg.module.declPtr(fn_decl).name; |
| 3679 | try f.object.dg.renderDeclName(writer, fn_decl); | 3758 | try f.object.dg.renderDeclName(writer, fn_decl, 0); |
| 3680 | break :callee; | 3759 | break :callee; |
| 3681 | } | 3760 | } |
| 3682 | // Fall back to function pointer call. | 3761 | // Fall back to function pointer call. |
| ... | @@ -4195,7 +4274,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4195,7 +4274,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4195 | } | 4274 | } |
| 4196 | } | 4275 | } |
| 4197 | { | 4276 | { |
| 4198 | const asm_source = std.mem.sliceAsBytes(f.air.extra[extra_i..])[0..extra.data.source_len]; | 4277 | const asm_source = mem.sliceAsBytes(f.air.extra[extra_i..])[0..extra.data.source_len]; |
| 4199 | | 4278 | |
| 4200 | var stack = std.heap.stackFallback(256, f.object.dg.gpa); | 4279 | var stack = std.heap.stackFallback(256, f.object.dg.gpa); |
| 4201 | const allocator = stack.get(); | 4280 | const allocator = stack.get(); |
| ... | @@ -4204,29 +4283,43 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4204,29 +4283,43 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4204 | | 4283 | |
| 4205 | var src_i: usize = 0; | 4284 | var src_i: usize = 0; |
| 4206 | var dst_i: usize = 0; | 4285 | var dst_i: usize = 0; |
| 4207 | while (src_i < asm_source.len) : (src_i += 1) { | 4286 | while (true) { |
| 4208 | fixed_asm_source[dst_i] = asm_source[src_i]; | 4287 | const literal = mem.sliceTo(asm_source[src_i..], '%'); |
| 4209 | dst_i += 1; | 4288 | src_i += literal.len; |
| 4210 | if (asm_source[src_i] != '%' or src_i + 1 >= asm_source.len) continue; | 4289 | |
| | 4290 | mem.copy(u8, fixed_asm_source[dst_i..], literal); |
| | 4291 | dst_i += literal.len; |
| | 4292 | |
| | 4293 | if (src_i >= asm_source.len) break; |
| | 4294 | |
| 4211 | src_i += 1; | 4295 | src_i += 1; |
| | 4296 | if (src_i >= asm_source.len) |
| | 4297 | return f.fail("CBE: invalid inline asm string '{s}'", .{asm_source}); |
| | 4298 | |
| | 4299 | fixed_asm_source[dst_i] = '%'; |
| | 4300 | dst_i += 1; |
| | 4301 | |
| 4212 | if (asm_source[src_i] != '[') { | 4302 | if (asm_source[src_i] != '[') { |
| 4213 | // This handles %% | 4303 | // This also handles %% |
| 4214 | fixed_asm_source[dst_i] = asm_source[src_i]; | 4304 | fixed_asm_source[dst_i] = asm_source[src_i]; |
| | 4305 | src_i += 1; |
| 4215 | dst_i += 1; | 4306 | dst_i += 1; |
| 4216 | continue; | 4307 | continue; |
| 4217 | } | 4308 | } |
| 4218 | const len = std.mem.indexOfScalar(u8, asm_source[src_i + 1 ..], ']') orelse | | |
| 4219 | return f.fail("CBE: invalid inline asm string '{s}'", .{asm_source}); | | |
| 4220 | if (std.mem.indexOfScalar(u8, asm_source[src_i + 1 ..][0..len], ':')) |colon| { | | |
| 4221 | const modifier = asm_source[src_i + 1 + colon + 1 .. src_i + 1 + len]; | | |
| 4222 | std.mem.copy(u8, fixed_asm_source[dst_i..], modifier); | | |
| 4223 | dst_i += modifier.len; | | |
| 4224 | | 4309 | |
| 4225 | const name = asm_source[src_i .. src_i + 1 + colon]; | 4310 | const desc = mem.sliceTo(asm_source[src_i..], ']'); |
| 4226 | std.mem.copy(u8, fixed_asm_source[dst_i..], name); | 4311 | if (mem.indexOfScalar(u8, desc, ':')) |colon| { |
| | 4312 | const name = desc[0..colon]; |
| | 4313 | const modifier = desc[colon + 1 ..]; |
| | 4314 | |
| | 4315 | mem.copy(u8, fixed_asm_source[dst_i..], modifier); |
| | 4316 | dst_i += modifier.len; |
| | 4317 | mem.copy(u8, fixed_asm_source[dst_i..], name); |
| 4227 | dst_i += name.len; | 4318 | dst_i += name.len; |
| 4228 | | 4319 | |
| 4229 | src_i += len; | 4320 | src_i += desc.len; |
| | 4321 | if (src_i >= asm_source.len) |
| | 4322 | return f.fail("CBE: invalid inline asm string '{s}'", .{asm_source}); |
| 4230 | } | 4323 | } |
| 4231 | } | 4324 | } |
| 4232 | | 4325 | |
| ... | @@ -4535,9 +4628,18 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc | ... | @@ -4535,9 +4628,18 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc |
| 4535 | else => .none, | 4628 | else => .none, |
| 4536 | }; | 4629 | }; |
| 4537 | | 4630 | |
| 4538 | const field_name: CValue = switch (struct_ty.tag()) { | 4631 | const FieldLoc = union(enum) { |
| | 4632 | begin: void, |
| | 4633 | field: CValue, |
| | 4634 | end: void, |
| | 4635 | }; |
| | 4636 | const field_loc = switch (struct_ty.tag()) { |
| 4539 | .@"struct" => switch (struct_ty.containerLayout()) { | 4637 | .@"struct" => switch (struct_ty.containerLayout()) { |
| 4540 | .Auto, .Extern => CValue{ .identifier = struct_ty.structFieldName(index) }, | 4638 | .Auto, .Extern => for (struct_ty.structFields().values()[index..]) |field, offset| { |
| | 4639 | if (field.ty.hasRuntimeBitsIgnoreComptime()) break FieldLoc{ .field = .{ |
| | 4640 | .identifier = struct_ty.structFieldName(index + offset), |
| | 4641 | } }; |
| | 4642 | } else @as(FieldLoc, .end), |
| 4541 | .Packed => if (field_ptr_info.data.host_size == 0) { | 4643 | .Packed => if (field_ptr_info.data.host_size == 0) { |
| 4542 | const target = f.object.dg.module.getTarget(); | 4644 | const target = f.object.dg.module.getTarget(); |
| 4543 | | 4645 | |
| ... | @@ -4562,40 +4664,43 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc | ... | @@ -4562,40 +4664,43 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc |
| 4562 | try f.writeCValue(writer, struct_ptr, .Other); | 4664 | try f.writeCValue(writer, struct_ptr, .Other); |
| 4563 | try writer.print(")[{}];\n", .{try f.fmtIntLiteral(Type.usize, byte_offset_val)}); | 4665 | try writer.print(")[{}];\n", .{try f.fmtIntLiteral(Type.usize, byte_offset_val)}); |
| 4564 | return local; | 4666 | return local; |
| 4565 | } else @as(CValue, CValue.none), // this @as is needed because of a stage1 bug | 4667 | } else @as(FieldLoc, .begin), |
| 4566 | }, | 4668 | }, |
| 4567 | .@"union", .union_safety_tagged, .union_tagged => if (struct_ty.containerLayout() == .Packed) { | 4669 | .@"union", .union_safety_tagged, .union_tagged => if (struct_ty.containerLayout() == .Packed) { |
| 4568 | try f.writeCValue(writer, struct_ptr, .Other); | 4670 | try f.writeCValue(writer, struct_ptr, .Other); |
| 4569 | try writer.writeAll(";\n"); | 4671 | try writer.writeAll(";\n"); |
| 4570 | return local; | 4672 | return local; |
| 4571 | } else .{ | 4673 | } else if (field_ty.hasRuntimeBitsIgnoreComptime()) FieldLoc{ .field = .{ |
| 4572 | .identifier = struct_ty.unionFields().keys()[index], | 4674 | .identifier = struct_ty.unionFields().keys()[index], |
| 4573 | }, | 4675 | } } else @as(FieldLoc, .end), |
| 4574 | .tuple, .anon_struct => field_name: { | 4676 | .tuple, .anon_struct => field_name: { |
| 4575 | const tuple = struct_ty.tupleFields(); | 4677 | const tuple = struct_ty.tupleFields(); |
| 4576 | if (tuple.values[index].tag() != .unreachable_value) return CValue.none; | 4678 | if (tuple.values[index].tag() != .unreachable_value) return CValue.none; |
| 4577 | | 4679 | |
| 4578 | var id: usize = 0; | 4680 | var id: usize = 0; |
| 4579 | for (tuple.values[0..index]) |value| | 4681 | break :field_name for (tuple.values) |value, i| { |
| 4580 | id += @boolToInt(value.tag() == .unreachable_value); | 4682 | if (value.tag() != .unreachable_value) continue; |
| 4581 | break :field_name .{ .field = id }; | 4683 | if (!tuple.types[i].hasRuntimeBitsIgnoreComptime()) continue; |
| | 4684 | if (i >= index) break FieldLoc{ .field = .{ .field = id } }; |
| | 4685 | id += 1; |
| | 4686 | } else @as(FieldLoc, .end); |
| 4582 | }, | 4687 | }, |
| 4583 | else => unreachable, | 4688 | else => unreachable, |
| 4584 | }; | 4689 | }; |
| 4585 | | 4690 | |
| 4586 | if (field_ty.hasRuntimeBitsIgnoreComptime()) { | 4691 | try writer.writeByte('&'); |
| 4587 | try writer.writeByte('&'); | 4692 | switch (field_loc) { |
| 4588 | if (extra_name != .none) { | 4693 | .begin, .end => { |
| | 4694 | try writer.writeByte('('); |
| | 4695 | try f.writeCValue(writer, struct_ptr, .Other); |
| | 4696 | try writer.print(")[{}]", .{@boolToInt(field_loc == .end)}); |
| | 4697 | }, |
| | 4698 | .field => |field| if (extra_name != .none) { |
| 4589 | try f.writeCValueDerefMember(writer, struct_ptr, extra_name); | 4699 | try f.writeCValueDerefMember(writer, struct_ptr, extra_name); |
| 4590 | if (field_name != .none) { | 4700 | try writer.writeByte('.'); |
| 4591 | try writer.writeByte('.'); | 4701 | try f.writeCValue(writer, field, .Other); |
| 4592 | try f.writeCValue(writer, field_name, .Other); | 4702 | } else try f.writeCValueDerefMember(writer, struct_ptr, field), |
| 4593 | } | 4703 | } |
| 4594 | } else if (field_name != .none) | | |
| 4595 | try f.writeCValueDerefMember(writer, struct_ptr, field_name) | | |
| 4596 | else | | |
| 4597 | try f.writeCValueDeref(writer, struct_ptr); | | |
| 4598 | } else try f.writeCValue(writer, struct_ptr, .Other); | | |
| 4599 | try writer.writeAll(";\n"); | 4704 | try writer.writeAll(";\n"); |
| 4600 | return local; | 4705 | return local; |
| 4601 | } | 4706 | } |