| author | |
| committer | |
| log | 4cb2f11693b1bf13770b8ad6a8b8a1e37101a516 |
| tree | 5c874f02332d2cefabc66fd5d5d6d6e505ea6599 |
| parent | e15a267668bae168f2bba06cc3706c54bc062522 |
This implements the flags for both the linker frontend as well as the self-hosted linker.
Closes #57905 files changed, 76 insertions(+), 6 deletions(-)
lib/std/build.zig+8| ... | @@ -1479,6 +1479,8 @@ pub const LibExeObjStep = struct { | ... | @@ -1479,6 +1479,8 @@ pub const LibExeObjStep = struct { |
| 1479 | sanitize_thread: bool, | 1479 | sanitize_thread: bool, |
| 1480 | rdynamic: bool, | 1480 | rdynamic: bool, |
| 1481 | import_memory: bool = false, | 1481 | import_memory: bool = false, |
| 1482 | import_table: bool = false, | ||
| 1483 | export_table: bool = false, | ||
| 1482 | initial_memory: ?u64 = null, | 1484 | initial_memory: ?u64 = null, |
| 1483 | max_memory: ?u64 = null, | 1485 | max_memory: ?u64 = null, |
| 1484 | global_base: ?u64 = null, | 1486 | global_base: ?u64 = null, |
| ... | @@ -2509,6 +2511,12 @@ pub const LibExeObjStep = struct { | ... | @@ -2509,6 +2511,12 @@ pub const LibExeObjStep = struct { |
| 2509 | if (self.import_memory) { | 2511 | if (self.import_memory) { |
| 2510 | try zig_args.append("--import-memory"); | 2512 | try zig_args.append("--import-memory"); |
| 2511 | } | 2513 | } |
| 2514 | if (self.import_table) { | ||
| 2515 | try zig_args.append("--import-table"); | ||
| 2516 | } | ||
| 2517 | if (self.export_table) { | ||
| 2518 | try zig_args.append("--export-table"); | ||
| 2519 | } | ||
| 2512 | if (self.initial_memory) |initial_memory| { | 2520 | if (self.initial_memory) |initial_memory| { |
| 2513 | try zig_args.append(builder.fmt("--initial-memory={d}", .{initial_memory})); | 2521 | try zig_args.append(builder.fmt("--initial-memory={d}", .{initial_memory})); |
| 2514 | } | 2522 | } |
src/Compilation.zig+4| ... | @@ -724,6 +724,8 @@ pub const InitOptions = struct { | ... | @@ -724,6 +724,8 @@ pub const InitOptions = struct { |
| 724 | linker_allow_shlib_undefined: ?bool = null, | 724 | linker_allow_shlib_undefined: ?bool = null, |
| 725 | linker_bind_global_refs_locally: ?bool = null, | 725 | linker_bind_global_refs_locally: ?bool = null, |
| 726 | linker_import_memory: ?bool = null, | 726 | linker_import_memory: ?bool = null, |
| 727 | linker_import_table: bool = false, | ||
| 728 | linker_export_table: bool = false, | ||
| 727 | linker_initial_memory: ?u64 = null, | 729 | linker_initial_memory: ?u64 = null, |
| 728 | linker_max_memory: ?u64 = null, | 730 | linker_max_memory: ?u64 = null, |
| 729 | linker_global_base: ?u64 = null, | 731 | linker_global_base: ?u64 = null, |
| ... | @@ -1457,6 +1459,8 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { | ... | @@ -1457,6 +1459,8 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { |
| 1457 | .allow_shlib_undefined = options.linker_allow_shlib_undefined, | 1459 | .allow_shlib_undefined = options.linker_allow_shlib_undefined, |
| 1458 | .bind_global_refs_locally = options.linker_bind_global_refs_locally orelse false, | 1460 | .bind_global_refs_locally = options.linker_bind_global_refs_locally orelse false, |
| 1459 | .import_memory = options.linker_import_memory orelse false, | 1461 | .import_memory = options.linker_import_memory orelse false, |
| 1462 | .import_table = options.linker_import_table, | ||
| 1463 | .export_table = options.linker_export_table, | ||
| 1460 | .initial_memory = options.linker_initial_memory, | 1464 | .initial_memory = options.linker_initial_memory, |
| 1461 | .max_memory = options.linker_max_memory, | 1465 | .max_memory = options.linker_max_memory, |
| 1462 | .global_base = options.linker_global_base, | 1466 | .global_base = options.linker_global_base, |
src/link.zig+2| ... | @@ -102,6 +102,8 @@ pub const Options = struct { | ... | @@ -102,6 +102,8 @@ pub const Options = struct { |
| 102 | linker_optimization: u8, | 102 | linker_optimization: u8, |
| 103 | bind_global_refs_locally: bool, | 103 | bind_global_refs_locally: bool, |
| 104 | import_memory: bool, | 104 | import_memory: bool, |
| 105 | import_table: bool, | ||
| 106 | export_table: bool, | ||
| 105 | initial_memory: ?u64, | 107 | initial_memory: ?u64, |
| 106 | max_memory: ?u64, | 108 | max_memory: ?u64, |
| 107 | export_symbol_names: []const []const u8, | 109 | export_symbol_names: []const []const u8, |
src/link/Wasm.zig+48-6| ... | @@ -635,11 +635,30 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { | ... | @@ -635,11 +635,30 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { |
| 635 | } | 635 | } |
| 636 | 636 | ||
| 637 | // Import section | 637 | // Import section |
| 638 | const import_mem = self.base.options.import_memory; | 638 | const import_memory = self.base.options.import_memory; |
| 639 | if (self.imports.count() != 0 or import_mem) { | 639 | const import_table = self.base.options.import_table; |
| 640 | if (self.imports.count() != 0 or import_memory or import_table) { | ||
| 640 | const header_offset = try reserveVecSectionHeader(file); | 641 | const header_offset = try reserveVecSectionHeader(file); |
| 641 | const writer = file.writer(); | 642 | const writer = file.writer(); |
| 642 | 643 | ||
| 644 | // import table is always first table so emit that first | ||
| 645 | if (import_table) { | ||
| 646 | const table_imp: wasm.Import = .{ | ||
| 647 | .module_name = self.host_name, | ||
| 648 | .name = "__indirect_function_table", | ||
| 649 | .kind = .{ | ||
| 650 | .table = .{ | ||
| 651 | .limits = .{ | ||
| 652 | .min = @intCast(u32, self.imports.count()), | ||
| 653 | .max = null, | ||
| 654 | }, | ||
| 655 | .reftype = .funcref, | ||
| 656 | }, | ||
| 657 | }, | ||
| 658 | }; | ||
| 659 | try emitImport(writer, table_imp); | ||
| 660 | } | ||
| 661 | |||
| 643 | var it = self.imports.iterator(); | 662 | var it = self.imports.iterator(); |
| 644 | while (it.next()) |entry| { | 663 | while (it.next()) |entry| { |
| 645 | const import_symbol = self.symbols.items[entry.key_ptr.*]; | 664 | const import_symbol = self.symbols.items[entry.key_ptr.*]; |
| ... | @@ -648,7 +667,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { | ... | @@ -648,7 +667,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { |
| 648 | try emitImport(writer, import); | 667 | try emitImport(writer, import); |
| 649 | } | 668 | } |
| 650 | 669 | ||
| 651 | if (import_mem) { | 670 | if (import_memory) { |
| 652 | const mem_imp: wasm.Import = .{ | 671 | const mem_imp: wasm.Import = .{ |
| 653 | .module_name = self.host_name, | 672 | .module_name = self.host_name, |
| 654 | .name = "memory", | 673 | .name = "memory", |
| ... | @@ -662,7 +681,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { | ... | @@ -662,7 +681,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { |
| 662 | header_offset, | 681 | header_offset, |
| 663 | .import, | 682 | .import, |
| 664 | @intCast(u32, (try file.getPos()) - header_offset - header_size), | 683 | @intCast(u32, (try file.getPos()) - header_offset - header_size), |
| 665 | @intCast(u32, self.imports.count() + @boolToInt(import_mem)), | 684 | @intCast(u32, self.imports.count() + @boolToInt(import_memory)), |
| 666 | ); | 685 | ); |
| 667 | } | 686 | } |
| 668 | 687 | ||
| ... | @@ -684,7 +703,8 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { | ... | @@ -684,7 +703,8 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { |
| 684 | } | 703 | } |
| 685 | 704 | ||
| 686 | // Table section | 705 | // Table section |
| 687 | if (self.function_table.count() > 0) { | 706 | const export_table = self.base.options.export_table; |
| 707 | if (!import_table and (self.function_table.count() > 0 or export_table)) { | ||
| 688 | const header_offset = try reserveVecSectionHeader(file); | 708 | const header_offset = try reserveVecSectionHeader(file); |
| 689 | const writer = file.writer(); | 709 | const writer = file.writer(); |
| 690 | 710 | ||
| ... | @@ -767,7 +787,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { | ... | @@ -767,7 +787,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { |
| 767 | } | 787 | } |
| 768 | 788 | ||
| 769 | // export memory if size is not 0 | 789 | // export memory if size is not 0 |
| 770 | if (!self.base.options.import_memory) { | 790 | if (!import_memory) { |
| 771 | try leb.writeULEB128(writer, @intCast(u32, "memory".len)); | 791 | try leb.writeULEB128(writer, @intCast(u32, "memory".len)); |
| 772 | try writer.writeAll("memory"); | 792 | try writer.writeAll("memory"); |
| 773 | try writer.writeByte(wasm.externalKind(.memory)); | 793 | try writer.writeByte(wasm.externalKind(.memory)); |
| ... | @@ -775,6 +795,14 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { | ... | @@ -775,6 +795,14 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { |
| 775 | count += 1; | 795 | count += 1; |
| 776 | } | 796 | } |
| 777 | 797 | ||
| 798 | if (export_table) { | ||
| 799 | try leb.writeULEB128(writer, @intCast(u32, "__indirect_function_table".len)); | ||
| 800 | try writer.writeAll("__indirect_function_table"); | ||
| 801 | try writer.writeByte(wasm.externalKind(.table)); | ||
| 802 | try leb.writeULEB128(writer, @as(u32, 0)); // function table is always the first table | ||
| 803 | count += 1; | ||
| 804 | } | ||
| 805 | |||
| 778 | try writeVecSectionHeader( | 806 | try writeVecSectionHeader( |
| 779 | file, | 807 | file, |
| 780 | header_offset, | 808 | header_offset, |
| ... | @@ -1008,6 +1036,8 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void { | ... | @@ -1008,6 +1036,8 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void { |
| 1008 | try man.addOptionalFile(compiler_rt_path); | 1036 | try man.addOptionalFile(compiler_rt_path); |
| 1009 | man.hash.addOptional(self.base.options.stack_size_override); | 1037 | man.hash.addOptional(self.base.options.stack_size_override); |
| 1010 | man.hash.add(self.base.options.import_memory); | 1038 | man.hash.add(self.base.options.import_memory); |
| 1039 | man.hash.add(self.base.options.import_table); | ||
| 1040 | man.hash.add(self.base.options.export_table); | ||
| 1011 | man.hash.addOptional(self.base.options.initial_memory); | 1041 | man.hash.addOptional(self.base.options.initial_memory); |
| 1012 | man.hash.addOptional(self.base.options.max_memory); | 1042 | man.hash.addOptional(self.base.options.max_memory); |
| 1013 | man.hash.addOptional(self.base.options.global_base); | 1043 | man.hash.addOptional(self.base.options.global_base); |
| ... | @@ -1092,6 +1122,18 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void { | ... | @@ -1092,6 +1122,18 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void { |
| 1092 | try argv.append("--import-memory"); | 1122 | try argv.append("--import-memory"); |
| 1093 | } | 1123 | } |
| 1094 | 1124 | ||
| 1125 | if (self.base.options.import_table) { | ||
| 1126 | if (self.base.options.export_table) { | ||
| 1127 | log.err("--import-table and --export-table may not be used together", .{}); | ||
| 1128 | return error.InvalidArgs; | ||
| 1129 | } | ||
| 1130 | try argv.append("--import-table"); | ||
| 1131 | } | ||
| 1132 | |||
| 1133 | if (self.base.options.export_table) { | ||
| 1134 | try argv.append("--export-table"); | ||
| 1135 | } | ||
| 1136 | |||
| 1095 | if (self.base.options.initial_memory) |initial_memory| { | 1137 | if (self.base.options.initial_memory) |initial_memory| { |
| 1096 | const arg = try std.fmt.allocPrint(arena, "--initial-memory={d}", .{initial_memory}); | 1138 | const arg = try std.fmt.allocPrint(arena, "--initial-memory={d}", .{initial_memory}); |
| 1097 | try argv.append(arg); | 1139 | try argv.append(arg); |
src/main.zig+14| ... | @@ -432,6 +432,8 @@ const usage_build_generic = | ... | @@ -432,6 +432,8 @@ const usage_build_generic = |
| 432 | \\ -F[dir] (Darwin) add search path for frameworks | 432 | \\ -F[dir] (Darwin) add search path for frameworks |
| 433 | \\ -install_name=[value] (Darwin) add dylib's install name | 433 | \\ -install_name=[value] (Darwin) add dylib's install name |
| 434 | \\ --import-memory (WebAssembly) import memory from the environment | 434 | \\ --import-memory (WebAssembly) import memory from the environment |
| 435 | \\ --import-table (WebAssembly) import function table from the host environment | ||
| 436 | \\ --export-table (WebAssembly) export function table to the host environment | ||
| 435 | \\ --initial-memory=[bytes] (WebAssembly) initial size of the linear memory | 437 | \\ --initial-memory=[bytes] (WebAssembly) initial size of the linear memory |
| 436 | \\ --max-memory=[bytes] (WebAssembly) maximum size of the linear memory | 438 | \\ --max-memory=[bytes] (WebAssembly) maximum size of the linear memory |
| 437 | \\ --global-base=[addr] (WebAssembly) where to start to place global data | 439 | \\ --global-base=[addr] (WebAssembly) where to start to place global data |
| ... | @@ -627,6 +629,8 @@ fn buildOutputType( | ... | @@ -627,6 +629,8 @@ fn buildOutputType( |
| 627 | var linker_allow_shlib_undefined: ?bool = null; | 629 | var linker_allow_shlib_undefined: ?bool = null; |
| 628 | var linker_bind_global_refs_locally: ?bool = null; | 630 | var linker_bind_global_refs_locally: ?bool = null; |
| 629 | var linker_import_memory: ?bool = null; | 631 | var linker_import_memory: ?bool = null; |
| 632 | var linker_import_table: bool = false; | ||
| 633 | var linker_export_table: bool = false; | ||
| 630 | var linker_initial_memory: ?u64 = null; | 634 | var linker_initial_memory: ?u64 = null; |
| 631 | var linker_max_memory: ?u64 = null; | 635 | var linker_max_memory: ?u64 = null; |
| 632 | var linker_global_base: ?u64 = null; | 636 | var linker_global_base: ?u64 = null; |
| ... | @@ -1179,6 +1183,10 @@ fn buildOutputType( | ... | @@ -1179,6 +1183,10 @@ fn buildOutputType( |
| 1179 | } | 1183 | } |
| 1180 | } else if (mem.eql(u8, arg, "--import-memory")) { | 1184 | } else if (mem.eql(u8, arg, "--import-memory")) { |
| 1181 | linker_import_memory = true; | 1185 | linker_import_memory = true; |
| 1186 | } else if (mem.eql(u8, arg, "--import-table")) { | ||
| 1187 | linker_import_table = true; | ||
| 1188 | } else if (mem.eql(u8, arg, "--export-table")) { | ||
| 1189 | linker_export_table = true; | ||
| 1182 | } else if (mem.startsWith(u8, arg, "--initial-memory=")) { | 1190 | } else if (mem.startsWith(u8, arg, "--initial-memory=")) { |
| 1183 | linker_initial_memory = parseIntSuffix(arg, "--initial-memory=".len); | 1191 | linker_initial_memory = parseIntSuffix(arg, "--initial-memory=".len); |
| 1184 | } else if (mem.startsWith(u8, arg, "--max-memory=")) { | 1192 | } else if (mem.startsWith(u8, arg, "--max-memory=")) { |
| ... | @@ -1560,6 +1568,10 @@ fn buildOutputType( | ... | @@ -1560,6 +1568,10 @@ fn buildOutputType( |
| 1560 | linker_bind_global_refs_locally = true; | 1568 | linker_bind_global_refs_locally = true; |
| 1561 | } else if (mem.eql(u8, arg, "--import-memory")) { | 1569 | } else if (mem.eql(u8, arg, "--import-memory")) { |
| 1562 | linker_import_memory = true; | 1570 | linker_import_memory = true; |
| 1571 | } else if (mem.eql(u8, arg, "--import-table")) { | ||
| 1572 | linker_import_table = true; | ||
| 1573 | } else if (mem.eql(u8, arg, "--export-table")) { | ||
| 1574 | linker_export_table = true; | ||
| 1563 | } else if (mem.startsWith(u8, arg, "--initial-memory=")) { | 1575 | } else if (mem.startsWith(u8, arg, "--initial-memory=")) { |
| 1564 | linker_initial_memory = parseIntSuffix(arg, "--initial-memory=".len); | 1576 | linker_initial_memory = parseIntSuffix(arg, "--initial-memory=".len); |
| 1565 | } else if (mem.startsWith(u8, arg, "--max-memory=")) { | 1577 | } else if (mem.startsWith(u8, arg, "--max-memory=")) { |
| ... | @@ -2455,6 +2467,8 @@ fn buildOutputType( | ... | @@ -2455,6 +2467,8 @@ fn buildOutputType( |
| 2455 | .linker_allow_shlib_undefined = linker_allow_shlib_undefined, | 2467 | .linker_allow_shlib_undefined = linker_allow_shlib_undefined, |
| 2456 | .linker_bind_global_refs_locally = linker_bind_global_refs_locally, | 2468 | .linker_bind_global_refs_locally = linker_bind_global_refs_locally, |
| 2457 | .linker_import_memory = linker_import_memory, | 2469 | .linker_import_memory = linker_import_memory, |
| 2470 | .linker_import_table = linker_import_table, | ||
| 2471 | .linker_export_table = linker_export_table, | ||
| 2458 | .linker_initial_memory = linker_initial_memory, | 2472 | .linker_initial_memory = linker_initial_memory, |
| 2459 | .linker_max_memory = linker_max_memory, | 2473 | .linker_max_memory = linker_max_memory, |
| 2460 | .linker_global_base = linker_global_base, | 2474 | .linker_global_base = linker_global_base, |