| ... | ... | @@ -569,7 +569,7 @@ pub const DeclGen = struct { |
| 569 | 569 | try writer.writeByte(')'); |
| 570 | 570 | } |
| 571 | 571 | try writer.writeByte('&'); |
| 572 | | try dg.renderDeclName(writer, decl_index); |
| 572 | try dg.renderDeclName(writer, decl_index, 0); |
| 573 | 573 | if (need_typecast) try writer.writeByte(')'); |
| 574 | 574 | } |
| 575 | 575 | |
| ... | ... | @@ -1026,11 +1026,11 @@ pub const DeclGen = struct { |
| 1026 | 1026 | }, |
| 1027 | 1027 | .function => { |
| 1028 | 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 | 1031 | .extern_fn => { |
| 1032 | 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 | 1035 | .int_u64, .one => { |
| 1036 | 1036 | try writer.writeAll("(("); |
| ... | ... | @@ -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 | 1360 | const fn_info = dg.decl.ty.fnInfo(); |
| 1361 | 1361 | if (fn_info.cc == .Naked) try w.writeAll("zig_naked "); |
| 1362 | 1362 | if (dg.decl.val.castTag(.function)) |func_payload| |
| ... | ... | @@ -1368,7 +1368,7 @@ pub const DeclGen = struct { |
| 1368 | 1368 | |
| 1369 | 1369 | try dg.renderType(w, ret_ty, kind); |
| 1370 | 1370 | try w.writeByte(' '); |
| 1371 | | try dg.renderDeclName(w, dg.decl_index); |
| 1371 | try dg.renderDeclName(w, dg.decl_index, export_index); |
| 1372 | 1372 | try w.writeByte('('); |
| 1373 | 1373 | |
| 1374 | 1374 | var index: usize = 0; |
| ... | ... | @@ -1387,6 +1387,7 @@ pub const DeclGen = struct { |
| 1387 | 1387 | try dg.renderType(w, Type.void, kind); |
| 1388 | 1388 | } |
| 1389 | 1389 | try w.writeByte(')'); |
| 1390 | if (fn_info.alignment > 0) try w.print(" zig_align_fn({})", .{fn_info.alignment}); |
| 1390 | 1391 | } |
| 1391 | 1392 | |
| 1392 | 1393 | fn renderPtrToFnTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 { |
| ... | ... | @@ -1487,29 +1488,42 @@ pub const DeclGen = struct { |
| 1487 | 1488 | // The forward declaration for T is stored with a key of *const T. |
| 1488 | 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 | 1491 | var buffer = std.ArrayList(u8).init(dg.typedefs.allocator); |
| 1498 | 1492 | defer buffer.deinit(); |
| 1493 | const bw = buffer.writer(); |
| 1499 | 1494 | |
| 1500 | 1495 | const tag = switch (child_ty.zigTypeTag()) { |
| 1501 | | .Struct => "struct ", |
| 1502 | | .Union => if (child_ty.unionTagTypeSafety()) |_| "struct " else "union ", |
| 1496 | .Struct, .ErrorUnion, .Optional => "struct", |
| 1497 | .Union => if (child_ty.unionTagTypeSafety()) |_| "struct" else "union", |
| 1503 | 1498 | else => unreachable, |
| 1504 | 1499 | }; |
| 1505 | | const name_begin = buffer.items.len + "typedef ".len + tag.len; |
| 1506 | | try buffer.writer().print("typedef {s}zig_S_{}__{d} ", .{ |
| 1507 | | tag, |
| 1508 | | fmtIdent(fqn_buf.items), |
| 1509 | | @enumToInt(owner_decl_index), |
| 1510 | | }); |
| 1511 | | const name_end = buffer.items.len - " ".len; |
| 1512 | | 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(' '); |
| 1513 | 1527 | buffer.appendSliceAssumeCapacity(buffer.items[name_begin..name_end]); |
| 1514 | 1528 | buffer.appendSliceAssumeCapacity(";\n"); |
| 1515 | 1529 | |
| ... | ... | @@ -1569,7 +1583,11 @@ pub const DeclGen = struct { |
| 1569 | 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 | 1591 | var buffer = std.ArrayList(u8).init(dg.typedefs.allocator); |
| 1574 | 1592 | defer buffer.deinit(); |
| 1575 | 1593 | |
| ... | ... | @@ -1581,7 +1599,7 @@ pub const DeclGen = struct { |
| 1581 | 1599 | if (!field_ty.hasRuntimeBits() or fields.values[i].tag() != .unreachable_value) continue; |
| 1582 | 1600 | |
| 1583 | 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 | 1603 | try buffer.appendSlice(";\n"); |
| 1586 | 1604 | |
| 1587 | 1605 | field_id += 1; |
| ... | ... | @@ -1669,6 +1687,11 @@ pub const DeclGen = struct { |
| 1669 | 1687 | fn renderErrorUnionTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 { |
| 1670 | 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 | 1695 | var buffer = std.ArrayList(u8).init(dg.typedefs.allocator); |
| 1673 | 1696 | defer buffer.deinit(); |
| 1674 | 1697 | const bw = buffer.writer(); |
| ... | ... | @@ -1681,7 +1704,9 @@ pub const DeclGen = struct { |
| 1681 | 1704 | const target = dg.module.getTarget(); |
| 1682 | 1705 | const payload_align = payload_ty.abiAlignment(target); |
| 1683 | 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 | 1710 | if (error_align > payload_align) { |
| 1686 | 1711 | try dg.renderTypeAndName(bw, payload_ty, payload_name, .Mut, 0, .Complete); |
| 1687 | 1712 | try bw.writeAll(";\n "); |
| ... | ... | @@ -1691,15 +1716,10 @@ pub const DeclGen = struct { |
| 1691 | 1716 | try bw.writeAll(";\n "); |
| 1692 | 1717 | try dg.renderTypeAndName(bw, payload_ty, payload_name, .Mut, 0, .Complete); |
| 1693 | 1718 | } |
| 1694 | | try bw.writeAll(";\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"); |
| 1719 | try bw.writeAll(";\n};\n"); |
| 1699 | 1720 | |
| 1700 | 1721 | const rendered = try buffer.toOwnedSlice(); |
| 1701 | 1722 | errdefer dg.typedefs.allocator.free(rendered); |
| 1702 | | const name = rendered[name_begin..name_end]; |
| 1703 | 1723 | |
| 1704 | 1724 | try dg.typedefs.ensureUnusedCapacity(1); |
| 1705 | 1725 | dg.typedefs.putAssumeCapacityNoClobber( |
| ... | ... | @@ -1743,24 +1763,29 @@ pub const DeclGen = struct { |
| 1743 | 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 | 1772 | var buffer = std.ArrayList(u8).init(dg.typedefs.allocator); |
| 1748 | 1773 | defer buffer.deinit(); |
| 1749 | 1774 | const bw = buffer.writer(); |
| 1750 | 1775 | |
| 1751 | | try bw.writeAll("typedef struct {\n "); |
| 1752 | | 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); |
| 1753 | 1783 | try bw.writeAll(";\n "); |
| 1754 | 1784 | try dg.renderTypeAndName(bw, Type.bool, .{ .identifier = "is_null" }, .Mut, 0, .Complete); |
| 1755 | | try bw.writeAll(";\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"); |
| 1785 | try bw.writeAll(";\n};\n"); |
| 1760 | 1786 | |
| 1761 | 1787 | const rendered = try buffer.toOwnedSlice(); |
| 1762 | 1788 | errdefer dg.typedefs.allocator.free(rendered); |
| 1763 | | const name = rendered[name_begin..name_end]; |
| 1764 | 1789 | |
| 1765 | 1790 | try dg.typedefs.ensureUnusedCapacity(1); |
| 1766 | 1791 | dg.typedefs.putAssumeCapacityNoClobber( |
| ... | ... | @@ -1899,18 +1924,34 @@ pub const DeclGen = struct { |
| 1899 | 1924 | }, |
| 1900 | 1925 | .Optional => { |
| 1901 | 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 | 1930 | return dg.renderType(w, Type.bool, kind); |
| 1906 | 1931 | |
| 1907 | 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 |
| 1911 | | try dg.renderOptionalTypedef(t, child_type); |
| 1935 | switch (kind) { |
| 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 | 1956 | .ErrorUnion => { |
| 1916 | 1957 | const payload_ty = t.errorUnionPayload(); |
| ... | ... | @@ -1923,10 +1964,26 @@ pub const DeclGen = struct { |
| 1923 | 1964 | }; |
| 1924 | 1965 | const error_union_ty = Type.initPayload(&error_union_pl.base); |
| 1925 | 1966 | |
| 1926 | | const name = dg.getTypedefName(error_union_ty) orelse |
| 1927 | | 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); |
| 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 | 1988 | .Struct, .Union => |tag| if (t.containerLayout() == .Packed) { |
| 1932 | 1989 | if (t.castTag(.@"struct")) |struct_obj| { |
| ... | ... | @@ -1964,28 +2021,31 @@ pub const DeclGen = struct { |
| 1964 | 2021 | const tuple_ty = Type.initPayload(&tuple_pl.base); |
| 1965 | 2022 | |
| 1966 | 2023 | const name = dg.getTypedefName(tuple_ty) orelse |
| 1967 | | try dg.renderTupleTypedef(tuple_ty); |
| 2024 | try dg.renderTupleTypedef(tuple_ty, kind); |
| 1968 | 2025 | |
| 1969 | 2026 | try w.writeAll(name); |
| 1970 | | } else if (kind == .Complete) { |
| 1971 | | const name = dg.getTypedefName(t) orelse switch (tag) { |
| 1972 | | .Struct => try dg.renderStructTypedef(t), |
| 1973 | | .Union => try dg.renderUnionTypedef(t), |
| 1974 | | else => unreachable, |
| 1975 | | }; |
| 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 | }; |
| 1976 | 2034 | |
| 1977 | | try w.writeAll(name); |
| 1978 | | } else { |
| 1979 | | var ptr_pl = Type.Payload.ElemType{ |
| 1980 | | .base = .{ .tag = .single_const_pointer }, |
| 1981 | | .data = t, |
| 1982 | | }; |
| 1983 | | 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); |
| 1984 | 2043 | |
| 1985 | | const name = dg.getTypedefName(ptr_ty) orelse |
| 1986 | | try dg.renderFwdTypedef(ptr_ty); |
| 2044 | const name = dg.getTypedefName(ptr_ty) orelse |
| 2045 | try dg.renderFwdTypedef(ptr_ty); |
| 1987 | 2046 | |
| 1988 | | try w.writeAll(name); |
| 2047 | try w.writeAll(name); |
| 2048 | }, |
| 1989 | 2049 | }, |
| 1990 | 2050 | .Enum => { |
| 1991 | 2051 | // For enums, we simply use the integer tag type. |
| ... | ... | @@ -2213,10 +2273,10 @@ pub const DeclGen = struct { |
| 2213 | 2273 | .constant => unreachable, |
| 2214 | 2274 | .arg => |i| return w.print("a{d}", .{i}), |
| 2215 | 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 | 2277 | .decl_ref => |decl| { |
| 2218 | 2278 | try w.writeByte('&'); |
| 2219 | | return dg.renderDeclName(w, decl); |
| 2279 | return dg.renderDeclName(w, decl, 0); |
| 2220 | 2280 | }, |
| 2221 | 2281 | .undef => |ty| return dg.renderValue(w, ty, Value.undef, .Other), |
| 2222 | 2282 | .identifier => |ident| return w.print("{ }", .{fmtIdent(ident)}), |
| ... | ... | @@ -2234,10 +2294,10 @@ pub const DeclGen = struct { |
| 2234 | 2294 | .field => |i| return w.print("f{d}", .{i}), |
| 2235 | 2295 | .decl => |decl| { |
| 2236 | 2296 | try w.writeAll("(*"); |
| 2237 | | try dg.renderDeclName(w, decl); |
| 2297 | try dg.renderDeclName(w, decl, 0); |
| 2238 | 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 | 2301 | .undef => unreachable, |
| 2242 | 2302 | .identifier => |ident| return w.print("(*{ })", .{fmtIdent(ident)}), |
| 2243 | 2303 | .bytes => |bytes| { |
| ... | ... | @@ -2269,12 +2329,12 @@ pub const DeclGen = struct { |
| 2269 | 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 | 2333 | const decl = dg.module.declPtr(decl_index); |
| 2274 | 2334 | dg.module.markDeclAlive(decl); |
| 2275 | 2335 | |
| 2276 | 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 | 2338 | } else if (decl.isExtern()) { |
| 2279 | 2339 | return writer.writeAll(mem.sliceTo(decl.name, 0)); |
| 2280 | 2340 | } else if (dg.module.test_functions.get(decl_index)) |_| { |
| ... | ... | @@ -2422,24 +2482,44 @@ pub fn genErrDecls(o: *Object) !void { |
| 2422 | 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 | 2500 | pub fn genFunc(f: *Function) !void { |
| 2426 | 2501 | const tracy = trace(@src()); |
| 2427 | 2502 | defer tracy.end(); |
| 2428 | 2503 | |
| 2429 | 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 | 2510 | o.code_header = std.ArrayList(u8).init(f.object.dg.gpa); |
| 2432 | 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 | 2514 | const fwd_decl_writer = o.dg.fwd_decl.writer(); |
| 2436 | 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 | 2517 | try fwd_decl_writer.writeAll(";\n"); |
| 2518 | try genExports(o); |
| 2439 | 2519 | |
| 2440 | 2520 | try o.indent_writer.insertNewline(); |
| 2441 | 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 | 2523 | try o.writer().writeByte(' '); |
| 2444 | 2524 | |
| 2445 | 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 | 2554 | if (tv.val.tag() == .extern_fn) { |
| 2475 | 2555 | const fwd_decl_writer = o.dg.fwd_decl.writer(); |
| 2476 | 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 | 2558 | try fwd_decl_writer.writeAll(";\n"); |
| 2559 | try genExports(o); |
| 2479 | 2560 | } else if (tv.val.castTag(.variable)) |var_payload| { |
| 2480 | 2561 | const variable: *Module.Var = var_payload.data; |
| 2562 | |
| 2481 | 2563 | const is_global = o.dg.declIsGlobal(tv) or variable.is_extern; |
| 2482 | 2564 | const fwd_decl_writer = o.dg.fwd_decl.writer(); |
| 2483 | 2565 | |
| 2484 | | const decl_c_value: CValue = if (is_global) .{ |
| 2485 | | .bytes = mem.span(o.dg.decl.name), |
| 2486 | | } else .{ |
| 2487 | | .decl = o.dg.decl_index, |
| 2488 | | }; |
| 2566 | const decl_c_value = CValue{ .decl = o.dg.decl_index }; |
| 2489 | 2567 | |
| 2490 | 2568 | try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static "); |
| 2491 | 2569 | if (variable.is_threadlocal) try fwd_decl_writer.writeAll("zig_threadlocal "); |
| 2492 | 2570 | try o.dg.renderTypeAndName(fwd_decl_writer, o.dg.decl.ty, decl_c_value, .Mut, o.dg.decl.@"align", .Complete); |
| 2493 | 2571 | try fwd_decl_writer.writeAll(";\n"); |
| 2572 | try genExports(o); |
| 2494 | 2573 | |
| 2495 | 2574 | if (variable.is_extern) return; |
| 2496 | 2575 | |
| ... | ... | @@ -2536,7 +2615,7 @@ pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void { |
| 2536 | 2615 | const is_global = dg.declIsGlobal(tv); |
| 2537 | 2616 | if (is_global) { |
| 2538 | 2617 | try writer.writeAll("zig_extern "); |
| 2539 | | try dg.renderFunctionSignature(writer, .Complete); |
| 2618 | try dg.renderFunctionSignature(writer, .Complete, 0); |
| 2540 | 2619 | try dg.fwd_decl.appendSlice(";\n"); |
| 2541 | 2620 | } |
| 2542 | 2621 | }, |
| ... | ... | @@ -3676,7 +3755,7 @@ fn airCall( |
| 3676 | 3755 | }; |
| 3677 | 3756 | }; |
| 3678 | 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 | 3759 | break :callee; |
| 3681 | 3760 | } |
| 3682 | 3761 | // Fall back to function pointer call. |
| ... | ... | @@ -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 | 4279 | var stack = std.heap.stackFallback(256, f.object.dg.gpa); |
| 4201 | 4280 | const allocator = stack.get(); |
| ... | ... | @@ -4204,29 +4283,43 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4204 | 4283 | |
| 4205 | 4284 | var src_i: usize = 0; |
| 4206 | 4285 | var dst_i: usize = 0; |
| 4207 | | while (src_i < asm_source.len) : (src_i += 1) { |
| 4208 | | fixed_asm_source[dst_i] = asm_source[src_i]; |
| 4209 | | dst_i += 1; |
| 4210 | | if (asm_source[src_i] != '%' or src_i + 1 >= asm_source.len) continue; |
| 4286 | while (true) { |
| 4287 | const literal = mem.sliceTo(asm_source[src_i..], '%'); |
| 4288 | src_i += literal.len; |
| 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 | 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 | 4302 | if (asm_source[src_i] != '[') { |
| 4213 | | // This handles %% |
| 4303 | // This also handles %% |
| 4214 | 4304 | fixed_asm_source[dst_i] = asm_source[src_i]; |
| 4305 | src_i += 1; |
| 4215 | 4306 | dst_i += 1; |
| 4216 | 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]; |
| 4226 | | std.mem.copy(u8, fixed_asm_source[dst_i..], name); |
| 4310 | const desc = mem.sliceTo(asm_source[src_i..], ']'); |
| 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 | 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 | 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 | 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 | 4643 | .Packed => if (field_ptr_info.data.host_size == 0) { |
| 4542 | 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 | 4664 | try f.writeCValue(writer, struct_ptr, .Other); |
| 4563 | 4665 | try writer.print(")[{}];\n", .{try f.fmtIntLiteral(Type.usize, byte_offset_val)}); |
| 4564 | 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 | 4669 | .@"union", .union_safety_tagged, .union_tagged => if (struct_ty.containerLayout() == .Packed) { |
| 4568 | 4670 | try f.writeCValue(writer, struct_ptr, .Other); |
| 4569 | 4671 | try writer.writeAll(";\n"); |
| 4570 | 4672 | return local; |
| 4571 | | } else .{ |
| 4673 | } else if (field_ty.hasRuntimeBitsIgnoreComptime()) FieldLoc{ .field = .{ |
| 4572 | 4674 | .identifier = struct_ty.unionFields().keys()[index], |
| 4573 | | }, |
| 4675 | } } else @as(FieldLoc, .end), |
| 4574 | 4676 | .tuple, .anon_struct => field_name: { |
| 4575 | 4677 | const tuple = struct_ty.tupleFields(); |
| 4576 | 4678 | if (tuple.values[index].tag() != .unreachable_value) return CValue.none; |
| 4577 | 4679 | |
| 4578 | 4680 | var id: usize = 0; |
| 4579 | | for (tuple.values[0..index]) |value| |
| 4580 | | id += @boolToInt(value.tag() == .unreachable_value); |
| 4581 | | break :field_name .{ .field = id }; |
| 4681 | break :field_name for (tuple.values) |value, i| { |
| 4682 | if (value.tag() != .unreachable_value) continue; |
| 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 | 4688 | else => unreachable, |
| 4584 | 4689 | }; |
| 4585 | 4690 | |
| 4586 | | if (field_ty.hasRuntimeBitsIgnoreComptime()) { |
| 4587 | | try writer.writeByte('&'); |
| 4588 | | if (extra_name != .none) { |
| 4691 | try writer.writeByte('&'); |
| 4692 | switch (field_loc) { |
| 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 | 4699 | try f.writeCValueDerefMember(writer, struct_ptr, extra_name); |
| 4590 | | if (field_name != .none) { |
| 4591 | | try writer.writeByte('.'); |
| 4592 | | try f.writeCValue(writer, field_name, .Other); |
| 4593 | | } |
| 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); |
| 4700 | try writer.writeByte('.'); |
| 4701 | try f.writeCValue(writer, field, .Other); |
| 4702 | } else try f.writeCValueDerefMember(writer, struct_ptr, field), |
| 4703 | } |
| 4599 | 4704 | try writer.writeAll(";\n"); |
| 4600 | 4705 | return local; |
| 4601 | 4706 | } |