authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-06-30 00:11:51-04:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2024-07-04 21:01:42+01:00
log00da182e6875845d5727c399b3738a13b262832e
tree3a50d94d5f514ebb83f8c36754927ae360608512
parent0e5335aaf5e0ac646fbd46a319710019d10c2971
signature Commit is signed but in an unrecognized format.

cbe: fix for export changes


6 files changed, 286 insertions(+), 276 deletions(-)

lib/zig.h+4-4
...@@ -207,16 +207,16 @@ typedef char bool;...@@ -207,16 +207,16 @@ typedef char bool;
207 __asm(zig_mangle_c(name) " = " zig_mangle_c(symbol))207 __asm(zig_mangle_c(name) " = " zig_mangle_c(symbol))
208#endif208#endif
209209
210#define zig_mangled_tentative zig_mangled
211#define zig_mangled_final zig_mangled
210#if _MSC_VER212#if _MSC_VER
211#define zig_mangled_tentative(mangled, unmangled)213#define zig_mangled(mangled, unmangled) ; \
212#define zig_mangled_final(mangled, unmangled) ; \
213 zig_export(#mangled, unmangled)214 zig_export(#mangled, unmangled)
214#define zig_mangled_export(mangled, unmangled, symbol) \215#define zig_mangled_export(mangled, unmangled, symbol) \
215 zig_export(unmangled, #mangled) \216 zig_export(unmangled, #mangled) \
216 zig_export(symbol, unmangled)217 zig_export(symbol, unmangled)
217#else /* _MSC_VER */218#else /* _MSC_VER */
218#define zig_mangled_tentative(mangled, unmangled) __asm(zig_mangle_c(unmangled))219#define zig_mangled(mangled, unmangled) __asm(zig_mangle_c(unmangled))
219#define zig_mangled_final(mangled, unmangled) zig_mangled_tentative(mangled, unmangled)
220#define zig_mangled_export(mangled, unmangled, symbol) \220#define zig_mangled_export(mangled, unmangled, symbol) \
221 zig_mangled_final(mangled, unmangled) \221 zig_mangled_final(mangled, unmangled) \
222 zig_export(symbol, unmangled)222 zig_export(symbol, unmangled)
src/Compilation.zig+3
...@@ -3466,6 +3466,9 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: std.Progress.Node) !vo...@@ -3466,6 +3466,9 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: std.Progress.Node) !vo
3466 };3466 };
3467 },3467 },
3468 .emit_h_decl => |decl_index| {3468 .emit_h_decl => |decl_index| {
3469 if (true) @panic("regressed compiler feature: emit-h should hook into updateExports, " ++
3470 "not decl analysis, which is too early to know about @export calls");
3471
3469 const module = comp.module.?;3472 const module = comp.module.?;
3470 const decl = module.declPtr(decl_index);3473 const decl = module.declPtr(decl_index);
34713474
src/Zcu.zig+14
...@@ -268,6 +268,20 @@ pub const Exported = union(enum) {...@@ -268,6 +268,20 @@ pub const Exported = union(enum) {
268 decl_index: Decl.Index,268 decl_index: Decl.Index,
269 /// Constant value being exported.269 /// Constant value being exported.
270 value: InternPool.Index,270 value: InternPool.Index,
271
272 pub fn getValue(exported: Exported, zcu: *Zcu) Value {
273 return switch (exported) {
274 .decl_index => |decl_index| zcu.declPtr(decl_index).val,
275 .value => |value| Value.fromInterned(value),
276 };
277 }
278
279 pub fn getAlign(exported: Exported, zcu: *Zcu) Alignment {
280 return switch (exported) {
281 .decl_index => |decl_index| zcu.declPtr(decl_index).alignment,
282 .value => .none,
283 };
284 }
271};285};
272286
273pub const Export = struct {287pub const Export = struct {
src/codegen/c.zig+146-232
...@@ -731,8 +731,6 @@ pub const DeclGen = struct {...@@ -731,8 +731,6 @@ pub const DeclGen = struct {
731 if (decl.val.getExternFunc(zcu)) |extern_func| if (extern_func.decl != decl_index)731 if (decl.val.getExternFunc(zcu)) |extern_func| if (extern_func.decl != decl_index)
732 return dg.renderDeclValue(writer, extern_func.decl, location);732 return dg.renderDeclValue(writer, extern_func.decl, location);
733733
734 if (decl.val.getVariable(zcu)) |variable| try dg.renderFwdDecl(decl_index, variable, .tentative);
735
736 // We shouldn't cast C function pointers as this is UB (when you call734 // We shouldn't cast C function pointers as this is UB (when you call
737 // them). The analysis until now should ensure that the C function735 // them). The analysis until now should ensure that the C function
738 // pointers are compatible. If they are not, then there is a bug736 // pointers are compatible. If they are not, then there is a bug
...@@ -748,7 +746,7 @@ pub const DeclGen = struct {...@@ -748,7 +746,7 @@ pub const DeclGen = struct {
748 try writer.writeByte(')');746 try writer.writeByte(')');
749 }747 }
750 try writer.writeByte('&');748 try writer.writeByte('&');
751 try dg.renderDeclName(writer, decl_index, 0);749 try dg.renderDeclName(writer, decl_index);
752 if (need_cast) try writer.writeByte(')');750 if (need_cast) try writer.writeByte(')');
753 }751 }
754752
...@@ -1765,19 +1763,22 @@ pub const DeclGen = struct {...@@ -1765,19 +1763,22 @@ pub const DeclGen = struct {
1765 fn renderFunctionSignature(1763 fn renderFunctionSignature(
1766 dg: *DeclGen,1764 dg: *DeclGen,
1767 w: anytype,1765 w: anytype,
1768 fn_decl_index: InternPool.DeclIndex,1766 fn_val: Value,
1767 fn_align: InternPool.Alignment,
1769 kind: CType.Kind,1768 kind: CType.Kind,
1770 name: union(enum) {1769 name: union(enum) {
1771 export_index: u32,1770 decl: InternPool.DeclIndex,
1772 ident: []const u8,
1773 fmt_ctype_pool_string: std.fmt.Formatter(formatCTypePoolString),1771 fmt_ctype_pool_string: std.fmt.Formatter(formatCTypePoolString),
1772 @"export": struct {
1773 main_name: InternPool.NullTerminatedString,
1774 extern_name: InternPool.NullTerminatedString,
1775 },
1774 },1776 },
1775 ) !void {1777 ) !void {
1776 const zcu = dg.zcu;1778 const zcu = dg.zcu;
1777 const ip = &zcu.intern_pool;1779 const ip = &zcu.intern_pool;
17781780
1779 const fn_decl = zcu.declPtr(fn_decl_index);1781 const fn_ty = fn_val.typeOf(zcu);
1780 const fn_ty = fn_decl.typeOf(zcu);
1781 const fn_ctype = try dg.ctypeFromType(fn_ty, kind);1782 const fn_ctype = try dg.ctypeFromType(fn_ty, kind);
17821783
1783 const fn_info = zcu.typeToFunc(fn_ty).?;1784 const fn_info = zcu.typeToFunc(fn_ty).?;
...@@ -1788,7 +1789,7 @@ pub const DeclGen = struct {...@@ -1788,7 +1789,7 @@ pub const DeclGen = struct {
1788 else => unreachable,1789 else => unreachable,
1789 }1790 }
1790 }1791 }
1791 if (fn_decl.val.getFunction(zcu)) |func| if (func.analysis(ip).is_cold)1792 if (fn_val.getFunction(zcu)) |func| if (func.analysis(ip).is_cold)
1792 try w.writeAll("zig_cold ");1793 try w.writeAll("zig_cold ");
1793 if (fn_info.return_type == .noreturn_type) try w.writeAll("zig_noreturn ");1794 if (fn_info.return_type == .noreturn_type) try w.writeAll("zig_noreturn ");
17941795
...@@ -1799,22 +1800,11 @@ pub const DeclGen = struct {...@@ -1799,22 +1800,11 @@ pub const DeclGen = struct {
1799 trailing = .maybe_space;1800 trailing = .maybe_space;
1800 }1801 }
18011802
1802 switch (kind) {1803 try w.print("{}", .{trailing});
1803 .forward => {},
1804 .complete => if (fn_decl.alignment.toByteUnits()) |a| {
1805 try w.print("{}zig_align_fn({})", .{ trailing, a });
1806 trailing = .maybe_space;
1807 },
1808 else => unreachable,
1809 }
1810
1811 switch (name) {1804 switch (name) {
1812 .export_index => |export_index| {1805 .decl => |decl_index| try dg.renderDeclName(w, decl_index),
1813 try w.print("{}", .{trailing});1806 .fmt_ctype_pool_string => |fmt| try w.print("{ }", .{fmt}),
1814 try dg.renderDeclName(w, fn_decl_index, export_index);1807 .@"export" => |@"export"| try w.print("{ }", .{fmtIdent(@"export".extern_name.toSlice(ip))}),
1815 },
1816 .ident => |ident| try w.print("{}{ }", .{ trailing, fmtIdent(ident) }),
1817 .fmt_ctype_pool_string => |fmt| try w.print("{}{ }", .{ trailing, fmt }),
1818 }1808 }
18191809
1820 try renderTypeSuffix(1810 try renderTypeSuffix(
...@@ -1833,44 +1823,30 @@ pub const DeclGen = struct {...@@ -1833,44 +1823,30 @@ pub const DeclGen = struct {
18331823
1834 switch (kind) {1824 switch (kind) {
1835 .forward => {1825 .forward => {
1836 if (fn_decl.alignment.toByteUnits()) |a| {1826 if (fn_align.toByteUnits()) |a| try w.print(" zig_align_fn({})", .{a});
1837 try w.print(" zig_align_fn({})", .{a});
1838 }
1839 switch (name) {1827 switch (name) {
1840 .export_index => |export_index| mangled: {1828 .decl, .fmt_ctype_pool_string => {},
1841 const maybe_exports = zcu.decl_exports.get(fn_decl_index);1829 .@"export" => |@"export"| {
1842 const external_name = (if (maybe_exports) |exports|1830 const extern_name = @"export".extern_name.toSlice(ip);
1843 exports.items[export_index].opts.name1831 const is_mangled = isMangledIdent(extern_name, true);
1844 else if (fn_decl.isExtern(zcu))1832 const is_export = @"export".extern_name != @"export".main_name;
1845 fn_decl.name
1846 else
1847 break :mangled).toSlice(ip);
1848 const is_mangled = isMangledIdent(external_name, true);
1849 const is_export = export_index > 0;
1850 if (is_mangled and is_export) {1833 if (is_mangled and is_export) {
1851 try w.print(" zig_mangled_export({ }, {s}, {s})", .{1834 try w.print(" zig_mangled_export({ }, {s}, {s})", .{
1852 fmtIdent(external_name),1835 fmtIdent(extern_name),
1853 fmtStringLiteral(external_name, null),1836 fmtStringLiteral(extern_name, null),
1854 fmtStringLiteral(1837 fmtStringLiteral(@"export".main_name.toSlice(ip), null),
1855 maybe_exports.?.items[0].opts.name.toSlice(ip),
1856 null,
1857 ),
1858 });1838 });
1859 } else if (is_mangled) {1839 } else if (is_mangled) {
1860 try w.print(" zig_mangled_final({ }, {s})", .{1840 try w.print(" zig_mangled({ }, {s})", .{
1861 fmtIdent(external_name), fmtStringLiteral(external_name, null),1841 fmtIdent(extern_name), fmtStringLiteral(extern_name, null),
1862 });1842 });
1863 } else if (is_export) {1843 } else if (is_export) {
1864 try w.print(" zig_export({s}, {s})", .{1844 try w.print(" zig_export({s}, {s})", .{
1865 fmtStringLiteral(1845 fmtStringLiteral(@"export".main_name.toSlice(ip), null),
1866 maybe_exports.?.items[0].opts.name.toSlice(ip),1846 fmtStringLiteral(extern_name, null),
1867 null,
1868 ),
1869 fmtStringLiteral(external_name, null),
1870 });1847 });
1871 }1848 }
1872 },1849 },
1873 .ident, .fmt_ctype_pool_string => {},
1874 }1850 }
1875 },1851 },
1876 .complete => {},1852 .complete => {},
...@@ -2085,21 +2061,11 @@ pub const DeclGen = struct {...@@ -2085,21 +2061,11 @@ pub const DeclGen = struct {
2085 try renderTypeSuffix(dg.pass, &dg.ctype_pool, dg.zcu, w, ctype, .suffix, .{});2061 try renderTypeSuffix(dg.pass, &dg.ctype_pool, dg.zcu, w, ctype, .suffix, .{});
2086 }2062 }
20872063
2088 fn declIsGlobal(dg: *DeclGen, val: Value) bool {
2089 const zcu = dg.zcu;
2090 return switch (zcu.intern_pool.indexToKey(val.toIntern())) {
2091 .variable => |variable| zcu.decl_exports.contains(variable.decl),
2092 .extern_func => true,
2093 .func => |func| zcu.decl_exports.contains(func.owner_decl),
2094 else => unreachable,
2095 };
2096 }
2097
2098 fn writeName(dg: *DeclGen, w: anytype, c_value: CValue) !void {2064 fn writeName(dg: *DeclGen, w: anytype, c_value: CValue) !void {
2099 switch (c_value) {2065 switch (c_value) {
2100 .new_local, .local => |i| try w.print("t{d}", .{i}),2066 .new_local, .local => |i| try w.print("t{d}", .{i}),
2101 .constant => |val| try renderAnonDeclName(w, val),2067 .constant => |val| try renderAnonDeclName(w, val),
2102 .decl => |decl| try dg.renderDeclName(w, decl, 0),2068 .decl => |decl| try dg.renderDeclName(w, decl),
2103 .identifier => |ident| try w.print("{ }", .{fmtIdent(ident)}),2069 .identifier => |ident| try w.print("{ }", .{fmtIdent(ident)}),
2104 else => unreachable,2070 else => unreachable,
2105 }2071 }
...@@ -2111,10 +2077,10 @@ pub const DeclGen = struct {...@@ -2111,10 +2077,10 @@ pub const DeclGen = struct {
2111 .constant => |val| try renderAnonDeclName(w, val),2077 .constant => |val| try renderAnonDeclName(w, val),
2112 .arg, .arg_array => unreachable,2078 .arg, .arg_array => unreachable,
2113 .field => |i| try w.print("f{d}", .{i}),2079 .field => |i| try w.print("f{d}", .{i}),
2114 .decl => |decl| try dg.renderDeclName(w, decl, 0),2080 .decl => |decl| try dg.renderDeclName(w, decl),
2115 .decl_ref => |decl| {2081 .decl_ref => |decl| {
2116 try w.writeByte('&');2082 try w.writeByte('&');
2117 try dg.renderDeclName(w, decl, 0);2083 try dg.renderDeclName(w, decl);
2118 },2084 },
2119 .undef => |ty| try dg.renderUndefValue(w, ty, .Other),2085 .undef => |ty| try dg.renderUndefValue(w, ty, .Other),
2120 .identifier => |ident| try w.print("{ }", .{fmtIdent(ident)}),2086 .identifier => |ident| try w.print("{ }", .{fmtIdent(ident)}),
...@@ -2142,10 +2108,10 @@ pub const DeclGen = struct {...@@ -2142,10 +2108,10 @@ pub const DeclGen = struct {
2142 .field => |i| try w.print("f{d}", .{i}),2108 .field => |i| try w.print("f{d}", .{i}),
2143 .decl => |decl| {2109 .decl => |decl| {
2144 try w.writeAll("(*");2110 try w.writeAll("(*");
2145 try dg.renderDeclName(w, decl, 0);2111 try dg.renderDeclName(w, decl);
2146 try w.writeByte(')');2112 try w.writeByte(')');
2147 },2113 },
2148 .decl_ref => |decl| try dg.renderDeclName(w, decl, 0),2114 .decl_ref => |decl| try dg.renderDeclName(w, decl),
2149 .undef => unreachable,2115 .undef => unreachable,
2150 .identifier => |ident| try w.print("(*{ })", .{fmtIdent(ident)}),2116 .identifier => |ident| try w.print("(*{ })", .{fmtIdent(ident)}),
2151 .payload_identifier => |ident| try w.print("(*{ }.{ })", .{2117 .payload_identifier => |ident| try w.print("(*{ }.{ })", .{
...@@ -2195,19 +2161,12 @@ pub const DeclGen = struct {...@@ -2195,19 +2161,12 @@ pub const DeclGen = struct {
2195 dg: *DeclGen,2161 dg: *DeclGen,
2196 decl_index: InternPool.DeclIndex,2162 decl_index: InternPool.DeclIndex,
2197 variable: InternPool.Key.Variable,2163 variable: InternPool.Key.Variable,
2198 fwd_kind: enum { tentative, final },
2199 ) !void {2164 ) !void {
2200 const zcu = dg.zcu;2165 const zcu = dg.zcu;
2201 const decl = zcu.declPtr(decl_index);2166 const decl = zcu.declPtr(decl_index);
2202 const fwd = dg.fwdDeclWriter();2167 const fwd = dg.fwdDeclWriter();
2203 const is_global = variable.is_extern or dg.declIsGlobal(decl.val);2168 try fwd.writeAll(if (variable.is_extern) "zig_extern " else "static ");
2204 try fwd.writeAll(if (is_global) "zig_extern " else "static ");2169 if (variable.is_weak_linkage) try fwd.writeAll("zig_weak_linkage ");
2205 const maybe_exports = zcu.decl_exports.get(decl_index);
2206 const export_weak_linkage = if (maybe_exports) |exports|
2207 exports.items[0].opts.linkage == .weak
2208 else
2209 false;
2210 if (variable.is_weak_linkage or export_weak_linkage) try fwd.writeAll("zig_weak_linkage ");
2211 if (variable.is_threadlocal and !dg.mod.single_threaded) try fwd.writeAll("zig_threadlocal ");2170 if (variable.is_threadlocal and !dg.mod.single_threaded) try fwd.writeAll("zig_threadlocal ");
2212 try dg.renderTypeAndName(2171 try dg.renderTypeAndName(
2213 fwd,2172 fwd,
...@@ -2217,38 +2176,17 @@ pub const DeclGen = struct {...@@ -2217,38 +2176,17 @@ pub const DeclGen = struct {
2217 decl.alignment,2176 decl.alignment,
2218 .complete,2177 .complete,
2219 );2178 );
2220 mangled: {
2221 const external_name = (if (maybe_exports) |exports|
2222 exports.items[0].opts.name
2223 else if (variable.is_extern)
2224 decl.name
2225 else
2226 break :mangled).toSlice(&zcu.intern_pool);
2227 if (isMangledIdent(external_name, true)) {
2228 try fwd.print(" zig_mangled_{s}({ }, {s})", .{
2229 @tagName(fwd_kind),
2230 fmtIdent(external_name),
2231 fmtStringLiteral(external_name, null),
2232 });
2233 }
2234 }
2235 try fwd.writeAll(";\n");2179 try fwd.writeAll(";\n");
2236 }2180 }
22372181
2238 fn renderDeclName(dg: *DeclGen, writer: anytype, decl_index: InternPool.DeclIndex, export_index: u32) !void {2182 fn renderDeclName(dg: *DeclGen, writer: anytype, decl_index: InternPool.DeclIndex) !void {
2239 const zcu = dg.zcu;2183 const zcu = dg.zcu;
2240 const ip = &zcu.intern_pool;2184 const ip = &zcu.intern_pool;
2241 const decl = zcu.declPtr(decl_index);2185 const decl = zcu.declPtr(decl_index);
22422186
2243 if (zcu.decl_exports.get(decl_index)) |exports| {2187 if (decl.getExternDecl(zcu).unwrap()) |extern_decl_index| try writer.print("{ }", .{
2244 try writer.print("{ }", .{2188 fmtIdent(zcu.declPtr(extern_decl_index).name.toSlice(ip)),
2245 fmtIdent(exports.items[export_index].opts.name.toSlice(ip)),2189 }) else {
2246 });
2247 } else if (decl.getExternDecl(zcu).unwrap()) |extern_decl_index| {
2248 try writer.print("{ }", .{
2249 fmtIdent(zcu.declPtr(extern_decl_index).name.toSlice(ip)),
2250 });
2251 } else {
2252 // MSVC has a limit of 4095 character token length limit, and fmtIdent can (worst case),2190 // MSVC has a limit of 4095 character token length limit, and fmtIdent can (worst case),
2253 // expand to 3x the length of its input, but let's cut it off at a much shorter limit.2191 // expand to 3x the length of its input, but let's cut it off at a much shorter limit.
2254 var name: [100]u8 = undefined;2192 var name: [100]u8 = undefined;
...@@ -2761,69 +2699,6 @@ pub fn genErrDecls(o: *Object) !void {...@@ -2761,69 +2699,6 @@ pub fn genErrDecls(o: *Object) !void {
2761 try writer.writeAll("};\n");2699 try writer.writeAll("};\n");
2762}2700}
27632701
2764fn genExports(o: *Object) !void {
2765 const tracy = trace(@src());
2766 defer tracy.end();
2767
2768 const zcu = o.dg.zcu;
2769 const ip = &zcu.intern_pool;
2770 const decl_index = switch (o.dg.pass) {
2771 .decl => |decl| decl,
2772 .anon, .flush => return,
2773 };
2774 const decl = zcu.declPtr(decl_index);
2775 const fwd = o.dg.fwdDeclWriter();
2776
2777 const exports = zcu.decl_exports.get(decl_index) orelse return;
2778 if (exports.items.len < 2) return;
2779
2780 const is_variable_const = switch (ip.indexToKey(decl.val.toIntern())) {
2781 .func => return for (exports.items[1..], 1..) |@"export", i| {
2782 try fwd.writeAll("zig_extern ");
2783 if (@"export".opts.linkage == .weak) try fwd.writeAll("zig_weak_linkage_fn ");
2784 try o.dg.renderFunctionSignature(
2785 fwd,
2786 decl_index,
2787 .forward,
2788 .{ .export_index = @intCast(i) },
2789 );
2790 try fwd.writeAll(";\n");
2791 },
2792 .extern_func => {
2793 // TODO: when sema allows re-exporting extern decls
2794 unreachable;
2795 },
2796 .variable => |variable| variable.is_const,
2797 else => true,
2798 };
2799 for (exports.items[1..]) |@"export"| {
2800 try fwd.writeAll("zig_extern ");
2801 if (@"export".opts.linkage == .weak) try fwd.writeAll("zig_weak_linkage ");
2802 const export_name = @"export".opts.name.toSlice(ip);
2803 try o.dg.renderTypeAndName(
2804 fwd,
2805 decl.typeOf(zcu),
2806 .{ .identifier = export_name },
2807 CQualifiers.init(.{ .@"const" = is_variable_const }),
2808 decl.alignment,
2809 .complete,
2810 );
2811 if (isMangledIdent(export_name, true)) {
2812 try fwd.print(" zig_mangled_export({ }, {s}, {s})", .{
2813 fmtIdent(export_name),
2814 fmtStringLiteral(export_name, null),
2815 fmtStringLiteral(exports.items[0].opts.name.toSlice(ip), null),
2816 });
2817 } else {
2818 try fwd.print(" zig_export({s}, {s})", .{
2819 fmtStringLiteral(exports.items[0].opts.name.toSlice(ip), null),
2820 fmtStringLiteral(export_name, null),
2821 });
2822 }
2823 try fwd.writeAll(";\n");
2824 }
2825}
2826
2827pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFnMap.Entry) !void {2702pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFnMap.Entry) !void {
2828 const zcu = o.dg.zcu;2703 const zcu = o.dg.zcu;
2829 const ip = &zcu.intern_pool;2704 const ip = &zcu.intern_pool;
...@@ -2885,19 +2760,19 @@ pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFn...@@ -2885,19 +2760,19 @@ pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFn
2885 const fn_info = fn_ctype.info(ctype_pool).function;2760 const fn_info = fn_ctype.info(ctype_pool).function;
2886 const fn_name = fmtCTypePoolString(val.fn_name, lazy_ctype_pool);2761 const fn_name = fmtCTypePoolString(val.fn_name, lazy_ctype_pool);
28872762
2888 const fwd_decl_writer = o.dg.fwdDeclWriter();2763 const fwd = o.dg.fwdDeclWriter();
2889 try fwd_decl_writer.print("static zig_{s} ", .{@tagName(key)});2764 try fwd.print("static zig_{s} ", .{@tagName(key)});
2890 try o.dg.renderFunctionSignature(fwd_decl_writer, fn_decl_index, .forward, .{2765 try o.dg.renderFunctionSignature(fwd, fn_decl.val, fn_decl.alignment, .forward, .{
2891 .fmt_ctype_pool_string = fn_name,2766 .fmt_ctype_pool_string = fn_name,
2892 });2767 });
2893 try fwd_decl_writer.writeAll(";\n");2768 try fwd.writeAll(";\n");
28942769
2895 try w.print("static zig_{s} ", .{@tagName(key)});2770 try w.print("zig_{s} ", .{@tagName(key)});
2896 try o.dg.renderFunctionSignature(w, fn_decl_index, .complete, .{2771 try o.dg.renderFunctionSignature(w, fn_decl.val, .none, .complete, .{
2897 .fmt_ctype_pool_string = fn_name,2772 .fmt_ctype_pool_string = fn_name,
2898 });2773 });
2899 try w.writeAll(" {\n return ");2774 try w.writeAll(" {\n return ");
2900 try o.dg.renderDeclName(w, fn_decl_index, 0);2775 try o.dg.renderDeclName(w, fn_decl_index);
2901 try w.writeByte('(');2776 try w.writeByte('(');
2902 for (0..fn_info.param_ctypes.len) |arg| {2777 for (0..fn_info.param_ctypes.len) |arg| {
2903 if (arg > 0) try w.writeAll(", ");2778 if (arg > 0) try w.writeAll(", ");
...@@ -2921,21 +2796,26 @@ pub fn genFunc(f: *Function) !void {...@@ -2921,21 +2796,26 @@ pub fn genFunc(f: *Function) !void {
2921 o.code_header = std.ArrayList(u8).init(gpa);2796 o.code_header = std.ArrayList(u8).init(gpa);
2922 defer o.code_header.deinit();2797 defer o.code_header.deinit();
29232798
2924 const is_global = o.dg.declIsGlobal(decl.val);2799 const fwd = o.dg.fwdDeclWriter();
2925 const fwd_decl_writer = o.dg.fwdDeclWriter();2800 try fwd.writeAll("static ");
2926 try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static ");2801 try o.dg.renderFunctionSignature(
29272802 fwd,
2928 if (zcu.decl_exports.get(decl_index)) |exports|2803 decl.val,
2929 if (exports.items[0].opts.linkage == .weak) try fwd_decl_writer.writeAll("zig_weak_linkage_fn ");2804 decl.alignment,
2930 try o.dg.renderFunctionSignature(fwd_decl_writer, decl_index, .forward, .{ .export_index = 0 });2805 .forward,
2931 try fwd_decl_writer.writeAll(";\n");2806 .{ .decl = decl_index },
2932 try genExports(o);2807 );
2808 try fwd.writeAll(";\n");
29332809
2934 try o.indent_writer.insertNewline();
2935 if (!is_global) try o.writer().writeAll("static ");
2936 if (decl.@"linksection".toSlice(&zcu.intern_pool)) |s|2810 if (decl.@"linksection".toSlice(&zcu.intern_pool)) |s|
2937 try o.writer().print("zig_linksection_fn({s}) ", .{fmtStringLiteral(s, null)});2811 try o.writer().print("zig_linksection_fn({s}) ", .{fmtStringLiteral(s, null)});
2938 try o.dg.renderFunctionSignature(o.writer(), decl_index, .complete, .{ .export_index = 0 });2812 try o.dg.renderFunctionSignature(
2813 o.writer(),
2814 decl.val,
2815 .none,
2816 .complete,
2817 .{ .decl = decl_index },
2818 );
2939 try o.writer().writeByte(' ');2819 try o.writer().writeByte(' ');
29402820
2941 // In case we need to use the header, populate it with a copy of the function2821 // In case we need to use the header, populate it with a copy of the function
...@@ -2949,7 +2829,6 @@ pub fn genFunc(f: *Function) !void {...@@ -2949,7 +2829,6 @@ pub fn genFunc(f: *Function) !void {
29492829
2950 const main_body = f.air.getMainBody();2830 const main_body = f.air.getMainBody();
2951 try genBodyResolveState(f, undefined, &.{}, main_body, false);2831 try genBodyResolveState(f, undefined, &.{}, main_body, false);
2952
2953 try o.indent_writer.insertNewline();2832 try o.indent_writer.insertNewline();
29542833
2955 // Take advantage of the free_locals map to bucket locals per type. All2834 // Take advantage of the free_locals map to bucket locals per type. All
...@@ -3007,20 +2886,25 @@ pub fn genDecl(o: *Object) !void {...@@ -3007,20 +2886,25 @@ pub fn genDecl(o: *Object) !void {
30072886
3008 if (!decl_ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) return;2887 if (!decl_ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) return;
3009 if (decl.val.getExternFunc(zcu)) |_| {2888 if (decl.val.getExternFunc(zcu)) |_| {
3010 const fwd_decl_writer = o.dg.fwdDeclWriter();2889 const fwd = o.dg.fwdDeclWriter();
3011 try fwd_decl_writer.writeAll("zig_extern ");2890 try fwd.writeAll("zig_extern ");
3012 try o.dg.renderFunctionSignature(fwd_decl_writer, decl_index, .forward, .{ .export_index = 0 });2891 try o.dg.renderFunctionSignature(
3013 try fwd_decl_writer.writeAll(";\n");2892 fwd,
3014 try genExports(o);2893 decl.val,
2894 decl.alignment,
2895 .forward,
2896 .{ .@"export" = .{
2897 .main_name = decl.name,
2898 .extern_name = decl.name,
2899 } },
2900 );
2901 try fwd.writeAll(";\n");
3015 } else if (decl.val.getVariable(zcu)) |variable| {2902 } else if (decl.val.getVariable(zcu)) |variable| {
3016 try o.dg.renderFwdDecl(decl_index, variable, .final);2903 try o.dg.renderFwdDecl(decl_index, variable);
3017 try genExports(o);
30182904
3019 if (variable.is_extern) return;2905 if (variable.is_extern) return;
30202906
3021 const is_global = variable.is_extern or o.dg.declIsGlobal(decl.val);
3022 const w = o.writer();2907 const w = o.writer();
3023 if (!is_global) try w.writeAll("static ");
3024 if (variable.is_weak_linkage) try w.writeAll("zig_weak_linkage ");2908 if (variable.is_weak_linkage) try w.writeAll("zig_weak_linkage ");
3025 if (variable.is_threadlocal and !o.dg.mod.single_threaded) try w.writeAll("zig_threadlocal ");2909 if (variable.is_threadlocal and !o.dg.mod.single_threaded) try w.writeAll("zig_threadlocal ");
3026 if (decl.@"linksection".toSlice(&zcu.intern_pool)) |s|2910 if (decl.@"linksection".toSlice(&zcu.intern_pool)) |s|
...@@ -3032,46 +2916,27 @@ pub fn genDecl(o: *Object) !void {...@@ -3032,46 +2916,27 @@ pub fn genDecl(o: *Object) !void {
3032 try w.writeByte(';');2916 try w.writeByte(';');
3033 try o.indent_writer.insertNewline();2917 try o.indent_writer.insertNewline();
3034 } else {2918 } else {
3035 const is_global = o.dg.zcu.decl_exports.contains(decl_index);
3036 const decl_c_value = .{ .decl = decl_index };2919 const decl_c_value = .{ .decl = decl_index };
3037 try genDeclValue(o, decl.val, is_global, decl_c_value, decl.alignment, decl.@"linksection");2920 try genDeclValue(o, decl.val, decl_c_value, decl.alignment, decl.@"linksection");
3038 }2921 }
3039}2922}
30402923
3041pub fn genDeclValue(2924pub fn genDeclValue(
3042 o: *Object,2925 o: *Object,
3043 val: Value,2926 val: Value,
3044 is_global: bool,
3045 decl_c_value: CValue,2927 decl_c_value: CValue,
3046 alignment: Alignment,2928 alignment: Alignment,
3047 @"linksection": InternPool.OptionalNullTerminatedString,2929 @"linksection": InternPool.OptionalNullTerminatedString,
3048) !void {2930) !void {
3049 const zcu = o.dg.zcu;2931 const zcu = o.dg.zcu;
3050 const fwd_decl_writer = o.dg.fwdDeclWriter();
3051
3052 const ty = val.typeOf(zcu);2932 const ty = val.typeOf(zcu);
30532933
3054 try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static ");2934 const fwd = o.dg.fwdDeclWriter();
3055 try o.dg.renderTypeAndName(fwd_decl_writer, ty, decl_c_value, Const, alignment, .complete);2935 try fwd.writeAll("static ");
3056 switch (o.dg.pass) {2936 try o.dg.renderTypeAndName(fwd, ty, decl_c_value, Const, alignment, .complete);
3057 .decl => |decl_index| {2937 try fwd.writeAll(";\n");
3058 if (zcu.decl_exports.get(decl_index)) |exports| {
3059 const export_name = exports.items[0].opts.name.toSlice(&zcu.intern_pool);
3060 if (isMangledIdent(export_name, true)) {
3061 try fwd_decl_writer.print(" zig_mangled_final({ }, {s})", .{
3062 fmtIdent(export_name), fmtStringLiteral(export_name, null),
3063 });
3064 }
3065 }
3066 },
3067 .anon => {},
3068 .flush => unreachable,
3069 }
3070 try fwd_decl_writer.writeAll(";\n");
3071 try genExports(o);
30722938
3073 const w = o.writer();2939 const w = o.writer();
3074 if (!is_global) try w.writeAll("static ");
3075 if (@"linksection".toSlice(&zcu.intern_pool)) |s|2940 if (@"linksection".toSlice(&zcu.intern_pool)) |s|
3076 try w.print("zig_linksection({s}) ", .{fmtStringLiteral(s, null)});2941 try w.print("zig_linksection({s}) ", .{fmtStringLiteral(s, null)});
3077 try o.dg.renderTypeAndName(w, ty, decl_c_value, Const, alignment, .complete);2942 try o.dg.renderTypeAndName(w, ty, decl_c_value, Const, alignment, .complete);
...@@ -3080,24 +2945,73 @@ pub fn genDeclValue(...@@ -3080,24 +2945,73 @@ pub fn genDeclValue(
3080 try w.writeAll(";\n");2945 try w.writeAll(";\n");
3081}2946}
30822947
3083pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void {2948pub fn genExports(dg: *DeclGen, exported: Zcu.Exported, export_indices: []const u32) !void {
3084 if (true) @panic("TODO jacobly");
3085
3086 const tracy = trace(@src());
3087 defer tracy.end();
3088
3089 const zcu = dg.zcu;2949 const zcu = dg.zcu;
3090 const decl_index = dg.pass.decl;2950 const ip = &zcu.intern_pool;
3091 const decl = zcu.declPtr(decl_index);2951 const fwd = dg.fwdDeclWriter();
3092 const writer = dg.fwdDeclWriter();
30932952
3094 switch (decl.typeOf(zcu).zigTypeTag(zcu)) {2953 const main_name = zcu.all_exports.items[export_indices[0]].opts.name;
3095 .Fn => if (dg.declIsGlobal(decl.val)) {2954 try fwd.writeAll("#define ");
3096 try writer.writeAll("zig_extern ");2955 switch (exported) {
3097 try dg.renderFunctionSignature(writer, dg.pass.decl, .complete, .{ .export_index = 0 });2956 .decl_index => |decl_index| try dg.renderDeclName(fwd, decl_index),
3098 try dg.fwd_decl.appendSlice(";\n");2957 .value => |value| try DeclGen.renderAnonDeclName(fwd, Value.fromInterned(value)),
2958 }
2959 try fwd.writeByte(' ');
2960 try fwd.print("{ }", .{fmtIdent(main_name.toSlice(ip))});
2961 try fwd.writeByte('\n');
2962
2963 const is_const = switch (ip.indexToKey(exported.getValue(zcu).toIntern())) {
2964 .func, .extern_func => return for (export_indices) |export_index| {
2965 const @"export" = &zcu.all_exports.items[export_index];
2966 try fwd.writeAll("zig_extern ");
2967 if (@"export".opts.linkage == .weak) try fwd.writeAll("zig_weak_linkage_fn ");
2968 try dg.renderFunctionSignature(
2969 fwd,
2970 exported.getValue(zcu),
2971 exported.getAlign(zcu),
2972 .forward,
2973 .{ .@"export" = .{
2974 .main_name = main_name,
2975 .extern_name = @"export".opts.name,
2976 } },
2977 );
2978 try fwd.writeAll(";\n");
3099 },2979 },
3100 else => {},2980 .variable => |variable| variable.is_const,
2981 else => true,
2982 };
2983 for (export_indices) |export_index| {
2984 const @"export" = &zcu.all_exports.items[export_index];
2985 try fwd.writeAll("zig_extern ");
2986 if (@"export".opts.linkage == .weak) try fwd.writeAll("zig_weak_linkage ");
2987 const extern_name = @"export".opts.name.toSlice(ip);
2988 const is_mangled = isMangledIdent(extern_name, true);
2989 const is_export = @"export".opts.name != main_name;
2990 try dg.renderTypeAndName(
2991 fwd,
2992 exported.getValue(zcu).typeOf(zcu),
2993 .{ .identifier = extern_name },
2994 CQualifiers.init(.{ .@"const" = is_const }),
2995 exported.getAlign(zcu),
2996 .complete,
2997 );
2998 if (is_mangled and is_export) {
2999 try fwd.print(" zig_mangled_export({ }, {s}, {s})", .{
3000 fmtIdent(extern_name),
3001 fmtStringLiteral(extern_name, null),
3002 fmtStringLiteral(main_name.toSlice(ip), null),
3003 });
3004 } else if (is_mangled) {
3005 try fwd.print(" zig_mangled({ }, {s})", .{
3006 fmtIdent(extern_name), fmtStringLiteral(extern_name, null),
3007 });
3008 } else if (is_export) {
3009 try fwd.print(" zig_export({s}, {s})", .{
3010 fmtStringLiteral(main_name.toSlice(ip), null),
3011 fmtStringLiteral(extern_name, null),
3012 });
3013 }
3014 try fwd.writeAll(";\n");
3101 }3015 }
3102}3016}
31033017
...@@ -4554,7 +4468,7 @@ fn airCall(...@@ -4554,7 +4468,7 @@ fn airCall(
4554 };4468 };
4555 };4469 };
4556 switch (modifier) {4470 switch (modifier) {
4557 .auto, .always_tail => try f.object.dg.renderDeclName(writer, fn_decl, 0),4471 .auto, .always_tail => try f.object.dg.renderDeclName(writer, fn_decl),
4558 inline .never_tail, .never_inline => |m| try writer.writeAll(try f.getLazyFnName(4472 inline .never_tail, .never_inline => |m| try writer.writeAll(try f.getLazyFnName(
4559 @unionInit(LazyFnKey, @tagName(m), fn_decl),4473 @unionInit(LazyFnKey, @tagName(m), fn_decl),
4560 @unionInit(LazyFnValue.Data, @tagName(m), {}),4474 @unionInit(LazyFnValue.Data, @tagName(m), {}),
src/link.zig-1
...@@ -679,7 +679,6 @@ pub const File = struct {...@@ -679,7 +679,6 @@ pub const File = struct {
679 if (build_options.only_c) @compileError("unreachable");679 if (build_options.only_c) @compileError("unreachable");
680 switch (base.tag) {680 switch (base.tag) {
681 .plan9,681 .plan9,
682 .c,
683 .spirv,682 .spirv,
684 .nvptx,683 .nvptx,
685 => {},684 => {},
src/link/C.zig+119-39
...@@ -39,6 +39,9 @@ anon_decls: std.AutoArrayHashMapUnmanaged(InternPool.Index, DeclBlock) = .{},...@@ -39,6 +39,9 @@ anon_decls: std.AutoArrayHashMapUnmanaged(InternPool.Index, DeclBlock) = .{},
39/// the keys of `anon_decls`.39/// the keys of `anon_decls`.
40aligned_anon_decls: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment) = .{},40aligned_anon_decls: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment) = .{},
4141
42exported_decls: std.AutoArrayHashMapUnmanaged(InternPool.DeclIndex, ExportedBlock) = .{},
43exported_values: std.AutoArrayHashMapUnmanaged(InternPool.Index, ExportedBlock) = .{},
44
42/// Optimization, `updateDecl` reuses this buffer rather than creating a new45/// Optimization, `updateDecl` reuses this buffer rather than creating a new
43/// one with every call.46/// one with every call.
44fwd_decl_buf: std.ArrayListUnmanaged(u8) = .{},47fwd_decl_buf: std.ArrayListUnmanaged(u8) = .{},
...@@ -80,6 +83,11 @@ pub const DeclBlock = struct {...@@ -80,6 +83,11 @@ pub const DeclBlock = struct {
80 }83 }
81};84};
8285
86/// Per-exported-symbol data.
87pub const ExportedBlock = struct {
88 fwd_decl: String = String.empty,
89};
90
83pub fn getString(this: C, s: String) []const u8 {91pub fn getString(this: C, s: String) []const u8 {
84 return this.string_bytes.items[s.start..][0..s.len];92 return this.string_bytes.items[s.start..][0..s.len];
85}93}
...@@ -183,8 +191,6 @@ pub fn updateFunc(...@@ -183,8 +191,6 @@ pub fn updateFunc(
183 air: Air,191 air: Air,
184 liveness: Liveness,192 liveness: Liveness,
185) !void {193) !void {
186 if (true) @panic("TODO jacobly");
187
188 const gpa = self.base.comp.gpa;194 const gpa = self.base.comp.gpa;
189195
190 const func = zcu.funcInfo(func_index);196 const func = zcu.funcInfo(func_index);
...@@ -240,9 +246,13 @@ pub fn updateFunc(...@@ -240,9 +246,13 @@ pub fn updateFunc(
240 function.deinit();246 function.deinit();
241 }247 }
242248
249 try zcu.failed_analysis.ensureUnusedCapacity(gpa, 1);
243 codegen.genFunc(&function) catch |err| switch (err) {250 codegen.genFunc(&function) catch |err| switch (err) {
244 error.AnalysisFail => {251 error.AnalysisFail => {
245 try zcu.failed_decls.put(gpa, decl_index, function.object.dg.error_msg.?);252 zcu.failed_analysis.putAssumeCapacityNoClobber(
253 InternPool.AnalUnit.wrap(.{ .decl = decl_index }),
254 function.object.dg.error_msg.?,
255 );
246 return;256 return;
247 },257 },
248 else => |e| return e,258 else => |e| return e,
...@@ -252,8 +262,6 @@ pub fn updateFunc(...@@ -252,8 +262,6 @@ pub fn updateFunc(
252}262}
253263
254fn updateAnonDecl(self: *C, zcu: *Zcu, i: usize) !void {264fn updateAnonDecl(self: *C, zcu: *Zcu, i: usize) !void {
255 if (true) @panic("TODO jacobly");
256
257 const gpa = self.base.comp.gpa;265 const gpa = self.base.comp.gpa;
258 const anon_decl = self.anon_decls.keys()[i];266 const anon_decl = self.anon_decls.keys()[i];
259267
...@@ -292,7 +300,7 @@ fn updateAnonDecl(self: *C, zcu: *Zcu, i: usize) !void {...@@ -292,7 +300,7 @@ fn updateAnonDecl(self: *C, zcu: *Zcu, i: usize) !void {
292300
293 const c_value: codegen.CValue = .{ .constant = Value.fromInterned(anon_decl) };301 const c_value: codegen.CValue = .{ .constant = Value.fromInterned(anon_decl) };
294 const alignment: Alignment = self.aligned_anon_decls.get(anon_decl) orelse .none;302 const alignment: Alignment = self.aligned_anon_decls.get(anon_decl) orelse .none;
295 codegen.genDeclValue(&object, c_value.constant, false, c_value, alignment, .none) catch |err| switch (err) {303 codegen.genDeclValue(&object, c_value.constant, c_value, alignment, .none) catch |err| switch (err) {
296 error.AnalysisFail => {304 error.AnalysisFail => {
297 @panic("TODO: C backend AnalysisFail on anonymous decl");305 @panic("TODO: C backend AnalysisFail on anonymous decl");
298 //try zcu.failed_decls.put(gpa, decl_index, object.dg.error_msg.?);306 //try zcu.failed_decls.put(gpa, decl_index, object.dg.error_msg.?);
...@@ -310,8 +318,6 @@ fn updateAnonDecl(self: *C, zcu: *Zcu, i: usize) !void {...@@ -310,8 +318,6 @@ fn updateAnonDecl(self: *C, zcu: *Zcu, i: usize) !void {
310}318}
311319
312pub fn updateDecl(self: *C, zcu: *Zcu, decl_index: InternPool.DeclIndex) !void {320pub fn updateDecl(self: *C, zcu: *Zcu, decl_index: InternPool.DeclIndex) !void {
313 if (true) @panic("TODO jacobly");
314
315 const tracy = trace(@src());321 const tracy = trace(@src());
316 defer tracy.end();322 defer tracy.end();
317323
...@@ -357,9 +363,13 @@ pub fn updateDecl(self: *C, zcu: *Zcu, decl_index: InternPool.DeclIndex) !void {...@@ -357,9 +363,13 @@ pub fn updateDecl(self: *C, zcu: *Zcu, decl_index: InternPool.DeclIndex) !void {
357 code.* = object.code.moveToUnmanaged();363 code.* = object.code.moveToUnmanaged();
358 }364 }
359365
366 try zcu.failed_analysis.ensureUnusedCapacity(gpa, 1);
360 codegen.genDecl(&object) catch |err| switch (err) {367 codegen.genDecl(&object) catch |err| switch (err) {
361 error.AnalysisFail => {368 error.AnalysisFail => {
362 try zcu.failed_decls.put(gpa, decl_index, object.dg.error_msg.?);369 zcu.failed_analysis.putAssumeCapacityNoClobber(
370 InternPool.AnalUnit.wrap(.{ .decl = decl_index }),
371 object.dg.error_msg.?,
372 );
363 return;373 return;
364 },374 },
365 else => |e| return e,375 else => |e| return e,
...@@ -396,8 +406,6 @@ fn abiDefines(self: *C, target: std.Target) !std.ArrayList(u8) {...@@ -396,8 +406,6 @@ fn abiDefines(self: *C, target: std.Target) !std.ArrayList(u8) {
396}406}
397407
398pub fn flushModule(self: *C, arena: Allocator, prog_node: std.Progress.Node) !void {408pub fn flushModule(self: *C, arena: Allocator, prog_node: std.Progress.Node) !void {
399 if (true) @panic("TODO jacobly");
400
401 _ = arena; // Has the same lifetime as the call to Compilation.update.409 _ = arena; // Has the same lifetime as the call to Compilation.update.
402410
403 const tracy = trace(@src());411 const tracy = trace(@src());
...@@ -460,26 +468,39 @@ pub fn flushModule(self: *C, arena: Allocator, prog_node: std.Progress.Node) !vo...@@ -460,26 +468,39 @@ pub fn flushModule(self: *C, arena: Allocator, prog_node: std.Progress.Node) !vo
460 var export_names: std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, void) = .{};468 var export_names: std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, void) = .{};
461 defer export_names.deinit(gpa);469 defer export_names.deinit(gpa);
462 try export_names.ensureTotalCapacity(gpa, @intCast(zcu.single_exports.count()));470 try export_names.ensureTotalCapacity(gpa, @intCast(zcu.single_exports.count()));
463 for (zcu.single_exports.values()) |export_idx| {471 for (zcu.single_exports.values()) |export_index| {
464 export_names.putAssumeCapacity(gpa, zcu.all_exports.items[export_idx].opts.name, {});472 export_names.putAssumeCapacity(zcu.all_exports.items[export_index].opts.name, {});
465 }473 }
466 for (zcu.multi_exports.values()) |info| {474 for (zcu.multi_exports.values()) |info| {
467 try export_names.ensureUnusedCapacity(info.len);475 try export_names.ensureUnusedCapacity(gpa, info.len);
468 for (zcu.all_exports.items[info.index..][0..info.len]) |export_idx| {476 for (zcu.all_exports.items[info.index..][0..info.len]) |@"export"| {
469 export_names.putAssumeCapacity(gpa, zcu.all_exports.items[export_idx].opts.name, {});477 export_names.putAssumeCapacity(@"export".opts.name, {});
470 }478 }
471 }479 }
472480
473 for (self.anon_decls.values()) |*decl_block| {481 for (self.anon_decls.keys(), self.anon_decls.values()) |value, *decl_block| try self.flushDeclBlock(
474 try self.flushDeclBlock(zcu, zcu.root_mod, &f, decl_block, export_names, .none);482 zcu,
475 }483 zcu.root_mod,
484 &f,
485 decl_block,
486 self.exported_values.getPtr(value),
487 export_names,
488 .none,
489 );
476490
477 for (self.decl_table.keys(), self.decl_table.values()) |decl_index, *decl_block| {491 for (self.decl_table.keys(), self.decl_table.values()) |decl_index, *decl_block| {
478 const decl = zcu.declPtr(decl_index);492 const decl = zcu.declPtr(decl_index);
479 assert(decl.has_tv);493 const extern_name = if (decl.isExtern(zcu)) decl.name.toOptional() else .none;
480 const extern_symbol_name = if (decl.isExtern(zcu)) decl.name.toOptional() else .none;
481 const mod = zcu.namespacePtr(decl.src_namespace).file_scope.mod;494 const mod = zcu.namespacePtr(decl.src_namespace).file_scope.mod;
482 try self.flushDeclBlock(zcu, mod, &f, decl_block, export_names, extern_symbol_name);495 try self.flushDeclBlock(
496 zcu,
497 mod,
498 &f,
499 decl_block,
500 self.exported_decls.getPtr(decl_index),
501 export_names,
502 extern_name,
503 );
483 }504 }
484 }505 }
485506
...@@ -512,12 +533,16 @@ pub fn flushModule(self: *C, arena: Allocator, prog_node: std.Progress.Node) !vo...@@ -512,12 +533,16 @@ pub fn flushModule(self: *C, arena: Allocator, prog_node: std.Progress.Node) !vo
512 f.file_size += lazy_fwd_decl_len;533 f.file_size += lazy_fwd_decl_len;
513534
514 // Now the code.535 // Now the code.
515 const anon_decl_values = self.anon_decls.values();536 try f.all_buffers.ensureUnusedCapacity(gpa, 1 + (self.anon_decls.count() + self.decl_table.count()) * 2);
516 const decl_values = self.decl_table.values();
517 try f.all_buffers.ensureUnusedCapacity(gpa, 1 + anon_decl_values.len + decl_values.len);
518 f.appendBufAssumeCapacity(self.lazy_code_buf.items);537 f.appendBufAssumeCapacity(self.lazy_code_buf.items);
519 for (anon_decl_values) |db| f.appendBufAssumeCapacity(self.getString(db.code));538 for (self.anon_decls.keys(), self.anon_decls.values()) |anon_decl, decl_block| f.appendCodeAssumeCapacity(
520 for (decl_values) |db| f.appendBufAssumeCapacity(self.getString(db.code));539 self.exported_values.contains(anon_decl),
540 self.getString(decl_block.code),
541 );
542 for (self.decl_table.keys(), self.decl_table.values()) |decl_index, decl_block| f.appendCodeAssumeCapacity(
543 self.exported_decls.contains(decl_index),
544 self.getString(decl_block.code),
545 );
521546
522 const file = self.base.file.?;547 const file = self.base.file.?;
523 try file.setEndPos(f.file_size);548 try file.setEndPos(f.file_size);
...@@ -547,6 +572,12 @@ const Flush = struct {...@@ -547,6 +572,12 @@ const Flush = struct {
547 f.file_size += buf.len;572 f.file_size += buf.len;
548 }573 }
549574
575 fn appendCodeAssumeCapacity(f: *Flush, is_extern: bool, code: []const u8) void {
576 if (code.len == 0) return;
577 f.appendBufAssumeCapacity(if (is_extern) "\nzig_extern " else "\nstatic ");
578 f.appendBufAssumeCapacity(code);
579 }
580
550 fn deinit(f: *Flush, gpa: Allocator) void {581 fn deinit(f: *Flush, gpa: Allocator) void {
551 f.all_buffers.deinit(gpa);582 f.all_buffers.deinit(gpa);
552 f.asm_buf.deinit(gpa);583 f.asm_buf.deinit(gpa);
...@@ -734,19 +765,20 @@ fn flushDeclBlock(...@@ -734,19 +765,20 @@ fn flushDeclBlock(
734 zcu: *Zcu,765 zcu: *Zcu,
735 mod: *Module,766 mod: *Module,
736 f: *Flush,767 f: *Flush,
737 decl_block: *DeclBlock,768 decl_block: *const DeclBlock,
769 exported_block: ?*const ExportedBlock,
738 export_names: std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, void),770 export_names: std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, void),
739 extern_symbol_name: InternPool.OptionalNullTerminatedString,771 extern_name: InternPool.OptionalNullTerminatedString,
740) FlushDeclError!void {772) FlushDeclError!void {
741 const gpa = self.base.comp.gpa;773 const gpa = self.base.comp.gpa;
742 try self.flushLazyFns(zcu, mod, f, &decl_block.ctype_pool, decl_block.lazy_fns);774 try self.flushLazyFns(zcu, mod, f, &decl_block.ctype_pool, decl_block.lazy_fns);
743 try f.all_buffers.ensureUnusedCapacity(gpa, 1);775 try f.all_buffers.ensureUnusedCapacity(gpa, 1);
744 fwd_decl: {776 // avoid emitting extern decls that are already exported
745 if (extern_symbol_name.unwrap()) |name| {777 if (extern_name.unwrap()) |name| if (export_names.contains(name)) return;
746 if (export_names.contains(name)) break :fwd_decl;778 f.appendBufAssumeCapacity(self.getString(if (exported_block) |exported|
747 }779 exported.fwd_decl
748 f.appendBufAssumeCapacity(self.getString(decl_block.fwd_decl));780 else
749 }781 decl_block.fwd_decl));
750}782}
751783
752pub fn flushEmitH(zcu: *Zcu) !void {784pub fn flushEmitH(zcu: *Zcu) !void {
...@@ -798,8 +830,56 @@ pub fn updateExports(...@@ -798,8 +830,56 @@ pub fn updateExports(
798 exported: Zcu.Exported,830 exported: Zcu.Exported,
799 export_indices: []const u32,831 export_indices: []const u32,
800) !void {832) !void {
801 _ = self;833 const gpa = self.base.comp.gpa;
802 _ = zcu;834 const mod, const pass: codegen.DeclGen.Pass, const decl_block, const exported_block = switch (exported) {
803 _ = exported;835 .decl_index => |decl_index| .{
804 _ = export_indices;836 zcu.namespacePtr(zcu.declPtr(decl_index).src_namespace).file_scope.mod,
837 .{ .decl = decl_index },
838 self.decl_table.getPtr(decl_index).?,
839 (try self.exported_decls.getOrPut(gpa, decl_index)).value_ptr,
840 },
841 .value => |value| .{
842 zcu.root_mod,
843 .{ .anon = value },
844 self.anon_decls.getPtr(value).?,
845 (try self.exported_values.getOrPut(gpa, value)).value_ptr,
846 },
847 };
848 const ctype_pool = &decl_block.ctype_pool;
849 const fwd_decl = &self.fwd_decl_buf;
850 fwd_decl.clearRetainingCapacity();
851 var dg: codegen.DeclGen = .{
852 .gpa = gpa,
853 .zcu = zcu,
854 .mod = mod,
855 .error_msg = null,
856 .pass = pass,
857 .is_naked_fn = false,
858 .fwd_decl = fwd_decl.toManaged(gpa),
859 .ctype_pool = decl_block.ctype_pool,
860 .scratch = .{},
861 .anon_decl_deps = .{},
862 .aligned_anon_decls = .{},
863 };
864 defer {
865 assert(dg.anon_decl_deps.count() == 0);
866 assert(dg.aligned_anon_decls.count() == 0);
867 fwd_decl.* = dg.fwd_decl.moveToUnmanaged();
868 ctype_pool.* = dg.ctype_pool.move();
869 ctype_pool.freeUnusedCapacity(gpa);
870 dg.scratch.deinit(gpa);
871 }
872 try codegen.genExports(&dg, exported, export_indices);
873 exported_block.* = .{ .fwd_decl = try self.addString(dg.fwd_decl.items) };
874}
875
876pub fn deleteExport(
877 self: *C,
878 exported: Zcu.Exported,
879 _: InternPool.NullTerminatedString,
880) void {
881 switch (exported) {
882 .decl_index => |decl_index| _ = self.exported_decls.swapRemove(decl_index),
883 .value => |value| _ = self.exported_values.swapRemove(value),
884 }
805}885}