diff options
| author | Luuk de Gram <luuk@degram.dev> | 2021-12-21 20:10:36 +0100 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2021-12-21 12:38:50 -0800 |
| commit | 4cb2f11693b1bf13770b8ad6a8b8a1e37101a516 (patch) | |
| tree | 5c874f02332d2cefabc66fd5d5d6d6e505ea6599 /src | |
| parent | e15a267668bae168f2bba06cc3706c54bc062522 (diff) | |
| download | zig-4cb2f11693b1bf13770b8ad6a8b8a1e37101a516.tar.gz zig-4cb2f11693b1bf13770b8ad6a8b8a1e37101a516.zip | |
wasm-linker: Implement the --export-table and --import-table flags.
This implements the flags for both the linker frontend as well as the self-hosted linker.
Closes #5790
Diffstat (limited to 'src')
| -rw-r--r-- | src/Compilation.zig | 4 | ||||
| -rw-r--r-- | src/link.zig | 2 | ||||
| -rw-r--r-- | src/link/Wasm.zig | 54 | ||||
| -rw-r--r-- | src/main.zig | 14 |
4 files changed, 68 insertions, 6 deletions
diff --git a/src/Compilation.zig b/src/Compilation.zig index 861771def4..9a9ac5592a 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -724,6 +724,8 @@ pub const InitOptions = struct { linker_allow_shlib_undefined: ?bool = null, linker_bind_global_refs_locally: ?bool = null, linker_import_memory: ?bool = null, + linker_import_table: bool = false, + linker_export_table: bool = false, linker_initial_memory: ?u64 = null, linker_max_memory: ?u64 = null, linker_global_base: ?u64 = null, @@ -1457,6 +1459,8 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .allow_shlib_undefined = options.linker_allow_shlib_undefined, .bind_global_refs_locally = options.linker_bind_global_refs_locally orelse false, .import_memory = options.linker_import_memory orelse false, + .import_table = options.linker_import_table, + .export_table = options.linker_export_table, .initial_memory = options.linker_initial_memory, .max_memory = options.linker_max_memory, .global_base = options.linker_global_base, diff --git a/src/link.zig b/src/link.zig index 70e360d373..464d96ddac 100644 --- a/src/link.zig +++ b/src/link.zig @@ -102,6 +102,8 @@ pub const Options = struct { linker_optimization: u8, bind_global_refs_locally: bool, import_memory: bool, + import_table: bool, + export_table: bool, initial_memory: ?u64, max_memory: ?u64, export_symbol_names: []const []const u8, diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index cde0cdf890..c305959e56 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -635,11 +635,30 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { } // Import section - const import_mem = self.base.options.import_memory; - if (self.imports.count() != 0 or import_mem) { + const import_memory = self.base.options.import_memory; + const import_table = self.base.options.import_table; + if (self.imports.count() != 0 or import_memory or import_table) { const header_offset = try reserveVecSectionHeader(file); const writer = file.writer(); + // import table is always first table so emit that first + if (import_table) { + const table_imp: wasm.Import = .{ + .module_name = self.host_name, + .name = "__indirect_function_table", + .kind = .{ + .table = .{ + .limits = .{ + .min = @intCast(u32, self.imports.count()), + .max = null, + }, + .reftype = .funcref, + }, + }, + }; + try emitImport(writer, table_imp); + } + var it = self.imports.iterator(); while (it.next()) |entry| { const import_symbol = self.symbols.items[entry.key_ptr.*]; @@ -648,7 +667,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { try emitImport(writer, import); } - if (import_mem) { + if (import_memory) { const mem_imp: wasm.Import = .{ .module_name = self.host_name, .name = "memory", @@ -662,7 +681,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { header_offset, .import, @intCast(u32, (try file.getPos()) - header_offset - header_size), - @intCast(u32, self.imports.count() + @boolToInt(import_mem)), + @intCast(u32, self.imports.count() + @boolToInt(import_memory)), ); } @@ -684,7 +703,8 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { } // Table section - if (self.function_table.count() > 0) { + const export_table = self.base.options.export_table; + if (!import_table and (self.function_table.count() > 0 or export_table)) { const header_offset = try reserveVecSectionHeader(file); const writer = file.writer(); @@ -767,7 +787,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { } // export memory if size is not 0 - if (!self.base.options.import_memory) { + if (!import_memory) { try leb.writeULEB128(writer, @intCast(u32, "memory".len)); try writer.writeAll("memory"); try writer.writeByte(wasm.externalKind(.memory)); @@ -775,6 +795,14 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { count += 1; } + if (export_table) { + try leb.writeULEB128(writer, @intCast(u32, "__indirect_function_table".len)); + try writer.writeAll("__indirect_function_table"); + try writer.writeByte(wasm.externalKind(.table)); + try leb.writeULEB128(writer, @as(u32, 0)); // function table is always the first table + count += 1; + } + try writeVecSectionHeader( file, header_offset, @@ -1008,6 +1036,8 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void { try man.addOptionalFile(compiler_rt_path); man.hash.addOptional(self.base.options.stack_size_override); man.hash.add(self.base.options.import_memory); + man.hash.add(self.base.options.import_table); + man.hash.add(self.base.options.export_table); man.hash.addOptional(self.base.options.initial_memory); man.hash.addOptional(self.base.options.max_memory); man.hash.addOptional(self.base.options.global_base); @@ -1092,6 +1122,18 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void { try argv.append("--import-memory"); } + if (self.base.options.import_table) { + if (self.base.options.export_table) { + log.err("--import-table and --export-table may not be used together", .{}); + return error.InvalidArgs; + } + try argv.append("--import-table"); + } + + if (self.base.options.export_table) { + try argv.append("--export-table"); + } + if (self.base.options.initial_memory) |initial_memory| { const arg = try std.fmt.allocPrint(arena, "--initial-memory={d}", .{initial_memory}); try argv.append(arg); diff --git a/src/main.zig b/src/main.zig index 61b4ebb7e9..effcef40d9 100644 --- a/src/main.zig +++ b/src/main.zig @@ -432,6 +432,8 @@ const usage_build_generic = \\ -F[dir] (Darwin) add search path for frameworks \\ -install_name=[value] (Darwin) add dylib's install name \\ --import-memory (WebAssembly) import memory from the environment + \\ --import-table (WebAssembly) import function table from the host environment + \\ --export-table (WebAssembly) export function table to the host environment \\ --initial-memory=[bytes] (WebAssembly) initial size of the linear memory \\ --max-memory=[bytes] (WebAssembly) maximum size of the linear memory \\ --global-base=[addr] (WebAssembly) where to start to place global data @@ -627,6 +629,8 @@ fn buildOutputType( var linker_allow_shlib_undefined: ?bool = null; var linker_bind_global_refs_locally: ?bool = null; var linker_import_memory: ?bool = null; + var linker_import_table: bool = false; + var linker_export_table: bool = false; var linker_initial_memory: ?u64 = null; var linker_max_memory: ?u64 = null; var linker_global_base: ?u64 = null; @@ -1179,6 +1183,10 @@ fn buildOutputType( } } else if (mem.eql(u8, arg, "--import-memory")) { linker_import_memory = true; + } else if (mem.eql(u8, arg, "--import-table")) { + linker_import_table = true; + } else if (mem.eql(u8, arg, "--export-table")) { + linker_export_table = true; } else if (mem.startsWith(u8, arg, "--initial-memory=")) { linker_initial_memory = parseIntSuffix(arg, "--initial-memory=".len); } else if (mem.startsWith(u8, arg, "--max-memory=")) { @@ -1560,6 +1568,10 @@ fn buildOutputType( linker_bind_global_refs_locally = true; } else if (mem.eql(u8, arg, "--import-memory")) { linker_import_memory = true; + } else if (mem.eql(u8, arg, "--import-table")) { + linker_import_table = true; + } else if (mem.eql(u8, arg, "--export-table")) { + linker_export_table = true; } else if (mem.startsWith(u8, arg, "--initial-memory=")) { linker_initial_memory = parseIntSuffix(arg, "--initial-memory=".len); } else if (mem.startsWith(u8, arg, "--max-memory=")) { @@ -2455,6 +2467,8 @@ fn buildOutputType( .linker_allow_shlib_undefined = linker_allow_shlib_undefined, .linker_bind_global_refs_locally = linker_bind_global_refs_locally, .linker_import_memory = linker_import_memory, + .linker_import_table = linker_import_table, + .linker_export_table = linker_export_table, .linker_initial_memory = linker_initial_memory, .linker_max_memory = linker_max_memory, .linker_global_base = linker_global_base, |
