authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-11-05 18:44:12-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2023-11-05 18:44:12-05:00
log702b809ea3e9b9dbdc1fd6efe9306442487e7103
treebd639378ad2931013ff49789aadfc2104093261c
parentbec36aa7c028f2eaec94a2358f3e1326fcb9a30c
parentc893f837151d4764fd34911376836a01192b4d75
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #17815 from Luukdegram/wasm-no-entry

wasm-linker: implement `-fno-entry` and correctly pass `--shared` and `--pie` when given

21 files changed, 209 insertions(+), 130 deletions(-)

doc/langref.html.in+4-4
......@@ -11336,12 +11336,12 @@ all your base are belong to us{#end_shell_samp#}
1133611336 {#header_open|WebAssembly#}
1133711337 <p>Zig supports building for WebAssembly out of the box.</p>
1133811338 {#header_open|Freestanding#}
11339 <p>For host environments like the web browser and nodejs, build as a dynamic library using the freestanding
11339 <p>For host environments like the web browser and nodejs, build as an executable using the freestanding
1134011340 OS target. Here's an example of running Zig code compiled to WebAssembly with nodejs.</p>
11341 {#code_begin|lib|math#}
11341 {#code_begin|exe|math#}
1134211342 {#target_wasm#}
11343 {#link_mode_dynamic#}
11344 {#additonal_option|-rdynamic#}
11343 {#additonal_option|-fno-entry#}
11344 {#additonal_option|--export=add#}
1134511345extern fn print(i32) void;
1134611346
1134711347export fn add(a: i32, b: i32) void {
lib/std/Build/Step/Compile.zig+21-4
......@@ -189,7 +189,8 @@ dll_export_fns: ?bool = null,
189189
190190subsystem: ?std.Target.SubSystem = null,
191191
192entry_symbol_name: ?[]const u8 = null,
192/// How the linker must handle the entry point of the executable.
193entry: Entry = .default,
193194
194195/// List of symbols forced as undefined in the symbol table
195196/// thus forcing their resolution by the linker.
......@@ -304,6 +305,18 @@ const FrameworkLinkInfo = struct {
304305 weak: bool = false,
305306};
306307
308const Entry = union(enum) {
309 /// Let the compiler decide whether to make an entry point and what to name
310 /// it.
311 default,
312 /// The executable will have no entry point.
313 disabled,
314 /// The executable will have an entry point with the default symbol name.
315 enabled,
316 /// The executable will have an entry point with the specified symbol name.
317 symbol_name: []const u8,
318};
319
307320pub const IncludeDir = union(enum) {
308321 path: LazyPath,
309322 path_system: LazyPath,
......@@ -1418,9 +1431,13 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
14181431 try zig_args.append(try std.fmt.allocPrint(b.allocator, "-ofmt={s}", .{@tagName(ofmt)}));
14191432 }
14201433
1421 if (self.entry_symbol_name) |entry| {
1422 try zig_args.append("--entry");
1423 try zig_args.append(entry);
1434 switch (self.entry) {
1435 .default => {},
1436 .disabled => try zig_args.append("-fno-entry"),
1437 .enabled => try zig_args.append("-fentry"),
1438 .symbol_name => |entry_name| {
1439 try zig_args.append(try std.fmt.allocPrint(b.allocator, "-fentry={s}", .{entry_name}));
1440 },
14241441 }
14251442
14261443 {
lib/std/start.zig+6-2
......@@ -82,11 +82,15 @@ comptime {
8282 .reactor => "_initialize",
8383 .command => "_start",
8484 };
85 if (!@hasDecl(root, wasm_start_sym)) {
85 if (!@hasDecl(root, wasm_start_sym) and @hasDecl(root, "main")) {
86 // Only call main when defined. For WebAssembly it's allowed to pass `-fno-entry` in which
87 // case it's not required to provide an entrypoint such as main.
8688 @export(wasi_start, .{ .name = wasm_start_sym });
8789 }
8890 } else if (native_arch.isWasm() and native_os == .freestanding) {
89 if (!@hasDecl(root, start_sym_name)) @export(wasm_freestanding_start, .{ .name = start_sym_name });
91 // Only call main when defined. For WebAssembly it's allowed to pass `-fno-entry` in which
92 // case it's not required to provide an entrypoint such as main.
93 if (!@hasDecl(root, start_sym_name) and @hasDecl(root, "main")) @export(wasm_freestanding_start, .{ .name = start_sym_name });
9094 } else if (native_os != .other and native_os != .freestanding) {
9195 if (!@hasDecl(root, start_sym_name)) @export(_start, .{ .name = start_sym_name });
9296 }
src/link/Wasm.zig+12-21
......@@ -2817,15 +2817,11 @@ fn setupExports(wasm: *Wasm) !void {
28172817}
28182818
28192819fn setupStart(wasm: *Wasm) !void {
2820 const entry_name = wasm.base.options.entry orelse "_start";
2820 // do not export entry point if user set none or no default was set.
2821 const entry_name = wasm.base.options.entry orelse return;
28212822
28222823 const symbol_loc = wasm.findGlobalSymbol(entry_name) orelse {
2823 if (wasm.base.options.output_mode == .Exe) {
2824 if (wasm.base.options.wasi_exec_model == .reactor) return; // Not required for reactors
2825 } else {
2826 return; // No entry point needed for non-executable wasm files
2827 }
2828 log.err("Entry symbol '{s}' missing", .{entry_name});
2824 log.err("Entry symbol '{s}' missing, use '-fno-entry' to suppress", .{entry_name});
28292825 return error.MissingSymbol;
28302826 };
28312827
......@@ -4535,6 +4531,8 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
45354531 if (wasm.base.options.entry) |entry| {
45364532 try argv.append("--entry");
45374533 try argv.append(entry);
4534 } else {
4535 try argv.append("--no-entry");
45384536 }
45394537
45404538 // Increase the default stack size to a more reasonable value of 1MB instead of
......@@ -4544,24 +4542,17 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
45444542 const arg = try std.fmt.allocPrint(arena, "stack-size={d}", .{stack_size});
45454543 try argv.append(arg);
45464544
4547 if (wasm.base.options.output_mode == .Exe) {
4548 if (wasm.base.options.wasi_exec_model == .reactor) {
4549 // Reactor execution model does not have _start so lld doesn't look for it.
4550 try argv.append("--no-entry");
4551 // Make sure "_initialize" and other used-defined functions are exported if this is WASI reactor.
4552 // If rdynamic is true, it will already be appended, so only verify if the user did not specify
4553 // the flag in which case, we ensure `--export-dynamic` is called.
4554 if (!wasm.base.options.rdynamic) {
4555 try argv.append("--export-dynamic");
4556 }
4557 }
4558 } else if (wasm.base.options.entry == null) {
4559 try argv.append("--no-entry"); // So lld doesn't look for _start.
4560 }
45614545 if (wasm.base.options.import_symbols) {
45624546 try argv.append("--allow-undefined");
45634547 }
45644548
4549 if (wasm.base.options.output_mode == .Lib and wasm.base.options.link_mode == .Dynamic) {
4550 try argv.append("--shared");
4551 }
4552 if (wasm.base.options.pie) {
4553 try argv.append("--pie");
4554 }
4555
45654556 // XXX - TODO: add when wasm-ld supports --build-id.
45664557 // if (wasm.base.options.build_id) {
45674558 // try argv.append("--build-id=tree");
src/main.zig+54-3
......@@ -519,7 +519,9 @@ const usage_build_generic =
519519 \\ --dynamic-linker [path] Set the dynamic interpreter path (usually ld.so)
520520 \\ --sysroot [path] Set the system root directory (usually /)
521521 \\ --version [ver] Dynamic library semver
522 \\ --entry [name] Set the entrypoint symbol name
522 \\ -fentry Enable entry point with default symbol name
523 \\ -fentry=[name] Override the entry point symbol name
524 \\ -fno-entry Do not output any entry point
523525 \\ --force_undefined [name] Specify the symbol must be defined for the link to succeed
524526 \\ -fsoname[=name] Override the default SONAME value
525527 \\ -fno-soname Disable emitting a SONAME
......@@ -845,6 +847,7 @@ fn buildOutputType(
845847 var linker_import_symbols: bool = false;
846848 var linker_import_table: bool = false;
847849 var linker_export_table: bool = false;
850 var linker_force_entry: ?bool = null;
848851 var linker_initial_memory: ?u64 = null;
849852 var linker_max_memory: ?u64 = null;
850853 var linker_shared_memory: bool = false;
......@@ -1081,8 +1084,8 @@ fn buildOutputType(
10811084 subsystem = try parseSubSystem(args_iter.nextOrFatal());
10821085 } else if (mem.eql(u8, arg, "-O")) {
10831086 optimize_mode_string = args_iter.nextOrFatal();
1084 } else if (mem.eql(u8, arg, "--entry")) {
1085 entry = args_iter.nextOrFatal();
1087 } else if (mem.startsWith(u8, arg, "-fentry=")) {
1088 entry = arg["-fentry=".len..];
10861089 } else if (mem.eql(u8, arg, "--force_undefined")) {
10871090 try force_undefined_symbols.put(gpa, args_iter.nextOrFatal(), {});
10881091 } else if (mem.eql(u8, arg, "--stack")) {
......@@ -1513,6 +1516,10 @@ fn buildOutputType(
15131516 }
15141517 } else if (mem.eql(u8, arg, "--import-memory")) {
15151518 linker_import_memory = true;
1519 } else if (mem.eql(u8, arg, "-fentry")) {
1520 linker_force_entry = true;
1521 } else if (mem.eql(u8, arg, "-fno-entry")) {
1522 linker_force_entry = false;
15161523 } else if (mem.eql(u8, arg, "--export-memory")) {
15171524 linker_export_memory = true;
15181525 } else if (mem.eql(u8, arg, "--import-symbols")) {
......@@ -2144,6 +2151,8 @@ fn buildOutputType(
21442151 linker_import_table = true;
21452152 } else if (mem.eql(u8, arg, "--export-table")) {
21462153 linker_export_table = true;
2154 } else if (mem.eql(u8, arg, "--no-entry")) {
2155 linker_force_entry = false;
21472156 } else if (mem.eql(u8, arg, "--initial-memory")) {
21482157 const next_arg = linker_args_it.nextOrFatal();
21492158 linker_initial_memory = std.fmt.parseUnsigned(u32, eatIntPrefix(next_arg, 16), 16) catch |err| {
......@@ -2606,6 +2615,23 @@ fn buildOutputType(
26062615 link_libcpp = true;
26072616 }
26082617
2618 if (linker_force_entry) |force| {
2619 if (!force) {
2620 entry = null;
2621 } else if (entry == null and output_mode == .Exe) {
2622 entry = switch (target_info.target.ofmt) {
2623 .coff => "wWinMainCRTStartup",
2624 .macho => "_main",
2625 .elf, .plan9 => "_start",
2626 .wasm => defaultWasmEntryName(wasi_exec_model),
2627 else => |tag| fatal("No default entry point available for output format {s}", .{@tagName(tag)}),
2628 };
2629 }
2630 } else if (entry == null and target_info.target.isWasm() and output_mode == .Exe) {
2631 // For WebAssembly the compiler defaults to setting the entry name when no flags are set.
2632 entry = defaultWasmEntryName(wasi_exec_model);
2633 }
2634
26092635 if (target_info.target.ofmt == .coff) {
26102636 // Now that we know the target supports resources,
26112637 // we can add the res files as link objects.
......@@ -2628,6 +2654,23 @@ fn buildOutputType(
26282654 if (single_threaded == null) {
26292655 single_threaded = true;
26302656 }
2657 if (link_mode) |mode| {
2658 if (mode == .Dynamic) {
2659 if (linker_export_memory != null and linker_export_memory.?) {
2660 fatal("flags '-dynamic' and '--export-memory' are incompatible", .{});
2661 }
2662 // User did not supply `--export-memory` which is incompatible with -dynamic, therefore
2663 // set the flag to false to ensure it does not get enabled by default.
2664 linker_export_memory = false;
2665 }
2666 }
2667 if (wasi_exec_model != null and wasi_exec_model.? == .reactor) {
2668 if (entry) |entry_name| {
2669 if (!mem.eql(u8, "_initialize", entry_name)) {
2670 fatal("the entry symbol of the reactor model must be '_initialize', but found '{s}'", .{entry_name});
2671 }
2672 }
2673 }
26312674 if (linker_shared_memory) {
26322675 if (output_mode == .Obj) {
26332676 fatal("shared memory is not allowed in object files", .{});
......@@ -7225,3 +7268,11 @@ fn createDependenciesModule(
72257268 try main_mod.deps.put(arena, "@dependencies", deps_mod);
72267269 return deps_mod;
72277270}
7271
7272fn defaultWasmEntryName(exec_model: ?std.builtin.WasiExecModel) []const u8 {
7273 const model = exec_model orelse .command;
7274 if (model == .reactor) {
7275 return "_initialize";
7276 }
7277 return "_start";
7278}
test/link/elf.zig+2-2
......@@ -658,7 +658,7 @@ fn testEntryPoint(b: *Build, opts: Options) *Step {
658658 const exe = addExecutable(b, "main", opts);
659659 exe.addObject(a_o);
660660 exe.addObject(b_o);
661 exe.entry_symbol_name = "foo";
661 exe.entry = .{ .symbol_name = "foo" };
662662
663663 const check = exe.checkObject();
664664 check.checkStart();
......@@ -674,7 +674,7 @@ fn testEntryPoint(b: *Build, opts: Options) *Step {
674674 const exe = addExecutable(b, "other", opts);
675675 exe.addObject(a_o);
676676 exe.addObject(b_o);
677 exe.entry_symbol_name = "bar";
677 exe.entry = .{ .symbol_name = "bar" };
678678
679679 const check = exe.checkObject();
680680 check.checkStart();
test/link/macho/entry/build.zig+1-1
......@@ -20,7 +20,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize
2020 });
2121 exe.addCSourceFile(.{ .file = .{ .path = "main.c" }, .flags = &.{} });
2222 exe.linkLibC();
23 exe.entry_symbol_name = "_non_main";
23 exe.entry = .{ .symbol_name = "_non_main" };
2424
2525 const check_exe = exe.checkObject();
2626
test/link/macho/entry_in_dylib/build.zig+1-1
......@@ -30,7 +30,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize
3030 exe.addCSourceFile(.{ .file = .{ .path = "main.c" }, .flags = &.{} });
3131 exe.linkLibrary(lib);
3232 exe.linkLibC();
33 exe.entry_symbol_name = "_bootstrap";
33 exe.entry = .{ .symbol_name = "_bootstrap" };
3434 exe.forceUndefinedSymbol("_my_main");
3535
3636 const check_exe = exe.checkObject();
test/link/wasm/archive/build.zig+2-1
......@@ -15,12 +15,13 @@ pub fn build(b: *std.Build) void {
1515fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void {
1616 // The code in question will pull-in compiler-rt,
1717 // and therefore link with its archive file.
18 const lib = b.addSharedLibrary(.{
18 const lib = b.addExecutable(.{
1919 .name = "main",
2020 .root_source_file = .{ .path = "main.zig" },
2121 .optimize = optimize,
2222 .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding },
2323 });
24 lib.entry = .disabled;
2425 lib.use_llvm = false;
2526 lib.use_lld = false;
2627 lib.strip = false;
test/link/wasm/basic-features/build.zig+2-1
......@@ -4,7 +4,7 @@ pub const requires_stage2 = true;
44
55pub fn build(b: *std.Build) void {
66 // Library with explicitly set cpu features
7 const lib = b.addSharedLibrary(.{
7 const lib = b.addExecutable(.{
88 .name = "lib",
99 .root_source_file = .{ .path = "main.zig" },
1010 .optimize = .Debug,
......@@ -15,6 +15,7 @@ pub fn build(b: *std.Build) void {
1515 .os_tag = .freestanding,
1616 },
1717 });
18 lib.entry = .disabled;
1819 lib.use_llvm = false;
1920 lib.use_lld = false;
2021
test/link/wasm/bss/build.zig+4-2
......@@ -14,12 +14,13 @@ pub fn build(b: *std.Build) void {
1414
1515fn add(b: *std.Build, test_step: *std.Build.Step, optimize_mode: std.builtin.OptimizeMode, is_safe: bool) void {
1616 {
17 const lib = b.addSharedLibrary(.{
17 const lib = b.addExecutable(.{
1818 .name = "lib",
1919 .root_source_file = .{ .path = "lib.zig" },
2020 .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding },
2121 .optimize = optimize_mode,
2222 });
23 lib.entry = .disabled;
2324 lib.use_llvm = false;
2425 lib.use_lld = false;
2526 lib.strip = false;
......@@ -60,12 +61,13 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize_mode: std.builtin.Opt
6061
6162 // verify zero'd declaration is stored in bss for all optimization modes.
6263 {
63 const lib = b.addSharedLibrary(.{
64 const lib = b.addExecutable(.{
6465 .name = "lib",
6566 .root_source_file = .{ .path = "lib2.zig" },
6667 .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding },
6768 .optimize = optimize_mode,
6869 });
70 lib.entry = .disabled;
6971 lib.use_llvm = false;
7072 lib.use_lld = false;
7173 lib.strip = false;
test/link/wasm/export-data/build.zig+2-1
......@@ -9,12 +9,13 @@ pub fn build(b: *std.Build) void {
99 return;
1010 }
1111
12 const lib = b.addSharedLibrary(.{
12 const lib = b.addExecutable(.{
1313 .name = "lib",
1414 .root_source_file = .{ .path = "lib.zig" },
1515 .optimize = .ReleaseSafe, // to make the output deterministic in address positions
1616 .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding },
1717 });
18 lib.entry = .disabled;
1819 lib.use_lld = false;
1920 lib.export_symbol_names = &.{ "foo", "bar" };
2021 lib.global_base = 0; // put data section at address 0 to make data symbols easier to parse
test/link/wasm/export/build.zig+6-3
......@@ -13,31 +13,34 @@ pub fn build(b: *std.Build) void {
1313}
1414
1515fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void {
16 const no_export = b.addSharedLibrary(.{
16 const no_export = b.addExecutable(.{
1717 .name = "no-export",
1818 .root_source_file = .{ .path = "main.zig" },
1919 .optimize = optimize,
2020 .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding },
2121 });
22 no_export.entry = .disabled;
2223 no_export.use_llvm = false;
2324 no_export.use_lld = false;
2425
25 const dynamic_export = b.addSharedLibrary(.{
26 const dynamic_export = b.addExecutable(.{
2627 .name = "dynamic",
2728 .root_source_file = .{ .path = "main.zig" },
2829 .optimize = optimize,
2930 .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding },
3031 });
32 dynamic_export.entry = .disabled;
3133 dynamic_export.rdynamic = true;
3234 dynamic_export.use_llvm = false;
3335 dynamic_export.use_lld = false;
3436
35 const force_export = b.addSharedLibrary(.{
37 const force_export = b.addExecutable(.{
3638 .name = "force",
3739 .root_source_file = .{ .path = "main.zig" },
3840 .optimize = optimize,
3941 .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding },
4042 });
43 force_export.entry = .disabled;
4144 force_export.export_symbol_names = &.{"foo"};
4245 force_export.use_llvm = false;
4346 force_export.use_lld = false;
test/link/wasm/extern-mangle/build.zig+2-1
......@@ -11,12 +11,13 @@ pub fn build(b: *std.Build) void {
1111}
1212
1313fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void {
14 const lib = b.addSharedLibrary(.{
14 const lib = b.addExecutable(.{
1515 .name = "lib",
1616 .root_source_file = .{ .path = "lib.zig" },
1717 .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding },
1818 .optimize = optimize,
1919 });
20 lib.entry = .disabled;
2021 lib.import_symbols = true; // import `a` and `b`
2122 lib.rdynamic = true; // export `foo`
2223
test/link/wasm/function-table/build.zig+6-3
......@@ -13,32 +13,35 @@ pub fn build(b: *std.Build) void {
1313}
1414
1515fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void {
16 const import_table = b.addSharedLibrary(.{
16 const import_table = b.addExecutable(.{
1717 .name = "import_table",
1818 .root_source_file = .{ .path = "lib.zig" },
1919 .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding },
2020 .optimize = optimize,
2121 });
22 import_table.entry = .disabled;
2223 import_table.use_llvm = false;
2324 import_table.use_lld = false;
2425 import_table.import_table = true;
2526
26 const export_table = b.addSharedLibrary(.{
27 const export_table = b.addExecutable(.{
2728 .name = "export_table",
2829 .root_source_file = .{ .path = "lib.zig" },
2930 .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding },
3031 .optimize = optimize,
3132 });
33 export_table.entry = .disabled;
3234 export_table.use_llvm = false;
3335 export_table.use_lld = false;
3436 export_table.export_table = true;
3537
36 const regular_table = b.addSharedLibrary(.{
38 const regular_table = b.addExecutable(.{
3739 .name = "regular_table",
3840 .root_source_file = .{ .path = "lib.zig" },
3941 .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding },
4042 .optimize = optimize,
4143 });
44 regular_table.entry = .disabled;
4245 regular_table.use_llvm = false;
4346 regular_table.use_lld = false;
4447
test/link/wasm/infer-features/build.zig+2-1
......@@ -17,7 +17,7 @@ pub fn build(b: *std.Build) void {
1717
1818 // Wasm library that doesn't have any features specified. This will
1919 // infer its featureset from other linked object files.
20 const lib = b.addSharedLibrary(.{
20 const lib = b.addExecutable(.{
2121 .name = "lib",
2222 .root_source_file = .{ .path = "main.zig" },
2323 .optimize = .Debug,
......@@ -27,6 +27,7 @@ pub fn build(b: *std.Build) void {
2727 .os_tag = .freestanding,
2828 },
2929 });
30 lib.entry = .disabled;
3031 lib.use_llvm = false;
3132 lib.use_lld = false;
3233 lib.addObject(c_obj);
test/link/wasm/producers/build.zig+2-1
......@@ -14,12 +14,13 @@ pub fn build(b: *std.Build) void {
1414}
1515
1616fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void {
17 const lib = b.addSharedLibrary(.{
17 const lib = b.addExecutable(.{
1818 .name = "lib",
1919 .root_source_file = .{ .path = "lib.zig" },
2020 .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding },
2121 .optimize = optimize,
2222 });
23 lib.entry = .disabled;
2324 lib.use_llvm = false;
2425 lib.use_lld = false;
2526 lib.strip = false;
test/link/wasm/segments/build.zig+2-1
......@@ -13,12 +13,13 @@ pub fn build(b: *std.Build) void {
1313}
1414
1515fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void {
16 const lib = b.addSharedLibrary(.{
16 const lib = b.addExecutable(.{
1717 .name = "lib",
1818 .root_source_file = .{ .path = "lib.zig" },
1919 .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding },
2020 .optimize = optimize,
2121 });
22 lib.entry = .disabled;
2223 lib.use_llvm = false;
2324 lib.use_lld = false;
2425 lib.strip = false;
test/link/wasm/shared-memory/build.zig+74-75
......@@ -11,88 +11,87 @@ pub fn build(b: *std.Build) void {
1111}
1212
1313fn add(b: *std.Build, test_step: *std.Build.Step, optimize_mode: std.builtin.OptimizeMode) void {
14 {
15 const lib = b.addSharedLibrary(.{
16 .name = "lib",
17 .root_source_file = .{ .path = "lib.zig" },
18 .target = .{
19 .cpu_arch = .wasm32,
20 .cpu_model = .{ .explicit = &std.Target.wasm.cpu.mvp },
21 .cpu_features_add = std.Target.wasm.featureSet(&.{ .atomics, .bulk_memory }),
22 .os_tag = .freestanding,
23 },
24 .optimize = optimize_mode,
25 });
26 lib.use_lld = false;
27 lib.strip = false;
28 lib.import_memory = true;
29 lib.export_memory = true;
30 lib.shared_memory = true;
31 lib.max_memory = 67108864;
32 lib.single_threaded = false;
33 lib.export_symbol_names = &.{"foo"};
14 const lib = b.addExecutable(.{
15 .name = "lib",
16 .root_source_file = .{ .path = "lib.zig" },
17 .target = .{
18 .cpu_arch = .wasm32,
19 .cpu_model = .{ .explicit = &std.Target.wasm.cpu.mvp },
20 .cpu_features_add = std.Target.wasm.featureSet(&.{ .atomics, .bulk_memory }),
21 .os_tag = .freestanding,
22 },
23 .optimize = optimize_mode,
24 });
25 lib.entry = .disabled;
26 lib.use_lld = false;
27 lib.strip = false;
28 lib.import_memory = true;
29 lib.export_memory = true;
30 lib.shared_memory = true;
31 lib.max_memory = 67108864;
32 lib.single_threaded = false;
33 lib.export_symbol_names = &.{"foo"};
3434
35 const check_lib = lib.checkObject();
35 const check_lib = lib.checkObject();
3636
37 check_lib.checkStart("Section import");
38 check_lib.checkNext("entries 1");
39 check_lib.checkNext("module env");
40 check_lib.checkNext("name memory"); // ensure we are importing memory
37 check_lib.checkStart("Section import");
38 check_lib.checkNext("entries 1");
39 check_lib.checkNext("module env");
40 check_lib.checkNext("name memory"); // ensure we are importing memory
4141
42 check_lib.checkStart("Section export");
43 check_lib.checkNext("entries 2");
44 check_lib.checkNext("name memory"); // ensure we also export memory again
42 check_lib.checkStart("Section export");
43 check_lib.checkNext("entries 2");
44 check_lib.checkNext("name memory"); // ensure we also export memory again
4545
46 // This section *must* be emit as the start function is set to the index
47 // of __wasm_init_memory
48 // release modes will have the TLS segment optimized out in our test-case.
49 // This means we won't have __wasm_init_memory in such case, and therefore
50 // should also not have a section "start"
51 if (optimize_mode == .Debug) {
52 check_lib.checkStart("Section start");
53 }
54
55 // This section is only and *must* be emit when shared-memory is enabled
56 // release modes will have the TLS segment optimized out in our test-case.
57 if (optimize_mode == .Debug) {
58 check_lib.checkStart("Section data_count");
59 check_lib.checkNext("count 3");
60 }
46 // This section *must* be emit as the start function is set to the index
47 // of __wasm_init_memory
48 // release modes will have the TLS segment optimized out in our test-case.
49 // This means we won't have __wasm_init_memory in such case, and therefore
50 // should also not have a section "start"
51 if (optimize_mode == .Debug) {
52 check_lib.checkStart("Section start");
53 }
6154
62 check_lib.checkStart("Section custom");
63 check_lib.checkNext("name name");
64 check_lib.checkNext("type function");
65 if (optimize_mode == .Debug) {
66 check_lib.checkNext("name __wasm_init_memory");
67 }
68 check_lib.checkNext("name __wasm_init_tls");
69 check_lib.checkNext("type global");
55 // This section is only and *must* be emit when shared-memory is enabled
56 // release modes will have the TLS segment optimized out in our test-case.
57 if (optimize_mode == .Debug) {
58 check_lib.checkStart("Section data_count");
59 check_lib.checkNext("count 3");
60 }
7061
71 // In debug mode the symbol __tls_base is resolved to an undefined symbol
72 // from the object file, hence its placement differs than in release modes
73 // where the entire tls segment is optimized away, and tls_base will have
74 // its original position.
75 if (optimize_mode == .Debug) {
76 check_lib.checkNext("name __tls_size");
77 check_lib.checkNext("name __tls_align");
78 check_lib.checkNext("name __tls_base");
79 } else {
80 check_lib.checkNext("name __tls_base");
81 check_lib.checkNext("name __tls_size");
82 check_lib.checkNext("name __tls_align");
83 }
62 check_lib.checkStart("Section custom");
63 check_lib.checkNext("name name");
64 check_lib.checkNext("type function");
65 if (optimize_mode == .Debug) {
66 check_lib.checkNext("name __wasm_init_memory");
67 }
68 check_lib.checkNext("name __wasm_init_tls");
69 check_lib.checkNext("type global");
8470
85 check_lib.checkNext("type data_segment");
86 if (optimize_mode == .Debug) {
87 check_lib.checkNext("names 3");
88 check_lib.checkNext("index 0");
89 check_lib.checkNext("name .rodata");
90 check_lib.checkNext("index 1");
91 check_lib.checkNext("name .bss");
92 check_lib.checkNext("index 2");
93 check_lib.checkNext("name .tdata");
94 }
71 // In debug mode the symbol __tls_base is resolved to an undefined symbol
72 // from the object file, hence its placement differs than in release modes
73 // where the entire tls segment is optimized away, and tls_base will have
74 // its original position.
75 if (optimize_mode == .Debug) {
76 check_lib.checkNext("name __tls_size");
77 check_lib.checkNext("name __tls_align");
78 check_lib.checkNext("name __tls_base");
79 } else {
80 check_lib.checkNext("name __tls_base");
81 check_lib.checkNext("name __tls_size");
82 check_lib.checkNext("name __tls_align");
83 }
9584
96 test_step.dependOn(&check_lib.step);
85 check_lib.checkNext("type data_segment");
86 if (optimize_mode == .Debug) {
87 check_lib.checkNext("names 3");
88 check_lib.checkNext("index 0");
89 check_lib.checkNext("name .rodata");
90 check_lib.checkNext("index 1");
91 check_lib.checkNext("name .bss");
92 check_lib.checkNext("index 2");
93 check_lib.checkNext("name .tdata");
9794 }
95
96 test_step.dependOn(&check_lib.step);
9897}
test/link/wasm/stack_pointer/build.zig+2-1
......@@ -13,12 +13,13 @@ pub fn build(b: *std.Build) void {
1313}
1414
1515fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void {
16 const lib = b.addSharedLibrary(.{
16 const lib = b.addExecutable(.{
1717 .name = "lib",
1818 .root_source_file = .{ .path = "lib.zig" },
1919 .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding },
2020 .optimize = optimize,
2121 });
22 lib.entry = .disabled;
2223 lib.use_llvm = false;
2324 lib.use_lld = false;
2425 lib.strip = false;
test/link/wasm/type/build.zig+2-1
......@@ -13,12 +13,13 @@ pub fn build(b: *std.Build) void {
1313}
1414
1515fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void {
16 const lib = b.addSharedLibrary(.{
16 const lib = b.addExecutable(.{
1717 .name = "lib",
1818 .root_source_file = .{ .path = "lib.zig" },
1919 .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding },
2020 .optimize = optimize,
2121 });
22 lib.entry = .disabled;
2223 lib.use_llvm = false;
2324 lib.use_lld = false;
2425 lib.strip = false;