authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-11-09 14:29:20-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-11-09 14:29:20-07:00
logd2cdfb949033cfd463cdd4ef1bbf93f94d4d190a
tree6f329fbd1402f5776dc0b8f654452a8ae1471956
parent9bb7ff68ccab8700cb787a83359df02a5bb4370f

stage2: add 4 new linker flags for WebAssembly

--import-memory import memory from the environment --initial-memory=[bytes] initial size of the linear memory --max-memory=[bytes] maximum size of the linear memory --global-base=[addr] where to start to place global data See #8633

5 files changed, 86 insertions(+), 1 deletions(-)

lib/std/build.zig+16
......@@ -1439,6 +1439,10 @@ pub const LibExeObjStep = struct {
14391439 disable_sanitize_c: bool,
14401440 sanitize_thread: bool,
14411441 rdynamic: bool,
1442 import_memory: bool = false,
1443 initial_memory: ?u64 = null,
1444 max_memory: ?u64 = null,
1445 global_base: ?u64 = null,
14421446 c_std: Builder.CStd,
14431447 override_lib_dir: ?[]const u8,
14441448 main_pkg_path: ?[]const u8,
......@@ -2431,6 +2435,18 @@ pub const LibExeObjStep = struct {
24312435 if (self.rdynamic) {
24322436 try zig_args.append("-rdynamic");
24332437 }
2438 if (self.import_memory) {
2439 try zig_args.append("--import-memory");
2440 }
2441 if (self.initial_memory) |initial_memory| {
2442 try zig_args.append(builder.fmt("--initial-memory={d}", .{initial_memory}));
2443 }
2444 if (self.max_memory) |max_memory| {
2445 try zig_args.append(builder.fmt("--max-memory={d}", .{max_memory}));
2446 }
2447 if (self.global_base) |global_base| {
2448 try zig_args.append(builder.fmt("--global-base={d}", .{global_base}));
2449 }
24342450
24352451 if (self.code_model != .default) {
24362452 try zig_args.append("-mcmodel");
src/Compilation.zig+8
......@@ -716,6 +716,10 @@ pub const InitOptions = struct {
716716 linker_gc_sections: ?bool = null,
717717 linker_allow_shlib_undefined: ?bool = null,
718718 linker_bind_global_refs_locally: ?bool = null,
719 linker_import_memory: ?bool = null,
720 linker_initial_memory: ?u64 = null,
721 linker_max_memory: ?u64 = null,
722 linker_global_base: ?u64 = null,
719723 each_lib_rpath: ?bool = null,
720724 disable_c_depfile: bool = false,
721725 linker_z_nodelete: bool = false,
......@@ -1401,6 +1405,10 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
14011405 .function_sections = options.function_sections,
14021406 .allow_shlib_undefined = options.linker_allow_shlib_undefined,
14031407 .bind_global_refs_locally = options.linker_bind_global_refs_locally orelse false,
1408 .import_memory = options.linker_import_memory orelse false,
1409 .initial_memory = options.linker_initial_memory,
1410 .max_memory = options.linker_max_memory,
1411 .global_base = options.linker_global_base,
14041412 .z_nodelete = options.linker_z_nodelete,
14051413 .z_notext = options.linker_z_notext,
14061414 .z_defs = options.linker_z_defs,
src/link.zig+4
......@@ -82,6 +82,10 @@ pub const Options = struct {
8282 nxcompat: bool,
8383 dynamicbase: bool,
8484 bind_global_refs_locally: bool,
85 import_memory: bool,
86 initial_memory: ?u64,
87 max_memory: ?u64,
88 global_base: ?u64,
8589 is_native_os: bool,
8690 is_native_abi: bool,
8791 pic: bool,
src/link/Wasm.zig+23
......@@ -681,6 +681,10 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void {
681681 try man.addOptionalFile(compiler_rt_path);
682682 man.hash.addOptional(self.base.options.stack_size_override);
683683 man.hash.addListOfBytes(self.base.options.extra_lld_args);
684 man.hash.add(self.base.options.import_memory);
685 man.hash.addOptional(self.base.options.initial_memory);
686 man.hash.addOptional(self.base.options.max_memory);
687 man.hash.addOptional(self.base.options.global_base);
684688
685689 // We don't actually care whether it's a cache hit or miss; we just need the digest and the lock.
686690 _ = try man.hit();
......@@ -754,6 +758,25 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void {
754758 }
755759 }
756760
761 if (self.base.options.import_memory) {
762 try argv.append("--import-memory");
763 }
764
765 if (self.base.options.initial_memory) |initial_memory| {
766 const arg = try std.fmt.allocPrint(arena, "--initial-memory={d}", .{initial_memory});
767 try argv.append(arg);
768 }
769
770 if (self.base.options.max_memory) |max_memory| {
771 const arg = try std.fmt.allocPrint(arena, "--max-memory={d}", .{max_memory});
772 try argv.append(arg);
773 }
774
775 if (self.base.options.global_base) |global_base| {
776 const arg = try std.fmt.allocPrint(arena, "--global-base={d}", .{global_base});
777 try argv.append(arg);
778 }
779
757780 if (self.base.options.output_mode == .Exe) {
758781 // Increase the default stack size to a more reasonable value of 1MB instead of
759782 // the default of 1 Wasm page being 64KB, unless overridden by the user.
src/main.zig+35-1
......@@ -332,7 +332,7 @@ const usage_build_generic =
332332 \\ -mno-red-zone Force-disable the "red-zone"
333333 \\ -fomit-frame-pointer Omit the stack frame pointer
334334 \\ -fno-omit-frame-pointer Store the stack frame pointer
335 \\ -mexec-model=[value] Execution model (WASI only)
335 \\ -mexec-model=[value] (WASI) Execution model
336336 \\ --name [name] Override root name (not a file path)
337337 \\ -O [mode] Choose what to optimize for
338338 \\ Debug (default) Optimizations off, safety on
......@@ -424,6 +424,10 @@ const usage_build_generic =
424424 \\ --image-base [addr] Set base address for executable image
425425 \\ -framework [name] (Darwin) link against framework
426426 \\ -F[dir] (Darwin) add search path for frameworks
427 \\ --import-memory (WebAssembly) import memory from the environment
428 \\ --initial-memory=[bytes] (WebAssembly) initial size of the linear memory
429 \\ --max-memory=[bytes] (WebAssembly) maximum size of the linear memory
430 \\ --global-base=[addr] (WebAssembly) where to start to place global data
427431 \\
428432 \\Test Options:
429433 \\ --test-filter [text] Skip tests that do not match filter
......@@ -609,6 +613,10 @@ fn buildOutputType(
609613 var linker_gc_sections: ?bool = null;
610614 var linker_allow_shlib_undefined: ?bool = null;
611615 var linker_bind_global_refs_locally: ?bool = null;
616 var linker_import_memory: ?bool = null;
617 var linker_initial_memory: ?u64 = null;
618 var linker_max_memory: ?u64 = null;
619 var linker_global_base: ?u64 = null;
612620 var linker_z_nodelete = false;
613621 var linker_z_notext = false;
614622 var linker_z_defs = false;
......@@ -1125,6 +1133,14 @@ fn buildOutputType(
11251133 } else {
11261134 warn("unsupported linker extension flag: -z {s}", .{z_arg});
11271135 }
1136 } else if (mem.eql(u8, arg, "--import-memory")) {
1137 linker_import_memory = true;
1138 } else if (mem.startsWith(u8, arg, "--initial-memory=")) {
1139 linker_initial_memory = parseIntSuffix(arg, "--initial-memory=".len);
1140 } else if (mem.startsWith(u8, arg, "--max-memory=")) {
1141 linker_max_memory = parseIntSuffix(arg, "--max-memory=".len);
1142 } else if (mem.startsWith(u8, arg, "--global-base=")) {
1143 linker_global_base = parseIntSuffix(arg, "--global-base=".len);
11281144 } else if (mem.eql(u8, arg, "-Bsymbolic")) {
11291145 linker_bind_global_refs_locally = true;
11301146 } else if (mem.eql(u8, arg, "--debug-compile-errors")) {
......@@ -1453,6 +1469,14 @@ fn buildOutputType(
14531469 linker_allow_shlib_undefined = false;
14541470 } else if (mem.eql(u8, arg, "-Bsymbolic")) {
14551471 linker_bind_global_refs_locally = true;
1472 } else if (mem.eql(u8, arg, "--import-memory")) {
1473 linker_import_memory = true;
1474 } else if (mem.startsWith(u8, arg, "--initial-memory=")) {
1475 linker_initial_memory = parseIntSuffix(arg, "--initial-memory=".len);
1476 } else if (mem.startsWith(u8, arg, "--max-memory=")) {
1477 linker_max_memory = parseIntSuffix(arg, "--max-memory=".len);
1478 } else if (mem.startsWith(u8, arg, "--global-base=")) {
1479 linker_global_base = parseIntSuffix(arg, "--global-base=".len);
14561480 } else if (mem.eql(u8, arg, "-z")) {
14571481 i += 1;
14581482 if (i >= linker_args.items.len) {
......@@ -2148,6 +2172,10 @@ fn buildOutputType(
21482172 .linker_gc_sections = linker_gc_sections,
21492173 .linker_allow_shlib_undefined = linker_allow_shlib_undefined,
21502174 .linker_bind_global_refs_locally = linker_bind_global_refs_locally,
2175 .linker_import_memory = linker_import_memory,
2176 .linker_initial_memory = linker_initial_memory,
2177 .linker_max_memory = linker_max_memory,
2178 .linker_global_base = linker_global_base,
21512179 .linker_z_nodelete = linker_z_nodelete,
21522180 .linker_z_notext = linker_z_notext,
21532181 .linker_z_defs = linker_z_defs,
......@@ -4371,3 +4399,9 @@ pub fn cmdChangelist(
43714399 }
43724400 try bw.flush();
43734401}
4402
4403fn parseIntSuffix(arg: []const u8, prefix_len: usize) u64 {
4404 return std.fmt.parseUnsigned(u64, arg[prefix_len..], 0) catch |err| {
4405 fatal("unable to parse '{s}': {s}", .{ arg, @errorName(err) });
4406 };
4407}