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
signaturelock-open 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;
207207 __asm(zig_mangle_c(name) " = " zig_mangle_c(symbol))
208208#endif
209209
210#define zig_mangled_tentative zig_mangled
211#define zig_mangled_final zig_mangled
210212#if _MSC_VER
211#define zig_mangled_tentative(mangled, unmangled)
212#define zig_mangled_final(mangled, unmangled) ; \
213#define zig_mangled(mangled, unmangled) ; \
213214 zig_export(#mangled, unmangled)
214215#define zig_mangled_export(mangled, unmangled, symbol) \
215216 zig_export(unmangled, #mangled) \
216217 zig_export(symbol, unmangled)
217218#else /* _MSC_VER */
218#define zig_mangled_tentative(mangled, unmangled) __asm(zig_mangle_c(unmangled))
219#define zig_mangled_final(mangled, unmangled) zig_mangled_tentative(mangled, unmangled)
219#define zig_mangled(mangled, unmangled) __asm(zig_mangle_c(unmangled))
220220#define zig_mangled_export(mangled, unmangled, symbol) \
221221 zig_mangled_final(mangled, unmangled) \
222222 zig_export(symbol, unmangled)
src/Compilation.zig+3
......@@ -3466,6 +3466,9 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: std.Progress.Node) !vo
34663466 };
34673467 },
34683468 .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
34693472 const module = comp.module.?;
34703473 const decl = module.declPtr(decl_index);
34713474
src/Zcu.zig+14
......@@ -268,6 +268,20 @@ pub const Exported = union(enum) {
268268 decl_index: Decl.Index,
269269 /// Constant value being exported.
270270 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 }
271285};
272286
273287pub const Export = struct {
src/codegen/c.zig+146-232
......@@ -731,8 +731,6 @@ pub const DeclGen = struct {
731731 if (decl.val.getExternFunc(zcu)) |extern_func| if (extern_func.decl != decl_index)
732732 return dg.renderDeclValue(writer, extern_func.decl, location);
733733
734 if (decl.val.getVariable(zcu)) |variable| try dg.renderFwdDecl(decl_index, variable, .tentative);
735
736734 // We shouldn't cast C function pointers as this is UB (when you call
737735 // them). The analysis until now should ensure that the C function
738736 // pointers are compatible. If they are not, then there is a bug
......@@ -748,7 +746,7 @@ pub const DeclGen = struct {
748746 try writer.writeByte(')');
749747 }
750748 try writer.writeByte('&');
751 try dg.renderDeclName(writer, decl_index, 0);
749 try dg.renderDeclName(writer, decl_index);
752750 if (need_cast) try writer.writeByte(')');
753751 }
754752
......@@ -1765,19 +1763,22 @@ pub const DeclGen = struct {
17651763 fn renderFunctionSignature(
17661764 dg: *DeclGen,
17671765 w: anytype,
1768 fn_decl_index: InternPool.DeclIndex,
1766 fn_val: Value,
1767 fn_align: InternPool.Alignment,
17691768 kind: CType.Kind,
17701769 name: union(enum) {
1771 export_index: u32,
1772 ident: []const u8,
1770 decl: InternPool.DeclIndex,
17731771 fmt_ctype_pool_string: std.fmt.Formatter(formatCTypePoolString),
1772 @"export": struct {
1773 main_name: InternPool.NullTerminatedString,
1774 extern_name: InternPool.NullTerminatedString,
1775 },
17741776 },
17751777 ) !void {
17761778 const zcu = dg.zcu;
17771779 const ip = &zcu.intern_pool;
17781780
1779 const fn_decl = zcu.declPtr(fn_decl_index);
1780 const fn_ty = fn_decl.typeOf(zcu);
1781 const fn_ty = fn_val.typeOf(zcu);
17811782 const fn_ctype = try dg.ctypeFromType(fn_ty, kind);
17821783
17831784 const fn_info = zcu.typeToFunc(fn_ty).?;
......@@ -1788,7 +1789,7 @@ pub const DeclGen = struct {
17881789 else => unreachable,
17891790 }
17901791 }
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)
17921793 try w.writeAll("zig_cold ");
17931794 if (fn_info.return_type == .noreturn_type) try w.writeAll("zig_noreturn ");
17941795
......@@ -1799,22 +1800,11 @@ pub const DeclGen = struct {
17991800 trailing = .maybe_space;
18001801 }
18011802
1802 switch (kind) {
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
1803 try w.print("{}", .{trailing});
18111804 switch (name) {
1812 .export_index => |export_index| {
1813 try w.print("{}", .{trailing});
1814 try dg.renderDeclName(w, fn_decl_index, export_index);
1815 },
1816 .ident => |ident| try w.print("{}{ }", .{ trailing, fmtIdent(ident) }),
1817 .fmt_ctype_pool_string => |fmt| try w.print("{}{ }", .{ trailing, fmt }),
1805 .decl => |decl_index| try dg.renderDeclName(w, decl_index),
1806 .fmt_ctype_pool_string => |fmt| try w.print("{ }", .{fmt}),
1807 .@"export" => |@"export"| try w.print("{ }", .{fmtIdent(@"export".extern_name.toSlice(ip))}),
18181808 }
18191809
18201810 try renderTypeSuffix(
......@@ -1833,44 +1823,30 @@ pub const DeclGen = struct {
18331823
18341824 switch (kind) {
18351825 .forward => {
1836 if (fn_decl.alignment.toByteUnits()) |a| {
1837 try w.print(" zig_align_fn({})", .{a});
1838 }
1826 if (fn_align.toByteUnits()) |a| try w.print(" zig_align_fn({})", .{a});
18391827 switch (name) {
1840 .export_index => |export_index| mangled: {
1841 const maybe_exports = zcu.decl_exports.get(fn_decl_index);
1842 const external_name = (if (maybe_exports) |exports|
1843 exports.items[export_index].opts.name
1844 else if (fn_decl.isExtern(zcu))
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;
1828 .decl, .fmt_ctype_pool_string => {},
1829 .@"export" => |@"export"| {
1830 const extern_name = @"export".extern_name.toSlice(ip);
1831 const is_mangled = isMangledIdent(extern_name, true);
1832 const is_export = @"export".extern_name != @"export".main_name;
18501833 if (is_mangled and is_export) {
18511834 try w.print(" zig_mangled_export({ }, {s}, {s})", .{
1852 fmtIdent(external_name),
1853 fmtStringLiteral(external_name, null),
1854 fmtStringLiteral(
1855 maybe_exports.?.items[0].opts.name.toSlice(ip),
1856 null,
1857 ),
1835 fmtIdent(extern_name),
1836 fmtStringLiteral(extern_name, null),
1837 fmtStringLiteral(@"export".main_name.toSlice(ip), null),
18581838 });
18591839 } else if (is_mangled) {
1860 try w.print(" zig_mangled_final({ }, {s})", .{
1861 fmtIdent(external_name), fmtStringLiteral(external_name, null),
1840 try w.print(" zig_mangled({ }, {s})", .{
1841 fmtIdent(extern_name), fmtStringLiteral(extern_name, null),
18621842 });
18631843 } else if (is_export) {
18641844 try w.print(" zig_export({s}, {s})", .{
1865 fmtStringLiteral(
1866 maybe_exports.?.items[0].opts.name.toSlice(ip),
1867 null,
1868 ),
1869 fmtStringLiteral(external_name, null),
1845 fmtStringLiteral(@"export".main_name.toSlice(ip), null),
1846 fmtStringLiteral(extern_name, null),
18701847 });
18711848 }
18721849 },
1873 .ident, .fmt_ctype_pool_string => {},
18741850 }
18751851 },
18761852 .complete => {},
......@@ -2085,21 +2061,11 @@ pub const DeclGen = struct {
20852061 try renderTypeSuffix(dg.pass, &dg.ctype_pool, dg.zcu, w, ctype, .suffix, .{});
20862062 }
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
20982064 fn writeName(dg: *DeclGen, w: anytype, c_value: CValue) !void {
20992065 switch (c_value) {
21002066 .new_local, .local => |i| try w.print("t{d}", .{i}),
21012067 .constant => |val| try renderAnonDeclName(w, val),
2102 .decl => |decl| try dg.renderDeclName(w, decl, 0),
2068 .decl => |decl| try dg.renderDeclName(w, decl),
21032069 .identifier => |ident| try w.print("{ }", .{fmtIdent(ident)}),
21042070 else => unreachable,
21052071 }
......@@ -2111,10 +2077,10 @@ pub const DeclGen = struct {
21112077 .constant => |val| try renderAnonDeclName(w, val),
21122078 .arg, .arg_array => unreachable,
21132079 .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),
21152081 .decl_ref => |decl| {
21162082 try w.writeByte('&');
2117 try dg.renderDeclName(w, decl, 0);
2083 try dg.renderDeclName(w, decl);
21182084 },
21192085 .undef => |ty| try dg.renderUndefValue(w, ty, .Other),
21202086 .identifier => |ident| try w.print("{ }", .{fmtIdent(ident)}),
......@@ -2142,10 +2108,10 @@ pub const DeclGen = struct {
21422108 .field => |i| try w.print("f{d}", .{i}),
21432109 .decl => |decl| {
21442110 try w.writeAll("(*");
2145 try dg.renderDeclName(w, decl, 0);
2111 try dg.renderDeclName(w, decl);
21462112 try w.writeByte(')');
21472113 },
2148 .decl_ref => |decl| try dg.renderDeclName(w, decl, 0),
2114 .decl_ref => |decl| try dg.renderDeclName(w, decl),
21492115 .undef => unreachable,
21502116 .identifier => |ident| try w.print("(*{ })", .{fmtIdent(ident)}),
21512117 .payload_identifier => |ident| try w.print("(*{ }.{ })", .{
......@@ -2195,19 +2161,12 @@ pub const DeclGen = struct {
21952161 dg: *DeclGen,
21962162 decl_index: InternPool.DeclIndex,
21972163 variable: InternPool.Key.Variable,
2198 fwd_kind: enum { tentative, final },
21992164 ) !void {
22002165 const zcu = dg.zcu;
22012166 const decl = zcu.declPtr(decl_index);
22022167 const fwd = dg.fwdDeclWriter();
2203 const is_global = variable.is_extern or dg.declIsGlobal(decl.val);
2204 try fwd.writeAll(if (is_global) "zig_extern " else "static ");
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 ");
2168 try fwd.writeAll(if (variable.is_extern) "zig_extern " else "static ");
2169 if (variable.is_weak_linkage) try fwd.writeAll("zig_weak_linkage ");
22112170 if (variable.is_threadlocal and !dg.mod.single_threaded) try fwd.writeAll("zig_threadlocal ");
22122171 try dg.renderTypeAndName(
22132172 fwd,
......@@ -2217,38 +2176,17 @@ pub const DeclGen = struct {
22172176 decl.alignment,
22182177 .complete,
22192178 );
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 }
22352179 try fwd.writeAll(";\n");
22362180 }
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 {
22392183 const zcu = dg.zcu;
22402184 const ip = &zcu.intern_pool;
22412185 const decl = zcu.declPtr(decl_index);
22422186
2243 if (zcu.decl_exports.get(decl_index)) |exports| {
2244 try writer.print("{ }", .{
2245 fmtIdent(exports.items[export_index].opts.name.toSlice(ip)),
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 {
2187 if (decl.getExternDecl(zcu).unwrap()) |extern_decl_index| try writer.print("{ }", .{
2188 fmtIdent(zcu.declPtr(extern_decl_index).name.toSlice(ip)),
2189 }) else {
22522190 // MSVC has a limit of 4095 character token length limit, and fmtIdent can (worst case),
22532191 // expand to 3x the length of its input, but let's cut it off at a much shorter limit.
22542192 var name: [100]u8 = undefined;
......@@ -2761,69 +2699,6 @@ pub fn genErrDecls(o: *Object) !void {
27612699 try writer.writeAll("};\n");
27622700}
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
28272702pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFnMap.Entry) !void {
28282703 const zcu = o.dg.zcu;
28292704 const ip = &zcu.intern_pool;
......@@ -2885,19 +2760,19 @@ pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFn
28852760 const fn_info = fn_ctype.info(ctype_pool).function;
28862761 const fn_name = fmtCTypePoolString(val.fn_name, lazy_ctype_pool);
28872762
2888 const fwd_decl_writer = o.dg.fwdDeclWriter();
2889 try fwd_decl_writer.print("static zig_{s} ", .{@tagName(key)});
2890 try o.dg.renderFunctionSignature(fwd_decl_writer, fn_decl_index, .forward, .{
2763 const fwd = o.dg.fwdDeclWriter();
2764 try fwd.print("static zig_{s} ", .{@tagName(key)});
2765 try o.dg.renderFunctionSignature(fwd, fn_decl.val, fn_decl.alignment, .forward, .{
28912766 .fmt_ctype_pool_string = fn_name,
28922767 });
2893 try fwd_decl_writer.writeAll(";\n");
2768 try fwd.writeAll(";\n");
28942769
2895 try w.print("static zig_{s} ", .{@tagName(key)});
2896 try o.dg.renderFunctionSignature(w, fn_decl_index, .complete, .{
2770 try w.print("zig_{s} ", .{@tagName(key)});
2771 try o.dg.renderFunctionSignature(w, fn_decl.val, .none, .complete, .{
28972772 .fmt_ctype_pool_string = fn_name,
28982773 });
28992774 try w.writeAll(" {\n return ");
2900 try o.dg.renderDeclName(w, fn_decl_index, 0);
2775 try o.dg.renderDeclName(w, fn_decl_index);
29012776 try w.writeByte('(');
29022777 for (0..fn_info.param_ctypes.len) |arg| {
29032778 if (arg > 0) try w.writeAll(", ");
......@@ -2921,21 +2796,26 @@ pub fn genFunc(f: *Function) !void {
29212796 o.code_header = std.ArrayList(u8).init(gpa);
29222797 defer o.code_header.deinit();
29232798
2924 const is_global = o.dg.declIsGlobal(decl.val);
2925 const fwd_decl_writer = o.dg.fwdDeclWriter();
2926 try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static ");
2927
2928 if (zcu.decl_exports.get(decl_index)) |exports|
2929 if (exports.items[0].opts.linkage == .weak) try fwd_decl_writer.writeAll("zig_weak_linkage_fn ");
2930 try o.dg.renderFunctionSignature(fwd_decl_writer, decl_index, .forward, .{ .export_index = 0 });
2931 try fwd_decl_writer.writeAll(";\n");
2932 try genExports(o);
2799 const fwd = o.dg.fwdDeclWriter();
2800 try fwd.writeAll("static ");
2801 try o.dg.renderFunctionSignature(
2802 fwd,
2803 decl.val,
2804 decl.alignment,
2805 .forward,
2806 .{ .decl = decl_index },
2807 );
2808 try fwd.writeAll(";\n");
29332809
2934 try o.indent_writer.insertNewline();
2935 if (!is_global) try o.writer().writeAll("static ");
29362810 if (decl.@"linksection".toSlice(&zcu.intern_pool)) |s|
29372811 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 );
29392819 try o.writer().writeByte(' ');
29402820
29412821 // 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 {
29492829
29502830 const main_body = f.air.getMainBody();
29512831 try genBodyResolveState(f, undefined, &.{}, main_body, false);
2952
29532832 try o.indent_writer.insertNewline();
29542833
29552834 // Take advantage of the free_locals map to bucket locals per type. All
......@@ -3007,20 +2886,25 @@ pub fn genDecl(o: *Object) !void {
30072886
30082887 if (!decl_ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) return;
30092888 if (decl.val.getExternFunc(zcu)) |_| {
3010 const fwd_decl_writer = o.dg.fwdDeclWriter();
3011 try fwd_decl_writer.writeAll("zig_extern ");
3012 try o.dg.renderFunctionSignature(fwd_decl_writer, decl_index, .forward, .{ .export_index = 0 });
3013 try fwd_decl_writer.writeAll(";\n");
3014 try genExports(o);
2889 const fwd = o.dg.fwdDeclWriter();
2890 try fwd.writeAll("zig_extern ");
2891 try o.dg.renderFunctionSignature(
2892 fwd,
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");
30152902 } else if (decl.val.getVariable(zcu)) |variable| {
3016 try o.dg.renderFwdDecl(decl_index, variable, .final);
3017 try genExports(o);
2903 try o.dg.renderFwdDecl(decl_index, variable);
30182904
30192905 if (variable.is_extern) return;
30202906
3021 const is_global = variable.is_extern or o.dg.declIsGlobal(decl.val);
30222907 const w = o.writer();
3023 if (!is_global) try w.writeAll("static ");
30242908 if (variable.is_weak_linkage) try w.writeAll("zig_weak_linkage ");
30252909 if (variable.is_threadlocal and !o.dg.mod.single_threaded) try w.writeAll("zig_threadlocal ");
30262910 if (decl.@"linksection".toSlice(&zcu.intern_pool)) |s|
......@@ -3032,46 +2916,27 @@ pub fn genDecl(o: *Object) !void {
30322916 try w.writeByte(';');
30332917 try o.indent_writer.insertNewline();
30342918 } else {
3035 const is_global = o.dg.zcu.decl_exports.contains(decl_index);
30362919 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");
30382921 }
30392922}
30402923
30412924pub fn genDeclValue(
30422925 o: *Object,
30432926 val: Value,
3044 is_global: bool,
30452927 decl_c_value: CValue,
30462928 alignment: Alignment,
30472929 @"linksection": InternPool.OptionalNullTerminatedString,
30482930) !void {
30492931 const zcu = o.dg.zcu;
3050 const fwd_decl_writer = o.dg.fwdDeclWriter();
3051
30522932 const ty = val.typeOf(zcu);
30532933
3054 try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static ");
3055 try o.dg.renderTypeAndName(fwd_decl_writer, ty, decl_c_value, Const, alignment, .complete);
3056 switch (o.dg.pass) {
3057 .decl => |decl_index| {
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);
2934 const fwd = o.dg.fwdDeclWriter();
2935 try fwd.writeAll("static ");
2936 try o.dg.renderTypeAndName(fwd, ty, decl_c_value, Const, alignment, .complete);
2937 try fwd.writeAll(";\n");
30722938
30732939 const w = o.writer();
3074 if (!is_global) try w.writeAll("static ");
30752940 if (@"linksection".toSlice(&zcu.intern_pool)) |s|
30762941 try w.print("zig_linksection({s}) ", .{fmtStringLiteral(s, null)});
30772942 try o.dg.renderTypeAndName(w, ty, decl_c_value, Const, alignment, .complete);
......@@ -3080,24 +2945,73 @@ pub fn genDeclValue(
30802945 try w.writeAll(";\n");
30812946}
30822947
3083pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void {
3084 if (true) @panic("TODO jacobly");
3085
3086 const tracy = trace(@src());
3087 defer tracy.end();
3088
2948pub fn genExports(dg: *DeclGen, exported: Zcu.Exported, export_indices: []const u32) !void {
30892949 const zcu = dg.zcu;
3090 const decl_index = dg.pass.decl;
3091 const decl = zcu.declPtr(decl_index);
3092 const writer = dg.fwdDeclWriter();
2950 const ip = &zcu.intern_pool;
2951 const fwd = dg.fwdDeclWriter();
30932952
3094 switch (decl.typeOf(zcu).zigTypeTag(zcu)) {
3095 .Fn => if (dg.declIsGlobal(decl.val)) {
3096 try writer.writeAll("zig_extern ");
3097 try dg.renderFunctionSignature(writer, dg.pass.decl, .complete, .{ .export_index = 0 });
3098 try dg.fwd_decl.appendSlice(";\n");
2953 const main_name = zcu.all_exports.items[export_indices[0]].opts.name;
2954 try fwd.writeAll("#define ");
2955 switch (exported) {
2956 .decl_index => |decl_index| try dg.renderDeclName(fwd, decl_index),
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");
30992979 },
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");
31013015 }
31023016}
31033017
......@@ -4554,7 +4468,7 @@ fn airCall(
45544468 };
45554469 };
45564470 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),
45584472 inline .never_tail, .never_inline => |m| try writer.writeAll(try f.getLazyFnName(
45594473 @unionInit(LazyFnKey, @tagName(m), fn_decl),
45604474 @unionInit(LazyFnValue.Data, @tagName(m), {}),
src/link.zig-1
......@@ -679,7 +679,6 @@ pub const File = struct {
679679 if (build_options.only_c) @compileError("unreachable");
680680 switch (base.tag) {
681681 .plan9,
682 .c,
683682 .spirv,
684683 .nvptx,
685684 => {},
src/link/C.zig+119-39
......@@ -39,6 +39,9 @@ anon_decls: std.AutoArrayHashMapUnmanaged(InternPool.Index, DeclBlock) = .{},
3939/// the keys of `anon_decls`.
4040aligned_anon_decls: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment) = .{},
4141
42exported_decls: std.AutoArrayHashMapUnmanaged(InternPool.DeclIndex, ExportedBlock) = .{},
43exported_values: std.AutoArrayHashMapUnmanaged(InternPool.Index, ExportedBlock) = .{},
44
4245/// Optimization, `updateDecl` reuses this buffer rather than creating a new
4346/// one with every call.
4447fwd_decl_buf: std.ArrayListUnmanaged(u8) = .{},
......@@ -80,6 +83,11 @@ pub const DeclBlock = struct {
8083 }
8184};
8285
86/// Per-exported-symbol data.
87pub const ExportedBlock = struct {
88 fwd_decl: String = String.empty,
89};
90
8391pub fn getString(this: C, s: String) []const u8 {
8492 return this.string_bytes.items[s.start..][0..s.len];
8593}
......@@ -183,8 +191,6 @@ pub fn updateFunc(
183191 air: Air,
184192 liveness: Liveness,
185193) !void {
186 if (true) @panic("TODO jacobly");
187
188194 const gpa = self.base.comp.gpa;
189195
190196 const func = zcu.funcInfo(func_index);
......@@ -240,9 +246,13 @@ pub fn updateFunc(
240246 function.deinit();
241247 }
242248
249 try zcu.failed_analysis.ensureUnusedCapacity(gpa, 1);
243250 codegen.genFunc(&function) catch |err| switch (err) {
244251 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 );
246256 return;
247257 },
248258 else => |e| return e,
......@@ -252,8 +262,6 @@ pub fn updateFunc(
252262}
253263
254264fn updateAnonDecl(self: *C, zcu: *Zcu, i: usize) !void {
255 if (true) @panic("TODO jacobly");
256
257265 const gpa = self.base.comp.gpa;
258266 const anon_decl = self.anon_decls.keys()[i];
259267
......@@ -292,7 +300,7 @@ fn updateAnonDecl(self: *C, zcu: *Zcu, i: usize) !void {
292300
293301 const c_value: codegen.CValue = .{ .constant = Value.fromInterned(anon_decl) };
294302 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) {
296304 error.AnalysisFail => {
297305 @panic("TODO: C backend AnalysisFail on anonymous decl");
298306 //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 {
310318}
311319
312320pub fn updateDecl(self: *C, zcu: *Zcu, decl_index: InternPool.DeclIndex) !void {
313 if (true) @panic("TODO jacobly");
314
315321 const tracy = trace(@src());
316322 defer tracy.end();
317323
......@@ -357,9 +363,13 @@ pub fn updateDecl(self: *C, zcu: *Zcu, decl_index: InternPool.DeclIndex) !void {
357363 code.* = object.code.moveToUnmanaged();
358364 }
359365
366 try zcu.failed_analysis.ensureUnusedCapacity(gpa, 1);
360367 codegen.genDecl(&object) catch |err| switch (err) {
361368 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 );
363373 return;
364374 },
365375 else => |e| return e,
......@@ -396,8 +406,6 @@ fn abiDefines(self: *C, target: std.Target) !std.ArrayList(u8) {
396406}
397407
398408pub fn flushModule(self: *C, arena: Allocator, prog_node: std.Progress.Node) !void {
399 if (true) @panic("TODO jacobly");
400
401409 _ = arena; // Has the same lifetime as the call to Compilation.update.
402410
403411 const tracy = trace(@src());
......@@ -460,26 +468,39 @@ pub fn flushModule(self: *C, arena: Allocator, prog_node: std.Progress.Node) !vo
460468 var export_names: std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, void) = .{};
461469 defer export_names.deinit(gpa);
462470 try export_names.ensureTotalCapacity(gpa, @intCast(zcu.single_exports.count()));
463 for (zcu.single_exports.values()) |export_idx| {
464 export_names.putAssumeCapacity(gpa, zcu.all_exports.items[export_idx].opts.name, {});
471 for (zcu.single_exports.values()) |export_index| {
472 export_names.putAssumeCapacity(zcu.all_exports.items[export_index].opts.name, {});
465473 }
466474 for (zcu.multi_exports.values()) |info| {
467 try export_names.ensureUnusedCapacity(info.len);
468 for (zcu.all_exports.items[info.index..][0..info.len]) |export_idx| {
469 export_names.putAssumeCapacity(gpa, zcu.all_exports.items[export_idx].opts.name, {});
475 try export_names.ensureUnusedCapacity(gpa, info.len);
476 for (zcu.all_exports.items[info.index..][0..info.len]) |@"export"| {
477 export_names.putAssumeCapacity(@"export".opts.name, {});
470478 }
471479 }
472480
473 for (self.anon_decls.values()) |*decl_block| {
474 try self.flushDeclBlock(zcu, zcu.root_mod, &f, decl_block, export_names, .none);
475 }
481 for (self.anon_decls.keys(), self.anon_decls.values()) |value, *decl_block| try self.flushDeclBlock(
482 zcu,
483 zcu.root_mod,
484 &f,
485 decl_block,
486 self.exported_values.getPtr(value),
487 export_names,
488 .none,
489 );
476490
477491 for (self.decl_table.keys(), self.decl_table.values()) |decl_index, *decl_block| {
478492 const decl = zcu.declPtr(decl_index);
479 assert(decl.has_tv);
480 const extern_symbol_name = if (decl.isExtern(zcu)) decl.name.toOptional() else .none;
493 const extern_name = if (decl.isExtern(zcu)) decl.name.toOptional() else .none;
481494 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 );
483504 }
484505 }
485506
......@@ -512,12 +533,16 @@ pub fn flushModule(self: *C, arena: Allocator, prog_node: std.Progress.Node) !vo
512533 f.file_size += lazy_fwd_decl_len;
513534
514535 // Now the code.
515 const anon_decl_values = self.anon_decls.values();
516 const decl_values = self.decl_table.values();
517 try f.all_buffers.ensureUnusedCapacity(gpa, 1 + anon_decl_values.len + decl_values.len);
536 try f.all_buffers.ensureUnusedCapacity(gpa, 1 + (self.anon_decls.count() + self.decl_table.count()) * 2);
518537 f.appendBufAssumeCapacity(self.lazy_code_buf.items);
519 for (anon_decl_values) |db| f.appendBufAssumeCapacity(self.getString(db.code));
520 for (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(
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
522547 const file = self.base.file.?;
523548 try file.setEndPos(f.file_size);
......@@ -547,6 +572,12 @@ const Flush = struct {
547572 f.file_size += buf.len;
548573 }
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
550581 fn deinit(f: *Flush, gpa: Allocator) void {
551582 f.all_buffers.deinit(gpa);
552583 f.asm_buf.deinit(gpa);
......@@ -734,19 +765,20 @@ fn flushDeclBlock(
734765 zcu: *Zcu,
735766 mod: *Module,
736767 f: *Flush,
737 decl_block: *DeclBlock,
768 decl_block: *const DeclBlock,
769 exported_block: ?*const ExportedBlock,
738770 export_names: std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, void),
739 extern_symbol_name: InternPool.OptionalNullTerminatedString,
771 extern_name: InternPool.OptionalNullTerminatedString,
740772) FlushDeclError!void {
741773 const gpa = self.base.comp.gpa;
742774 try self.flushLazyFns(zcu, mod, f, &decl_block.ctype_pool, decl_block.lazy_fns);
743775 try f.all_buffers.ensureUnusedCapacity(gpa, 1);
744 fwd_decl: {
745 if (extern_symbol_name.unwrap()) |name| {
746 if (export_names.contains(name)) break :fwd_decl;
747 }
748 f.appendBufAssumeCapacity(self.getString(decl_block.fwd_decl));
749 }
776 // avoid emitting extern decls that are already exported
777 if (extern_name.unwrap()) |name| if (export_names.contains(name)) return;
778 f.appendBufAssumeCapacity(self.getString(if (exported_block) |exported|
779 exported.fwd_decl
780 else
781 decl_block.fwd_decl));
750782}
751783
752784pub fn flushEmitH(zcu: *Zcu) !void {
......@@ -798,8 +830,56 @@ pub fn updateExports(
798830 exported: Zcu.Exported,
799831 export_indices: []const u32,
800832) !void {
801 _ = self;
802 _ = zcu;
803 _ = exported;
804 _ = export_indices;
833 const gpa = self.base.comp.gpa;
834 const mod, const pass: codegen.DeclGen.Pass, const decl_block, const exported_block = switch (exported) {
835 .decl_index => |decl_index| .{
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 }
805885}