mirror of
https://github.com/ziglang/zig.git
synced 2026-02-12 20:37:54 +00:00
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
This commit is contained in:
parent
e15a267668
commit
4cb2f11693
@ -1479,6 +1479,8 @@ pub const LibExeObjStep = struct {
|
||||
sanitize_thread: bool,
|
||||
rdynamic: bool,
|
||||
import_memory: bool = false,
|
||||
import_table: bool = false,
|
||||
export_table: bool = false,
|
||||
initial_memory: ?u64 = null,
|
||||
max_memory: ?u64 = null,
|
||||
global_base: ?u64 = null,
|
||||
@ -2509,6 +2511,12 @@ pub const LibExeObjStep = struct {
|
||||
if (self.import_memory) {
|
||||
try zig_args.append("--import-memory");
|
||||
}
|
||||
if (self.import_table) {
|
||||
try zig_args.append("--import-table");
|
||||
}
|
||||
if (self.export_table) {
|
||||
try zig_args.append("--export-table");
|
||||
}
|
||||
if (self.initial_memory) |initial_memory| {
|
||||
try zig_args.append(builder.fmt("--initial-memory={d}", .{initial_memory}));
|
||||
}
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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);
|
||||
|
||||
14
src/main.zig
14
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,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user