| 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 | 1479 | sanitize_thread: bool, |
| 1480 | 1480 | rdynamic: bool, |
| 1481 | 1481 | import_memory: bool = false, |
| 1482 | import_table: bool = false, | |
| 1483 | export_table: bool = false, | |
| 1482 | 1484 | initial_memory: ?u64 = null, |
| 1483 | 1485 | max_memory: ?u64 = null, |
| 1484 | 1486 | global_base: ?u64 = null, |
| ... | ... | @@ -2509,6 +2511,12 @@ pub const LibExeObjStep = struct { |
| 2509 | 2511 | if (self.import_memory) { |
| 2510 | 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 | 2520 | if (self.initial_memory) |initial_memory| { |
| 2513 | 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 | 724 | linker_allow_shlib_undefined: ?bool = null, |
| 725 | 725 | linker_bind_global_refs_locally: ?bool = null, |
| 726 | 726 | linker_import_memory: ?bool = null, |
| 727 | linker_import_table: bool = false, | |
| 728 | linker_export_table: bool = false, | |
| 727 | 729 | linker_initial_memory: ?u64 = null, |
| 728 | 730 | linker_max_memory: ?u64 = null, |
| 729 | 731 | linker_global_base: ?u64 = null, |
| ... | ... | @@ -1457,6 +1459,8 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { |
| 1457 | 1459 | .allow_shlib_undefined = options.linker_allow_shlib_undefined, |
| 1458 | 1460 | .bind_global_refs_locally = options.linker_bind_global_refs_locally orelse false, |
| 1459 | 1461 | .import_memory = options.linker_import_memory orelse false, |
| 1462 | .import_table = options.linker_import_table, | |
| 1463 | .export_table = options.linker_export_table, | |
| 1460 | 1464 | .initial_memory = options.linker_initial_memory, |
| 1461 | 1465 | .max_memory = options.linker_max_memory, |
| 1462 | 1466 | .global_base = options.linker_global_base, |
src/link.zig+2| ... | ... | @@ -102,6 +102,8 @@ pub const Options = struct { |
| 102 | 102 | linker_optimization: u8, |
| 103 | 103 | bind_global_refs_locally: bool, |
| 104 | 104 | import_memory: bool, |
| 105 | import_table: bool, | |
| 106 | export_table: bool, | |
| 105 | 107 | initial_memory: ?u64, |
| 106 | 108 | max_memory: ?u64, |
| 107 | 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 | 635 | } |
| 636 | 636 | |
| 637 | 637 | // Import section |
| 638 | const import_mem = self.base.options.import_memory; | |
| 639 | if (self.imports.count() != 0 or import_mem) { | |
| 638 | const import_memory = self.base.options.import_memory; | |
| 639 | const import_table = self.base.options.import_table; | |
| 640 | if (self.imports.count() != 0 or import_memory or import_table) { | |
| 640 | 641 | const header_offset = try reserveVecSectionHeader(file); |
| 641 | 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 | 662 | var it = self.imports.iterator(); |
| 644 | 663 | while (it.next()) |entry| { |
| 645 | 664 | const import_symbol = self.symbols.items[entry.key_ptr.*]; |
| ... | ... | @@ -648,7 +667,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { |
| 648 | 667 | try emitImport(writer, import); |
| 649 | 668 | } |
| 650 | 669 | |
| 651 | if (import_mem) { | |
| 670 | if (import_memory) { | |
| 652 | 671 | const mem_imp: wasm.Import = .{ |
| 653 | 672 | .module_name = self.host_name, |
| 654 | 673 | .name = "memory", |
| ... | ... | @@ -662,7 +681,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { |
| 662 | 681 | header_offset, |
| 663 | 682 | .import, |
| 664 | 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 | 703 | } |
| 685 | 704 | |
| 686 | 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 | 708 | const header_offset = try reserveVecSectionHeader(file); |
| 689 | 709 | const writer = file.writer(); |
| 690 | 710 | |
| ... | ... | @@ -767,7 +787,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { |
| 767 | 787 | } |
| 768 | 788 | |
| 769 | 789 | // export memory if size is not 0 |
| 770 | if (!self.base.options.import_memory) { | |
| 790 | if (!import_memory) { | |
| 771 | 791 | try leb.writeULEB128(writer, @intCast(u32, "memory".len)); |
| 772 | 792 | try writer.writeAll("memory"); |
| 773 | 793 | try writer.writeByte(wasm.externalKind(.memory)); |
| ... | ... | @@ -775,6 +795,14 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { |
| 775 | 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 | 806 | try writeVecSectionHeader( |
| 779 | 807 | file, |
| 780 | 808 | header_offset, |
| ... | ... | @@ -1008,6 +1036,8 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void { |
| 1008 | 1036 | try man.addOptionalFile(compiler_rt_path); |
| 1009 | 1037 | man.hash.addOptional(self.base.options.stack_size_override); |
| 1010 | 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 | 1041 | man.hash.addOptional(self.base.options.initial_memory); |
| 1012 | 1042 | man.hash.addOptional(self.base.options.max_memory); |
| 1013 | 1043 | man.hash.addOptional(self.base.options.global_base); |
| ... | ... | @@ -1092,6 +1122,18 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void { |
| 1092 | 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 | 1137 | if (self.base.options.initial_memory) |initial_memory| { |
| 1096 | 1138 | const arg = try std.fmt.allocPrint(arena, "--initial-memory={d}", .{initial_memory}); |
| 1097 | 1139 | try argv.append(arg); |
src/main.zig+14| ... | ... | @@ -432,6 +432,8 @@ const usage_build_generic = |
| 432 | 432 | \\ -F[dir] (Darwin) add search path for frameworks |
| 433 | 433 | \\ -install_name=[value] (Darwin) add dylib's install name |
| 434 | 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 | 437 | \\ --initial-memory=[bytes] (WebAssembly) initial size of the linear memory |
| 436 | 438 | \\ --max-memory=[bytes] (WebAssembly) maximum size of the linear memory |
| 437 | 439 | \\ --global-base=[addr] (WebAssembly) where to start to place global data |
| ... | ... | @@ -627,6 +629,8 @@ fn buildOutputType( |
| 627 | 629 | var linker_allow_shlib_undefined: ?bool = null; |
| 628 | 630 | var linker_bind_global_refs_locally: ?bool = null; |
| 629 | 631 | var linker_import_memory: ?bool = null; |
| 632 | var linker_import_table: bool = false; | |
| 633 | var linker_export_table: bool = false; | |
| 630 | 634 | var linker_initial_memory: ?u64 = null; |
| 631 | 635 | var linker_max_memory: ?u64 = null; |
| 632 | 636 | var linker_global_base: ?u64 = null; |
| ... | ... | @@ -1179,6 +1183,10 @@ fn buildOutputType( |
| 1179 | 1183 | } |
| 1180 | 1184 | } else if (mem.eql(u8, arg, "--import-memory")) { |
| 1181 | 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 | 1190 | } else if (mem.startsWith(u8, arg, "--initial-memory=")) { |
| 1183 | 1191 | linker_initial_memory = parseIntSuffix(arg, "--initial-memory=".len); |
| 1184 | 1192 | } else if (mem.startsWith(u8, arg, "--max-memory=")) { |
| ... | ... | @@ -1560,6 +1568,10 @@ fn buildOutputType( |
| 1560 | 1568 | linker_bind_global_refs_locally = true; |
| 1561 | 1569 | } else if (mem.eql(u8, arg, "--import-memory")) { |
| 1562 | 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 | 1575 | } else if (mem.startsWith(u8, arg, "--initial-memory=")) { |
| 1564 | 1576 | linker_initial_memory = parseIntSuffix(arg, "--initial-memory=".len); |
| 1565 | 1577 | } else if (mem.startsWith(u8, arg, "--max-memory=")) { |
| ... | ... | @@ -2455,6 +2467,8 @@ fn buildOutputType( |
| 2455 | 2467 | .linker_allow_shlib_undefined = linker_allow_shlib_undefined, |
| 2456 | 2468 | .linker_bind_global_refs_locally = linker_bind_global_refs_locally, |
| 2457 | 2469 | .linker_import_memory = linker_import_memory, |
| 2470 | .linker_import_table = linker_import_table, | |
| 2471 | .linker_export_table = linker_export_table, | |
| 2458 | 2472 | .linker_initial_memory = linker_initial_memory, |
| 2459 | 2473 | .linker_max_memory = linker_max_memory, |
| 2460 | 2474 | .linker_global_base = linker_global_base, |