authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2022-12-03 05:26:43-05:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2022-12-03 08:21:03-05:00
log7fb6eb3d14c232d397a4737f9dbd24dbae3db60f
tree3f95b1f1998409107b085c334da45381d21a46d0
parent81c271cc6298bf164b202a194ef18b56665ce2d9

cbe: implement multiple exports of a symbols


3 files changed, 40 insertions(+), 17 deletions(-)

lib/zig.h+6
...@@ -81,6 +81,12 @@ typedef char bool;...@@ -81,6 +81,12 @@ typedef char bool;
81#define zig_extern extern81#define zig_extern extern
82#endif82#endif
8383
84#if zig_has_attribute(alias)
85#define zig_export(sig, symbol, name) zig_extern sig __attribute__((alias(symbol)))
86#else
87#define zig_export(sig, symbol, name) __asm(name " = " symbol)
88#endif
89
84#if zig_has_builtin(debugtrap)90#if zig_has_builtin(debugtrap)
85#define zig_breakpoint() __builtin_debugtrap()91#define zig_breakpoint() __builtin_debugtrap()
86#elif zig_has_builtin(trap)92#elif zig_has_builtin(trap)
src/codegen/c.zig+34-16
...@@ -569,7 +569,7 @@ pub const DeclGen = struct {...@@ -569,7 +569,7 @@ pub const DeclGen = struct {
569 try writer.writeByte(')');569 try writer.writeByte(')');
570 }570 }
571 try writer.writeByte('&');571 try writer.writeByte('&');
572 try dg.renderDeclName(writer, decl_index);572 try dg.renderDeclName(writer, decl_index, 0);
573 if (need_typecast) try writer.writeByte(')');573 if (need_typecast) try writer.writeByte(')');
574 }574 }
575575
...@@ -1026,11 +1026,11 @@ pub const DeclGen = struct {...@@ -1026,11 +1026,11 @@ pub const DeclGen = struct {
1026 },1026 },
1027 .function => {1027 .function => {
1028 const func = val.castTag(.function).?.data;1028 const func = val.castTag(.function).?.data;
1029 try dg.renderDeclName(writer, func.owner_decl);1029 try dg.renderDeclName(writer, func.owner_decl, 0);
1030 },1030 },
1031 .extern_fn => {1031 .extern_fn => {
1032 const extern_fn = val.castTag(.extern_fn).?.data;1032 const extern_fn = val.castTag(.extern_fn).?.data;
1033 try dg.renderDeclName(writer, extern_fn.owner_decl);1033 try dg.renderDeclName(writer, extern_fn.owner_decl, 0);
1034 },1034 },
1035 .int_u64, .one => {1035 .int_u64, .one => {
1036 try writer.writeAll("((");1036 try writer.writeAll("((");
...@@ -1356,7 +1356,7 @@ pub const DeclGen = struct {...@@ -1356,7 +1356,7 @@ pub const DeclGen = struct {
1356 }1356 }
1357 }1357 }
13581358
1359 fn renderFunctionSignature(dg: *DeclGen, w: anytype, kind: TypedefKind) !void {1359 fn renderFunctionSignature(dg: *DeclGen, w: anytype, kind: TypedefKind, export_index: u32) !void {
1360 const fn_info = dg.decl.ty.fnInfo();1360 const fn_info = dg.decl.ty.fnInfo();
1361 if (fn_info.cc == .Naked) try w.writeAll("zig_naked ");1361 if (fn_info.cc == .Naked) try w.writeAll("zig_naked ");
1362 if (dg.decl.val.castTag(.function)) |func_payload|1362 if (dg.decl.val.castTag(.function)) |func_payload|
...@@ -1368,7 +1368,7 @@ pub const DeclGen = struct {...@@ -1368,7 +1368,7 @@ pub const DeclGen = struct {
13681368
1369 try dg.renderType(w, ret_ty, kind);1369 try dg.renderType(w, ret_ty, kind);
1370 try w.writeByte(' ');1370 try w.writeByte(' ');
1371 try dg.renderDeclName(w, dg.decl_index);1371 try dg.renderDeclName(w, dg.decl_index, export_index);
1372 try w.writeByte('(');1372 try w.writeByte('(');
13731373
1374 var index: usize = 0;1374 var index: usize = 0;
...@@ -2213,10 +2213,10 @@ pub const DeclGen = struct {...@@ -2213,10 +2213,10 @@ pub const DeclGen = struct {
2213 .constant => unreachable,2213 .constant => unreachable,
2214 .arg => |i| return w.print("a{d}", .{i}),2214 .arg => |i| return w.print("a{d}", .{i}),
2215 .field => |i| return w.print("f{d}", .{i}),2215 .field => |i| return w.print("f{d}", .{i}),
2216 .decl => |decl| return dg.renderDeclName(w, decl),2216 .decl => |decl| return dg.renderDeclName(w, decl, 0),
2217 .decl_ref => |decl| {2217 .decl_ref => |decl| {
2218 try w.writeByte('&');2218 try w.writeByte('&');
2219 return dg.renderDeclName(w, decl);2219 return dg.renderDeclName(w, decl, 0);
2220 },2220 },
2221 .undef => |ty| return dg.renderValue(w, ty, Value.undef, .Other),2221 .undef => |ty| return dg.renderValue(w, ty, Value.undef, .Other),
2222 .identifier => |ident| return w.print("{ }", .{fmtIdent(ident)}),2222 .identifier => |ident| return w.print("{ }", .{fmtIdent(ident)}),
...@@ -2234,10 +2234,10 @@ pub const DeclGen = struct {...@@ -2234,10 +2234,10 @@ pub const DeclGen = struct {
2234 .field => |i| return w.print("f{d}", .{i}),2234 .field => |i| return w.print("f{d}", .{i}),
2235 .decl => |decl| {2235 .decl => |decl| {
2236 try w.writeAll("(*");2236 try w.writeAll("(*");
2237 try dg.renderDeclName(w, decl);2237 try dg.renderDeclName(w, decl, 0);
2238 return w.writeByte(')');2238 return w.writeByte(')');
2239 },2239 },
2240 .decl_ref => |decl| return dg.renderDeclName(w, decl),2240 .decl_ref => |decl| return dg.renderDeclName(w, decl, 0),
2241 .undef => unreachable,2241 .undef => unreachable,
2242 .identifier => |ident| return w.print("(*{ })", .{fmtIdent(ident)}),2242 .identifier => |ident| return w.print("(*{ })", .{fmtIdent(ident)}),
2243 .bytes => |bytes| {2243 .bytes => |bytes| {
...@@ -2269,12 +2269,12 @@ pub const DeclGen = struct {...@@ -2269,12 +2269,12 @@ pub const DeclGen = struct {
2269 try dg.writeCValue(writer, member);2269 try dg.writeCValue(writer, member);
2270 }2270 }
22712271
2272 fn renderDeclName(dg: *DeclGen, writer: anytype, decl_index: Decl.Index) !void {2272 fn renderDeclName(dg: *DeclGen, writer: anytype, decl_index: Decl.Index, export_index: u32) !void {
2273 const decl = dg.module.declPtr(decl_index);2273 const decl = dg.module.declPtr(decl_index);
2274 dg.module.markDeclAlive(decl);2274 dg.module.markDeclAlive(decl);
22752275
2276 if (dg.module.decl_exports.get(decl_index)) |exports| {2276 if (dg.module.decl_exports.get(decl_index)) |exports| {
2277 return writer.writeAll(exports.items[0].options.name);2277 return writer.writeAll(exports.items[export_index].options.name);
2278 } else if (decl.isExtern()) {2278 } else if (decl.isExtern()) {
2279 return writer.writeAll(mem.sliceTo(decl.name, 0));2279 return writer.writeAll(mem.sliceTo(decl.name, 0));
2280 } else if (dg.module.test_functions.get(decl_index)) |_| {2280 } else if (dg.module.test_functions.get(decl_index)) |_| {
...@@ -2422,6 +2422,21 @@ pub fn genErrDecls(o: *Object) !void {...@@ -2422,6 +2422,21 @@ pub fn genErrDecls(o: *Object) !void {
2422 try writer.writeAll("};\n");2422 try writer.writeAll("};\n");
2423}2423}
24242424
2425fn genExports(o: *Object) !void {
2426 const tracy = trace(@src());
2427 defer tracy.end();
2428
2429 const fwd_decl_writer = o.dg.fwd_decl.writer();
2430 if (o.dg.module.decl_exports.get(o.dg.decl_index)) |exports| for (exports.items[1..]) |@"export", i| {
2431 try fwd_decl_writer.writeAll("zig_export(");
2432 try o.dg.renderFunctionSignature(fwd_decl_writer, .Forward, @intCast(u32, 1 + i));
2433 try fwd_decl_writer.print(", {s}, {s});\n", .{
2434 fmtStringLiteral(exports.items[0].options.name),
2435 fmtStringLiteral(@"export".options.name),
2436 });
2437 };
2438}
2439
2425pub fn genFunc(f: *Function) !void {2440pub fn genFunc(f: *Function) !void {
2426 const tracy = trace(@src());2441 const tracy = trace(@src());
2427 defer tracy.end();2442 defer tracy.end();
...@@ -2438,12 +2453,13 @@ pub fn genFunc(f: *Function) !void {...@@ -2438,12 +2453,13 @@ pub fn genFunc(f: *Function) !void {
2438 const is_global = o.dg.declIsGlobal(tv);2453 const is_global = o.dg.declIsGlobal(tv);
2439 const fwd_decl_writer = o.dg.fwd_decl.writer();2454 const fwd_decl_writer = o.dg.fwd_decl.writer();
2440 try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static ");2455 try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static ");
2441 try o.dg.renderFunctionSignature(fwd_decl_writer, .Forward);2456 try o.dg.renderFunctionSignature(fwd_decl_writer, .Forward, 0);
2442 try fwd_decl_writer.writeAll(";\n");2457 try fwd_decl_writer.writeAll(";\n");
2458 try genExports(o);
24432459
2444 try o.indent_writer.insertNewline();2460 try o.indent_writer.insertNewline();
2445 if (!is_global) try o.writer().writeAll("static ");2461 if (!is_global) try o.writer().writeAll("static ");
2446 try o.dg.renderFunctionSignature(o.writer(), .Complete);2462 try o.dg.renderFunctionSignature(o.writer(), .Complete, 0);
2447 try o.writer().writeByte(' ');2463 try o.writer().writeByte(' ');
24482464
2449 // In case we need to use the header, populate it with a copy of the function2465 // In case we need to use the header, populate it with a copy of the function
...@@ -2478,8 +2494,9 @@ pub fn genDecl(o: *Object) !void {...@@ -2478,8 +2494,9 @@ pub fn genDecl(o: *Object) !void {
2478 if (tv.val.tag() == .extern_fn) {2494 if (tv.val.tag() == .extern_fn) {
2479 const fwd_decl_writer = o.dg.fwd_decl.writer();2495 const fwd_decl_writer = o.dg.fwd_decl.writer();
2480 try fwd_decl_writer.writeAll("zig_extern ");2496 try fwd_decl_writer.writeAll("zig_extern ");
2481 try o.dg.renderFunctionSignature(fwd_decl_writer, .Forward);2497 try o.dg.renderFunctionSignature(fwd_decl_writer, .Forward, 0);
2482 try fwd_decl_writer.writeAll(";\n");2498 try fwd_decl_writer.writeAll(";\n");
2499 try genExports(o);
2483 } else if (tv.val.castTag(.variable)) |var_payload| {2500 } else if (tv.val.castTag(.variable)) |var_payload| {
2484 const variable: *Module.Var = var_payload.data;2501 const variable: *Module.Var = var_payload.data;
24852502
...@@ -2492,6 +2509,7 @@ pub fn genDecl(o: *Object) !void {...@@ -2492,6 +2509,7 @@ pub fn genDecl(o: *Object) !void {
2492 if (variable.is_threadlocal) try fwd_decl_writer.writeAll("zig_threadlocal ");2509 if (variable.is_threadlocal) try fwd_decl_writer.writeAll("zig_threadlocal ");
2493 try o.dg.renderTypeAndName(fwd_decl_writer, o.dg.decl.ty, decl_c_value, .Mut, o.dg.decl.@"align", .Complete);2510 try o.dg.renderTypeAndName(fwd_decl_writer, o.dg.decl.ty, decl_c_value, .Mut, o.dg.decl.@"align", .Complete);
2494 try fwd_decl_writer.writeAll(";\n");2511 try fwd_decl_writer.writeAll(";\n");
2512 try genExports(o);
24952513
2496 if (variable.is_extern) return;2514 if (variable.is_extern) return;
24972515
...@@ -2537,7 +2555,7 @@ pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void {...@@ -2537,7 +2555,7 @@ pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void {
2537 const is_global = dg.declIsGlobal(tv);2555 const is_global = dg.declIsGlobal(tv);
2538 if (is_global) {2556 if (is_global) {
2539 try writer.writeAll("zig_extern ");2557 try writer.writeAll("zig_extern ");
2540 try dg.renderFunctionSignature(writer, .Complete);2558 try dg.renderFunctionSignature(writer, .Complete, 0);
2541 try dg.fwd_decl.appendSlice(";\n");2559 try dg.fwd_decl.appendSlice(";\n");
2542 }2560 }
2543 },2561 },
...@@ -3677,7 +3695,7 @@ fn airCall(...@@ -3677,7 +3695,7 @@ fn airCall(
3677 };3695 };
3678 };3696 };
3679 name = f.object.dg.module.declPtr(fn_decl).name;3697 name = f.object.dg.module.declPtr(fn_decl).name;
3680 try f.object.dg.renderDeclName(writer, fn_decl);3698 try f.object.dg.renderDeclName(writer, fn_decl, 0);
3681 break :callee;3699 break :callee;
3682 }3700 }
3683 // Fall back to function pointer call.3701 // Fall back to function pointer call.
test/behavior/bugs/12680.zig-1
...@@ -8,7 +8,6 @@ extern fn test_func() callconv(.C) usize;...@@ -8,7 +8,6 @@ extern fn test_func() callconv(.C) usize;
8test "export a function twice" {8test "export a function twice" {
9 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;9 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
10 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;10 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
11 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
12 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;11 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
13 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;12 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1413