| ... | ... | @@ -122,6 +122,19 @@ pub const ScratchSpace = struct { |
| 122 | 122 | func_imports: std.ArrayListUnmanaged(FunctionImport) = .empty, |
| 123 | 123 | symbol_table: std.ArrayListUnmanaged(Symbol) = .empty, |
| 124 | 124 | segment_info: std.ArrayListUnmanaged(SegmentInfo) = .empty, |
| 125 | exports: std.ArrayListUnmanaged(Export) = .empty, |
| 126 | |
| 127 | const Export = struct { |
| 128 | name: Wasm.String, |
| 129 | pointee: Pointee, |
| 130 | |
| 131 | const Pointee = union(std.wasm.ExternalKind) { |
| 132 | function: Wasm.ObjectFunctionIndex, |
| 133 | table: Wasm.ObjectTableIndex, |
| 134 | memory: Wasm.ObjectMemoryIndex, |
| 135 | global: Wasm.ObjectGlobalIndex, |
| 136 | }; |
| 137 | }; |
| 125 | 138 | |
| 126 | 139 | /// Index into `func_imports`. |
| 127 | 140 | const FuncImportIndex = enum(u32) { |
| ... | ... | @@ -142,6 +155,7 @@ pub const ScratchSpace = struct { |
| 142 | 155 | }; |
| 143 | 156 | |
| 144 | 157 | pub fn deinit(ss: *ScratchSpace, gpa: Allocator) void { |
| 158 | ss.exports.deinit(gpa); |
| 145 | 159 | ss.func_types.deinit(gpa); |
| 146 | 160 | ss.func_type_indexes.deinit(gpa); |
| 147 | 161 | ss.func_imports.deinit(gpa); |
| ... | ... | @@ -151,6 +165,7 @@ pub const ScratchSpace = struct { |
| 151 | 165 | } |
| 152 | 166 | |
| 153 | 167 | fn clear(ss: *ScratchSpace) void { |
| 168 | ss.exports.clearRetainingCapacity(); |
| 154 | 169 | ss.func_types.clearRetainingCapacity(); |
| 155 | 170 | ss.func_type_indexes.clearRetainingCapacity(); |
| 156 | 171 | ss.func_imports.clearRetainingCapacity(); |
| ... | ... | @@ -622,24 +637,22 @@ pub fn parse( |
| 622 | 637 | }, |
| 623 | 638 | .@"export" => { |
| 624 | 639 | const exports_len, pos = readLeb(u32, bytes, pos); |
| 625 | | // TODO: instead, read into scratch space, and then later |
| 626 | | // add this data as if it were extra symbol table entries, |
| 627 | | // but allow merging with existing symbol table data if the name matches. |
| 628 | | for (try wasm.object_exports.addManyAsSlice(gpa, exports_len)) |*exp| { |
| 640 | // Read into scratch space, and then later add this data as if |
| 641 | // it were extra symbol table entries, but allow merging with |
| 642 | // existing symbol table data if the name matches. |
| 643 | for (try ss.exports.addManyAsSlice(gpa, exports_len)) |*exp| { |
| 629 | 644 | const name, pos = readBytes(bytes, pos); |
| 630 | 645 | const kind: std.wasm.ExternalKind = @enumFromInt(bytes[pos]); |
| 631 | 646 | pos += 1; |
| 632 | 647 | const index, pos = readLeb(u32, bytes, pos); |
| 633 | | const rebased_index = index + switch (kind) { |
| 634 | | .function => functions_start, |
| 635 | | .table => tables_start, |
| 636 | | .memory => memories_start, |
| 637 | | .global => globals_start, |
| 638 | | }; |
| 639 | 648 | exp.* = .{ |
| 640 | 649 | .name = try wasm.internString(name), |
| 641 | | .kind = kind, |
| 642 | | .index = rebased_index, |
| 650 | .pointee = switch (kind) { |
| 651 | .function => .{ .function = @enumFromInt(functions_start + index) }, |
| 652 | .table => .{ .table = @enumFromInt(tables_start + index) }, |
| 653 | .memory => .{ .memory = @enumFromInt(memories_start + index) }, |
| 654 | .global => .{ .global = @enumFromInt(globals_start + index) }, |
| 655 | }, |
| 643 | 656 | }; |
| 644 | 657 | } |
| 645 | 658 | }, |
| ... | ... | @@ -828,6 +841,21 @@ pub fn parse( |
| 828 | 841 | }, |
| 829 | 842 | }; |
| 830 | 843 | |
| 844 | // Apply export section info. This is done after the symbol table above so |
| 845 | // that the symbol table can take precedence, overriding the export name. |
| 846 | for (ss.exports.items) |*exp| { |
| 847 | switch (exp.pointee) { |
| 848 | inline .function, .table, .memory, .global => |index| { |
| 849 | const ptr = index.ptr(wasm); |
| 850 | if (ptr.name == .none) { |
| 851 | // Missng symbol table entry; use defaults for exported things. |
| 852 | ptr.name = exp.name.toOptional(); |
| 853 | ptr.flags.exported = true; |
| 854 | } |
| 855 | }, |
| 856 | } |
| 857 | } |
| 858 | |
| 831 | 859 | // Apply segment_info. |
| 832 | 860 | for (wasm.object_data_segments.items[data_segment_start..], ss.segment_info.items) |*data, info| { |
| 833 | 861 | data.name = info.name.toOptional(); |