| author | |
| committer | |
| log | 031c84c8cb29e9b22cd5a131c147d3910c5ba345 |
| tree | bde0cd18d6f125711a320f2cdca220d2d206d62f |
| parent | b3ecdb21eedeb8be099cf1ef43ceff68592593ed |
Still, the branch is not yet passing semantic analysis.5 files changed, 546 insertions(+), 263 deletions(-)
src/arch/wasm/Emit.zig+13-13| ... | ... | @@ -89,7 +89,7 @@ pub fn lowerToCode(emit: *Emit) Error!void { |
| 89 | 89 | if (is_obj) { |
| 90 | 90 | try wasm.out_relocs.append(gpa, .{ |
| 91 | 91 | .offset = @intCast(code.items.len), |
| 92 | .index = try wasm.errorNameTableSymbolIndex(), | |
| 92 | .pointee = .{ .symbol_index = try wasm.errorNameTableSymbolIndex() }, | |
| 93 | 93 | .tag = if (is_wasm32) .MEMORY_ADDR_LEB else .MEMORY_ADDR_LEB64, |
| 94 | 94 | .addend = 0, |
| 95 | 95 | }); |
| ... | ... | @@ -143,7 +143,7 @@ pub fn lowerToCode(emit: *Emit) Error!void { |
| 143 | 143 | if (is_obj) { |
| 144 | 144 | try wasm.out_relocs.append(gpa, .{ |
| 145 | 145 | .offset = @intCast(code.items.len), |
| 146 | .index = try wasm.navSymbolIndex(datas[inst].nav_index), | |
| 146 | .pointee = .{ .symbol_index = try wasm.navSymbolIndex(datas[inst].nav_index) }, | |
| 147 | 147 | .tag = .FUNCTION_INDEX_LEB, |
| 148 | 148 | .addend = 0, |
| 149 | 149 | }); |
| ... | ... | @@ -164,7 +164,7 @@ pub fn lowerToCode(emit: *Emit) Error!void { |
| 164 | 164 | if (is_obj) { |
| 165 | 165 | try wasm.out_relocs.append(gpa, .{ |
| 166 | 166 | .offset = @intCast(code.items.len), |
| 167 | .index = func_ty_index, | |
| 167 | .pointee = .{ .type_index = func_ty_index }, | |
| 168 | 168 | .tag = .TYPE_INDEX_LEB, |
| 169 | 169 | .addend = 0, |
| 170 | 170 | }); |
| ... | ... | @@ -184,7 +184,7 @@ pub fn lowerToCode(emit: *Emit) Error!void { |
| 184 | 184 | if (is_obj) { |
| 185 | 185 | try wasm.out_relocs.append(gpa, .{ |
| 186 | 186 | .offset = @intCast(code.items.len), |
| 187 | .index = try wasm.tagNameSymbolIndex(datas[inst].ip_index), | |
| 187 | .pointee = .{ .symbol_index = try wasm.tagNameSymbolIndex(datas[inst].ip_index) }, | |
| 188 | 188 | .tag = .FUNCTION_INDEX_LEB, |
| 189 | 189 | .addend = 0, |
| 190 | 190 | }); |
| ... | ... | @@ -209,7 +209,7 @@ pub fn lowerToCode(emit: *Emit) Error!void { |
| 209 | 209 | if (is_obj) { |
| 210 | 210 | try wasm.out_relocs.append(gpa, .{ |
| 211 | 211 | .offset = @intCast(code.items.len), |
| 212 | .index = try wasm.symbolNameIndex(symbol_name), | |
| 212 | .pointee = .{ .symbol_index = try wasm.symbolNameIndex(symbol_name) }, | |
| 213 | 213 | .tag = .FUNCTION_INDEX_LEB, |
| 214 | 214 | .addend = 0, |
| 215 | 215 | }); |
| ... | ... | @@ -229,7 +229,7 @@ pub fn lowerToCode(emit: *Emit) Error!void { |
| 229 | 229 | if (is_obj) { |
| 230 | 230 | try wasm.out_relocs.append(gpa, .{ |
| 231 | 231 | .offset = @intCast(code.items.len), |
| 232 | .index = try wasm.stackPointerSymbolIndex(), | |
| 232 | .pointee = .{ .symbol_index = try wasm.stackPointerSymbolIndex() }, | |
| 233 | 233 | .tag = .GLOBAL_INDEX_LEB, |
| 234 | 234 | .addend = 0, |
| 235 | 235 | }); |
| ... | ... | @@ -249,7 +249,7 @@ pub fn lowerToCode(emit: *Emit) Error!void { |
| 249 | 249 | if (is_obj) { |
| 250 | 250 | try wasm.out_relocs.append(gpa, .{ |
| 251 | 251 | .offset = @intCast(code.items.len), |
| 252 | .index = try wasm.functionSymbolIndex(datas[inst].ip_index), | |
| 252 | .pointee = .{ .symbol_index = try wasm.functionSymbolIndex(datas[inst].ip_index) }, | |
| 253 | 253 | .tag = .TABLE_INDEX_SLEB, |
| 254 | 254 | .addend = 0, |
| 255 | 255 | }); |
| ... | ... | @@ -691,7 +691,7 @@ fn uavRefOff(wasm: *link.File.Wasm, code: *std.ArrayListUnmanaged(u8), data: Mir |
| 691 | 691 | if (is_obj) { |
| 692 | 692 | try wasm.out_relocs.append(gpa, .{ |
| 693 | 693 | .offset = @intCast(code.items.len), |
| 694 | .index = try wasm.uavSymbolIndex(data.ip_index), | |
| 694 | .pointee = .{ .symbol_index = try wasm.uavSymbolIndex(data.ip_index) }, | |
| 695 | 695 | .tag = if (is_wasm32) .MEMORY_ADDR_LEB else .MEMORY_ADDR_LEB64, |
| 696 | 696 | .addend = data.offset, |
| 697 | 697 | }); |
| ... | ... | @@ -700,7 +700,7 @@ fn uavRefOff(wasm: *link.File.Wasm, code: *std.ArrayListUnmanaged(u8), data: Mir |
| 700 | 700 | } |
| 701 | 701 | |
| 702 | 702 | // When linking into the final binary, no relocation mechanism is necessary. |
| 703 | const addr: i64 = try wasm.uavAddr(data.ip_index); | |
| 703 | const addr = try wasm.uavAddr(data.ip_index); | |
| 704 | 704 | leb.writeUleb128(code.fixedWriter(), addr + data.offset) catch unreachable; |
| 705 | 705 | } |
| 706 | 706 | |
| ... | ... | @@ -720,13 +720,13 @@ fn navRefOff(wasm: *link.File.Wasm, code: *std.ArrayListUnmanaged(u8), data: Mir |
| 720 | 720 | if (is_obj) { |
| 721 | 721 | try wasm.out_relocs.append(gpa, .{ |
| 722 | 722 | .offset = @intCast(code.items.len), |
| 723 | .index = try wasm.navSymbolIndex(data.nav_index), | |
| 723 | .pointee = .{ .symbol_index = try wasm.navSymbolIndex(data.nav_index) }, | |
| 724 | 724 | .tag = .TABLE_INDEX_SLEB, |
| 725 | 725 | .addend = data.offset, |
| 726 | 726 | }); |
| 727 | 727 | code.appendNTimesAssumeCapacity(0, 5); |
| 728 | 728 | } else { |
| 729 | const addr: i64 = try wasm.navAddr(data.nav_index); | |
| 729 | const addr = try wasm.navAddr(data.nav_index); | |
| 730 | 730 | leb.writeUleb128(code.fixedWriter(), addr + data.offset) catch unreachable; |
| 731 | 731 | } |
| 732 | 732 | } else { |
| ... | ... | @@ -735,13 +735,13 @@ fn navRefOff(wasm: *link.File.Wasm, code: *std.ArrayListUnmanaged(u8), data: Mir |
| 735 | 735 | if (is_obj) { |
| 736 | 736 | try wasm.out_relocs.append(gpa, .{ |
| 737 | 737 | .offset = @intCast(code.items.len), |
| 738 | .index = try wasm.navSymbolIndex(data.nav_index), | |
| 738 | .pointee = .{ .symbol_index = try wasm.navSymbolIndex(data.nav_index) }, | |
| 739 | 739 | .tag = if (is_wasm32) .MEMORY_ADDR_LEB else .MEMORY_ADDR_LEB64, |
| 740 | 740 | .addend = data.offset, |
| 741 | 741 | }); |
| 742 | 742 | code.appendNTimesAssumeCapacity(0, if (is_wasm32) 5 else 10); |
| 743 | 743 | } else { |
| 744 | const addr: i64 = try wasm.navAddr(data.nav_index); | |
| 744 | const addr = try wasm.navAddr(data.nav_index); | |
| 745 | 745 | leb.writeUleb128(code.fixedWriter(), addr + data.offset) catch unreachable; |
| 746 | 746 | } |
| 747 | 747 | } |
src/codegen.zig+47-27| ... | ... | @@ -2,7 +2,6 @@ const std = @import("std"); |
| 2 | 2 | const build_options = @import("build_options"); |
| 3 | 3 | const builtin = @import("builtin"); |
| 4 | 4 | const assert = std.debug.assert; |
| 5 | const leb128 = std.leb; | |
| 6 | 5 | const link = @import("link.zig"); |
| 7 | 6 | const log = std.log.scoped(.codegen); |
| 8 | 7 | const mem = std.mem; |
| ... | ... | @@ -643,15 +642,19 @@ fn lowerUavRef( |
| 643 | 642 | const zcu = pt.zcu; |
| 644 | 643 | const gpa = zcu.gpa; |
| 645 | 644 | const ip = &zcu.intern_pool; |
| 646 | const target = lf.comp.root_mod.resolved_target.result; | |
| 647 | ||
| 645 | const comp = lf.comp; | |
| 646 | const target = &comp.root_mod.resolved_target.result; | |
| 648 | 647 | const ptr_width_bytes = @divExact(target.ptrBitWidth(), 8); |
| 648 | const is_obj = comp.config.output_mode == .Obj; | |
| 649 | 649 | const uav_val = uav.val; |
| 650 | 650 | const uav_ty = Type.fromInterned(ip.typeOf(uav_val)); |
| 651 | log.debug("lowerUavRef: ty = {}", .{uav_ty.fmt(pt)}); | |
| 652 | 651 | const is_fn_body = uav_ty.zigTypeTag(zcu) == .@"fn"; |
| 652 | ||
| 653 | log.debug("lowerUavRef: ty = {}", .{uav_ty.fmt(pt)}); | |
| 654 | try code.ensureUnusedCapacity(gpa, ptr_width_bytes); | |
| 655 | ||
| 653 | 656 | if (!is_fn_body and !uav_ty.hasRuntimeBits(zcu)) { |
| 654 | try code.appendNTimes(gpa, 0xaa, ptr_width_bytes); | |
| 657 | code.appendNTimesAssumeCapacity(0xaa, ptr_width_bytes); | |
| 655 | 658 | return; |
| 656 | 659 | } |
| 657 | 660 | |
| ... | ... | @@ -663,13 +666,20 @@ fn lowerUavRef( |
| 663 | 666 | dev.check(link.File.Tag.wasm.devFeature()); |
| 664 | 667 | const wasm = lf.cast(.wasm).?; |
| 665 | 668 | assert(reloc_parent == .none); |
| 666 | try wasm.relocations.append(gpa, .{ | |
| 667 | .tag = .uav_index, | |
| 668 | .addend = @intCast(offset), | |
| 669 | .offset = @intCast(code.items.len), | |
| 670 | .pointee = .{ .uav_index = uav.val }, | |
| 671 | }); | |
| 672 | try code.appendNTimes(gpa, 0, ptr_width_bytes); | |
| 669 | if (is_obj) { | |
| 670 | try wasm.out_relocs.append(gpa, .{ | |
| 671 | .offset = @intCast(code.items.len), | |
| 672 | .pointee = .{ .symbol_index = try wasm.uavSymbolIndex(uav.val) }, | |
| 673 | .tag = if (ptr_width_bytes == 4) .MEMORY_ADDR_I32 else .MEMORY_ADDR_I64, | |
| 674 | .addend = @intCast(offset), | |
| 675 | }); | |
| 676 | } else { | |
| 677 | try wasm.uav_fixups.append(gpa, .{ | |
| 678 | .ip_index = uav.val, | |
| 679 | .offset = @intCast(code.items.len), | |
| 680 | }); | |
| 681 | } | |
| 682 | code.appendNTimesAssumeCapacity(0, ptr_width_bytes); | |
| 673 | 683 | return; |
| 674 | 684 | }, |
| 675 | 685 | else => {}, |
| ... | ... | @@ -688,9 +698,9 @@ fn lowerUavRef( |
| 688 | 698 | }); |
| 689 | 699 | const endian = target.cpu.arch.endian(); |
| 690 | 700 | switch (ptr_width_bytes) { |
| 691 | 2 => mem.writeInt(u16, try code.addManyAsArray(gpa, 2), @intCast(vaddr), endian), | |
| 692 | 4 => mem.writeInt(u32, try code.addManyAsArray(gpa, 4), @intCast(vaddr), endian), | |
| 693 | 8 => mem.writeInt(u64, try code.addManyAsArray(gpa, 8), vaddr, endian), | |
| 701 | 2 => mem.writeInt(u16, code.addManyAsArrayAssumeCapacity(2), @intCast(vaddr), endian), | |
| 702 | 4 => mem.writeInt(u32, code.addManyAsArrayAssumeCapacity(4), @intCast(vaddr), endian), | |
| 703 | 8 => mem.writeInt(u64, code.addManyAsArrayAssumeCapacity(8), vaddr, endian), | |
| 694 | 704 | else => unreachable, |
| 695 | 705 | } |
| 696 | 706 | } |
| ... | ... | @@ -709,12 +719,15 @@ fn lowerNavRef( |
| 709 | 719 | const gpa = zcu.gpa; |
| 710 | 720 | const ip = &zcu.intern_pool; |
| 711 | 721 | const target = zcu.navFileScope(nav_index).mod.resolved_target.result; |
| 712 | ||
| 713 | 722 | const ptr_width_bytes = @divExact(target.ptrBitWidth(), 8); |
| 723 | const is_obj = lf.comp.config.output_mode == .Obj; | |
| 714 | 724 | const nav_ty = Type.fromInterned(ip.getNav(nav_index).typeOf(ip)); |
| 715 | 725 | const is_fn_body = nav_ty.zigTypeTag(zcu) == .@"fn"; |
| 726 | ||
| 727 | try code.ensureUnusedCapacity(gpa, ptr_width_bytes); | |
| 728 | ||
| 716 | 729 | if (!is_fn_body and !nav_ty.hasRuntimeBits(zcu)) { |
| 717 | try code.appendNTimes(gpa, 0xaa, ptr_width_bytes); | |
| 730 | code.appendNTimesAssumeCapacity(0xaa, ptr_width_bytes); | |
| 718 | 731 | return; |
| 719 | 732 | } |
| 720 | 733 | |
| ... | ... | @@ -726,13 +739,20 @@ fn lowerNavRef( |
| 726 | 739 | dev.check(link.File.Tag.wasm.devFeature()); |
| 727 | 740 | const wasm = lf.cast(.wasm).?; |
| 728 | 741 | assert(reloc_parent == .none); |
| 729 | try wasm.relocations.append(gpa, .{ | |
| 730 | .tag = .nav_index, | |
| 731 | .addend = @intCast(offset), | |
| 732 | .offset = @intCast(code.items.len), | |
| 733 | .pointee = .{ .nav_index = nav_index }, | |
| 734 | }); | |
| 735 | try code.appendNTimes(gpa, 0, ptr_width_bytes); | |
| 742 | if (is_obj) { | |
| 743 | try wasm.out_relocs.append(gpa, .{ | |
| 744 | .offset = @intCast(code.items.len), | |
| 745 | .pointee = .{ .symbol_index = try wasm.navSymbolIndex(nav_index) }, | |
| 746 | .tag = if (ptr_width_bytes == 4) .MEMORY_ADDR_I32 else .MEMORY_ADDR_I64, | |
| 747 | .addend = @intCast(offset), | |
| 748 | }); | |
| 749 | } else { | |
| 750 | try wasm.nav_fixups.append(gpa, .{ | |
| 751 | .nav_index = nav_index, | |
| 752 | .offset = @intCast(code.items.len), | |
| 753 | }); | |
| 754 | } | |
| 755 | code.appendNTimesAssumeCapacity(0, ptr_width_bytes); | |
| 736 | 756 | return; |
| 737 | 757 | }, |
| 738 | 758 | else => {}, |
| ... | ... | @@ -745,9 +765,9 @@ fn lowerNavRef( |
| 745 | 765 | }) catch @panic("TODO rework getNavVAddr"); |
| 746 | 766 | const endian = target.cpu.arch.endian(); |
| 747 | 767 | switch (ptr_width_bytes) { |
| 748 | 2 => mem.writeInt(u16, try code.addManyAsArray(gpa, 2), @intCast(vaddr), endian), | |
| 749 | 4 => mem.writeInt(u32, try code.addManyAsArray(gpa, 4), @intCast(vaddr), endian), | |
| 750 | 8 => mem.writeInt(u64, try code.addManyAsArray(gpa, 8), vaddr, endian), | |
| 768 | 2 => mem.writeInt(u16, code.addManyAsArrayAssumeCapacity(2), @intCast(vaddr), endian), | |
| 769 | 4 => mem.writeInt(u32, code.addManyAsArrayAssumeCapacity(4), @intCast(vaddr), endian), | |
| 770 | 8 => mem.writeInt(u64, code.addManyAsArrayAssumeCapacity(8), vaddr, endian), | |
| 751 | 771 | else => unreachable, |
| 752 | 772 | } |
| 753 | 773 | } |
src/link/Wasm.zig+324-95| ... | ... | @@ -100,7 +100,7 @@ object_global_imports: std.AutoArrayHashMapUnmanaged(String, GlobalImport) = .em |
| 100 | 100 | object_globals: std.ArrayListUnmanaged(Global) = .empty, |
| 101 | 101 | |
| 102 | 102 | /// All table imports for all objects. |
| 103 | object_table_imports: std.ArrayListUnmanaged(TableImport) = .empty, | |
| 103 | object_table_imports: std.AutoArrayHashMapUnmanaged(String, TableImport) = .empty, | |
| 104 | 104 | /// All parsed table sections for all objects. |
| 105 | 105 | object_tables: std.ArrayListUnmanaged(Table) = .empty, |
| 106 | 106 | |
| ... | ... | @@ -109,12 +109,28 @@ object_memory_imports: std.ArrayListUnmanaged(MemoryImport) = .empty, |
| 109 | 109 | /// All parsed memory sections for all objects. |
| 110 | 110 | object_memories: std.ArrayListUnmanaged(std.wasm.Memory) = .empty, |
| 111 | 111 | |
| 112 | /// All relocations from all objects concatenated. `relocs_start` marks the end | |
| 113 | /// point of object relocations and start point of Zcu relocations. | |
| 114 | object_relocations: std.MultiArrayList(ObjectRelocation) = .empty, | |
| 115 | ||
| 112 | 116 | /// List of initialization functions. These must be called in order of priority |
| 113 | 117 | /// by the (synthetic) __wasm_call_ctors function. |
| 114 | 118 | object_init_funcs: std.ArrayListUnmanaged(InitFunc) = .empty, |
| 115 | /// All relocations from all objects concatenated. `relocs_start` marks the end | |
| 116 | /// point of object relocations and start point of Zcu relocations. | |
| 117 | relocations: std.MultiArrayList(Relocation) = .empty, | |
| 119 | ||
| 120 | /// Relocations to be emitted into an object file. Remains empty when not | |
| 121 | /// emitting an object file. | |
| 122 | out_relocs: std.MultiArrayList(OutReloc) = .empty, | |
| 123 | /// List of locations within `string_bytes` that must be patched with the virtual | |
| 124 | /// memory address of a Uav during `flush`. | |
| 125 | /// When emitting an object file, `out_relocs` is used instead. | |
| 126 | uav_fixups: std.ArrayListUnmanaged(UavFixup) = .empty, | |
| 127 | /// List of locations within `string_bytes` that must be patched with the virtual | |
| 128 | /// memory address of a Nav during `flush`. | |
| 129 | /// When emitting an object file, `out_relocs` is used instead. | |
| 130 | nav_fixups: std.ArrayListUnmanaged(NavFixup) = .empty, | |
| 131 | /// Symbols to be emitted into an object file. Remains empty when not emitting | |
| 132 | /// an object file. | |
| 133 | symbol_table: std.AutoArrayHashMapUnmanaged(String, void) = .empty, | |
| 118 | 134 | |
| 119 | 135 | /// Non-synthetic section that can essentially be mem-cpy'd into place after performing relocations. |
| 120 | 136 | object_data_segments: std.ArrayListUnmanaged(DataSegment) = .empty, |
| ... | ... | @@ -125,7 +141,7 @@ object_custom_segments: std.AutoArrayHashMapUnmanaged(ObjectSectionIndex, Custom |
| 125 | 141 | object_comdats: std.ArrayListUnmanaged(Comdat) = .empty, |
| 126 | 142 | /// A table that maps the relocations to be performed where the key represents |
| 127 | 143 | /// the section (across all objects) that the slice of relocations applies to. |
| 128 | object_relocations_table: std.AutoArrayHashMapUnmanaged(ObjectSectionIndex, Relocation.Slice) = .empty, | |
| 144 | object_relocations_table: std.AutoArrayHashMapUnmanaged(ObjectSectionIndex, ObjectRelocation.Slice) = .empty, | |
| 129 | 145 | /// Incremented across all objects in order to enable calculation of `ObjectSectionIndex` values. |
| 130 | 146 | object_total_sections: u32 = 0, |
| 131 | 147 | /// All comdat symbols from all objects concatenated. |
| ... | ... | @@ -151,7 +167,10 @@ dump_argv_list: std.ArrayListUnmanaged([]const u8), |
| 151 | 167 | |
| 152 | 168 | preloaded_strings: PreloadedStrings, |
| 153 | 169 | |
| 154 | navs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, Nav) = .empty, | |
| 170 | /// This field is used when emitting an object; `navs_exe` used otherwise. | |
| 171 | navs_obj: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, NavObj) = .empty, | |
| 172 | /// This field is unused when emitting an object; `navs_exe` used otherwise. | |
| 173 | navs_exe: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, NavExe) = .empty, | |
| 155 | 174 | zcu_funcs: std.AutoArrayHashMapUnmanaged(InternPool.Index, ZcuFunc) = .empty, |
| 156 | 175 | nav_exports: std.AutoArrayHashMapUnmanaged(NavExport, Zcu.Export.Index) = .empty, |
| 157 | 176 | uav_exports: std.AutoArrayHashMapUnmanaged(UavExport, Zcu.Export.Index) = .empty, |
| ... | ... | @@ -201,9 +220,14 @@ global_imports: std.AutoArrayHashMapUnmanaged(String, GlobalImportId) = .empty, |
| 201 | 220 | /// Ordered list of non-import tables that will appear in the final binary. |
| 202 | 221 | /// Empty until prelink. |
| 203 | 222 | tables: std.AutoArrayHashMapUnmanaged(TableImport.Resolution, void) = .empty, |
| 204 | table_imports: std.AutoArrayHashMapUnmanaged(String, ObjectTableImportIndex) = .empty, | |
| 223 | table_imports: std.AutoArrayHashMapUnmanaged(String, TableImport.Index) = .empty, | |
| 205 | 224 | |
| 206 | 225 | any_exports_updated: bool = true, |
| 226 | /// Set to true if any `GLOBAL_INDEX` relocation is encountered with | |
| 227 | /// `SymbolFlags.tls` set to true. This is for objects only; final | |
| 228 | /// value must be this OR'd with the same logic for zig functions | |
| 229 | /// (set to true if any threadlocal global is used). | |
| 230 | any_tls_relocs: bool = false, | |
| 207 | 231 | |
| 208 | 232 | /// All MIR instructions for all Zcu functions. |
| 209 | 233 | mir_instructions: std.MultiArrayList(Mir.Inst) = .{}, |
| ... | ... | @@ -212,6 +236,18 @@ mir_extra: std.ArrayListUnmanaged(u32) = .empty, |
| 212 | 236 | /// All local types for all Zcu functions. |
| 213 | 237 | all_zcu_locals: std.ArrayListUnmanaged(u8) = .empty, |
| 214 | 238 | |
| 239 | pub const UavFixup = extern struct { | |
| 240 | ip_index: InternPool.Index, | |
| 241 | /// Index into `string_bytes`. | |
| 242 | offset: u32, | |
| 243 | }; | |
| 244 | ||
| 245 | pub const NavFixup = extern struct { | |
| 246 | nav_index: InternPool.Nav.Index, | |
| 247 | /// Index into `string_bytes`. | |
| 248 | offset: u32, | |
| 249 | }; | |
| 250 | ||
| 215 | 251 | /// Index into `objects`. |
| 216 | 252 | pub const ObjectIndex = enum(u32) { |
| 217 | 253 | _, |
| ... | ... | @@ -300,6 +336,10 @@ pub const SourceLocation = enum(u32) { |
| 300 | 336 | }; |
| 301 | 337 | } |
| 302 | 338 | |
| 339 | pub fn fromObject(object_index: ObjectIndex, wasm: *const Wasm) SourceLocation { | |
| 340 | return pack(.{ .object_index = object_index }, wasm); | |
| 341 | } | |
| 342 | ||
| 303 | 343 | pub fn addError(sl: SourceLocation, wasm: *Wasm, comptime f: []const u8, args: anytype) void { |
| 304 | 344 | const diags = &wasm.base.comp.link_diags; |
| 305 | 345 | switch (sl.unpack(wasm)) { |
| ... | ... | @@ -345,7 +385,7 @@ pub const SymbolFlags = packed struct(u32) { |
| 345 | 385 | |
| 346 | 386 | // Above here matches the tooling conventions ABI. |
| 347 | 387 | |
| 348 | padding1: u8 = 0, | |
| 388 | padding1: u5 = 0, | |
| 349 | 389 | /// Zig-specific. Dead things are allowed to be garbage collected. |
| 350 | 390 | alive: bool = false, |
| 351 | 391 | /// Zig-specific. Segments only. Signals that the segment contains only |
| ... | ... | @@ -360,6 +400,12 @@ pub const SymbolFlags = packed struct(u32) { |
| 360 | 400 | alignment: Alignment = .none, |
| 361 | 401 | /// Zig-specific. Globals only. |
| 362 | 402 | global_type: Global.Type = .zero, |
| 403 | /// Zig-specific. Tables only. | |
| 404 | limits_has_max: bool = false, | |
| 405 | /// Zig-specific. Tables only. | |
| 406 | limits_is_shared: bool = false, | |
| 407 | /// Zig-specific. Tables only. | |
| 408 | ref_type: RefType1 = .funcref, | |
| 363 | 409 | |
| 364 | 410 | pub const Binding = enum(u2) { |
| 365 | 411 | strong = 0, |
| ... | ... | @@ -378,13 +424,16 @@ pub const SymbolFlags = packed struct(u32) { |
| 378 | 424 | }; |
| 379 | 425 | |
| 380 | 426 | pub fn initZigSpecific(flags: *SymbolFlags, must_link: bool, no_strip: bool) void { |
| 427 | flags.no_strip = no_strip; | |
| 381 | 428 | flags.alive = false; |
| 382 | 429 | flags.strings = false; |
| 383 | 430 | flags.must_link = must_link; |
| 384 | flags.no_strip = no_strip; | |
| 431 | flags.is_passive = false; | |
| 385 | 432 | flags.alignment = .none; |
| 386 | 433 | flags.global_type = .zero; |
| 387 | flags.is_passive = false; | |
| 434 | flags.limits_has_max = false; | |
| 435 | flags.limits_is_shared = false; | |
| 436 | flags.ref_type = .funcref; | |
| 388 | 437 | } |
| 389 | 438 | |
| 390 | 439 | pub fn isIncluded(flags: SymbolFlags, is_dynamic: bool) bool { |
| ... | ... | @@ -427,11 +476,28 @@ pub const SymbolFlags = packed struct(u32) { |
| 427 | 476 | } |
| 428 | 477 | }; |
| 429 | 478 | |
| 430 | pub const Nav = extern struct { | |
| 479 | pub const NavObj = extern struct { | |
| 431 | 480 | code: DataSegment.Payload, |
| 432 | relocs: Relocation.Slice, | |
| 481 | /// Empty if not emitting an object. | |
| 482 | relocs: OutReloc.Slice, | |
| 433 | 483 | |
| 434 | pub const Code = DataSegment.Payload; | |
| 484 | /// Index into `navs`. | |
| 485 | /// Note that swapRemove is sometimes performed on `navs`. | |
| 486 | pub const Index = enum(u32) { | |
| 487 | _, | |
| 488 | ||
| 489 | pub fn key(i: @This(), wasm: *const Wasm) *InternPool.Nav.Index { | |
| 490 | return &wasm.navs_obj.keys()[@intFromEnum(i)]; | |
| 491 | } | |
| 492 | ||
| 493 | pub fn value(i: @This(), wasm: *const Wasm) *NavObj { | |
| 494 | return &wasm.navs_obj.values()[@intFromEnum(i)]; | |
| 495 | } | |
| 496 | }; | |
| 497 | }; | |
| 498 | ||
| 499 | pub const NavExe = extern struct { | |
| 500 | code: DataSegment.Payload, | |
| 435 | 501 | |
| 436 | 502 | /// Index into `navs`. |
| 437 | 503 | /// Note that swapRemove is sometimes performed on `navs`. |
| ... | ... | @@ -439,11 +505,11 @@ pub const Nav = extern struct { |
| 439 | 505 | _, |
| 440 | 506 | |
| 441 | 507 | pub fn key(i: @This(), wasm: *const Wasm) *InternPool.Nav.Index { |
| 442 | return &wasm.navs.keys()[@intFromEnum(i)]; | |
| 508 | return &wasm.navs_exe.keys()[@intFromEnum(i)]; | |
| 443 | 509 | } |
| 444 | 510 | |
| 445 | pub fn value(i: @This(), wasm: *const Wasm) *Nav { | |
| 446 | return &wasm.navs.values()[@intFromEnum(i)]; | |
| 511 | pub fn value(i: @This(), wasm: *const Wasm) *NavExe { | |
| 512 | return &wasm.navs_exe.values()[@intFromEnum(i)]; | |
| 447 | 513 | } |
| 448 | 514 | }; |
| 449 | 515 | }; |
| ... | ... | @@ -506,7 +572,7 @@ pub const FunctionImport = extern struct { |
| 506 | 572 | __wasm_init_tls, |
| 507 | 573 | __zig_error_names, |
| 508 | 574 | // Next, index into `object_functions`. |
| 509 | // Next, index into `navs`. | |
| 575 | // Next, index into `navs_exe` or `navs_obj` depending on whether emitting an object. | |
| 510 | 576 | _, |
| 511 | 577 | |
| 512 | 578 | const first_object_function = @intFromEnum(Resolution.__zig_error_names) + 1; |
| ... | ... | @@ -519,7 +585,8 @@ pub const FunctionImport = extern struct { |
| 519 | 585 | __wasm_init_tls, |
| 520 | 586 | __zig_error_names, |
| 521 | 587 | object_function: ObjectFunctionIndex, |
| 522 | nav: Nav.Index, | |
| 588 | nav_exe: NavExe.Index, | |
| 589 | nav_obj: NavExe.Index, | |
| 523 | 590 | }; |
| 524 | 591 | |
| 525 | 592 | pub fn unpack(r: Resolution, wasm: *const Wasm) Unpacked { |
| ... | ... | @@ -535,8 +602,14 @@ pub const FunctionImport = extern struct { |
| 535 | 602 | const object_function_index = i - first_object_function; |
| 536 | 603 | if (object_function_index < wasm.object_functions.items.len) |
| 537 | 604 | return .{ .object_function = @enumFromInt(object_function_index) }; |
| 605 | const comp = wasm.base.comp; | |
| 606 | const is_obj = comp.config.output_mode == .Obj; | |
| 538 | 607 | const nav_index = object_function_index - wasm.object_functions.items.len; |
| 539 | return .{ .nav = @enumFromInt(nav_index) }; | |
| 608 | return if (is_obj) .{ | |
| 609 | .nav_obj = @enumFromInt(nav_index), | |
| 610 | } else .{ | |
| 611 | .nav_exe = @enumFromInt(nav_index), | |
| 612 | }; | |
| 540 | 613 | }, |
| 541 | 614 | }; |
| 542 | 615 | } |
| ... | ... | @@ -550,17 +623,24 @@ pub const FunctionImport = extern struct { |
| 550 | 623 | .__wasm_init_tls => .__wasm_init_tls, |
| 551 | 624 | .__zig_error_names => .__zig_error_names, |
| 552 | 625 | .object_function => |i| @enumFromInt(first_object_function + @intFromEnum(i)), |
| 553 | .nav => |i| @enumFromInt(first_object_function + wasm.object_functions.items.len + @intFromEnum(i)), | |
| 626 | .nav_obj => |i| @enumFromInt(first_object_function + wasm.object_functions.items.len + @intFromEnum(i)), | |
| 627 | .nav_exe => |i| @enumFromInt(first_object_function + wasm.object_functions.items.len + @intFromEnum(i)), | |
| 554 | 628 | }; |
| 555 | 629 | } |
| 556 | 630 | |
| 557 | 631 | pub fn fromIpNav(wasm: *const Wasm, ip_nav: InternPool.Nav.Index) Resolution { |
| 558 | return pack(wasm, .{ .nav = @enumFromInt(wasm.navs.getIndex(ip_nav).?) }); | |
| 632 | const comp = wasm.base.comp; | |
| 633 | const is_obj = comp.config.output_mode == .Obj; | |
| 634 | return pack(wasm, if (is_obj) .{ | |
| 635 | .nav_obj = @enumFromInt(wasm.navs_obj.getIndex(ip_nav).?), | |
| 636 | } else .{ | |
| 637 | .nav_exe = @enumFromInt(wasm.navs_exe.getIndex(ip_nav).?), | |
| 638 | }); | |
| 559 | 639 | } |
| 560 | 640 | |
| 561 | 641 | pub fn isNavOrUnresolved(r: Resolution, wasm: *const Wasm) bool { |
| 562 | 642 | return switch (r.unpack(wasm)) { |
| 563 | .unresolved, .nav => true, | |
| 643 | .unresolved, .nav_obj, .nav_exe => true, | |
| 564 | 644 | else => false, |
| 565 | 645 | }; |
| 566 | 646 | } |
| ... | ... | @@ -608,7 +688,7 @@ pub const GlobalImport = extern struct { |
| 608 | 688 | __tls_size, |
| 609 | 689 | __zig_error_name_table, |
| 610 | 690 | // Next, index into `object_globals`. |
| 611 | // Next, index into `navs`. | |
| 691 | // Next, index into `navs_obj` or `navs_exe` depending on whether emitting an object. | |
| 612 | 692 | _, |
| 613 | 693 | |
| 614 | 694 | const first_object_global = @intFromEnum(Resolution.__zig_error_name_table) + 1; |
| ... | ... | @@ -623,7 +703,8 @@ pub const GlobalImport = extern struct { |
| 623 | 703 | __tls_size, |
| 624 | 704 | __zig_error_name_table, |
| 625 | 705 | object_global: ObjectGlobalIndex, |
| 626 | nav: Nav.Index, | |
| 706 | nav_exe: NavExe.Index, | |
| 707 | nav_obj: NavObj.Index, | |
| 627 | 708 | }; |
| 628 | 709 | |
| 629 | 710 | pub fn unpack(r: Resolution, wasm: *const Wasm) Unpacked { |
| ... | ... | @@ -639,8 +720,14 @@ pub const GlobalImport = extern struct { |
| 639 | 720 | const object_global_index = i - first_object_global; |
| 640 | 721 | if (object_global_index < wasm.object_globals.items.len) |
| 641 | 722 | return .{ .object_global = @enumFromInt(object_global_index) }; |
| 723 | const comp = wasm.base.comp; | |
| 724 | const is_obj = comp.config.output_mode == .Obj; | |
| 642 | 725 | const nav_index = object_global_index - wasm.object_globals.items.len; |
| 643 | return .{ .nav = @enumFromInt(nav_index) }; | |
| 726 | return if (is_obj) .{ | |
| 727 | .nav_obj = @enumFromInt(nav_index), | |
| 728 | } else .{ | |
| 729 | .nav_exe = @enumFromInt(nav_index), | |
| 730 | }; | |
| 644 | 731 | }, |
| 645 | 732 | }; |
| 646 | 733 | } |
| ... | ... | @@ -656,12 +743,19 @@ pub const GlobalImport = extern struct { |
| 656 | 743 | .__tls_size => .__tls_size, |
| 657 | 744 | .__zig_error_name_table => .__zig_error_name_table, |
| 658 | 745 | .object_global => |i| @enumFromInt(first_object_global + @intFromEnum(i)), |
| 659 | .nav => |i| @enumFromInt(first_object_global + wasm.object_globals.items.len + @intFromEnum(i)), | |
| 746 | .nav_obj => |i| @enumFromInt(first_object_global + wasm.object_globals.items.len + @intFromEnum(i)), | |
| 747 | .nav_exe => |i| @enumFromInt(first_object_global + wasm.object_globals.items.len + @intFromEnum(i)), | |
| 660 | 748 | }; |
| 661 | 749 | } |
| 662 | 750 | |
| 663 | 751 | pub fn fromIpNav(wasm: *const Wasm, ip_nav: InternPool.Nav.Index) Resolution { |
| 664 | return pack(wasm, .{ .nav = @enumFromInt(wasm.navs.getIndex(ip_nav).?) }); | |
| 752 | const comp = wasm.base.comp; | |
| 753 | const is_obj = comp.config.output_mode == .Obj; | |
| 754 | return pack(wasm, if (is_obj) .{ | |
| 755 | .nav_obj = @enumFromInt(wasm.navs_obj.getIndex(ip_nav).?), | |
| 756 | } else .{ | |
| 757 | .nav_exe = @enumFromInt(wasm.navs_exe.getIndex(ip_nav).?), | |
| 758 | }); | |
| 665 | 759 | } |
| 666 | 760 | }; |
| 667 | 761 | |
| ... | ... | @@ -717,11 +811,32 @@ pub const Global = extern struct { |
| 717 | 811 | }; |
| 718 | 812 | }; |
| 719 | 813 | |
| 814 | pub const RefType1 = enum(u1) { | |
| 815 | funcref, | |
| 816 | externref, | |
| 817 | ||
| 818 | pub fn from(rt: std.wasm.RefType) RefType1 { | |
| 819 | return switch (rt) { | |
| 820 | .funcref => .funcref, | |
| 821 | .externref => .externref, | |
| 822 | }; | |
| 823 | } | |
| 824 | ||
| 825 | pub fn to(rt: RefType1) std.wasm.RefType { | |
| 826 | return switch (rt) { | |
| 827 | .funcref => .funcref, | |
| 828 | .externref => .externref, | |
| 829 | }; | |
| 830 | } | |
| 831 | }; | |
| 832 | ||
| 720 | 833 | pub const TableImport = extern struct { |
| 721 | 834 | flags: SymbolFlags, |
| 722 | 835 | module_name: String, |
| 723 | 836 | source_location: SourceLocation, |
| 724 | 837 | resolution: Resolution, |
| 838 | limits_min: u32, | |
| 839 | limits_max: u32, | |
| 725 | 840 | |
| 726 | 841 | /// Represents a synthetic table, or a table from an object. |
| 727 | 842 | pub const Resolution = enum(u32) { |
| ... | ... | @@ -730,35 +845,36 @@ pub const TableImport = extern struct { |
| 730 | 845 | // Next, index into `object_tables`. |
| 731 | 846 | _, |
| 732 | 847 | }; |
| 848 | ||
| 849 | /// Index into `object_table_imports`. | |
| 850 | pub const Index = enum(u32) { | |
| 851 | _, | |
| 852 | ||
| 853 | pub fn key(index: Index, wasm: *const Wasm) *String { | |
| 854 | return &wasm.object_table_imports.keys()[@intFromEnum(index)]; | |
| 855 | } | |
| 856 | ||
| 857 | pub fn value(index: Index, wasm: *const Wasm) *TableImport { | |
| 858 | return &wasm.object_table_imports.values()[@intFromEnum(index)]; | |
| 859 | } | |
| 860 | }; | |
| 733 | 861 | }; |
| 734 | 862 | |
| 735 | 863 | pub const Table = extern struct { |
| 736 | module_name: String, | |
| 737 | name: String, | |
| 864 | module_name: OptionalString, | |
| 865 | name: OptionalString, | |
| 738 | 866 | flags: SymbolFlags, |
| 739 | 867 | limits_min: u32, |
| 740 | 868 | limits_max: u32, |
| 741 | limits_has_max: bool, | |
| 742 | limits_is_shared: bool, | |
| 743 | reftype: std.wasm.RefType, | |
| 744 | padding: [1]u8 = .{0}, | |
| 745 | 869 | }; |
| 746 | 870 | |
| 747 | /// Uniquely identifies a section across all objects. Each Object has a section_start field. | |
| 748 | /// By subtracting that value from this one, the Object section index is obtained. | |
| 871 | /// Uniquely identifies a section across all objects. By subtracting | |
| 872 | /// `Object.local_section_index_base` from this one, the Object section index | |
| 873 | /// is obtained. | |
| 749 | 874 | pub const ObjectSectionIndex = enum(u32) { |
| 750 | 875 | _, |
| 751 | 876 | }; |
| 752 | 877 | |
| 753 | /// Index into `object_table_imports`. | |
| 754 | pub const ObjectTableImportIndex = enum(u32) { | |
| 755 | _, | |
| 756 | ||
| 757 | pub fn ptr(index: ObjectTableImportIndex, wasm: *const Wasm) *TableImport { | |
| 758 | return &wasm.object_table_imports.items[@intFromEnum(index)]; | |
| 759 | } | |
| 760 | }; | |
| 761 | ||
| 762 | 878 | /// Index into `object_tables`. |
| 763 | 879 | pub const ObjectTableIndex = enum(u32) { |
| 764 | 880 | _, |
| ... | ... | @@ -820,13 +936,18 @@ pub const DataSegment = extern struct { |
| 820 | 936 | len: u32, |
| 821 | 937 | |
| 822 | 938 | fn slice(p: DataSegment.Payload, wasm: *const Wasm) []const u8 { |
| 939 | assert(p.off != p.len); | |
| 823 | 940 | return wasm.string_bytes.items[p.off..][0..p.len]; |
| 824 | 941 | } |
| 825 | 942 | }; |
| 826 | 943 | |
| 827 | /// Index into `object_data_segments`. | |
| 944 | /// Index into `Wasm.object_data_segments`. | |
| 828 | 945 | pub const Index = enum(u32) { |
| 829 | 946 | _, |
| 947 | ||
| 948 | pub fn ptr(i: Index, wasm: *const Wasm) *DataSegment { | |
| 949 | return &wasm.object_data_segments.items[@intFromEnum(i)]; | |
| 950 | } | |
| 830 | 951 | }; |
| 831 | 952 | }; |
| 832 | 953 | |
| ... | ... | @@ -992,6 +1113,10 @@ pub const FunctionImportId = enum(u32) { |
| 992 | 1113 | return .{ .zcu_import = @enumFromInt(zcu_import_i) }; |
| 993 | 1114 | } |
| 994 | 1115 | |
| 1116 | pub fn fromObject(function_import_index: FunctionImport.Index, wasm: *const Wasm) FunctionImportId { | |
| 1117 | return pack(.{ .object_function_import = function_import_index }, wasm); | |
| 1118 | } | |
| 1119 | ||
| 995 | 1120 | /// This function is allowed O(N) lookup because it is only called during |
| 996 | 1121 | /// diagnostic generation. |
| 997 | 1122 | pub fn sourceLocation(id: FunctionImportId, wasm: *const Wasm) SourceLocation { |
| ... | ... | @@ -1035,6 +1160,10 @@ pub const GlobalImportId = enum(u32) { |
| 1035 | 1160 | return .{ .zcu_import = @enumFromInt(zcu_import_i) }; |
| 1036 | 1161 | } |
| 1037 | 1162 | |
| 1163 | pub fn fromObject(object_global_import: GlobalImport.Index, wasm: *const Wasm) GlobalImportId { | |
| 1164 | return pack(.{ .object_global_import = object_global_import }, wasm); | |
| 1165 | } | |
| 1166 | ||
| 1038 | 1167 | /// This function is allowed O(N) lookup because it is only called during |
| 1039 | 1168 | /// diagnostic generation. |
| 1040 | 1169 | pub fn sourceLocation(id: GlobalImportId, wasm: *const Wasm) SourceLocation { |
| ... | ... | @@ -1054,7 +1183,38 @@ pub const GlobalImportId = enum(u32) { |
| 1054 | 1183 | } |
| 1055 | 1184 | }; |
| 1056 | 1185 | |
| 1057 | pub const Relocation = struct { | |
| 1186 | /// Index into `Wasm.symbol_table`. | |
| 1187 | pub const SymbolTableIndex = enum(u32) { | |
| 1188 | _, | |
| 1189 | ||
| 1190 | pub fn key(i: @This(), wasm: *const Wasm) *String { | |
| 1191 | return &wasm.symbol_table.keys()[@intFromEnum(i)]; | |
| 1192 | } | |
| 1193 | }; | |
| 1194 | ||
| 1195 | pub const OutReloc = struct { | |
| 1196 | tag: ObjectRelocation.Tag, | |
| 1197 | offset: u32, | |
| 1198 | pointee: Pointee, | |
| 1199 | addend: i32, | |
| 1200 | ||
| 1201 | pub const Pointee = union { | |
| 1202 | symbol_index: SymbolTableIndex, | |
| 1203 | type_index: FunctionType.Index, | |
| 1204 | }; | |
| 1205 | ||
| 1206 | pub const Slice = extern struct { | |
| 1207 | /// Index into `out_relocs`. | |
| 1208 | off: u32, | |
| 1209 | len: u32, | |
| 1210 | ||
| 1211 | pub fn slice(s: Slice, wasm: *const Wasm) []OutReloc { | |
| 1212 | return wasm.relocations.items[s.off..][0..s.len]; | |
| 1213 | } | |
| 1214 | }; | |
| 1215 | }; | |
| 1216 | ||
| 1217 | pub const ObjectRelocation = struct { | |
| 1058 | 1218 | tag: Tag, |
| 1059 | 1219 | /// Offset of the value to rewrite relative to the relevant section's contents. |
| 1060 | 1220 | /// When `offset` is zero, its position is immediately after the id and size of the section. |
| ... | ... | @@ -1067,8 +1227,6 @@ pub const Relocation = struct { |
| 1067 | 1227 | symbol_name: String, |
| 1068 | 1228 | type_index: FunctionType.Index, |
| 1069 | 1229 | section: ObjectSectionIndex, |
| 1070 | nav_index: InternPool.Nav.Index, | |
| 1071 | uav_index: InternPool.Index, | |
| 1072 | 1230 | }; |
| 1073 | 1231 | |
| 1074 | 1232 | pub const Slice = extern struct { |
| ... | ... | @@ -1076,7 +1234,7 @@ pub const Relocation = struct { |
| 1076 | 1234 | off: u32, |
| 1077 | 1235 | len: u32, |
| 1078 | 1236 | |
| 1079 | pub fn slice(s: Slice, wasm: *const Wasm) []Relocation { | |
| 1237 | pub fn slice(s: Slice, wasm: *const Wasm) []ObjectRelocation { | |
| 1080 | 1238 | return wasm.relocations.items[s.off..][0..s.len]; |
| 1081 | 1239 | } |
| 1082 | 1240 | }; |
| ... | ... | @@ -1122,11 +1280,6 @@ pub const Relocation = struct { |
| 1122 | 1280 | // Above here, the tags correspond to symbol table ABI described in |
| 1123 | 1281 | // https://github.com/WebAssembly/tool-conventions/blob/main/Linking.md |
| 1124 | 1282 | // Below, the tags are compiler-internal. |
| 1125 | ||
| 1126 | /// Uses `nav_index`. 4 or 8 bytes depending on wasm32 or wasm64. | |
| 1127 | nav_index, | |
| 1128 | /// Uses `uav_index`. 4 or 8 bytes depending on wasm32 or wasm64. | |
| 1129 | uav_index, | |
| 1130 | 1283 | }; |
| 1131 | 1284 | }; |
| 1132 | 1285 | |
| ... | ... | @@ -1456,7 +1609,8 @@ pub fn deinit(wasm: *Wasm) void { |
| 1456 | 1609 | const gpa = wasm.base.comp.gpa; |
| 1457 | 1610 | if (wasm.llvm_object) |llvm_object| llvm_object.deinit(); |
| 1458 | 1611 | |
| 1459 | wasm.navs.deinit(gpa); | |
| 1612 | wasm.navs_exe.deinit(gpa); | |
| 1613 | wasm.navs_obj.deinit(gpa); | |
| 1460 | 1614 | wasm.zcu_funcs.deinit(gpa); |
| 1461 | 1615 | wasm.nav_exports.deinit(gpa); |
| 1462 | 1616 | wasm.uav_exports.deinit(gpa); |
| ... | ... | @@ -1478,7 +1632,7 @@ pub fn deinit(wasm: *Wasm) void { |
| 1478 | 1632 | wasm.object_tables.deinit(gpa); |
| 1479 | 1633 | wasm.object_memory_imports.deinit(gpa); |
| 1480 | 1634 | wasm.object_memories.deinit(gpa); |
| 1481 | ||
| 1635 | wasm.object_relocations.deinit(gpa); | |
| 1482 | 1636 | wasm.object_data_segments.deinit(gpa); |
| 1483 | 1637 | wasm.object_custom_segments.deinit(gpa); |
| 1484 | 1638 | wasm.object_init_funcs.deinit(gpa); |
| ... | ... | @@ -1492,8 +1646,13 @@ pub fn deinit(wasm: *Wasm) void { |
| 1492 | 1646 | wasm.function_imports.deinit(gpa); |
| 1493 | 1647 | wasm.functions.deinit(gpa); |
| 1494 | 1648 | wasm.globals.deinit(gpa); |
| 1649 | wasm.global_exports.deinit(gpa); | |
| 1495 | 1650 | wasm.global_imports.deinit(gpa); |
| 1496 | 1651 | wasm.table_imports.deinit(gpa); |
| 1652 | wasm.symbol_table.deinit(gpa); | |
| 1653 | wasm.out_relocs.deinit(gpa); | |
| 1654 | wasm.uav_fixups.deinit(gpa); | |
| 1655 | wasm.nav_fixups.deinit(gpa); | |
| 1497 | 1656 | |
| 1498 | 1657 | wasm.string_bytes.deinit(gpa); |
| 1499 | 1658 | wasm.string_table.deinit(gpa); |
| ... | ... | @@ -1527,7 +1686,9 @@ pub fn updateNav(wasm: *Wasm, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index |
| 1527 | 1686 | const zcu = pt.zcu; |
| 1528 | 1687 | const ip = &zcu.intern_pool; |
| 1529 | 1688 | const nav = ip.getNav(nav_index); |
| 1530 | const gpa = wasm.base.comp.gpa; | |
| 1689 | const comp = wasm.base.comp; | |
| 1690 | const gpa = comp.gpa; | |
| 1691 | const is_obj = comp.config.output_mode == .Obj; | |
| 1531 | 1692 | |
| 1532 | 1693 | const nav_val = zcu.navValue(nav_index); |
| 1533 | 1694 | const is_extern, const nav_init = switch (ip.indexToKey(nav_val.toIntern())) { |
| ... | ... | @@ -1542,22 +1703,26 @@ pub fn updateNav(wasm: *Wasm, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index |
| 1542 | 1703 | |
| 1543 | 1704 | if (!nav_init.typeOf(zcu).hasRuntimeBits(zcu)) { |
| 1544 | 1705 | _ = wasm.imports.swapRemove(nav_index); |
| 1545 | if (wasm.navs.swapRemove(nav_index)) { | |
| 1546 | @panic("TODO reclaim resources"); | |
| 1706 | if (is_obj) { | |
| 1707 | if (wasm.navs_obj.swapRemove(nav_index)) @panic("TODO reclaim resources"); | |
| 1708 | } else { | |
| 1709 | if (wasm.navs_exe.swapRemove(nav_index)) @panic("TODO reclaim resources"); | |
| 1547 | 1710 | } |
| 1548 | 1711 | return; |
| 1549 | 1712 | } |
| 1550 | 1713 | |
| 1551 | 1714 | if (is_extern) { |
| 1552 | 1715 | try wasm.imports.put(gpa, nav_index, {}); |
| 1553 | if (wasm.navs.swapRemove(nav_index)) { | |
| 1554 | @panic("TODO reclaim resources"); | |
| 1716 | if (is_obj) { | |
| 1717 | if (wasm.navs_obj.swapRemove(nav_index)) @panic("TODO reclaim resources"); | |
| 1718 | } else { | |
| 1719 | if (wasm.navs_exe.swapRemove(nav_index)) @panic("TODO reclaim resources"); | |
| 1555 | 1720 | } |
| 1556 | 1721 | return; |
| 1557 | 1722 | } |
| 1558 | 1723 | |
| 1559 | 1724 | const code_start: u32 = @intCast(wasm.string_bytes.items.len); |
| 1560 | const relocs_start: u32 = @intCast(wasm.relocations.len); | |
| 1725 | const relocs_start: u32 = @intCast(wasm.out_relocs.len); | |
| 1561 | 1726 | wasm.string_bytes_lock.lock(); |
| 1562 | 1727 | |
| 1563 | 1728 | try codegen.generateSymbol( |
| ... | ... | @@ -1570,15 +1735,45 @@ pub fn updateNav(wasm: *Wasm, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index |
| 1570 | 1735 | ); |
| 1571 | 1736 | |
| 1572 | 1737 | const code_len: u32 = @intCast(wasm.string_bytes.items.len - code_start); |
| 1573 | const relocs_len: u32 = @intCast(wasm.relocations.len - relocs_start); | |
| 1738 | const relocs_len: u32 = @intCast(wasm.out_relocs.len - relocs_start); | |
| 1574 | 1739 | wasm.string_bytes_lock.unlock(); |
| 1575 | 1740 | |
| 1576 | const code: Nav.Code = .{ | |
| 1741 | const naive_code: DataSegment.Payload = .{ | |
| 1577 | 1742 | .off = code_start, |
| 1578 | 1743 | .len = code_len, |
| 1579 | 1744 | }; |
| 1580 | 1745 | |
| 1581 | const gop = try wasm.navs.getOrPut(gpa, nav_index); | |
| 1746 | // Only nonzero init values need to take up space in the output. | |
| 1747 | const all_zeroes = std.mem.allEqual(u8, naive_code.slice(wasm), 0); | |
| 1748 | const code: DataSegment.Payload = if (!all_zeroes) naive_code else c: { | |
| 1749 | wasm.string_bytes.shrinkRetainingCapacity(code_start); | |
| 1750 | // Indicate empty by making off and len the same value, however, still | |
| 1751 | // transmit the data size by using the size as that value. | |
| 1752 | break :c .{ | |
| 1753 | .off = naive_code.len, | |
| 1754 | .len = naive_code.len, | |
| 1755 | }; | |
| 1756 | }; | |
| 1757 | ||
| 1758 | if (is_obj) { | |
| 1759 | const gop = try wasm.navs_obj.getOrPut(gpa, nav_index); | |
| 1760 | if (gop.found_existing) { | |
| 1761 | @panic("TODO reuse these resources"); | |
| 1762 | } else { | |
| 1763 | _ = wasm.imports.swapRemove(nav_index); | |
| 1764 | } | |
| 1765 | gop.value_ptr.* = .{ | |
| 1766 | .code = code, | |
| 1767 | .relocs = .{ | |
| 1768 | .off = relocs_start, | |
| 1769 | .len = relocs_len, | |
| 1770 | }, | |
| 1771 | }; | |
| 1772 | } | |
| 1773 | ||
| 1774 | assert(relocs_len == 0); | |
| 1775 | ||
| 1776 | const gop = try wasm.navs_exe.getOrPut(gpa, nav_index); | |
| 1582 | 1777 | if (gop.found_existing) { |
| 1583 | 1778 | @panic("TODO reuse these resources"); |
| 1584 | 1779 | } else { |
| ... | ... | @@ -1586,10 +1781,6 @@ pub fn updateNav(wasm: *Wasm, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index |
| 1586 | 1781 | } |
| 1587 | 1782 | gop.value_ptr.* = .{ |
| 1588 | 1783 | .code = code, |
| 1589 | .relocs = .{ | |
| 1590 | .off = relocs_start, | |
| 1591 | .len = relocs_len, | |
| 1592 | }, | |
| 1593 | 1784 | }; |
| 1594 | 1785 | } |
| 1595 | 1786 | |
| ... | ... | @@ -1705,6 +1896,12 @@ pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.File.FlushError!v |
| 1705 | 1896 | continue; |
| 1706 | 1897 | } |
| 1707 | 1898 | } |
| 1899 | if (wasm.object_table_imports.getPtr(exp_name_interned)) |import| { | |
| 1900 | if (import.resolution != .unresolved) { | |
| 1901 | import.flags.exported = true; | |
| 1902 | continue; | |
| 1903 | } | |
| 1904 | } | |
| 1708 | 1905 | try missing_exports.put(gpa, exp_name_interned, {}); |
| 1709 | 1906 | } |
| 1710 | 1907 | wasm.missing_exports_init = try gpa.dupe(String, missing_exports.keys()); |
| ... | ... | @@ -1724,32 +1921,28 @@ pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.File.FlushError!v |
| 1724 | 1921 | for (wasm.object_function_imports.keys(), wasm.object_function_imports.values(), 0..) |name, *import, i| { |
| 1725 | 1922 | if (import.flags.isIncluded(rdynamic)) { |
| 1726 | 1923 | try markFunction(wasm, name, import, @enumFromInt(i)); |
| 1727 | continue; | |
| 1728 | 1924 | } |
| 1729 | 1925 | } |
| 1730 | 1926 | wasm.functions_len = @intCast(wasm.functions.entries.len); |
| 1731 | 1927 | wasm.function_imports_init_keys = try gpa.dupe(String, wasm.function_imports.keys()); |
| 1732 | wasm.function_imports_init_vals = try gpa.dupe(FunctionImportId, wasm.function_imports.vals()); | |
| 1928 | wasm.function_imports_init_vals = try gpa.dupe(FunctionImportId, wasm.function_imports.values()); | |
| 1733 | 1929 | wasm.function_exports_len = @intCast(wasm.function_exports.items.len); |
| 1734 | 1930 | |
| 1735 | 1931 | for (wasm.object_global_imports.keys(), wasm.object_global_imports.values(), 0..) |name, *import, i| { |
| 1736 | 1932 | if (import.flags.isIncluded(rdynamic)) { |
| 1737 | 1933 | try markGlobal(wasm, name, import, @enumFromInt(i)); |
| 1738 | continue; | |
| 1739 | 1934 | } |
| 1740 | 1935 | } |
| 1741 | wasm.globals_len = @intCast(wasm.globals.items.len); | |
| 1936 | wasm.globals_len = @intCast(wasm.globals.entries.len); | |
| 1742 | 1937 | wasm.global_imports_init_keys = try gpa.dupe(String, wasm.global_imports.keys()); |
| 1743 | 1938 | wasm.global_imports_init_vals = try gpa.dupe(GlobalImportId, wasm.global_imports.values()); |
| 1744 | 1939 | wasm.global_exports_len = @intCast(wasm.global_exports.items.len); |
| 1745 | 1940 | |
| 1746 | for (wasm.object_table_imports.items, 0..) |*import, i| { | |
| 1941 | for (wasm.object_table_imports.keys(), wasm.object_table_imports.values(), 0..) |name, *import, i| { | |
| 1747 | 1942 | if (import.flags.isIncluded(rdynamic)) { |
| 1748 | try markTable(wasm, import.name, import, @enumFromInt(i)); | |
| 1749 | continue; | |
| 1943 | try markTable(wasm, name, import, @enumFromInt(i)); | |
| 1750 | 1944 | } |
| 1751 | 1945 | } |
| 1752 | wasm.tables_len = @intCast(wasm.tables.items.len); | |
| 1753 | 1946 | } |
| 1754 | 1947 | |
| 1755 | 1948 | /// Recursively mark alive everything referenced by the function. |
| ... | ... | @@ -1758,7 +1951,7 @@ fn markFunction( |
| 1758 | 1951 | name: String, |
| 1759 | 1952 | import: *FunctionImport, |
| 1760 | 1953 | func_index: FunctionImport.Index, |
| 1761 | ) error{OutOfMemory}!void { | |
| 1954 | ) Allocator.Error!void { | |
| 1762 | 1955 | if (import.flags.alive) return; |
| 1763 | 1956 | import.flags.alive = true; |
| 1764 | 1957 | |
| ... | ... | @@ -1783,15 +1976,15 @@ fn markFunction( |
| 1783 | 1976 | import.resolution = .__wasm_init_tls; |
| 1784 | 1977 | wasm.functions.putAssumeCapacity(.__wasm_init_tls, {}); |
| 1785 | 1978 | } else { |
| 1786 | try wasm.function_imports.put(gpa, name, .fromObject(func_index)); | |
| 1979 | try wasm.function_imports.put(gpa, name, .fromObject(func_index, wasm)); | |
| 1787 | 1980 | } |
| 1788 | 1981 | } else { |
| 1789 | 1982 | const gop = wasm.functions.getOrPutAssumeCapacity(import.resolution); |
| 1790 | 1983 | |
| 1791 | 1984 | if (!is_obj and import.flags.isExported(rdynamic)) |
| 1792 | try wasm.function_exports.append(gpa, @intCast(gop.index)); | |
| 1985 | try wasm.function_exports.append(gpa, @enumFromInt(gop.index)); | |
| 1793 | 1986 | |
| 1794 | for (wasm.functionResolutionRelocSlice(import.resolution)) |reloc| | |
| 1987 | for (try wasm.functionResolutionRelocSlice(import.resolution)) |reloc| | |
| 1795 | 1988 | try wasm.markReloc(reloc); |
| 1796 | 1989 | } |
| 1797 | 1990 | } |
| ... | ... | @@ -1833,15 +2026,15 @@ fn markGlobal( |
| 1833 | 2026 | import.resolution = .__tls_size; |
| 1834 | 2027 | wasm.globals.putAssumeCapacity(.__tls_size, {}); |
| 1835 | 2028 | } else { |
| 1836 | try wasm.global_imports.put(gpa, name, .fromObject(global_index)); | |
| 2029 | try wasm.global_imports.put(gpa, name, .fromObject(global_index, wasm)); | |
| 1837 | 2030 | } |
| 1838 | 2031 | } else { |
| 1839 | 2032 | const gop = wasm.globals.getOrPutAssumeCapacity(import.resolution); |
| 1840 | 2033 | |
| 1841 | 2034 | if (!is_obj and import.flags.isExported(rdynamic)) |
| 1842 | try wasm.global_exports.append(gpa, @intCast(gop.index)); | |
| 2035 | try wasm.global_exports.append(gpa, @enumFromInt(gop.index)); | |
| 1843 | 2036 | |
| 1844 | for (wasm.globalResolutionRelocSlice(import.resolution)) |reloc| | |
| 2037 | for (try wasm.globalResolutionRelocSlice(import.resolution)) |reloc| | |
| 1845 | 2038 | try wasm.markReloc(reloc); |
| 1846 | 2039 | } |
| 1847 | 2040 | } |
| ... | ... | @@ -1850,7 +2043,7 @@ fn markTable( |
| 1850 | 2043 | wasm: *Wasm, |
| 1851 | 2044 | name: String, |
| 1852 | 2045 | import: *TableImport, |
| 1853 | table_index: ObjectTableImportIndex, | |
| 2046 | table_index: TableImport.Index, | |
| 1854 | 2047 | ) !void { |
| 1855 | 2048 | if (import.flags.alive) return; |
| 1856 | 2049 | import.flags.alive = true; |
| ... | ... | @@ -1865,7 +2058,7 @@ fn markTable( |
| 1865 | 2058 | import.resolution = .__indirect_function_table; |
| 1866 | 2059 | wasm.tables.putAssumeCapacity(.__indirect_function_table, {}); |
| 1867 | 2060 | } else { |
| 1868 | try wasm.table_imports.put(gpa, name, .fromObject(table_index)); | |
| 2061 | try wasm.table_imports.put(gpa, name, table_index); | |
| 1869 | 2062 | } |
| 1870 | 2063 | } else { |
| 1871 | 2064 | wasm.tables.putAssumeCapacity(import.resolution, {}); |
| ... | ... | @@ -1873,18 +2066,24 @@ fn markTable( |
| 1873 | 2066 | } |
| 1874 | 2067 | } |
| 1875 | 2068 | |
| 1876 | fn globalResolutionRelocSlice(wasm: *Wasm, resolution: GlobalImport.Resolution) ![]const Relocation { | |
| 1877 | assert(resolution != .none); | |
| 2069 | fn globalResolutionRelocSlice(wasm: *Wasm, resolution: GlobalImport.Resolution) ![]const ObjectRelocation { | |
| 2070 | assert(resolution != .unresolved); | |
| 1878 | 2071 | _ = wasm; |
| 1879 | 2072 | @panic("TODO"); |
| 1880 | 2073 | } |
| 1881 | 2074 | |
| 1882 | fn functionResolutionRelocSlice(wasm: *Wasm, resolution: FunctionImport.Resolution) ![]const Relocation { | |
| 1883 | assert(resolution != .none); | |
| 2075 | fn functionResolutionRelocSlice(wasm: *Wasm, resolution: FunctionImport.Resolution) ![]const ObjectRelocation { | |
| 2076 | assert(resolution != .unresolved); | |
| 1884 | 2077 | _ = wasm; |
| 1885 | 2078 | @panic("TODO"); |
| 1886 | 2079 | } |
| 1887 | 2080 | |
| 2081 | fn markReloc(wasm: *Wasm, reloc: ObjectRelocation) !void { | |
| 2082 | _ = wasm; | |
| 2083 | _ = reloc; | |
| 2084 | @panic("TODO"); | |
| 2085 | } | |
| 2086 | ||
| 1888 | 2087 | pub fn flushModule( |
| 1889 | 2088 | wasm: *Wasm, |
| 1890 | 2089 | arena: Allocator, |
| ... | ... | @@ -2349,8 +2548,10 @@ fn defaultEntrySymbolName( |
| 2349 | 2548 | }; |
| 2350 | 2549 | } |
| 2351 | 2550 | |
| 2352 | pub fn internString(wasm: *Wasm, bytes: []const u8) error{OutOfMemory}!String { | |
| 2551 | pub fn internString(wasm: *Wasm, bytes: []const u8) Allocator.Error!String { | |
| 2353 | 2552 | assert(mem.indexOfScalar(u8, bytes, 0) == null); |
| 2553 | wasm.string_bytes_lock.lock(); | |
| 2554 | defer wasm.string_bytes_lock.unlock(); | |
| 2354 | 2555 | const gpa = wasm.base.comp.gpa; |
| 2355 | 2556 | const gop = try wasm.string_table.getOrPutContextAdapted( |
| 2356 | 2557 | gpa, |
| ... | ... | @@ -2371,6 +2572,13 @@ pub fn internString(wasm: *Wasm, bytes: []const u8) error{OutOfMemory}!String { |
| 2371 | 2572 | return new_off; |
| 2372 | 2573 | } |
| 2373 | 2574 | |
| 2575 | // TODO implement instead by appending to string_bytes | |
| 2576 | pub fn internStringFmt(wasm: *Wasm, comptime format: []const u8, args: anytype) Allocator.Error!String { | |
| 2577 | var buffer: [32]u8 = undefined; | |
| 2578 | const slice = std.fmt.bufPrint(&buffer, format, args) catch unreachable; | |
| 2579 | return internString(wasm, slice); | |
| 2580 | } | |
| 2581 | ||
| 2374 | 2582 | pub fn getExistingString(wasm: *const Wasm, bytes: []const u8) ?String { |
| 2375 | 2583 | assert(mem.indexOfScalar(u8, bytes, 0) == null); |
| 2376 | 2584 | return wasm.string_table.getKeyAdapted(bytes, @as(String.TableIndexAdapter, .{ |
| ... | ... | @@ -2378,17 +2586,17 @@ pub fn getExistingString(wasm: *const Wasm, bytes: []const u8) ?String { |
| 2378 | 2586 | })); |
| 2379 | 2587 | } |
| 2380 | 2588 | |
| 2381 | pub fn internValtypeList(wasm: *Wasm, valtype_list: []const std.wasm.Valtype) error{OutOfMemory}!ValtypeList { | |
| 2589 | pub fn internValtypeList(wasm: *Wasm, valtype_list: []const std.wasm.Valtype) Allocator.Error!ValtypeList { | |
| 2382 | 2590 | return .fromString(try internString(wasm, @ptrCast(valtype_list))); |
| 2383 | 2591 | } |
| 2384 | 2592 | |
| 2385 | pub fn addFuncType(wasm: *Wasm, ft: FunctionType) error{OutOfMemory}!FunctionType.Index { | |
| 2593 | pub fn addFuncType(wasm: *Wasm, ft: FunctionType) Allocator.Error!FunctionType.Index { | |
| 2386 | 2594 | const gpa = wasm.base.comp.gpa; |
| 2387 | 2595 | const gop = try wasm.func_types.getOrPut(gpa, ft); |
| 2388 | 2596 | return @enumFromInt(gop.index); |
| 2389 | 2597 | } |
| 2390 | 2598 | |
| 2391 | pub fn addExpr(wasm: *Wasm, bytes: []const u8) error{OutOfMemory}!Expr { | |
| 2599 | pub fn addExpr(wasm: *Wasm, bytes: []const u8) Allocator.Error!Expr { | |
| 2392 | 2600 | const gpa = wasm.base.comp.gpa; |
| 2393 | 2601 | // We can't use string table deduplication here since these expressions can |
| 2394 | 2602 | // have null bytes in them however it may be interesting to explore since |
| ... | ... | @@ -2398,8 +2606,29 @@ pub fn addExpr(wasm: *Wasm, bytes: []const u8) error{OutOfMemory}!Expr { |
| 2398 | 2606 | return @enumFromInt(wasm.string_bytes.items.len - bytes.len); |
| 2399 | 2607 | } |
| 2400 | 2608 | |
| 2401 | pub fn addRelocatableDataPayload(wasm: *Wasm, bytes: []const u8) error{OutOfMemory}!DataSegment.Payload { | |
| 2609 | pub fn addRelocatableDataPayload(wasm: *Wasm, bytes: []const u8) Allocator.Error!DataSegment.Payload { | |
| 2402 | 2610 | const gpa = wasm.base.comp.gpa; |
| 2403 | 2611 | try wasm.string_bytes.appendSlice(gpa, bytes); |
| 2404 | 2612 | return @enumFromInt(wasm.string_bytes.items.len - bytes.len); |
| 2405 | 2613 | } |
| 2614 | ||
| 2615 | pub fn uavSymbolIndex(wasm: *Wasm, ip_index: InternPool.Index) Allocator.Error!SymbolTableIndex { | |
| 2616 | const comp = wasm.base.comp; | |
| 2617 | assert(comp.config.output_mode == .Obj); | |
| 2618 | const gpa = comp.gpa; | |
| 2619 | const name = try wasm.internStringFmt("__anon_{d}", .{@intFromEnum(ip_index)}); | |
| 2620 | const gop = try wasm.symbol_table.getOrPut(gpa, name); | |
| 2621 | return @enumFromInt(gop.index); | |
| 2622 | } | |
| 2623 | ||
| 2624 | pub fn navSymbolIndex(wasm: *Wasm, nav_index: InternPool.Nav.Index) Allocator.Error!SymbolTableIndex { | |
| 2625 | const comp = wasm.base.comp; | |
| 2626 | assert(comp.config.output_mode == .Obj); | |
| 2627 | const zcu = comp.zcu.?; | |
| 2628 | const ip = &zcu.intern_pool; | |
| 2629 | const gpa = comp.gpa; | |
| 2630 | const nav = ip.getNav(nav_index); | |
| 2631 | const name = try wasm.internString(nav.fqn.toSlice(ip)); | |
| 2632 | const gop = try wasm.symbol_table.getOrPut(gpa, name); | |
| 2633 | return @enumFromInt(gop.index); | |
| 2634 | } |
src/link/Wasm/Flush.zig+51-49| ... | ... | @@ -42,7 +42,6 @@ pub fn clear(f: *Flush) void { |
| 42 | 42 | f.data_segments.clearRetainingCapacity(); |
| 43 | 43 | f.data_segment_groups.clearRetainingCapacity(); |
| 44 | 44 | f.indirect_function_table.clearRetainingCapacity(); |
| 45 | f.global_exports.clearRetainingCapacity(); | |
| 46 | 45 | } |
| 47 | 46 | |
| 48 | 47 | pub fn deinit(f: *Flush, gpa: Allocator) void { |
| ... | ... | @@ -50,11 +49,10 @@ pub fn deinit(f: *Flush, gpa: Allocator) void { |
| 50 | 49 | f.data_segments.deinit(gpa); |
| 51 | 50 | f.data_segment_groups.deinit(gpa); |
| 52 | 51 | f.indirect_function_table.deinit(gpa); |
| 53 | f.global_exports.deinit(gpa); | |
| 54 | 52 | f.* = undefined; |
| 55 | 53 | } |
| 56 | 54 | |
| 57 | pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) anyerror!void { | |
| 55 | pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) !void { | |
| 58 | 56 | const comp = wasm.base.comp; |
| 59 | 57 | const shared_memory = comp.config.shared_memory; |
| 60 | 58 | const diags = &comp.link_diags; |
| ... | ... | @@ -115,7 +113,7 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) anyerror!void { |
| 115 | 113 | src_loc.addError(wasm, "undefined global: {s}", .{name.slice(wasm)}); |
| 116 | 114 | } |
| 117 | 115 | for (wasm.table_imports.keys(), wasm.table_imports.values()) |name, table_import_id| { |
| 118 | const src_loc = table_import_id.ptr(wasm).source_location; | |
| 116 | const src_loc = table_import_id.value(wasm).source_location; | |
| 119 | 117 | src_loc.addError(wasm, "undefined table: {s}", .{name.slice(wasm)}); |
| 120 | 118 | } |
| 121 | 119 | } |
| ... | ... | @@ -142,7 +140,7 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) anyerror!void { |
| 142 | 140 | if (!ds.flags.alive) continue; |
| 143 | 141 | const data_segment_index: Wasm.DataSegment.Index = @enumFromInt(i); |
| 144 | 142 | any_passive_inits = any_passive_inits or ds.flags.is_passive or (import_memory and !isBss(wasm, ds.name)); |
| 145 | f.data_segments.putAssumeCapacityNoClobber(data_segment_index, .{ .offset = undefined }); | |
| 143 | f.data_segments.putAssumeCapacityNoClobber(data_segment_index, @as(u32, undefined)); | |
| 146 | 144 | } |
| 147 | 145 | |
| 148 | 146 | try wasm.functions.ensureUnusedCapacity(gpa, 3); |
| ... | ... | @@ -159,8 +157,10 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) anyerror!void { |
| 159 | 157 | // When we have TLS GOT entries and shared memory is enabled, |
| 160 | 158 | // we must perform runtime relocations or else we don't create the function. |
| 161 | 159 | if (shared_memory) { |
| 162 | if (f.need_tls_relocs) wasm.functions.putAssumeCapacity(.__wasm_apply_global_tls_relocs, {}); | |
| 163 | wasm.functions.putAssumeCapacity(gpa, .__wasm_init_tls, {}); | |
| 160 | // This logic that checks `any_tls_relocs` is missing the part where it | |
| 161 | // also notices threadlocal globals from Zcu code. | |
| 162 | if (wasm.any_tls_relocs) wasm.functions.putAssumeCapacity(.__wasm_apply_global_tls_relocs, {}); | |
| 163 | wasm.functions.putAssumeCapacity(.__wasm_init_tls, {}); | |
| 164 | 164 | } |
| 165 | 165 | |
| 166 | 166 | // Sort order: |
| ... | ... | @@ -178,14 +178,14 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) anyerror!void { |
| 178 | 178 | pub fn lessThan(ctx: @This(), lhs: usize, rhs: usize) bool { |
| 179 | 179 | const lhs_segment_index = ctx.segments[lhs]; |
| 180 | 180 | const rhs_segment_index = ctx.segments[rhs]; |
| 181 | const lhs_segment = lhs_segment_index.ptr(wasm); | |
| 182 | const rhs_segment = rhs_segment_index.ptr(wasm); | |
| 181 | const lhs_segment = lhs_segment_index.ptr(ctx.wasm); | |
| 182 | const rhs_segment = rhs_segment_index.ptr(ctx.wasm); | |
| 183 | 183 | const lhs_tls = @intFromBool(lhs_segment.flags.tls); |
| 184 | 184 | const rhs_tls = @intFromBool(rhs_segment.flags.tls); |
| 185 | 185 | if (lhs_tls < rhs_tls) return true; |
| 186 | 186 | if (lhs_tls > rhs_tls) return false; |
| 187 | const lhs_prefix, const lhs_suffix = splitSegmentName(lhs_segment.name.unwrap().slice(ctx.wasm)); | |
| 188 | const rhs_prefix, const rhs_suffix = splitSegmentName(rhs_segment.name.unwrap().slice(ctx.wasm)); | |
| 187 | const lhs_prefix, const lhs_suffix = splitSegmentName(lhs_segment.name.unwrap().?.slice(ctx.wasm)); | |
| 188 | const rhs_prefix, const rhs_suffix = splitSegmentName(rhs_segment.name.unwrap().?.slice(ctx.wasm)); | |
| 189 | 189 | switch (mem.order(u8, lhs_prefix, rhs_prefix)) { |
| 190 | 190 | .lt => return true, |
| 191 | 191 | .gt => return false, |
| ... | ... | @@ -213,14 +213,14 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) anyerror!void { |
| 213 | 213 | const heap_alignment: Alignment = .@"16"; // wasm's heap alignment as specified by tool-convention |
| 214 | 214 | const pointer_alignment: Alignment = .@"4"; |
| 215 | 215 | // Always place the stack at the start by default unless the user specified the global-base flag. |
| 216 | const place_stack_first, var memory_ptr: u32 = if (wasm.global_base) |base| .{ false, base } else .{ true, 0 }; | |
| 216 | const place_stack_first, var memory_ptr: u64 = if (wasm.global_base) |base| .{ false, base } else .{ true, 0 }; | |
| 217 | 217 | |
| 218 | 218 | const VirtualAddrs = struct { |
| 219 | 219 | stack_pointer: u32, |
| 220 | 220 | heap_base: u32, |
| 221 | 221 | heap_end: u32, |
| 222 | 222 | tls_base: ?u32, |
| 223 | tls_align: ?u32, | |
| 223 | tls_align: Alignment, | |
| 224 | 224 | tls_size: ?u32, |
| 225 | 225 | init_memory_flag: ?u32, |
| 226 | 226 | }; |
| ... | ... | @@ -229,7 +229,7 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) anyerror!void { |
| 229 | 229 | .heap_base = undefined, |
| 230 | 230 | .heap_end = undefined, |
| 231 | 231 | .tls_base = null, |
| 232 | .tls_align = null, | |
| 232 | .tls_align = .none, | |
| 233 | 233 | .tls_size = null, |
| 234 | 234 | .init_memory_flag = null, |
| 235 | 235 | }; |
| ... | ... | @@ -237,7 +237,7 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) anyerror!void { |
| 237 | 237 | if (place_stack_first and !is_obj) { |
| 238 | 238 | memory_ptr = stack_alignment.forward(memory_ptr); |
| 239 | 239 | memory_ptr += wasm.base.stack_size; |
| 240 | virtual_addrs.stack_pointer = memory_ptr; | |
| 240 | virtual_addrs.stack_pointer = @intCast(memory_ptr); | |
| 241 | 241 | } |
| 242 | 242 | |
| 243 | 243 | const segment_indexes = f.data_segments.keys(); |
| ... | ... | @@ -247,27 +247,27 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) anyerror!void { |
| 247 | 247 | var seen_tls: enum { before, during, after } = .before; |
| 248 | 248 | var offset: u32 = 0; |
| 249 | 249 | for (segment_indexes, segment_offsets, 0..) |segment_index, *segment_offset, i| { |
| 250 | const segment = segment_index.ptr(f); | |
| 251 | memory_ptr = segment.alignment.forward(memory_ptr); | |
| 250 | const segment = segment_index.ptr(wasm); | |
| 251 | memory_ptr = segment.flags.alignment.forward(memory_ptr); | |
| 252 | 252 | |
| 253 | 253 | const want_new_segment = b: { |
| 254 | 254 | if (is_obj) break :b false; |
| 255 | 255 | switch (seen_tls) { |
| 256 | 256 | .before => if (segment.flags.tls) { |
| 257 | virtual_addrs.tls_base = if (shared_memory) 0 else memory_ptr; | |
| 257 | virtual_addrs.tls_base = if (shared_memory) 0 else @intCast(memory_ptr); | |
| 258 | 258 | virtual_addrs.tls_align = segment.flags.alignment; |
| 259 | 259 | seen_tls = .during; |
| 260 | 260 | break :b true; |
| 261 | 261 | }, |
| 262 | 262 | .during => if (!segment.flags.tls) { |
| 263 | virtual_addrs.tls_size = memory_ptr - virtual_addrs.tls_base; | |
| 263 | virtual_addrs.tls_size = @intCast(memory_ptr - virtual_addrs.tls_base.?); | |
| 264 | 264 | virtual_addrs.tls_align = virtual_addrs.tls_align.maxStrict(segment.flags.alignment); |
| 265 | 265 | seen_tls = .after; |
| 266 | 266 | break :b true; |
| 267 | 267 | }, |
| 268 | 268 | .after => {}, |
| 269 | 269 | } |
| 270 | break :b i >= 1 and !wasm.wantSegmentMerge(segment_indexes[i - 1], segment_index); | |
| 270 | break :b i >= 1 and !wantSegmentMerge(wasm, segment_indexes[i - 1], segment_index); | |
| 271 | 271 | }; |
| 272 | 272 | if (want_new_segment) { |
| 273 | 273 | if (offset > 0) try f.data_segment_groups.append(gpa, offset); |
| ... | ... | @@ -275,26 +275,26 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) anyerror!void { |
| 275 | 275 | } |
| 276 | 276 | |
| 277 | 277 | segment_offset.* = offset; |
| 278 | offset += segment.size; | |
| 279 | memory_ptr += segment.size; | |
| 278 | offset += segment.payload.len; | |
| 279 | memory_ptr += segment.payload.len; | |
| 280 | 280 | } |
| 281 | 281 | if (offset > 0) try f.data_segment_groups.append(gpa, offset); |
| 282 | 282 | } |
| 283 | 283 | |
| 284 | 284 | if (shared_memory and any_passive_inits) { |
| 285 | 285 | memory_ptr = pointer_alignment.forward(memory_ptr); |
| 286 | virtual_addrs.init_memory_flag = memory_ptr; | |
| 286 | virtual_addrs.init_memory_flag = @intCast(memory_ptr); | |
| 287 | 287 | memory_ptr += 4; |
| 288 | 288 | } |
| 289 | 289 | |
| 290 | 290 | if (!place_stack_first and !is_obj) { |
| 291 | 291 | memory_ptr = stack_alignment.forward(memory_ptr); |
| 292 | 292 | memory_ptr += wasm.base.stack_size; |
| 293 | virtual_addrs.stack_pointer = memory_ptr; | |
| 293 | virtual_addrs.stack_pointer = @intCast(memory_ptr); | |
| 294 | 294 | } |
| 295 | 295 | |
| 296 | 296 | memory_ptr = heap_alignment.forward(memory_ptr); |
| 297 | virtual_addrs.heap_base = memory_ptr; | |
| 297 | virtual_addrs.heap_base = @intCast(memory_ptr); | |
| 298 | 298 | |
| 299 | 299 | if (wasm.initial_memory) |initial_memory| { |
| 300 | 300 | if (!mem.isAlignedGeneric(u64, initial_memory, page_size)) { |
| ... | ... | @@ -311,7 +311,7 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) anyerror!void { |
| 311 | 311 | } else { |
| 312 | 312 | memory_ptr = mem.alignForward(u64, memory_ptr, std.wasm.page_size); |
| 313 | 313 | } |
| 314 | virtual_addrs.heap_end = memory_ptr; | |
| 314 | virtual_addrs.heap_end = @intCast(memory_ptr); | |
| 315 | 315 | |
| 316 | 316 | // In case we do not import memory, but define it ourselves, set the |
| 317 | 317 | // minimum amount of pages on the memory section. |
| ... | ... | @@ -326,7 +326,7 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) anyerror!void { |
| 326 | 326 | diags.addError("maximum memory value {d} insufficient; minimum {d}", .{ max_memory, memory_ptr }); |
| 327 | 327 | } |
| 328 | 328 | if (max_memory > std.math.maxInt(u32)) { |
| 329 | diags.addError("maximum memory exceeds 32-bit address space", .{max_memory}); | |
| 329 | diags.addError("maximum memory value {d} exceeds 32-bit address space", .{max_memory}); | |
| 330 | 330 | } |
| 331 | 331 | if (diags.hasErrors()) return error.LinkFailure; |
| 332 | 332 | wasm.memories.limits.max = @intCast(max_memory / page_size); |
| ... | ... | @@ -346,24 +346,26 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) anyerror!void { |
| 346 | 346 | const binary_bytes = &f.binary_bytes; |
| 347 | 347 | assert(binary_bytes.items.len == 0); |
| 348 | 348 | |
| 349 | try binary_bytes.appendSlice(gpa, std.wasm.magic ++ std.wasm.version); | |
| 349 | try binary_bytes.appendSlice(gpa, &std.wasm.magic ++ &std.wasm.version); | |
| 350 | 350 | assert(binary_bytes.items.len == 8); |
| 351 | 351 | |
| 352 | 352 | const binary_writer = binary_bytes.writer(gpa); |
| 353 | 353 | |
| 354 | 354 | // Type section |
| 355 | if (wasm.func_types.items.len != 0) { | |
| 355 | if (wasm.func_types.entries.len != 0) { | |
| 356 | 356 | const header_offset = try reserveVecSectionHeader(gpa, binary_bytes); |
| 357 | log.debug("Writing type section. Count: ({d})", .{wasm.func_types.items.len}); | |
| 358 | for (wasm.func_types.items) |func_type| { | |
| 357 | log.debug("Writing type section. Count: ({d})", .{wasm.func_types.entries.len}); | |
| 358 | for (wasm.func_types.keys()) |func_type| { | |
| 359 | 359 | try leb.writeUleb128(binary_writer, std.wasm.function_type); |
| 360 | try leb.writeUleb128(binary_writer, @as(u32, @intCast(func_type.params.len))); | |
| 361 | for (func_type.params) |param_ty| { | |
| 362 | try leb.writeUleb128(binary_writer, std.wasm.valtype(param_ty)); | |
| 360 | const params = func_type.params.slice(wasm); | |
| 361 | try leb.writeUleb128(binary_writer, @as(u32, @intCast(params.len))); | |
| 362 | for (params) |param_ty| { | |
| 363 | try leb.writeUleb128(binary_writer, @intFromEnum(param_ty)); | |
| 363 | 364 | } |
| 364 | try leb.writeUleb128(binary_writer, @as(u32, @intCast(func_type.returns.len))); | |
| 365 | for (func_type.returns) |ret_ty| { | |
| 366 | try leb.writeUleb128(binary_writer, std.wasm.valtype(ret_ty)); | |
| 365 | const returns = func_type.returns.slice(wasm); | |
| 366 | try leb.writeUleb128(binary_writer, @as(u32, @intCast(returns.len))); | |
| 367 | for (returns) |ret_ty| { | |
| 368 | try leb.writeUleb128(binary_writer, @intFromEnum(ret_ty)); | |
| 367 | 369 | } |
| 368 | 370 | } |
| 369 | 371 | |
| ... | ... | @@ -372,19 +374,19 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) anyerror!void { |
| 372 | 374 | header_offset, |
| 373 | 375 | .type, |
| 374 | 376 | @intCast(binary_bytes.items.len - header_offset - header_size), |
| 375 | @intCast(wasm.func_types.items.len), | |
| 377 | @intCast(wasm.func_types.entries.len), | |
| 376 | 378 | ); |
| 377 | 379 | section_index += 1; |
| 378 | 380 | } |
| 379 | 381 | |
| 380 | 382 | // Import section |
| 381 | const total_imports_len = wasm.function_imports.items.len + wasm.global_imports.items.len + | |
| 382 | wasm.table_imports.items.len + wasm.memory_imports.items.len + @intFromBool(import_memory); | |
| 383 | const total_imports_len = wasm.function_imports.entries.len + wasm.global_imports.entries.len + | |
| 384 | wasm.table_imports.entries.len + wasm.memory_imports.items.len + @intFromBool(import_memory); | |
| 383 | 385 | |
| 384 | 386 | if (total_imports_len > 0) { |
| 385 | 387 | const header_offset = try reserveVecSectionHeader(gpa, binary_bytes); |
| 386 | 388 | |
| 387 | for (wasm.function_imports.items) |*function_import| { | |
| 389 | for (wasm.function_imports.values()) |*function_import| { | |
| 388 | 390 | const module_name = function_import.module_name.slice(wasm); |
| 389 | 391 | try leb.writeUleb128(binary_writer, @as(u32, @intCast(module_name.len))); |
| 390 | 392 | try binary_writer.writeAll(module_name); |
| ... | ... | @@ -397,7 +399,7 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) anyerror!void { |
| 397 | 399 | try leb.writeUleb128(binary_writer, function_import.index); |
| 398 | 400 | } |
| 399 | 401 | |
| 400 | for (wasm.table_imports.items) |*table_import| { | |
| 402 | for (wasm.table_imports.values()) |*table_import| { | |
| 401 | 403 | const module_name = table_import.module_name.slice(wasm); |
| 402 | 404 | try leb.writeUleb128(binary_writer, @as(u32, @intCast(module_name.len))); |
| 403 | 405 | try binary_writer.writeAll(module_name); |
| ... | ... | @@ -424,7 +426,7 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) anyerror!void { |
| 424 | 426 | }); |
| 425 | 427 | } |
| 426 | 428 | |
| 427 | for (wasm.global_imports.items) |*global_import| { | |
| 429 | for (wasm.global_imports.values()) |*global_import| { | |
| 428 | 430 | const module_name = global_import.module_name.slice(wasm); |
| 429 | 431 | try leb.writeUleb128(binary_writer, @as(u32, @intCast(module_name.len))); |
| 430 | 432 | try binary_writer.writeAll(module_name); |
| ... | ... | @@ -504,7 +506,7 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) anyerror!void { |
| 504 | 506 | const header_offset = try reserveVecSectionHeader(gpa, binary_bytes); |
| 505 | 507 | |
| 506 | 508 | for (wasm.output_globals.items) |global| { |
| 507 | try binary_writer.writeByte(std.wasm.valtype(global.global_type.valtype)); | |
| 509 | try binary_writer.writeByte(@intFromEnum(global.global_type.valtype)); | |
| 508 | 510 | try binary_writer.writeByte(@intFromBool(global.global_type.mutable)); |
| 509 | 511 | try emitInit(binary_writer, global.init); |
| 510 | 512 | } |
| ... | ... | @@ -841,7 +843,7 @@ fn writeCustomSectionHeader(buffer: []u8, offset: u32, size: u32) !void { |
| 841 | 843 | buffer[offset..][0..buf.len].* = buf; |
| 842 | 844 | } |
| 843 | 845 | |
| 844 | fn reserveCustomSectionHeader(gpa: Allocator, bytes: *std.ArrayListUnmanaged(u8)) error{OutOfMemory}!u32 { | |
| 846 | fn reserveCustomSectionHeader(gpa: Allocator, bytes: *std.ArrayListUnmanaged(u8)) Allocator.Error!u32 { | |
| 845 | 847 | // unlike regular section, we don't emit the count |
| 846 | 848 | const header_size = 1 + 5; |
| 847 | 849 | try bytes.appendNTimes(gpa, 0, header_size); |
| ... | ... | @@ -1099,12 +1101,12 @@ fn wantSegmentMerge(wasm: *const Wasm, a_index: Wasm.DataSegment.Index, b_index: |
| 1099 | 1101 | if (a.flags.tls != b.flags.tls) return false; |
| 1100 | 1102 | if (a.flags.is_passive != b.flags.is_passive) return false; |
| 1101 | 1103 | if (a.name == b.name) return true; |
| 1102 | const a_prefix, _ = splitSegmentName(a.name.slice(wasm)); | |
| 1103 | const b_prefix, _ = splitSegmentName(b.name.slice(wasm)); | |
| 1104 | const a_prefix, _ = splitSegmentName(a.name.slice(wasm).?); | |
| 1105 | const b_prefix, _ = splitSegmentName(b.name.slice(wasm).?); | |
| 1104 | 1106 | return a_prefix.len > 0 and mem.eql(u8, a_prefix, b_prefix); |
| 1105 | 1107 | } |
| 1106 | 1108 | |
| 1107 | fn reserveVecSectionHeader(gpa: Allocator, bytes: *std.ArrayListUnmanaged(u8)) error{OutOfMemory}!u32 { | |
| 1109 | fn reserveVecSectionHeader(gpa: Allocator, bytes: *std.ArrayListUnmanaged(u8)) Allocator.Error!u32 { | |
| 1108 | 1110 | // section id + fixed leb contents size + fixed leb vector length |
| 1109 | 1111 | const header_size = 1 + 5 + 5; |
| 1110 | 1112 | try bytes.appendNTimes(gpa, 0, header_size); |
| ... | ... | @@ -1125,7 +1127,7 @@ fn emitLimits(writer: anytype, limits: std.wasm.Limits) !void { |
| 1125 | 1127 | if (limits.flags.has_max) try leb.writeUleb128(writer, limits.max); |
| 1126 | 1128 | } |
| 1127 | 1129 | |
| 1128 | fn emitMemoryImport(wasm: *Wasm, writer: anytype, memory_import: *const Wasm.MemoryImport) error{OutOfMemory}!void { | |
| 1130 | fn emitMemoryImport(wasm: *Wasm, writer: anytype, memory_import: *const Wasm.MemoryImport) Allocator.Error!void { | |
| 1129 | 1131 | const module_name = memory_import.module_name.slice(wasm); |
| 1130 | 1132 | try leb.writeUleb128(writer, @as(u32, @intCast(module_name.len))); |
| 1131 | 1133 | try writer.writeAll(module_name); |
src/link/Wasm/Object.zig+111-79| ... | ... | @@ -36,7 +36,7 @@ global_imports: RelativeSlice, |
| 36 | 36 | table_imports: RelativeSlice, |
| 37 | 37 | /// Points into Wasm object_custom_segments |
| 38 | 38 | custom_segments: RelativeSlice, |
| 39 | /// For calculating local section index from `Wasm.SectionIndex`. | |
| 39 | /// For calculating local section index from `Wasm.ObjectSectionIndex`. | |
| 40 | 40 | local_section_index_base: u32, |
| 41 | 41 | /// Points into Wasm object_init_funcs |
| 42 | 42 | init_funcs: RelativeSlice, |
| ... | ... | @@ -109,10 +109,10 @@ pub const Symbol = struct { |
| 109 | 109 | }, |
| 110 | 110 | data_import: void, |
| 111 | 111 | global: Wasm.ObjectGlobalIndex, |
| 112 | global_import: Wasm.ObjectGlobalImportIndex, | |
| 112 | global_import: Wasm.GlobalImport.Index, | |
| 113 | 113 | section: Wasm.ObjectSectionIndex, |
| 114 | 114 | table: Wasm.ObjectTableIndex, |
| 115 | table_import: Wasm.ObjectTableImportIndex, | |
| 115 | table_import: Wasm.TableImport.Index, | |
| 116 | 116 | }; |
| 117 | 117 | }; |
| 118 | 118 | |
| ... | ... | @@ -159,7 +159,7 @@ pub const ScratchSpace = struct { |
| 159 | 159 | } |
| 160 | 160 | }; |
| 161 | 161 | |
| 162 | fn parse( | |
| 162 | pub fn parse( | |
| 163 | 163 | wasm: *Wasm, |
| 164 | 164 | bytes: []const u8, |
| 165 | 165 | path: Path, |
| ... | ... | @@ -181,18 +181,18 @@ fn parse( |
| 181 | 181 | pos += 4; |
| 182 | 182 | |
| 183 | 183 | const data_segment_start: u32 = @intCast(wasm.object_data_segments.items.len); |
| 184 | const custom_segment_start: u32 = @intCast(wasm.object_custom_segments.items.len); | |
| 184 | const custom_segment_start: u32 = @intCast(wasm.object_custom_segments.entries.len); | |
| 185 | 185 | const functions_start: u32 = @intCast(wasm.object_functions.items.len); |
| 186 | 186 | const tables_start: u32 = @intCast(wasm.object_tables.items.len); |
| 187 | 187 | const memories_start: u32 = @intCast(wasm.object_memories.items.len); |
| 188 | 188 | const globals_start: u32 = @intCast(wasm.object_globals.items.len); |
| 189 | 189 | const init_funcs_start: u32 = @intCast(wasm.object_init_funcs.items.len); |
| 190 | 190 | const comdats_start: u32 = @intCast(wasm.object_comdats.items.len); |
| 191 | const function_imports_start: u32 = @intCast(wasm.object_function_imports.items.len); | |
| 192 | const global_imports_start: u32 = @intCast(wasm.object_global_imports.items.len); | |
| 193 | const table_imports_start: u32 = @intCast(wasm.object_table_imports.items.len); | |
| 191 | const function_imports_start: u32 = @intCast(wasm.object_function_imports.entries.len); | |
| 192 | const global_imports_start: u32 = @intCast(wasm.object_global_imports.entries.len); | |
| 193 | const table_imports_start: u32 = @intCast(wasm.object_table_imports.entries.len); | |
| 194 | 194 | const local_section_index_base = wasm.object_total_sections; |
| 195 | const source_location: Wasm.SourceLocation = .fromObjectIndex(wasm.objects.items.len); | |
| 195 | const source_location: Wasm.SourceLocation = .fromObject(@enumFromInt(wasm.objects.items.len), wasm); | |
| 196 | 196 | |
| 197 | 197 | ss.clear(); |
| 198 | 198 | |
| ... | ... | @@ -200,10 +200,9 @@ fn parse( |
| 200 | 200 | var opt_features: ?Wasm.Feature.Set = null; |
| 201 | 201 | var saw_linking_section = false; |
| 202 | 202 | var has_tls = false; |
| 203 | var local_section_index: u32 = 0; | |
| 204 | 203 | var table_count: usize = 0; |
| 205 | while (pos < bytes.len) : (local_section_index += 1) { | |
| 206 | const section_index: Wasm.SectionIndex = @enumFromInt(local_section_index_base + local_section_index); | |
| 204 | while (pos < bytes.len) : (wasm.object_total_sections += 1) { | |
| 205 | const section_index: Wasm.ObjectSectionIndex = @enumFromInt(wasm.object_total_sections); | |
| 207 | 206 | |
| 208 | 207 | const section_tag: std.wasm.Section = @enumFromInt(bytes[pos]); |
| 209 | 208 | pos += 1; |
| ... | ... | @@ -245,7 +244,7 @@ fn parse( |
| 245 | 244 | .strings = flags.strings, |
| 246 | 245 | .tls = tls, |
| 247 | 246 | .alignment = @enumFromInt(alignment), |
| 248 | .no_strip = flags.retain, | |
| 247 | .retain = flags.retain, | |
| 249 | 248 | }, |
| 250 | 249 | }; |
| 251 | 250 | } |
| ... | ... | @@ -257,13 +256,13 @@ fn parse( |
| 257 | 256 | if (symbol_index > ss.symbol_table.items.len) |
| 258 | 257 | return diags.failParse(path, "init_funcs before symbol table", .{}); |
| 259 | 258 | const sym = &ss.symbol_table.items[symbol_index]; |
| 260 | if (sym.tag != .function) { | |
| 259 | if (sym.pointee != .function) { | |
| 261 | 260 | return diags.failParse(path, "init_func symbol '{s}' not a function", .{ |
| 262 | wasm.stringSlice(sym.name), | |
| 261 | sym.name.slice(wasm).?, | |
| 263 | 262 | }); |
| 264 | 263 | } else if (sym.flags.undefined) { |
| 265 | 264 | return diags.failParse(path, "init_func symbol '{s}' is an import", .{ |
| 266 | wasm.stringSlice(sym.name), | |
| 265 | sym.name.slice(wasm).?, | |
| 267 | 266 | }); |
| 268 | 267 | } |
| 269 | 268 | func.* = .{ |
| ... | ... | @@ -278,22 +277,23 @@ fn parse( |
| 278 | 277 | const flags, pos = readLeb(u32, bytes, pos); |
| 279 | 278 | if (flags != 0) return error.UnexpectedComdatFlags; |
| 280 | 279 | const symbol_count, pos = readLeb(u32, bytes, pos); |
| 281 | const start_off: u32 = @intCast(wasm.object_comdat_symbols.items.len); | |
| 282 | for (try wasm.object_comdat_symbols.addManyAsSlice(gpa, symbol_count)) |*symbol| { | |
| 280 | const start_off: u32 = @intCast(wasm.object_comdat_symbols.len); | |
| 281 | try wasm.object_comdat_symbols.ensureUnusedCapacity(gpa, symbol_count); | |
| 282 | for (0..symbol_count) |_| { | |
| 283 | 283 | const kind, pos = readEnum(Wasm.Comdat.Symbol.Type, bytes, pos); |
| 284 | 284 | const index, pos = readLeb(u32, bytes, pos); |
| 285 | 285 | if (true) @panic("TODO rebase index depending on kind"); |
| 286 | symbol.* = .{ | |
| 286 | wasm.object_comdat_symbols.appendAssumeCapacity(.{ | |
| 287 | 287 | .kind = kind, |
| 288 | 288 | .index = index, |
| 289 | }; | |
| 289 | }); | |
| 290 | 290 | } |
| 291 | 291 | comdat.* = .{ |
| 292 | 292 | .name = try wasm.internString(name), |
| 293 | 293 | .flags = flags, |
| 294 | 294 | .symbols = .{ |
| 295 | 295 | .off = start_off, |
| 296 | .len = @intCast(wasm.object_comdat_symbols.items.len - start_off), | |
| 296 | .len = @intCast(wasm.object_comdat_symbols.len - start_off), | |
| 297 | 297 | }, |
| 298 | 298 | }; |
| 299 | 299 | } |
| ... | ... | @@ -321,7 +321,7 @@ fn parse( |
| 321 | 321 | const size, pos = readLeb(u32, bytes, pos); |
| 322 | 322 | |
| 323 | 323 | symbol.pointee = .{ .data = .{ |
| 324 | .index = @enumFromInt(data_segment_start + segment_index), | |
| 324 | .segment_index = @enumFromInt(data_segment_start + segment_index), | |
| 325 | 325 | .segment_offset = segment_offset, |
| 326 | 326 | .size = size, |
| 327 | 327 | } }; |
| ... | ... | @@ -329,7 +329,7 @@ fn parse( |
| 329 | 329 | }, |
| 330 | 330 | .section => { |
| 331 | 331 | const local_section, pos = readLeb(u32, bytes, pos); |
| 332 | const section: Wasm.SectionIndex = @enumFromInt(local_section_index_base + local_section); | |
| 332 | const section: Wasm.ObjectSectionIndex = @enumFromInt(local_section_index_base + local_section); | |
| 333 | 333 | symbol.pointee = .{ .section = section }; |
| 334 | 334 | }, |
| 335 | 335 | |
| ... | ... | @@ -337,7 +337,7 @@ fn parse( |
| 337 | 337 | const local_index, pos = readLeb(u32, bytes, pos); |
| 338 | 338 | if (symbol.flags.undefined) { |
| 339 | 339 | symbol.pointee = .{ .function_import = @enumFromInt(local_index) }; |
| 340 | if (flags.explicit_name) { | |
| 340 | if (symbol.flags.explicit_name) { | |
| 341 | 341 | const name, pos = readBytes(bytes, pos); |
| 342 | 342 | symbol.name = (try wasm.internString(name)).toOptional(); |
| 343 | 343 | } |
| ... | ... | @@ -351,7 +351,7 @@ fn parse( |
| 351 | 351 | const local_index, pos = readLeb(u32, bytes, pos); |
| 352 | 352 | if (symbol.flags.undefined) { |
| 353 | 353 | symbol.pointee = .{ .global_import = @enumFromInt(global_imports_start + local_index) }; |
| 354 | if (flags.explicit_name) { | |
| 354 | if (symbol.flags.explicit_name) { | |
| 355 | 355 | const name, pos = readBytes(bytes, pos); |
| 356 | 356 | symbol.name = (try wasm.internString(name)).toOptional(); |
| 357 | 357 | } |
| ... | ... | @@ -366,7 +366,7 @@ fn parse( |
| 366 | 366 | const local_index, pos = readLeb(u32, bytes, pos); |
| 367 | 367 | if (symbol.flags.undefined) { |
| 368 | 368 | symbol.pointee = .{ .table_import = @enumFromInt(table_imports_start + local_index) }; |
| 369 | if (flags.explicit_name) { | |
| 369 | if (symbol.flags.explicit_name) { | |
| 370 | 370 | const name, pos = readBytes(bytes, pos); |
| 371 | 371 | symbol.name = (try wasm.internString(name)).toOptional(); |
| 372 | 372 | } |
| ... | ... | @@ -377,7 +377,7 @@ fn parse( |
| 377 | 377 | } |
| 378 | 378 | }, |
| 379 | 379 | else => { |
| 380 | log.debug("unrecognized symbol type tag: {x}", .{tag}); | |
| 380 | log.debug("unrecognized symbol type tag: {x}", .{@intFromEnum(tag)}); | |
| 381 | 381 | return error.UnrecognizedSymbolType; |
| 382 | 382 | }, |
| 383 | 383 | } |
| ... | ... | @@ -396,14 +396,14 @@ fn parse( |
| 396 | 396 | // "Relocation sections can only target code, data and custom sections." |
| 397 | 397 | const local_section, pos = readLeb(u32, bytes, pos); |
| 398 | 398 | const count, pos = readLeb(u32, bytes, pos); |
| 399 | const section: Wasm.SectionIndex = @enumFromInt(local_section_index_base + local_section); | |
| 399 | const section: Wasm.ObjectSectionIndex = @enumFromInt(local_section_index_base + local_section); | |
| 400 | 400 | |
| 401 | 401 | log.debug("found {d} relocations for section={d}", .{ count, section }); |
| 402 | 402 | |
| 403 | 403 | var prev_offset: u32 = 0; |
| 404 | try wasm.relocations.ensureUnusedCapacity(gpa, count); | |
| 404 | try wasm.object_relocations.ensureUnusedCapacity(gpa, count); | |
| 405 | 405 | for (0..count) |_| { |
| 406 | const tag: Wasm.Relocation.Tag = @enumFromInt(bytes[pos]); | |
| 406 | const tag: Wasm.ObjectRelocation.Tag = @enumFromInt(bytes[pos]); | |
| 407 | 407 | pos += 1; |
| 408 | 408 | const offset, pos = readLeb(u32, bytes, pos); |
| 409 | 409 | const index, pos = readLeb(u32, bytes, pos); |
| ... | ... | @@ -426,9 +426,10 @@ fn parse( |
| 426 | 426 | .MEMORY_ADDR_TLS_SLEB64, |
| 427 | 427 | .FUNCTION_OFFSET_I32, |
| 428 | 428 | .SECTION_OFFSET_I32, |
| 429 | .FUNCTION_OFFSET_I64, | |
| 429 | 430 | => { |
| 430 | 431 | const addend: i32, pos = readLeb(i32, bytes, pos); |
| 431 | wasm.relocations.appendAssumeCapacity(.{ | |
| 432 | wasm.object_relocations.appendAssumeCapacity(.{ | |
| 432 | 433 | .tag = tag, |
| 433 | 434 | .offset = offset, |
| 434 | 435 | .pointee = .{ .section = ss.symbol_table.items[index].pointee.section }, |
| ... | ... | @@ -436,7 +437,7 @@ fn parse( |
| 436 | 437 | }); |
| 437 | 438 | }, |
| 438 | 439 | .TYPE_INDEX_LEB => { |
| 439 | wasm.relocations.appendAssumeCapacity(.{ | |
| 440 | wasm.object_relocations.appendAssumeCapacity(.{ | |
| 440 | 441 | .tag = tag, |
| 441 | 442 | .offset = offset, |
| 442 | 443 | .pointee = .{ .type_index = ss.func_types.items[index] }, |
| ... | ... | @@ -444,9 +445,19 @@ fn parse( |
| 444 | 445 | }); |
| 445 | 446 | }, |
| 446 | 447 | .FUNCTION_INDEX_LEB, |
| 448 | .FUNCTION_INDEX_I32, | |
| 447 | 449 | .GLOBAL_INDEX_LEB, |
| 450 | .GLOBAL_INDEX_I32, | |
| 451 | .TABLE_INDEX_SLEB, | |
| 452 | .TABLE_INDEX_I32, | |
| 453 | .TABLE_INDEX_SLEB64, | |
| 454 | .TABLE_INDEX_I64, | |
| 455 | .TABLE_NUMBER_LEB, | |
| 456 | .TABLE_INDEX_REL_SLEB, | |
| 457 | .TABLE_INDEX_REL_SLEB64, | |
| 458 | .TAG_INDEX_LEB, | |
| 448 | 459 | => { |
| 449 | wasm.relocations.appendAssumeCapacity(.{ | |
| 460 | wasm.object_relocations.appendAssumeCapacity(.{ | |
| 450 | 461 | .tag = tag, |
| 451 | 462 | .offset = offset, |
| 452 | 463 | .pointee = .{ .symbol_name = ss.symbol_table.items[index].name.unwrap().? }, |
| ... | ... | @@ -457,7 +468,7 @@ fn parse( |
| 457 | 468 | } |
| 458 | 469 | |
| 459 | 470 | try wasm.object_relocations_table.putNoClobber(gpa, section, .{ |
| 460 | .off = @intCast(wasm.relocations.items.len - count), | |
| 471 | .off = @intCast(wasm.object_relocations.len - count), | |
| 461 | 472 | .len = count, |
| 462 | 473 | }); |
| 463 | 474 | } else if (std.mem.eql(u8, section_name, "target_features")) { |
| ... | ... | @@ -466,15 +477,15 @@ fn parse( |
| 466 | 477 | const debug_content = bytes[pos..section_end]; |
| 467 | 478 | pos = section_end; |
| 468 | 479 | |
| 469 | const data_off: u32 = @enumFromInt(wasm.string_bytes.items.len); | |
| 480 | const data_off: u32 = @intCast(wasm.string_bytes.items.len); | |
| 470 | 481 | try wasm.string_bytes.appendSlice(gpa, debug_content); |
| 471 | 482 | |
| 472 | 483 | try wasm.object_custom_segments.put(gpa, section_index, .{ |
| 473 | .data_off = data_off, | |
| 474 | .flags = .{ | |
| 475 | .data_len = @intCast(debug_content.len), | |
| 476 | .represented = false, // set when scanning symbol table | |
| 484 | .payload = .{ | |
| 485 | .off = data_off, | |
| 486 | .len = @intCast(debug_content.len), | |
| 477 | 487 | }, |
| 488 | .flags = .{}, | |
| 478 | 489 | .section_name = try wasm.internString(section_name), |
| 479 | 490 | }); |
| 480 | 491 | } else { |
| ... | ... | @@ -483,7 +494,7 @@ fn parse( |
| 483 | 494 | }, |
| 484 | 495 | .type => { |
| 485 | 496 | const func_types_len, pos = readLeb(u32, bytes, pos); |
| 486 | for (ss.func_types.addManyAsSlice(gpa, func_types_len)) |*func_type| { | |
| 497 | for (try ss.func_types.addManyAsSlice(gpa, func_types_len)) |*func_type| { | |
| 487 | 498 | if (bytes[pos] != std.wasm.function_type) return error.ExpectedFuncType; |
| 488 | 499 | pos += 1; |
| 489 | 500 | |
| ... | ... | @@ -509,7 +520,7 @@ fn parse( |
| 509 | 520 | try ss.func_imports.append(gpa, .{ |
| 510 | 521 | .module_name = interned_module_name, |
| 511 | 522 | .name = interned_name, |
| 512 | .index = function, | |
| 523 | .function_index = @enumFromInt(function), | |
| 513 | 524 | }); |
| 514 | 525 | }, |
| 515 | 526 | .memory => { |
| ... | ... | @@ -527,24 +538,32 @@ fn parse( |
| 527 | 538 | const valtype, pos = readEnum(std.wasm.Valtype, bytes, pos); |
| 528 | 539 | const mutable = bytes[pos] == 0x01; |
| 529 | 540 | pos += 1; |
| 530 | try wasm.object_global_imports.append(gpa, .{ | |
| 541 | try wasm.object_global_imports.put(gpa, interned_name, .{ | |
| 542 | .flags = .{ | |
| 543 | .global_type = .{ | |
| 544 | .valtype = .from(valtype), | |
| 545 | .mutable = mutable, | |
| 546 | }, | |
| 547 | }, | |
| 531 | 548 | .module_name = interned_module_name, |
| 532 | .name = interned_name, | |
| 533 | .mutable = mutable, | |
| 534 | .valtype = valtype, | |
| 549 | .source_location = source_location, | |
| 550 | .resolution = .unresolved, | |
| 535 | 551 | }); |
| 536 | 552 | }, |
| 537 | 553 | .table => { |
| 538 | const reftype, pos = readEnum(std.wasm.RefType, bytes, pos); | |
| 554 | const ref_type, pos = readEnum(std.wasm.RefType, bytes, pos); | |
| 539 | 555 | const limits, pos = readLimits(bytes, pos); |
| 540 | try wasm.object_table_imports.append(gpa, .{ | |
| 556 | try wasm.object_table_imports.put(gpa, interned_name, .{ | |
| 557 | .flags = .{ | |
| 558 | .limits_has_max = limits.flags.has_max, | |
| 559 | .limits_is_shared = limits.flags.is_shared, | |
| 560 | .ref_type = .from(ref_type), | |
| 561 | }, | |
| 541 | 562 | .module_name = interned_module_name, |
| 542 | .name = interned_name, | |
| 563 | .source_location = source_location, | |
| 564 | .resolution = .unresolved, | |
| 543 | 565 | .limits_min = limits.min, |
| 544 | 566 | .limits_max = limits.max, |
| 545 | .limits_has_max = limits.flags.has_max, | |
| 546 | .limits_is_shared = limits.flags.is_shared, | |
| 547 | .reftype = reftype, | |
| 548 | 567 | }); |
| 549 | 568 | }, |
| 550 | 569 | } |
| ... | ... | @@ -553,17 +572,25 @@ fn parse( |
| 553 | 572 | .function => { |
| 554 | 573 | const functions_len, pos = readLeb(u32, bytes, pos); |
| 555 | 574 | for (try ss.func_type_indexes.addManyAsSlice(gpa, functions_len)) |*func_type_index| { |
| 556 | func_type_index.*, pos = readLeb(u32, bytes, pos); | |
| 575 | const i, pos = readLeb(u32, bytes, pos); | |
| 576 | func_type_index.* = @enumFromInt(i); | |
| 557 | 577 | } |
| 558 | 578 | }, |
| 559 | 579 | .table => { |
| 560 | 580 | const tables_len, pos = readLeb(u32, bytes, pos); |
| 561 | 581 | for (try wasm.object_tables.addManyAsSlice(gpa, tables_len)) |*table| { |
| 562 | const reftype, pos = readEnum(std.wasm.RefType, bytes, pos); | |
| 582 | const ref_type, pos = readEnum(std.wasm.RefType, bytes, pos); | |
| 563 | 583 | const limits, pos = readLimits(bytes, pos); |
| 564 | 584 | table.* = .{ |
| 565 | .reftype = reftype, | |
| 566 | .limits = limits, | |
| 585 | .name = .none, | |
| 586 | .module_name = .none, | |
| 587 | .flags = .{ | |
| 588 | .ref_type = .from(ref_type), | |
| 589 | .limits_has_max = limits.flags.has_max, | |
| 590 | .limits_is_shared = limits.flags.is_shared, | |
| 591 | }, | |
| 592 | .limits_min = limits.min, | |
| 593 | .limits_max = limits.max, | |
| 567 | 594 | }; |
| 568 | 595 | } |
| 569 | 596 | }, |
| ... | ... | @@ -582,8 +609,13 @@ fn parse( |
| 582 | 609 | pos += 1; |
| 583 | 610 | const expr, pos = try readInit(wasm, bytes, pos); |
| 584 | 611 | global.* = .{ |
| 585 | .valtype = valtype, | |
| 586 | .mutable = mutable, | |
| 612 | .name = .none, | |
| 613 | .flags = .{ | |
| 614 | .global_type = .{ | |
| 615 | .valtype = .from(valtype), | |
| 616 | .mutable = mutable, | |
| 617 | }, | |
| 618 | }, | |
| 587 | 619 | .expr = expr, |
| 588 | 620 | }; |
| 589 | 621 | } |
| ... | ... | @@ -668,8 +700,6 @@ fn parse( |
| 668 | 700 | } |
| 669 | 701 | if (!saw_linking_section) return error.MissingLinkingSection; |
| 670 | 702 | |
| 671 | wasm.object_total_sections = local_section_index_base + local_section_index; | |
| 672 | ||
| 673 | 703 | if (has_tls) { |
| 674 | 704 | const cpu_features = wasm.base.comp.root_mod.resolved_target.result.cpu.features; |
| 675 | 705 | if (!std.Target.wasm.featureSetHas(cpu_features, .atomics)) |
| ... | ... | @@ -770,7 +800,7 @@ fn parse( |
| 770 | 800 | ptr.name = symbol.name; |
| 771 | 801 | ptr.flags = symbol.flags; |
| 772 | 802 | if (symbol.flags.undefined and symbol.flags.binding == .local) { |
| 773 | const name = wasm.stringSlice(ptr.name.unwrap().?); | |
| 803 | const name = ptr.name.slice(wasm).?; | |
| 774 | 804 | diags.addParseError(path, "local symbol '{s}' references import", .{name}); |
| 775 | 805 | } |
| 776 | 806 | }, |
| ... | ... | @@ -779,7 +809,7 @@ fn parse( |
| 779 | 809 | const ptr = i.ptr(wasm); |
| 780 | 810 | ptr.flags = symbol.flags; |
| 781 | 811 | if (symbol.flags.undefined and symbol.flags.binding == .local) { |
| 782 | const name = wasm.stringSlice(ptr.name); | |
| 812 | const name = ptr.name.slice(wasm); | |
| 783 | 813 | diags.addParseError(path, "local symbol '{s}' references import", .{name}); |
| 784 | 814 | } |
| 785 | 815 | }, |
| ... | ... | @@ -806,19 +836,20 @@ fn parse( |
| 806 | 836 | data.flags.no_strip = info.flags.retain; |
| 807 | 837 | data.flags.alignment = info.flags.alignment; |
| 808 | 838 | if (data.flags.undefined and data.flags.binding == .local) { |
| 809 | const name = wasm.stringSlice(info.name); | |
| 839 | const name = info.name.slice(wasm); | |
| 810 | 840 | diags.addParseError(path, "local symbol '{s}' references import", .{name}); |
| 811 | 841 | } |
| 812 | 842 | } |
| 813 | 843 | |
| 814 | 844 | // Check for indirect function table in case of an MVP object file. |
| 815 | 845 | legacy_indirect_function_table: { |
| 816 | const table_imports = wasm.object_table_imports.items[table_imports_start..]; | |
| 846 | const table_import_names = wasm.object_table_imports.keys()[table_imports_start..]; | |
| 847 | const table_import_values = wasm.object_table_imports.values()[table_imports_start..]; | |
| 817 | 848 | // If there is a symbol for each import table, this is not a legacy object file. |
| 818 | if (table_imports.len == table_count) break :legacy_indirect_function_table; | |
| 849 | if (table_import_names.len == table_count) break :legacy_indirect_function_table; | |
| 819 | 850 | if (table_count != 0) { |
| 820 | 851 | return diags.failParse(path, "expected a table entry symbol for each of the {d} table(s), but instead got {d} symbols.", .{ |
| 821 | table_imports.len, table_count, | |
| 852 | table_import_names.len, table_count, | |
| 822 | 853 | }); |
| 823 | 854 | } |
| 824 | 855 | // MVP object files cannot have any table definitions, only |
| ... | ... | @@ -827,16 +858,16 @@ fn parse( |
| 827 | 858 | if (tables.len > 0) { |
| 828 | 859 | return diags.failParse(path, "table definition without representing table symbols", .{}); |
| 829 | 860 | } |
| 830 | if (table_imports.len != 1) { | |
| 861 | if (table_import_names.len != 1) { | |
| 831 | 862 | return diags.failParse(path, "found more than one table import, but no representing table symbols", .{}); |
| 832 | 863 | } |
| 833 | const table_import_name = table_imports[0].name; | |
| 864 | const table_import_name = table_import_names[0]; | |
| 834 | 865 | if (table_import_name != wasm.preloaded_strings.__indirect_function_table) { |
| 835 | 866 | return diags.failParse(path, "non-indirect function table import '{s}' is missing a corresponding symbol", .{ |
| 836 | wasm.stringSlice(table_import_name), | |
| 867 | table_import_name.slice(wasm), | |
| 837 | 868 | }); |
| 838 | 869 | } |
| 839 | table_imports[0].flags = .{ | |
| 870 | table_import_values[0].flags = .{ | |
| 840 | 871 | .undefined = true, |
| 841 | 872 | .no_strip = true, |
| 842 | 873 | }; |
| ... | ... | @@ -874,11 +905,11 @@ fn parse( |
| 874 | 905 | }, |
| 875 | 906 | .function_imports = .{ |
| 876 | 907 | .off = function_imports_start, |
| 877 | .len = @intCast(wasm.object_function_imports.items.len - function_imports_start), | |
| 908 | .len = @intCast(wasm.object_function_imports.entries.len - function_imports_start), | |
| 878 | 909 | }, |
| 879 | 910 | .global_imports = .{ |
| 880 | 911 | .off = global_imports_start, |
| 881 | .len = @intCast(wasm.object_global_imports.items.len - global_imports_start), | |
| 912 | .len = @intCast(wasm.object_global_imports.entries.len - global_imports_start), | |
| 882 | 913 | }, |
| 883 | 914 | .table_imports = .{ |
| 884 | 915 | .off = table_imports_start, |
| ... | ... | @@ -894,7 +925,7 @@ fn parse( |
| 894 | 925 | }, |
| 895 | 926 | .custom_segments = .{ |
| 896 | 927 | .off = custom_segment_start, |
| 897 | .len = @intCast(wasm.object_custom_segments.items.len - custom_segment_start), | |
| 928 | .len = @intCast(wasm.object_custom_segments.entries.len - custom_segment_start), | |
| 898 | 929 | }, |
| 899 | 930 | .local_section_index_base = local_section_index_base, |
| 900 | 931 | }; |
| ... | ... | @@ -920,7 +951,7 @@ fn parseFeatures( |
| 920 | 951 | '-' => .@"-", |
| 921 | 952 | '+' => .@"+", |
| 922 | 953 | '=' => .@"=", |
| 923 | else => return error.InvalidFeaturePrefix, | |
| 954 | else => |b| return diags.failParse(path, "invalid feature prefix: 0x{x}", .{b}), | |
| 924 | 955 | }; |
| 925 | 956 | pos += 1; |
| 926 | 957 | const name, pos = readBytes(bytes, pos); |
| ... | ... | @@ -935,7 +966,7 @@ fn parseFeatures( |
| 935 | 966 | std.mem.sortUnstable(Wasm.Feature, feature_buffer, {}, Wasm.Feature.lessThan); |
| 936 | 967 | |
| 937 | 968 | return .{ |
| 938 | .fromString(try wasm.internString(@bitCast(feature_buffer))), | |
| 969 | .fromString(try wasm.internString(@ptrCast(feature_buffer))), | |
| 939 | 970 | pos, |
| 940 | 971 | }; |
| 941 | 972 | } |
| ... | ... | @@ -966,9 +997,9 @@ fn readEnum(comptime T: type, bytes: []const u8, pos: usize) struct { T, usize } |
| 966 | 997 | } |
| 967 | 998 | |
| 968 | 999 | fn readLimits(bytes: []const u8, start_pos: usize) struct { std.wasm.Limits, usize } { |
| 969 | const flags = bytes[start_pos]; | |
| 1000 | const flags: std.wasm.Limits.Flags = @bitCast(bytes[start_pos]); | |
| 970 | 1001 | const min, const max_pos = readLeb(u32, bytes, start_pos + 1); |
| 971 | const max, const end_pos = if (flags.has_max) readLeb(u32, bytes, max_pos) else .{ undefined, max_pos }; | |
| 1002 | const max, const end_pos = if (flags.has_max) readLeb(u32, bytes, max_pos) else .{ 0, max_pos }; | |
| 972 | 1003 | return .{ .{ |
| 973 | 1004 | .flags = flags, |
| 974 | 1005 | .min = min, |
| ... | ... | @@ -977,7 +1008,7 @@ fn readLimits(bytes: []const u8, start_pos: usize) struct { std.wasm.Limits, usi |
| 977 | 1008 | } |
| 978 | 1009 | |
| 979 | 1010 | fn readInit(wasm: *Wasm, bytes: []const u8, pos: usize) !struct { Wasm.Expr, usize } { |
| 980 | const end_pos = skipInit(bytes, pos); // one after the end opcode | |
| 1011 | const end_pos = try skipInit(bytes, pos); // one after the end opcode | |
| 981 | 1012 | return .{ try wasm.addExpr(bytes[pos..end_pos]), end_pos }; |
| 982 | 1013 | } |
| 983 | 1014 | |
| ... | ... | @@ -991,6 +1022,7 @@ fn skipInit(bytes: []const u8, pos: usize) !usize { |
| 991 | 1022 | .global_get => readLeb(u32, bytes, pos + 1)[1], |
| 992 | 1023 | else => return error.InvalidInitOpcode, |
| 993 | 1024 | }; |
| 994 | if (readEnum(std.wasm.Opcode, bytes, end_pos) != .end) return error.InitExprMissingEnd; | |
| 995 | return end_pos + 1; | |
| 1025 | const op, const final_pos = readEnum(std.wasm.Opcode, bytes, end_pos); | |
| 1026 | if (op != .end) return error.InitExprMissingEnd; | |
| 1027 | return final_pos; | |
| 996 | 1028 | } |