| 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,7 +89,7 @@ pub fn lowerToCode(emit: *Emit) Error!void { |
| 89 | if (is_obj) { | 89 | if (is_obj) { |
| 90 | try wasm.out_relocs.append(gpa, .{ | 90 | try wasm.out_relocs.append(gpa, .{ |
| 91 | .offset = @intCast(code.items.len), | 91 | .offset = @intCast(code.items.len), |
| 92 | .index = try wasm.errorNameTableSymbolIndex(), | 92 | .pointee = .{ .symbol_index = try wasm.errorNameTableSymbolIndex() }, |
| 93 | .tag = if (is_wasm32) .MEMORY_ADDR_LEB else .MEMORY_ADDR_LEB64, | 93 | .tag = if (is_wasm32) .MEMORY_ADDR_LEB else .MEMORY_ADDR_LEB64, |
| 94 | .addend = 0, | 94 | .addend = 0, |
| 95 | }); | 95 | }); |
| ... | @@ -143,7 +143,7 @@ pub fn lowerToCode(emit: *Emit) Error!void { | ... | @@ -143,7 +143,7 @@ pub fn lowerToCode(emit: *Emit) Error!void { |
| 143 | if (is_obj) { | 143 | if (is_obj) { |
| 144 | try wasm.out_relocs.append(gpa, .{ | 144 | try wasm.out_relocs.append(gpa, .{ |
| 145 | .offset = @intCast(code.items.len), | 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 | .tag = .FUNCTION_INDEX_LEB, | 147 | .tag = .FUNCTION_INDEX_LEB, |
| 148 | .addend = 0, | 148 | .addend = 0, |
| 149 | }); | 149 | }); |
| ... | @@ -164,7 +164,7 @@ pub fn lowerToCode(emit: *Emit) Error!void { | ... | @@ -164,7 +164,7 @@ pub fn lowerToCode(emit: *Emit) Error!void { |
| 164 | if (is_obj) { | 164 | if (is_obj) { |
| 165 | try wasm.out_relocs.append(gpa, .{ | 165 | try wasm.out_relocs.append(gpa, .{ |
| 166 | .offset = @intCast(code.items.len), | 166 | .offset = @intCast(code.items.len), |
| 167 | .index = func_ty_index, | 167 | .pointee = .{ .type_index = func_ty_index }, |
| 168 | .tag = .TYPE_INDEX_LEB, | 168 | .tag = .TYPE_INDEX_LEB, |
| 169 | .addend = 0, | 169 | .addend = 0, |
| 170 | }); | 170 | }); |
| ... | @@ -184,7 +184,7 @@ pub fn lowerToCode(emit: *Emit) Error!void { | ... | @@ -184,7 +184,7 @@ pub fn lowerToCode(emit: *Emit) Error!void { |
| 184 | if (is_obj) { | 184 | if (is_obj) { |
| 185 | try wasm.out_relocs.append(gpa, .{ | 185 | try wasm.out_relocs.append(gpa, .{ |
| 186 | .offset = @intCast(code.items.len), | 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 | .tag = .FUNCTION_INDEX_LEB, | 188 | .tag = .FUNCTION_INDEX_LEB, |
| 189 | .addend = 0, | 189 | .addend = 0, |
| 190 | }); | 190 | }); |
| ... | @@ -209,7 +209,7 @@ pub fn lowerToCode(emit: *Emit) Error!void { | ... | @@ -209,7 +209,7 @@ pub fn lowerToCode(emit: *Emit) Error!void { |
| 209 | if (is_obj) { | 209 | if (is_obj) { |
| 210 | try wasm.out_relocs.append(gpa, .{ | 210 | try wasm.out_relocs.append(gpa, .{ |
| 211 | .offset = @intCast(code.items.len), | 211 | .offset = @intCast(code.items.len), |
| 212 | .index = try wasm.symbolNameIndex(symbol_name), | 212 | .pointee = .{ .symbol_index = try wasm.symbolNameIndex(symbol_name) }, |
| 213 | .tag = .FUNCTION_INDEX_LEB, | 213 | .tag = .FUNCTION_INDEX_LEB, |
| 214 | .addend = 0, | 214 | .addend = 0, |
| 215 | }); | 215 | }); |
| ... | @@ -229,7 +229,7 @@ pub fn lowerToCode(emit: *Emit) Error!void { | ... | @@ -229,7 +229,7 @@ pub fn lowerToCode(emit: *Emit) Error!void { |
| 229 | if (is_obj) { | 229 | if (is_obj) { |
| 230 | try wasm.out_relocs.append(gpa, .{ | 230 | try wasm.out_relocs.append(gpa, .{ |
| 231 | .offset = @intCast(code.items.len), | 231 | .offset = @intCast(code.items.len), |
| 232 | .index = try wasm.stackPointerSymbolIndex(), | 232 | .pointee = .{ .symbol_index = try wasm.stackPointerSymbolIndex() }, |
| 233 | .tag = .GLOBAL_INDEX_LEB, | 233 | .tag = .GLOBAL_INDEX_LEB, |
| 234 | .addend = 0, | 234 | .addend = 0, |
| 235 | }); | 235 | }); |
| ... | @@ -249,7 +249,7 @@ pub fn lowerToCode(emit: *Emit) Error!void { | ... | @@ -249,7 +249,7 @@ pub fn lowerToCode(emit: *Emit) Error!void { |
| 249 | if (is_obj) { | 249 | if (is_obj) { |
| 250 | try wasm.out_relocs.append(gpa, .{ | 250 | try wasm.out_relocs.append(gpa, .{ |
| 251 | .offset = @intCast(code.items.len), | 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 | .tag = .TABLE_INDEX_SLEB, | 253 | .tag = .TABLE_INDEX_SLEB, |
| 254 | .addend = 0, | 254 | .addend = 0, |
| 255 | }); | 255 | }); |
| ... | @@ -691,7 +691,7 @@ fn uavRefOff(wasm: *link.File.Wasm, code: *std.ArrayListUnmanaged(u8), data: Mir | ... | @@ -691,7 +691,7 @@ fn uavRefOff(wasm: *link.File.Wasm, code: *std.ArrayListUnmanaged(u8), data: Mir |
| 691 | if (is_obj) { | 691 | if (is_obj) { |
| 692 | try wasm.out_relocs.append(gpa, .{ | 692 | try wasm.out_relocs.append(gpa, .{ |
| 693 | .offset = @intCast(code.items.len), | 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 | .tag = if (is_wasm32) .MEMORY_ADDR_LEB else .MEMORY_ADDR_LEB64, | 695 | .tag = if (is_wasm32) .MEMORY_ADDR_LEB else .MEMORY_ADDR_LEB64, |
| 696 | .addend = data.offset, | 696 | .addend = data.offset, |
| 697 | }); | 697 | }); |
| ... | @@ -700,7 +700,7 @@ fn uavRefOff(wasm: *link.File.Wasm, code: *std.ArrayListUnmanaged(u8), data: Mir | ... | @@ -700,7 +700,7 @@ fn uavRefOff(wasm: *link.File.Wasm, code: *std.ArrayListUnmanaged(u8), data: Mir |
| 700 | } | 700 | } |
| 701 | 701 | ||
| 702 | // When linking into the final binary, no relocation mechanism is necessary. | 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 | leb.writeUleb128(code.fixedWriter(), addr + data.offset) catch unreachable; | 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,13 +720,13 @@ fn navRefOff(wasm: *link.File.Wasm, code: *std.ArrayListUnmanaged(u8), data: Mir |
| 720 | if (is_obj) { | 720 | if (is_obj) { |
| 721 | try wasm.out_relocs.append(gpa, .{ | 721 | try wasm.out_relocs.append(gpa, .{ |
| 722 | .offset = @intCast(code.items.len), | 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 | .tag = .TABLE_INDEX_SLEB, | 724 | .tag = .TABLE_INDEX_SLEB, |
| 725 | .addend = data.offset, | 725 | .addend = data.offset, |
| 726 | }); | 726 | }); |
| 727 | code.appendNTimesAssumeCapacity(0, 5); | 727 | code.appendNTimesAssumeCapacity(0, 5); |
| 728 | } else { | 728 | } else { |
| 729 | const addr: i64 = try wasm.navAddr(data.nav_index); | 729 | const addr = try wasm.navAddr(data.nav_index); |
| 730 | leb.writeUleb128(code.fixedWriter(), addr + data.offset) catch unreachable; | 730 | leb.writeUleb128(code.fixedWriter(), addr + data.offset) catch unreachable; |
| 731 | } | 731 | } |
| 732 | } else { | 732 | } else { |
| ... | @@ -735,13 +735,13 @@ fn navRefOff(wasm: *link.File.Wasm, code: *std.ArrayListUnmanaged(u8), data: Mir | ... | @@ -735,13 +735,13 @@ fn navRefOff(wasm: *link.File.Wasm, code: *std.ArrayListUnmanaged(u8), data: Mir |
| 735 | if (is_obj) { | 735 | if (is_obj) { |
| 736 | try wasm.out_relocs.append(gpa, .{ | 736 | try wasm.out_relocs.append(gpa, .{ |
| 737 | .offset = @intCast(code.items.len), | 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 | .tag = if (is_wasm32) .MEMORY_ADDR_LEB else .MEMORY_ADDR_LEB64, | 739 | .tag = if (is_wasm32) .MEMORY_ADDR_LEB else .MEMORY_ADDR_LEB64, |
| 740 | .addend = data.offset, | 740 | .addend = data.offset, |
| 741 | }); | 741 | }); |
| 742 | code.appendNTimesAssumeCapacity(0, if (is_wasm32) 5 else 10); | 742 | code.appendNTimesAssumeCapacity(0, if (is_wasm32) 5 else 10); |
| 743 | } else { | 743 | } else { |
| 744 | const addr: i64 = try wasm.navAddr(data.nav_index); | 744 | const addr = try wasm.navAddr(data.nav_index); |
| 745 | leb.writeUleb128(code.fixedWriter(), addr + data.offset) catch unreachable; | 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,7 +2,6 @@ const std = @import("std"); |
| 2 | const build_options = @import("build_options"); | 2 | const build_options = @import("build_options"); |
| 3 | const builtin = @import("builtin"); | 3 | const builtin = @import("builtin"); |
| 4 | const assert = std.debug.assert; | 4 | const assert = std.debug.assert; |
| 5 | const leb128 = std.leb; | ||
| 6 | const link = @import("link.zig"); | 5 | const link = @import("link.zig"); |
| 7 | const log = std.log.scoped(.codegen); | 6 | const log = std.log.scoped(.codegen); |
| 8 | const mem = std.mem; | 7 | const mem = std.mem; |
| ... | @@ -643,15 +642,19 @@ fn lowerUavRef( | ... | @@ -643,15 +642,19 @@ fn lowerUavRef( |
| 643 | const zcu = pt.zcu; | 642 | const zcu = pt.zcu; |
| 644 | const gpa = zcu.gpa; | 643 | const gpa = zcu.gpa; |
| 645 | const ip = &zcu.intern_pool; | 644 | const ip = &zcu.intern_pool; |
| 646 | const target = lf.comp.root_mod.resolved_target.result; | 645 | const comp = lf.comp; |
| 647 | 646 | const target = &comp.root_mod.resolved_target.result; | |
| 648 | const ptr_width_bytes = @divExact(target.ptrBitWidth(), 8); | 647 | const ptr_width_bytes = @divExact(target.ptrBitWidth(), 8); |
| 648 | const is_obj = comp.config.output_mode == .Obj; | ||
| 649 | const uav_val = uav.val; | 649 | const uav_val = uav.val; |
| 650 | const uav_ty = Type.fromInterned(ip.typeOf(uav_val)); | 650 | const uav_ty = Type.fromInterned(ip.typeOf(uav_val)); |
| 651 | log.debug("lowerUavRef: ty = {}", .{uav_ty.fmt(pt)}); | ||
| 652 | const is_fn_body = uav_ty.zigTypeTag(zcu) == .@"fn"; | 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 | if (!is_fn_body and !uav_ty.hasRuntimeBits(zcu)) { | 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 | return; | 658 | return; |
| 656 | } | 659 | } |
| 657 | 660 | ||
| ... | @@ -663,13 +666,20 @@ fn lowerUavRef( | ... | @@ -663,13 +666,20 @@ fn lowerUavRef( |
| 663 | dev.check(link.File.Tag.wasm.devFeature()); | 666 | dev.check(link.File.Tag.wasm.devFeature()); |
| 664 | const wasm = lf.cast(.wasm).?; | 667 | const wasm = lf.cast(.wasm).?; |
| 665 | assert(reloc_parent == .none); | 668 | assert(reloc_parent == .none); |
| 666 | try wasm.relocations.append(gpa, .{ | 669 | if (is_obj) { |
| 667 | .tag = .uav_index, | 670 | try wasm.out_relocs.append(gpa, .{ |
| 668 | .addend = @intCast(offset), | 671 | .offset = @intCast(code.items.len), |
| 669 | .offset = @intCast(code.items.len), | 672 | .pointee = .{ .symbol_index = try wasm.uavSymbolIndex(uav.val) }, |
| 670 | .pointee = .{ .uav_index = uav.val }, | 673 | .tag = if (ptr_width_bytes == 4) .MEMORY_ADDR_I32 else .MEMORY_ADDR_I64, |
| 671 | }); | 674 | .addend = @intCast(offset), |
| 672 | try code.appendNTimes(gpa, 0, ptr_width_bytes); | 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 | return; | 683 | return; |
| 674 | }, | 684 | }, |
| 675 | else => {}, | 685 | else => {}, |
| ... | @@ -688,9 +698,9 @@ fn lowerUavRef( | ... | @@ -688,9 +698,9 @@ fn lowerUavRef( |
| 688 | }); | 698 | }); |
| 689 | const endian = target.cpu.arch.endian(); | 699 | const endian = target.cpu.arch.endian(); |
| 690 | switch (ptr_width_bytes) { | 700 | switch (ptr_width_bytes) { |
| 691 | 2 => mem.writeInt(u16, try code.addManyAsArray(gpa, 2), @intCast(vaddr), endian), | 701 | 2 => mem.writeInt(u16, code.addManyAsArrayAssumeCapacity(2), @intCast(vaddr), endian), |
| 692 | 4 => mem.writeInt(u32, try code.addManyAsArray(gpa, 4), @intCast(vaddr), endian), | 702 | 4 => mem.writeInt(u32, code.addManyAsArrayAssumeCapacity(4), @intCast(vaddr), endian), |
| 693 | 8 => mem.writeInt(u64, try code.addManyAsArray(gpa, 8), vaddr, endian), | 703 | 8 => mem.writeInt(u64, code.addManyAsArrayAssumeCapacity(8), vaddr, endian), |
| 694 | else => unreachable, | 704 | else => unreachable, |
| 695 | } | 705 | } |
| 696 | } | 706 | } |
| ... | @@ -709,12 +719,15 @@ fn lowerNavRef( | ... | @@ -709,12 +719,15 @@ fn lowerNavRef( |
| 709 | const gpa = zcu.gpa; | 719 | const gpa = zcu.gpa; |
| 710 | const ip = &zcu.intern_pool; | 720 | const ip = &zcu.intern_pool; |
| 711 | const target = zcu.navFileScope(nav_index).mod.resolved_target.result; | 721 | const target = zcu.navFileScope(nav_index).mod.resolved_target.result; |
| 712 | |||
| 713 | const ptr_width_bytes = @divExact(target.ptrBitWidth(), 8); | 722 | const ptr_width_bytes = @divExact(target.ptrBitWidth(), 8); |
| 723 | const is_obj = lf.comp.config.output_mode == .Obj; | ||
| 714 | const nav_ty = Type.fromInterned(ip.getNav(nav_index).typeOf(ip)); | 724 | const nav_ty = Type.fromInterned(ip.getNav(nav_index).typeOf(ip)); |
| 715 | const is_fn_body = nav_ty.zigTypeTag(zcu) == .@"fn"; | 725 | const is_fn_body = nav_ty.zigTypeTag(zcu) == .@"fn"; |
| 726 | |||
| 727 | try code.ensureUnusedCapacity(gpa, ptr_width_bytes); | ||
| 728 | |||
| 716 | if (!is_fn_body and !nav_ty.hasRuntimeBits(zcu)) { | 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 | return; | 731 | return; |
| 719 | } | 732 | } |
| 720 | 733 | ||
| ... | @@ -726,13 +739,20 @@ fn lowerNavRef( | ... | @@ -726,13 +739,20 @@ fn lowerNavRef( |
| 726 | dev.check(link.File.Tag.wasm.devFeature()); | 739 | dev.check(link.File.Tag.wasm.devFeature()); |
| 727 | const wasm = lf.cast(.wasm).?; | 740 | const wasm = lf.cast(.wasm).?; |
| 728 | assert(reloc_parent == .none); | 741 | assert(reloc_parent == .none); |
| 729 | try wasm.relocations.append(gpa, .{ | 742 | if (is_obj) { |
| 730 | .tag = .nav_index, | 743 | try wasm.out_relocs.append(gpa, .{ |
| 731 | .addend = @intCast(offset), | 744 | .offset = @intCast(code.items.len), |
| 732 | .offset = @intCast(code.items.len), | 745 | .pointee = .{ .symbol_index = try wasm.navSymbolIndex(nav_index) }, |
| 733 | .pointee = .{ .nav_index = nav_index }, | 746 | .tag = if (ptr_width_bytes == 4) .MEMORY_ADDR_I32 else .MEMORY_ADDR_I64, |
| 734 | }); | 747 | .addend = @intCast(offset), |
| 735 | try code.appendNTimes(gpa, 0, ptr_width_bytes); | 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 | return; | 756 | return; |
| 737 | }, | 757 | }, |
| 738 | else => {}, | 758 | else => {}, |
| ... | @@ -745,9 +765,9 @@ fn lowerNavRef( | ... | @@ -745,9 +765,9 @@ fn lowerNavRef( |
| 745 | }) catch @panic("TODO rework getNavVAddr"); | 765 | }) catch @panic("TODO rework getNavVAddr"); |
| 746 | const endian = target.cpu.arch.endian(); | 766 | const endian = target.cpu.arch.endian(); |
| 747 | switch (ptr_width_bytes) { | 767 | switch (ptr_width_bytes) { |
| 748 | 2 => mem.writeInt(u16, try code.addManyAsArray(gpa, 2), @intCast(vaddr), endian), | 768 | 2 => mem.writeInt(u16, code.addManyAsArrayAssumeCapacity(2), @intCast(vaddr), endian), |
| 749 | 4 => mem.writeInt(u32, try code.addManyAsArray(gpa, 4), @intCast(vaddr), endian), | 769 | 4 => mem.writeInt(u32, code.addManyAsArrayAssumeCapacity(4), @intCast(vaddr), endian), |
| 750 | 8 => mem.writeInt(u64, try code.addManyAsArray(gpa, 8), vaddr, endian), | 770 | 8 => mem.writeInt(u64, code.addManyAsArrayAssumeCapacity(8), vaddr, endian), |
| 751 | else => unreachable, | 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,7 +100,7 @@ object_global_imports: std.AutoArrayHashMapUnmanaged(String, GlobalImport) = .em |
| 100 | object_globals: std.ArrayListUnmanaged(Global) = .empty, | 100 | object_globals: std.ArrayListUnmanaged(Global) = .empty, |
| 101 | 101 | ||
| 102 | /// All table imports for all objects. | 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 | /// All parsed table sections for all objects. | 104 | /// All parsed table sections for all objects. |
| 105 | object_tables: std.ArrayListUnmanaged(Table) = .empty, | 105 | object_tables: std.ArrayListUnmanaged(Table) = .empty, |
| 106 | 106 | ||
| ... | @@ -109,12 +109,28 @@ object_memory_imports: std.ArrayListUnmanaged(MemoryImport) = .empty, | ... | @@ -109,12 +109,28 @@ object_memory_imports: std.ArrayListUnmanaged(MemoryImport) = .empty, |
| 109 | /// All parsed memory sections for all objects. | 109 | /// All parsed memory sections for all objects. |
| 110 | object_memories: std.ArrayListUnmanaged(std.wasm.Memory) = .empty, | 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 | /// List of initialization functions. These must be called in order of priority | 116 | /// List of initialization functions. These must be called in order of priority |
| 113 | /// by the (synthetic) __wasm_call_ctors function. | 117 | /// by the (synthetic) __wasm_call_ctors function. |
| 114 | object_init_funcs: std.ArrayListUnmanaged(InitFunc) = .empty, | 118 | object_init_funcs: std.ArrayListUnmanaged(InitFunc) = .empty, |
| 115 | /// All relocations from all objects concatenated. `relocs_start` marks the end | 119 | |
| 116 | /// point of object relocations and start point of Zcu relocations. | 120 | /// Relocations to be emitted into an object file. Remains empty when not |
| 117 | relocations: std.MultiArrayList(Relocation) = .empty, | 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 | /// Non-synthetic section that can essentially be mem-cpy'd into place after performing relocations. | 135 | /// Non-synthetic section that can essentially be mem-cpy'd into place after performing relocations. |
| 120 | object_data_segments: std.ArrayListUnmanaged(DataSegment) = .empty, | 136 | object_data_segments: std.ArrayListUnmanaged(DataSegment) = .empty, |
| ... | @@ -125,7 +141,7 @@ object_custom_segments: std.AutoArrayHashMapUnmanaged(ObjectSectionIndex, Custom | ... | @@ -125,7 +141,7 @@ object_custom_segments: std.AutoArrayHashMapUnmanaged(ObjectSectionIndex, Custom |
| 125 | object_comdats: std.ArrayListUnmanaged(Comdat) = .empty, | 141 | object_comdats: std.ArrayListUnmanaged(Comdat) = .empty, |
| 126 | /// A table that maps the relocations to be performed where the key represents | 142 | /// A table that maps the relocations to be performed where the key represents |
| 127 | /// the section (across all objects) that the slice of relocations applies to. | 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 | /// Incremented across all objects in order to enable calculation of `ObjectSectionIndex` values. | 145 | /// Incremented across all objects in order to enable calculation of `ObjectSectionIndex` values. |
| 130 | object_total_sections: u32 = 0, | 146 | object_total_sections: u32 = 0, |
| 131 | /// All comdat symbols from all objects concatenated. | 147 | /// All comdat symbols from all objects concatenated. |
| ... | @@ -151,7 +167,10 @@ dump_argv_list: std.ArrayListUnmanaged([]const u8), | ... | @@ -151,7 +167,10 @@ dump_argv_list: std.ArrayListUnmanaged([]const u8), |
| 151 | 167 | ||
| 152 | preloaded_strings: PreloadedStrings, | 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 | zcu_funcs: std.AutoArrayHashMapUnmanaged(InternPool.Index, ZcuFunc) = .empty, | 174 | zcu_funcs: std.AutoArrayHashMapUnmanaged(InternPool.Index, ZcuFunc) = .empty, |
| 156 | nav_exports: std.AutoArrayHashMapUnmanaged(NavExport, Zcu.Export.Index) = .empty, | 175 | nav_exports: std.AutoArrayHashMapUnmanaged(NavExport, Zcu.Export.Index) = .empty, |
| 157 | uav_exports: std.AutoArrayHashMapUnmanaged(UavExport, Zcu.Export.Index) = .empty, | 176 | uav_exports: std.AutoArrayHashMapUnmanaged(UavExport, Zcu.Export.Index) = .empty, |
| ... | @@ -201,9 +220,14 @@ global_imports: std.AutoArrayHashMapUnmanaged(String, GlobalImportId) = .empty, | ... | @@ -201,9 +220,14 @@ global_imports: std.AutoArrayHashMapUnmanaged(String, GlobalImportId) = .empty, |
| 201 | /// Ordered list of non-import tables that will appear in the final binary. | 220 | /// Ordered list of non-import tables that will appear in the final binary. |
| 202 | /// Empty until prelink. | 221 | /// Empty until prelink. |
| 203 | tables: std.AutoArrayHashMapUnmanaged(TableImport.Resolution, void) = .empty, | 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 | any_exports_updated: bool = true, | 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 | /// All MIR instructions for all Zcu functions. | 232 | /// All MIR instructions for all Zcu functions. |
| 209 | mir_instructions: std.MultiArrayList(Mir.Inst) = .{}, | 233 | mir_instructions: std.MultiArrayList(Mir.Inst) = .{}, |
| ... | @@ -212,6 +236,18 @@ mir_extra: std.ArrayListUnmanaged(u32) = .empty, | ... | @@ -212,6 +236,18 @@ mir_extra: std.ArrayListUnmanaged(u32) = .empty, |
| 212 | /// All local types for all Zcu functions. | 236 | /// All local types for all Zcu functions. |
| 213 | all_zcu_locals: std.ArrayListUnmanaged(u8) = .empty, | 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 | /// Index into `objects`. | 251 | /// Index into `objects`. |
| 216 | pub const ObjectIndex = enum(u32) { | 252 | pub const ObjectIndex = enum(u32) { |
| 217 | _, | 253 | _, |
| ... | @@ -300,6 +336,10 @@ pub const SourceLocation = enum(u32) { | ... | @@ -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 | pub fn addError(sl: SourceLocation, wasm: *Wasm, comptime f: []const u8, args: anytype) void { | 343 | pub fn addError(sl: SourceLocation, wasm: *Wasm, comptime f: []const u8, args: anytype) void { |
| 304 | const diags = &wasm.base.comp.link_diags; | 344 | const diags = &wasm.base.comp.link_diags; |
| 305 | switch (sl.unpack(wasm)) { | 345 | switch (sl.unpack(wasm)) { |
| ... | @@ -345,7 +385,7 @@ pub const SymbolFlags = packed struct(u32) { | ... | @@ -345,7 +385,7 @@ pub const SymbolFlags = packed struct(u32) { |
| 345 | 385 | ||
| 346 | // Above here matches the tooling conventions ABI. | 386 | // Above here matches the tooling conventions ABI. |
| 347 | 387 | ||
| 348 | padding1: u8 = 0, | 388 | padding1: u5 = 0, |
| 349 | /// Zig-specific. Dead things are allowed to be garbage collected. | 389 | /// Zig-specific. Dead things are allowed to be garbage collected. |
| 350 | alive: bool = false, | 390 | alive: bool = false, |
| 351 | /// Zig-specific. Segments only. Signals that the segment contains only | 391 | /// Zig-specific. Segments only. Signals that the segment contains only |
| ... | @@ -360,6 +400,12 @@ pub const SymbolFlags = packed struct(u32) { | ... | @@ -360,6 +400,12 @@ pub const SymbolFlags = packed struct(u32) { |
| 360 | alignment: Alignment = .none, | 400 | alignment: Alignment = .none, |
| 361 | /// Zig-specific. Globals only. | 401 | /// Zig-specific. Globals only. |
| 362 | global_type: Global.Type = .zero, | 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 | pub const Binding = enum(u2) { | 410 | pub const Binding = enum(u2) { |
| 365 | strong = 0, | 411 | strong = 0, |
| ... | @@ -378,13 +424,16 @@ pub const SymbolFlags = packed struct(u32) { | ... | @@ -378,13 +424,16 @@ pub const SymbolFlags = packed struct(u32) { |
| 378 | }; | 424 | }; |
| 379 | 425 | ||
| 380 | pub fn initZigSpecific(flags: *SymbolFlags, must_link: bool, no_strip: bool) void { | 426 | pub fn initZigSpecific(flags: *SymbolFlags, must_link: bool, no_strip: bool) void { |
| 427 | flags.no_strip = no_strip; | ||
| 381 | flags.alive = false; | 428 | flags.alive = false; |
| 382 | flags.strings = false; | 429 | flags.strings = false; |
| 383 | flags.must_link = must_link; | 430 | flags.must_link = must_link; |
| 384 | flags.no_strip = no_strip; | 431 | flags.is_passive = false; |
| 385 | flags.alignment = .none; | 432 | flags.alignment = .none; |
| 386 | flags.global_type = .zero; | 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 | pub fn isIncluded(flags: SymbolFlags, is_dynamic: bool) bool { | 439 | pub fn isIncluded(flags: SymbolFlags, is_dynamic: bool) bool { |
| ... | @@ -427,11 +476,28 @@ pub const SymbolFlags = packed struct(u32) { | ... | @@ -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 | code: DataSegment.Payload, | 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 | /// Index into `navs`. | 502 | /// Index into `navs`. |
| 437 | /// Note that swapRemove is sometimes performed on `navs`. | 503 | /// Note that swapRemove is sometimes performed on `navs`. |
| ... | @@ -439,11 +505,11 @@ pub const Nav = extern struct { | ... | @@ -439,11 +505,11 @@ pub const Nav = extern struct { |
| 439 | _, | 505 | _, |
| 440 | 506 | ||
| 441 | pub fn key(i: @This(), wasm: *const Wasm) *InternPool.Nav.Index { | 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 { | 511 | pub fn value(i: @This(), wasm: *const Wasm) *NavExe { |
| 446 | return &wasm.navs.values()[@intFromEnum(i)]; | 512 | return &wasm.navs_exe.values()[@intFromEnum(i)]; |
| 447 | } | 513 | } |
| 448 | }; | 514 | }; |
| 449 | }; | 515 | }; |
| ... | @@ -506,7 +572,7 @@ pub const FunctionImport = extern struct { | ... | @@ -506,7 +572,7 @@ pub const FunctionImport = extern struct { |
| 506 | __wasm_init_tls, | 572 | __wasm_init_tls, |
| 507 | __zig_error_names, | 573 | __zig_error_names, |
| 508 | // Next, index into `object_functions`. | 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 | const first_object_function = @intFromEnum(Resolution.__zig_error_names) + 1; | 578 | const first_object_function = @intFromEnum(Resolution.__zig_error_names) + 1; |
| ... | @@ -519,7 +585,8 @@ pub const FunctionImport = extern struct { | ... | @@ -519,7 +585,8 @@ pub const FunctionImport = extern struct { |
| 519 | __wasm_init_tls, | 585 | __wasm_init_tls, |
| 520 | __zig_error_names, | 586 | __zig_error_names, |
| 521 | object_function: ObjectFunctionIndex, | 587 | object_function: ObjectFunctionIndex, |
| 522 | nav: Nav.Index, | 588 | nav_exe: NavExe.Index, |
| 589 | nav_obj: NavExe.Index, | ||
| 523 | }; | 590 | }; |
| 524 | 591 | ||
| 525 | pub fn unpack(r: Resolution, wasm: *const Wasm) Unpacked { | 592 | pub fn unpack(r: Resolution, wasm: *const Wasm) Unpacked { |
| ... | @@ -535,8 +602,14 @@ pub const FunctionImport = extern struct { | ... | @@ -535,8 +602,14 @@ pub const FunctionImport = extern struct { |
| 535 | const object_function_index = i - first_object_function; | 602 | const object_function_index = i - first_object_function; |
| 536 | if (object_function_index < wasm.object_functions.items.len) | 603 | if (object_function_index < wasm.object_functions.items.len) |
| 537 | return .{ .object_function = @enumFromInt(object_function_index) }; | 604 | return .{ .object_function = @enumFromInt(object_function_index) }; |
| 605 | const comp = wasm.base.comp; | ||
| 606 | const is_obj = comp.config.output_mode == .Obj; | ||
| 538 | const nav_index = object_function_index - wasm.object_functions.items.len; | 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,17 +623,24 @@ pub const FunctionImport = extern struct { |
| 550 | .__wasm_init_tls => .__wasm_init_tls, | 623 | .__wasm_init_tls => .__wasm_init_tls, |
| 551 | .__zig_error_names => .__zig_error_names, | 624 | .__zig_error_names => .__zig_error_names, |
| 552 | .object_function => |i| @enumFromInt(first_object_function + @intFromEnum(i)), | 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 | pub fn fromIpNav(wasm: *const Wasm, ip_nav: InternPool.Nav.Index) Resolution { | 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 | pub fn isNavOrUnresolved(r: Resolution, wasm: *const Wasm) bool { | 641 | pub fn isNavOrUnresolved(r: Resolution, wasm: *const Wasm) bool { |
| 562 | return switch (r.unpack(wasm)) { | 642 | return switch (r.unpack(wasm)) { |
| 563 | .unresolved, .nav => true, | 643 | .unresolved, .nav_obj, .nav_exe => true, |
| 564 | else => false, | 644 | else => false, |
| 565 | }; | 645 | }; |
| 566 | } | 646 | } |
| ... | @@ -608,7 +688,7 @@ pub const GlobalImport = extern struct { | ... | @@ -608,7 +688,7 @@ pub const GlobalImport = extern struct { |
| 608 | __tls_size, | 688 | __tls_size, |
| 609 | __zig_error_name_table, | 689 | __zig_error_name_table, |
| 610 | // Next, index into `object_globals`. | 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 | const first_object_global = @intFromEnum(Resolution.__zig_error_name_table) + 1; | 694 | const first_object_global = @intFromEnum(Resolution.__zig_error_name_table) + 1; |
| ... | @@ -623,7 +703,8 @@ pub const GlobalImport = extern struct { | ... | @@ -623,7 +703,8 @@ pub const GlobalImport = extern struct { |
| 623 | __tls_size, | 703 | __tls_size, |
| 624 | __zig_error_name_table, | 704 | __zig_error_name_table, |
| 625 | object_global: ObjectGlobalIndex, | 705 | object_global: ObjectGlobalIndex, |
| 626 | nav: Nav.Index, | 706 | nav_exe: NavExe.Index, |
| 707 | nav_obj: NavObj.Index, | ||
| 627 | }; | 708 | }; |
| 628 | 709 | ||
| 629 | pub fn unpack(r: Resolution, wasm: *const Wasm) Unpacked { | 710 | pub fn unpack(r: Resolution, wasm: *const Wasm) Unpacked { |
| ... | @@ -639,8 +720,14 @@ pub const GlobalImport = extern struct { | ... | @@ -639,8 +720,14 @@ pub const GlobalImport = extern struct { |
| 639 | const object_global_index = i - first_object_global; | 720 | const object_global_index = i - first_object_global; |
| 640 | if (object_global_index < wasm.object_globals.items.len) | 721 | if (object_global_index < wasm.object_globals.items.len) |
| 641 | return .{ .object_global = @enumFromInt(object_global_index) }; | 722 | return .{ .object_global = @enumFromInt(object_global_index) }; |
| 723 | const comp = wasm.base.comp; | ||
| 724 | const is_obj = comp.config.output_mode == .Obj; | ||
| 642 | const nav_index = object_global_index - wasm.object_globals.items.len; | 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,12 +743,19 @@ pub const GlobalImport = extern struct { |
| 656 | .__tls_size => .__tls_size, | 743 | .__tls_size => .__tls_size, |
| 657 | .__zig_error_name_table => .__zig_error_name_table, | 744 | .__zig_error_name_table => .__zig_error_name_table, |
| 658 | .object_global => |i| @enumFromInt(first_object_global + @intFromEnum(i)), | 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 | pub fn fromIpNav(wasm: *const Wasm, ip_nav: InternPool.Nav.Index) Resolution { | 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,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 | pub const TableImport = extern struct { | 833 | pub const TableImport = extern struct { |
| 721 | flags: SymbolFlags, | 834 | flags: SymbolFlags, |
| 722 | module_name: String, | 835 | module_name: String, |
| 723 | source_location: SourceLocation, | 836 | source_location: SourceLocation, |
| 724 | resolution: Resolution, | 837 | resolution: Resolution, |
| 838 | limits_min: u32, | ||
| 839 | limits_max: u32, | ||
| 725 | 840 | ||
| 726 | /// Represents a synthetic table, or a table from an object. | 841 | /// Represents a synthetic table, or a table from an object. |
| 727 | pub const Resolution = enum(u32) { | 842 | pub const Resolution = enum(u32) { |
| ... | @@ -730,35 +845,36 @@ pub const TableImport = extern struct { | ... | @@ -730,35 +845,36 @@ pub const TableImport = extern struct { |
| 730 | // Next, index into `object_tables`. | 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 | pub const Table = extern struct { | 863 | pub const Table = extern struct { |
| 736 | module_name: String, | 864 | module_name: OptionalString, |
| 737 | name: String, | 865 | name: OptionalString, |
| 738 | flags: SymbolFlags, | 866 | flags: SymbolFlags, |
| 739 | limits_min: u32, | 867 | limits_min: u32, |
| 740 | limits_max: u32, | 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. | 871 | /// Uniquely identifies a section across all objects. By subtracting |
| 748 | /// By subtracting that value from this one, the Object section index is obtained. | 872 | /// `Object.local_section_index_base` from this one, the Object section index |
| 873 | /// is obtained. | ||
| 749 | pub const ObjectSectionIndex = enum(u32) { | 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 | /// Index into `object_tables`. | 878 | /// Index into `object_tables`. |
| 763 | pub const ObjectTableIndex = enum(u32) { | 879 | pub const ObjectTableIndex = enum(u32) { |
| 764 | _, | 880 | _, |
| ... | @@ -820,13 +936,18 @@ pub const DataSegment = extern struct { | ... | @@ -820,13 +936,18 @@ pub const DataSegment = extern struct { |
| 820 | len: u32, | 936 | len: u32, |
| 821 | 937 | ||
| 822 | fn slice(p: DataSegment.Payload, wasm: *const Wasm) []const u8 { | 938 | fn slice(p: DataSegment.Payload, wasm: *const Wasm) []const u8 { |
| 939 | assert(p.off != p.len); | ||
| 823 | return wasm.string_bytes.items[p.off..][0..p.len]; | 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 | pub const Index = enum(u32) { | 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,6 +1113,10 @@ pub const FunctionImportId = enum(u32) { |
| 992 | return .{ .zcu_import = @enumFromInt(zcu_import_i) }; | 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 | /// This function is allowed O(N) lookup because it is only called during | 1120 | /// This function is allowed O(N) lookup because it is only called during |
| 996 | /// diagnostic generation. | 1121 | /// diagnostic generation. |
| 997 | pub fn sourceLocation(id: FunctionImportId, wasm: *const Wasm) SourceLocation { | 1122 | pub fn sourceLocation(id: FunctionImportId, wasm: *const Wasm) SourceLocation { |
| ... | @@ -1035,6 +1160,10 @@ pub const GlobalImportId = enum(u32) { | ... | @@ -1035,6 +1160,10 @@ pub const GlobalImportId = enum(u32) { |
| 1035 | return .{ .zcu_import = @enumFromInt(zcu_import_i) }; | 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 | /// This function is allowed O(N) lookup because it is only called during | 1167 | /// This function is allowed O(N) lookup because it is only called during |
| 1039 | /// diagnostic generation. | 1168 | /// diagnostic generation. |
| 1040 | pub fn sourceLocation(id: GlobalImportId, wasm: *const Wasm) SourceLocation { | 1169 | pub fn sourceLocation(id: GlobalImportId, wasm: *const Wasm) SourceLocation { |
| ... | @@ -1054,7 +1183,38 @@ pub const GlobalImportId = enum(u32) { | ... | @@ -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 | tag: Tag, | 1218 | tag: Tag, |
| 1059 | /// Offset of the value to rewrite relative to the relevant section's contents. | 1219 | /// Offset of the value to rewrite relative to the relevant section's contents. |
| 1060 | /// When `offset` is zero, its position is immediately after the id and size of the section. | 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,8 +1227,6 @@ pub const Relocation = struct { |
| 1067 | symbol_name: String, | 1227 | symbol_name: String, |
| 1068 | type_index: FunctionType.Index, | 1228 | type_index: FunctionType.Index, |
| 1069 | section: ObjectSectionIndex, | 1229 | section: ObjectSectionIndex, |
| 1070 | nav_index: InternPool.Nav.Index, | ||
| 1071 | uav_index: InternPool.Index, | ||
| 1072 | }; | 1230 | }; |
| 1073 | 1231 | ||
| 1074 | pub const Slice = extern struct { | 1232 | pub const Slice = extern struct { |
| ... | @@ -1076,7 +1234,7 @@ pub const Relocation = struct { | ... | @@ -1076,7 +1234,7 @@ pub const Relocation = struct { |
| 1076 | off: u32, | 1234 | off: u32, |
| 1077 | len: u32, | 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 | return wasm.relocations.items[s.off..][0..s.len]; | 1238 | return wasm.relocations.items[s.off..][0..s.len]; |
| 1081 | } | 1239 | } |
| 1082 | }; | 1240 | }; |
| ... | @@ -1122,11 +1280,6 @@ pub const Relocation = struct { | ... | @@ -1122,11 +1280,6 @@ pub const Relocation = struct { |
| 1122 | // Above here, the tags correspond to symbol table ABI described in | 1280 | // Above here, the tags correspond to symbol table ABI described in |
| 1123 | // https://github.com/WebAssembly/tool-conventions/blob/main/Linking.md | 1281 | // https://github.com/WebAssembly/tool-conventions/blob/main/Linking.md |
| 1124 | // Below, the tags are compiler-internal. | 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,7 +1609,8 @@ pub fn deinit(wasm: *Wasm) void { |
| 1456 | const gpa = wasm.base.comp.gpa; | 1609 | const gpa = wasm.base.comp.gpa; |
| 1457 | if (wasm.llvm_object) |llvm_object| llvm_object.deinit(); | 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 | wasm.zcu_funcs.deinit(gpa); | 1614 | wasm.zcu_funcs.deinit(gpa); |
| 1461 | wasm.nav_exports.deinit(gpa); | 1615 | wasm.nav_exports.deinit(gpa); |
| 1462 | wasm.uav_exports.deinit(gpa); | 1616 | wasm.uav_exports.deinit(gpa); |
| ... | @@ -1478,7 +1632,7 @@ pub fn deinit(wasm: *Wasm) void { | ... | @@ -1478,7 +1632,7 @@ pub fn deinit(wasm: *Wasm) void { |
| 1478 | wasm.object_tables.deinit(gpa); | 1632 | wasm.object_tables.deinit(gpa); |
| 1479 | wasm.object_memory_imports.deinit(gpa); | 1633 | wasm.object_memory_imports.deinit(gpa); |
| 1480 | wasm.object_memories.deinit(gpa); | 1634 | wasm.object_memories.deinit(gpa); |
| 1481 | 1635 | wasm.object_relocations.deinit(gpa); | |
| 1482 | wasm.object_data_segments.deinit(gpa); | 1636 | wasm.object_data_segments.deinit(gpa); |
| 1483 | wasm.object_custom_segments.deinit(gpa); | 1637 | wasm.object_custom_segments.deinit(gpa); |
| 1484 | wasm.object_init_funcs.deinit(gpa); | 1638 | wasm.object_init_funcs.deinit(gpa); |
| ... | @@ -1492,8 +1646,13 @@ pub fn deinit(wasm: *Wasm) void { | ... | @@ -1492,8 +1646,13 @@ pub fn deinit(wasm: *Wasm) void { |
| 1492 | wasm.function_imports.deinit(gpa); | 1646 | wasm.function_imports.deinit(gpa); |
| 1493 | wasm.functions.deinit(gpa); | 1647 | wasm.functions.deinit(gpa); |
| 1494 | wasm.globals.deinit(gpa); | 1648 | wasm.globals.deinit(gpa); |
| 1649 | wasm.global_exports.deinit(gpa); | ||
| 1495 | wasm.global_imports.deinit(gpa); | 1650 | wasm.global_imports.deinit(gpa); |
| 1496 | wasm.table_imports.deinit(gpa); | 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 | wasm.string_bytes.deinit(gpa); | 1657 | wasm.string_bytes.deinit(gpa); |
| 1499 | wasm.string_table.deinit(gpa); | 1658 | wasm.string_table.deinit(gpa); |
| ... | @@ -1527,7 +1686,9 @@ pub fn updateNav(wasm: *Wasm, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index | ... | @@ -1527,7 +1686,9 @@ pub fn updateNav(wasm: *Wasm, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index |
| 1527 | const zcu = pt.zcu; | 1686 | const zcu = pt.zcu; |
| 1528 | const ip = &zcu.intern_pool; | 1687 | const ip = &zcu.intern_pool; |
| 1529 | const nav = ip.getNav(nav_index); | 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 | const nav_val = zcu.navValue(nav_index); | 1693 | const nav_val = zcu.navValue(nav_index); |
| 1533 | const is_extern, const nav_init = switch (ip.indexToKey(nav_val.toIntern())) { | 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,22 +1703,26 @@ pub fn updateNav(wasm: *Wasm, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index |
| 1542 | 1703 | ||
| 1543 | if (!nav_init.typeOf(zcu).hasRuntimeBits(zcu)) { | 1704 | if (!nav_init.typeOf(zcu).hasRuntimeBits(zcu)) { |
| 1544 | _ = wasm.imports.swapRemove(nav_index); | 1705 | _ = wasm.imports.swapRemove(nav_index); |
| 1545 | if (wasm.navs.swapRemove(nav_index)) { | 1706 | if (is_obj) { |
| 1546 | @panic("TODO reclaim resources"); | 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 | return; | 1711 | return; |
| 1549 | } | 1712 | } |
| 1550 | 1713 | ||
| 1551 | if (is_extern) { | 1714 | if (is_extern) { |
| 1552 | try wasm.imports.put(gpa, nav_index, {}); | 1715 | try wasm.imports.put(gpa, nav_index, {}); |
| 1553 | if (wasm.navs.swapRemove(nav_index)) { | 1716 | if (is_obj) { |
| 1554 | @panic("TODO reclaim resources"); | 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 | return; | 1721 | return; |
| 1557 | } | 1722 | } |
| 1558 | 1723 | ||
| 1559 | const code_start: u32 = @intCast(wasm.string_bytes.items.len); | 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 | wasm.string_bytes_lock.lock(); | 1726 | wasm.string_bytes_lock.lock(); |
| 1562 | 1727 | ||
| 1563 | try codegen.generateSymbol( | 1728 | try codegen.generateSymbol( |
| ... | @@ -1570,15 +1735,45 @@ pub fn updateNav(wasm: *Wasm, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index | ... | @@ -1570,15 +1735,45 @@ pub fn updateNav(wasm: *Wasm, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index |
| 1570 | ); | 1735 | ); |
| 1571 | 1736 | ||
| 1572 | const code_len: u32 = @intCast(wasm.string_bytes.items.len - code_start); | 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 | wasm.string_bytes_lock.unlock(); | 1739 | wasm.string_bytes_lock.unlock(); |
| 1575 | 1740 | ||
| 1576 | const code: Nav.Code = .{ | 1741 | const naive_code: DataSegment.Payload = .{ |
| 1577 | .off = code_start, | 1742 | .off = code_start, |
| 1578 | .len = code_len, | 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 | if (gop.found_existing) { | 1777 | if (gop.found_existing) { |
| 1583 | @panic("TODO reuse these resources"); | 1778 | @panic("TODO reuse these resources"); |
| 1584 | } else { | 1779 | } else { |
| ... | @@ -1586,10 +1781,6 @@ pub fn updateNav(wasm: *Wasm, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index | ... | @@ -1586,10 +1781,6 @@ pub fn updateNav(wasm: *Wasm, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index |
| 1586 | } | 1781 | } |
| 1587 | gop.value_ptr.* = .{ | 1782 | gop.value_ptr.* = .{ |
| 1588 | .code = code, | 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,6 +1896,12 @@ pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.File.FlushError!v |
| 1705 | continue; | 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 | try missing_exports.put(gpa, exp_name_interned, {}); | 1905 | try missing_exports.put(gpa, exp_name_interned, {}); |
| 1709 | } | 1906 | } |
| 1710 | wasm.missing_exports_init = try gpa.dupe(String, missing_exports.keys()); | 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,32 +1921,28 @@ pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.File.FlushError!v |
| 1724 | for (wasm.object_function_imports.keys(), wasm.object_function_imports.values(), 0..) |name, *import, i| { | 1921 | for (wasm.object_function_imports.keys(), wasm.object_function_imports.values(), 0..) |name, *import, i| { |
| 1725 | if (import.flags.isIncluded(rdynamic)) { | 1922 | if (import.flags.isIncluded(rdynamic)) { |
| 1726 | try markFunction(wasm, name, import, @enumFromInt(i)); | 1923 | try markFunction(wasm, name, import, @enumFromInt(i)); |
| 1727 | continue; | ||
| 1728 | } | 1924 | } |
| 1729 | } | 1925 | } |
| 1730 | wasm.functions_len = @intCast(wasm.functions.entries.len); | 1926 | wasm.functions_len = @intCast(wasm.functions.entries.len); |
| 1731 | wasm.function_imports_init_keys = try gpa.dupe(String, wasm.function_imports.keys()); | 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 | wasm.function_exports_len = @intCast(wasm.function_exports.items.len); | 1929 | wasm.function_exports_len = @intCast(wasm.function_exports.items.len); |
| 1734 | 1930 | ||
| 1735 | for (wasm.object_global_imports.keys(), wasm.object_global_imports.values(), 0..) |name, *import, i| { | 1931 | for (wasm.object_global_imports.keys(), wasm.object_global_imports.values(), 0..) |name, *import, i| { |
| 1736 | if (import.flags.isIncluded(rdynamic)) { | 1932 | if (import.flags.isIncluded(rdynamic)) { |
| 1737 | try markGlobal(wasm, name, import, @enumFromInt(i)); | 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 | wasm.global_imports_init_keys = try gpa.dupe(String, wasm.global_imports.keys()); | 1937 | wasm.global_imports_init_keys = try gpa.dupe(String, wasm.global_imports.keys()); |
| 1743 | wasm.global_imports_init_vals = try gpa.dupe(GlobalImportId, wasm.global_imports.values()); | 1938 | wasm.global_imports_init_vals = try gpa.dupe(GlobalImportId, wasm.global_imports.values()); |
| 1744 | wasm.global_exports_len = @intCast(wasm.global_exports.items.len); | 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 | if (import.flags.isIncluded(rdynamic)) { | 1942 | if (import.flags.isIncluded(rdynamic)) { |
| 1748 | try markTable(wasm, import.name, import, @enumFromInt(i)); | 1943 | try markTable(wasm, name, import, @enumFromInt(i)); |
| 1749 | continue; | ||
| 1750 | } | 1944 | } |
| 1751 | } | 1945 | } |
| 1752 | wasm.tables_len = @intCast(wasm.tables.items.len); | ||
| 1753 | } | 1946 | } |
| 1754 | 1947 | ||
| 1755 | /// Recursively mark alive everything referenced by the function. | 1948 | /// Recursively mark alive everything referenced by the function. |
| ... | @@ -1758,7 +1951,7 @@ fn markFunction( | ... | @@ -1758,7 +1951,7 @@ fn markFunction( |
| 1758 | name: String, | 1951 | name: String, |
| 1759 | import: *FunctionImport, | 1952 | import: *FunctionImport, |
| 1760 | func_index: FunctionImport.Index, | 1953 | func_index: FunctionImport.Index, |
| 1761 | ) error{OutOfMemory}!void { | 1954 | ) Allocator.Error!void { |
| 1762 | if (import.flags.alive) return; | 1955 | if (import.flags.alive) return; |
| 1763 | import.flags.alive = true; | 1956 | import.flags.alive = true; |
| 1764 | 1957 | ||
| ... | @@ -1783,15 +1976,15 @@ fn markFunction( | ... | @@ -1783,15 +1976,15 @@ fn markFunction( |
| 1783 | import.resolution = .__wasm_init_tls; | 1976 | import.resolution = .__wasm_init_tls; |
| 1784 | wasm.functions.putAssumeCapacity(.__wasm_init_tls, {}); | 1977 | wasm.functions.putAssumeCapacity(.__wasm_init_tls, {}); |
| 1785 | } else { | 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 | } else { | 1981 | } else { |
| 1789 | const gop = wasm.functions.getOrPutAssumeCapacity(import.resolution); | 1982 | const gop = wasm.functions.getOrPutAssumeCapacity(import.resolution); |
| 1790 | 1983 | ||
| 1791 | if (!is_obj and import.flags.isExported(rdynamic)) | 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 | try wasm.markReloc(reloc); | 1988 | try wasm.markReloc(reloc); |
| 1796 | } | 1989 | } |
| 1797 | } | 1990 | } |
| ... | @@ -1833,15 +2026,15 @@ fn markGlobal( | ... | @@ -1833,15 +2026,15 @@ fn markGlobal( |
| 1833 | import.resolution = .__tls_size; | 2026 | import.resolution = .__tls_size; |
| 1834 | wasm.globals.putAssumeCapacity(.__tls_size, {}); | 2027 | wasm.globals.putAssumeCapacity(.__tls_size, {}); |
| 1835 | } else { | 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 | } else { | 2031 | } else { |
| 1839 | const gop = wasm.globals.getOrPutAssumeCapacity(import.resolution); | 2032 | const gop = wasm.globals.getOrPutAssumeCapacity(import.resolution); |
| 1840 | 2033 | ||
| 1841 | if (!is_obj and import.flags.isExported(rdynamic)) | 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 | try wasm.markReloc(reloc); | 2038 | try wasm.markReloc(reloc); |
| 1846 | } | 2039 | } |
| 1847 | } | 2040 | } |
| ... | @@ -1850,7 +2043,7 @@ fn markTable( | ... | @@ -1850,7 +2043,7 @@ fn markTable( |
| 1850 | wasm: *Wasm, | 2043 | wasm: *Wasm, |
| 1851 | name: String, | 2044 | name: String, |
| 1852 | import: *TableImport, | 2045 | import: *TableImport, |
| 1853 | table_index: ObjectTableImportIndex, | 2046 | table_index: TableImport.Index, |
| 1854 | ) !void { | 2047 | ) !void { |
| 1855 | if (import.flags.alive) return; | 2048 | if (import.flags.alive) return; |
| 1856 | import.flags.alive = true; | 2049 | import.flags.alive = true; |
| ... | @@ -1865,7 +2058,7 @@ fn markTable( | ... | @@ -1865,7 +2058,7 @@ fn markTable( |
| 1865 | import.resolution = .__indirect_function_table; | 2058 | import.resolution = .__indirect_function_table; |
| 1866 | wasm.tables.putAssumeCapacity(.__indirect_function_table, {}); | 2059 | wasm.tables.putAssumeCapacity(.__indirect_function_table, {}); |
| 1867 | } else { | 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 | } else { | 2063 | } else { |
| 1871 | wasm.tables.putAssumeCapacity(import.resolution, {}); | 2064 | wasm.tables.putAssumeCapacity(import.resolution, {}); |
| ... | @@ -1873,18 +2066,24 @@ fn markTable( | ... | @@ -1873,18 +2066,24 @@ fn markTable( |
| 1873 | } | 2066 | } |
| 1874 | } | 2067 | } |
| 1875 | 2068 | ||
| 1876 | fn globalResolutionRelocSlice(wasm: *Wasm, resolution: GlobalImport.Resolution) ![]const Relocation { | 2069 | fn globalResolutionRelocSlice(wasm: *Wasm, resolution: GlobalImport.Resolution) ![]const ObjectRelocation { |
| 1877 | assert(resolution != .none); | 2070 | assert(resolution != .unresolved); |
| 1878 | _ = wasm; | 2071 | _ = wasm; |
| 1879 | @panic("TODO"); | 2072 | @panic("TODO"); |
| 1880 | } | 2073 | } |
| 1881 | 2074 | ||
| 1882 | fn functionResolutionRelocSlice(wasm: *Wasm, resolution: FunctionImport.Resolution) ![]const Relocation { | 2075 | fn functionResolutionRelocSlice(wasm: *Wasm, resolution: FunctionImport.Resolution) ![]const ObjectRelocation { |
| 1883 | assert(resolution != .none); | 2076 | assert(resolution != .unresolved); |
| 1884 | _ = wasm; | 2077 | _ = wasm; |
| 1885 | @panic("TODO"); | 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 | pub fn flushModule( | 2087 | pub fn flushModule( |
| 1889 | wasm: *Wasm, | 2088 | wasm: *Wasm, |
| 1890 | arena: Allocator, | 2089 | arena: Allocator, |
| ... | @@ -2349,8 +2548,10 @@ fn defaultEntrySymbolName( | ... | @@ -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 | assert(mem.indexOfScalar(u8, bytes, 0) == null); | 2552 | assert(mem.indexOfScalar(u8, bytes, 0) == null); |
| 2553 | wasm.string_bytes_lock.lock(); | ||
| 2554 | defer wasm.string_bytes_lock.unlock(); | ||
| 2354 | const gpa = wasm.base.comp.gpa; | 2555 | const gpa = wasm.base.comp.gpa; |
| 2355 | const gop = try wasm.string_table.getOrPutContextAdapted( | 2556 | const gop = try wasm.string_table.getOrPutContextAdapted( |
| 2356 | gpa, | 2557 | gpa, |
| ... | @@ -2371,6 +2572,13 @@ pub fn internString(wasm: *Wasm, bytes: []const u8) error{OutOfMemory}!String { | ... | @@ -2371,6 +2572,13 @@ pub fn internString(wasm: *Wasm, bytes: []const u8) error{OutOfMemory}!String { |
| 2371 | return new_off; | 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 | pub fn getExistingString(wasm: *const Wasm, bytes: []const u8) ?String { | 2582 | pub fn getExistingString(wasm: *const Wasm, bytes: []const u8) ?String { |
| 2375 | assert(mem.indexOfScalar(u8, bytes, 0) == null); | 2583 | assert(mem.indexOfScalar(u8, bytes, 0) == null); |
| 2376 | return wasm.string_table.getKeyAdapted(bytes, @as(String.TableIndexAdapter, .{ | 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,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 | return .fromString(try internString(wasm, @ptrCast(valtype_list))); | 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 | const gpa = wasm.base.comp.gpa; | 2594 | const gpa = wasm.base.comp.gpa; |
| 2387 | const gop = try wasm.func_types.getOrPut(gpa, ft); | 2595 | const gop = try wasm.func_types.getOrPut(gpa, ft); |
| 2388 | return @enumFromInt(gop.index); | 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 | const gpa = wasm.base.comp.gpa; | 2600 | const gpa = wasm.base.comp.gpa; |
| 2393 | // We can't use string table deduplication here since these expressions can | 2601 | // We can't use string table deduplication here since these expressions can |
| 2394 | // have null bytes in them however it may be interesting to explore since | 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,8 +2606,29 @@ pub fn addExpr(wasm: *Wasm, bytes: []const u8) error{OutOfMemory}!Expr { |
| 2398 | return @enumFromInt(wasm.string_bytes.items.len - bytes.len); | 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 | const gpa = wasm.base.comp.gpa; | 2610 | const gpa = wasm.base.comp.gpa; |
| 2403 | try wasm.string_bytes.appendSlice(gpa, bytes); | 2611 | try wasm.string_bytes.appendSlice(gpa, bytes); |
| 2404 | return @enumFromInt(wasm.string_bytes.items.len - bytes.len); | 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,7 +42,6 @@ pub fn clear(f: *Flush) void { |
| 42 | f.data_segments.clearRetainingCapacity(); | 42 | f.data_segments.clearRetainingCapacity(); |
| 43 | f.data_segment_groups.clearRetainingCapacity(); | 43 | f.data_segment_groups.clearRetainingCapacity(); |
| 44 | f.indirect_function_table.clearRetainingCapacity(); | 44 | f.indirect_function_table.clearRetainingCapacity(); |
| 45 | f.global_exports.clearRetainingCapacity(); | ||
| 46 | } | 45 | } |
| 47 | 46 | ||
| 48 | pub fn deinit(f: *Flush, gpa: Allocator) void { | 47 | pub fn deinit(f: *Flush, gpa: Allocator) void { |
| ... | @@ -50,11 +49,10 @@ pub fn deinit(f: *Flush, gpa: Allocator) void { | ... | @@ -50,11 +49,10 @@ pub fn deinit(f: *Flush, gpa: Allocator) void { |
| 50 | f.data_segments.deinit(gpa); | 49 | f.data_segments.deinit(gpa); |
| 51 | f.data_segment_groups.deinit(gpa); | 50 | f.data_segment_groups.deinit(gpa); |
| 52 | f.indirect_function_table.deinit(gpa); | 51 | f.indirect_function_table.deinit(gpa); |
| 53 | f.global_exports.deinit(gpa); | ||
| 54 | f.* = undefined; | 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 | const comp = wasm.base.comp; | 56 | const comp = wasm.base.comp; |
| 59 | const shared_memory = comp.config.shared_memory; | 57 | const shared_memory = comp.config.shared_memory; |
| 60 | const diags = &comp.link_diags; | 58 | const diags = &comp.link_diags; |
| ... | @@ -115,7 +113,7 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) anyerror!void { | ... | @@ -115,7 +113,7 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) anyerror!void { |
| 115 | src_loc.addError(wasm, "undefined global: {s}", .{name.slice(wasm)}); | 113 | src_loc.addError(wasm, "undefined global: {s}", .{name.slice(wasm)}); |
| 116 | } | 114 | } |
| 117 | for (wasm.table_imports.keys(), wasm.table_imports.values()) |name, table_import_id| { | 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 | src_loc.addError(wasm, "undefined table: {s}", .{name.slice(wasm)}); | 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,7 +140,7 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) anyerror!void { |
| 142 | if (!ds.flags.alive) continue; | 140 | if (!ds.flags.alive) continue; |
| 143 | const data_segment_index: Wasm.DataSegment.Index = @enumFromInt(i); | 141 | const data_segment_index: Wasm.DataSegment.Index = @enumFromInt(i); |
| 144 | any_passive_inits = any_passive_inits or ds.flags.is_passive or (import_memory and !isBss(wasm, ds.name)); | 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 | try wasm.functions.ensureUnusedCapacity(gpa, 3); | 146 | try wasm.functions.ensureUnusedCapacity(gpa, 3); |
| ... | @@ -159,8 +157,10 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) anyerror!void { | ... | @@ -159,8 +157,10 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) anyerror!void { |
| 159 | // When we have TLS GOT entries and shared memory is enabled, | 157 | // When we have TLS GOT entries and shared memory is enabled, |
| 160 | // we must perform runtime relocations or else we don't create the function. | 158 | // we must perform runtime relocations or else we don't create the function. |
| 161 | if (shared_memory) { | 159 | if (shared_memory) { |
| 162 | if (f.need_tls_relocs) wasm.functions.putAssumeCapacity(.__wasm_apply_global_tls_relocs, {}); | 160 | // This logic that checks `any_tls_relocs` is missing the part where it |
| 163 | wasm.functions.putAssumeCapacity(gpa, .__wasm_init_tls, {}); | 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 | // Sort order: | 166 | // Sort order: |
| ... | @@ -178,14 +178,14 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) anyerror!void { | ... | @@ -178,14 +178,14 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) anyerror!void { |
| 178 | pub fn lessThan(ctx: @This(), lhs: usize, rhs: usize) bool { | 178 | pub fn lessThan(ctx: @This(), lhs: usize, rhs: usize) bool { |
| 179 | const lhs_segment_index = ctx.segments[lhs]; | 179 | const lhs_segment_index = ctx.segments[lhs]; |
| 180 | const rhs_segment_index = ctx.segments[rhs]; | 180 | const rhs_segment_index = ctx.segments[rhs]; |
| 181 | const lhs_segment = lhs_segment_index.ptr(wasm); | 181 | const lhs_segment = lhs_segment_index.ptr(ctx.wasm); |
| 182 | const rhs_segment = rhs_segment_index.ptr(wasm); | 182 | const rhs_segment = rhs_segment_index.ptr(ctx.wasm); |
| 183 | const lhs_tls = @intFromBool(lhs_segment.flags.tls); | 183 | const lhs_tls = @intFromBool(lhs_segment.flags.tls); |
| 184 | const rhs_tls = @intFromBool(rhs_segment.flags.tls); | 184 | const rhs_tls = @intFromBool(rhs_segment.flags.tls); |
| 185 | if (lhs_tls < rhs_tls) return true; | 185 | if (lhs_tls < rhs_tls) return true; |
| 186 | if (lhs_tls > rhs_tls) return false; | 186 | if (lhs_tls > rhs_tls) return false; |
| 187 | const lhs_prefix, const lhs_suffix = splitSegmentName(lhs_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)); | 188 | const rhs_prefix, const rhs_suffix = splitSegmentName(rhs_segment.name.unwrap().?.slice(ctx.wasm)); |
| 189 | switch (mem.order(u8, lhs_prefix, rhs_prefix)) { | 189 | switch (mem.order(u8, lhs_prefix, rhs_prefix)) { |
| 190 | .lt => return true, | 190 | .lt => return true, |
| 191 | .gt => return false, | 191 | .gt => return false, |
| ... | @@ -213,14 +213,14 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) anyerror!void { | ... | @@ -213,14 +213,14 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) anyerror!void { |
| 213 | const heap_alignment: Alignment = .@"16"; // wasm's heap alignment as specified by tool-convention | 213 | const heap_alignment: Alignment = .@"16"; // wasm's heap alignment as specified by tool-convention |
| 214 | const pointer_alignment: Alignment = .@"4"; | 214 | const pointer_alignment: Alignment = .@"4"; |
| 215 | // Always place the stack at the start by default unless the user specified the global-base flag. | 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 | const VirtualAddrs = struct { | 218 | const VirtualAddrs = struct { |
| 219 | stack_pointer: u32, | 219 | stack_pointer: u32, |
| 220 | heap_base: u32, | 220 | heap_base: u32, |
| 221 | heap_end: u32, | 221 | heap_end: u32, |
| 222 | tls_base: ?u32, | 222 | tls_base: ?u32, |
| 223 | tls_align: ?u32, | 223 | tls_align: Alignment, |
| 224 | tls_size: ?u32, | 224 | tls_size: ?u32, |
| 225 | init_memory_flag: ?u32, | 225 | init_memory_flag: ?u32, |
| 226 | }; | 226 | }; |
| ... | @@ -229,7 +229,7 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) anyerror!void { | ... | @@ -229,7 +229,7 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) anyerror!void { |
| 229 | .heap_base = undefined, | 229 | .heap_base = undefined, |
| 230 | .heap_end = undefined, | 230 | .heap_end = undefined, |
| 231 | .tls_base = null, | 231 | .tls_base = null, |
| 232 | .tls_align = null, | 232 | .tls_align = .none, |
| 233 | .tls_size = null, | 233 | .tls_size = null, |
| 234 | .init_memory_flag = null, | 234 | .init_memory_flag = null, |
| 235 | }; | 235 | }; |
| ... | @@ -237,7 +237,7 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) anyerror!void { | ... | @@ -237,7 +237,7 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) anyerror!void { |
| 237 | if (place_stack_first and !is_obj) { | 237 | if (place_stack_first and !is_obj) { |
| 238 | memory_ptr = stack_alignment.forward(memory_ptr); | 238 | memory_ptr = stack_alignment.forward(memory_ptr); |
| 239 | memory_ptr += wasm.base.stack_size; | 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 | const segment_indexes = f.data_segments.keys(); | 243 | const segment_indexes = f.data_segments.keys(); |
| ... | @@ -247,27 +247,27 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) anyerror!void { | ... | @@ -247,27 +247,27 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) anyerror!void { |
| 247 | var seen_tls: enum { before, during, after } = .before; | 247 | var seen_tls: enum { before, during, after } = .before; |
| 248 | var offset: u32 = 0; | 248 | var offset: u32 = 0; |
| 249 | for (segment_indexes, segment_offsets, 0..) |segment_index, *segment_offset, i| { | 249 | for (segment_indexes, segment_offsets, 0..) |segment_index, *segment_offset, i| { |
| 250 | const segment = segment_index.ptr(f); | 250 | const segment = segment_index.ptr(wasm); |
| 251 | memory_ptr = segment.alignment.forward(memory_ptr); | 251 | memory_ptr = segment.flags.alignment.forward(memory_ptr); |
| 252 | 252 | ||
| 253 | const want_new_segment = b: { | 253 | const want_new_segment = b: { |
| 254 | if (is_obj) break :b false; | 254 | if (is_obj) break :b false; |
| 255 | switch (seen_tls) { | 255 | switch (seen_tls) { |
| 256 | .before => if (segment.flags.tls) { | 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 | virtual_addrs.tls_align = segment.flags.alignment; | 258 | virtual_addrs.tls_align = segment.flags.alignment; |
| 259 | seen_tls = .during; | 259 | seen_tls = .during; |
| 260 | break :b true; | 260 | break :b true; |
| 261 | }, | 261 | }, |
| 262 | .during => if (!segment.flags.tls) { | 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 | virtual_addrs.tls_align = virtual_addrs.tls_align.maxStrict(segment.flags.alignment); | 264 | virtual_addrs.tls_align = virtual_addrs.tls_align.maxStrict(segment.flags.alignment); |
| 265 | seen_tls = .after; | 265 | seen_tls = .after; |
| 266 | break :b true; | 266 | break :b true; |
| 267 | }, | 267 | }, |
| 268 | .after => {}, | 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 | if (want_new_segment) { | 272 | if (want_new_segment) { |
| 273 | if (offset > 0) try f.data_segment_groups.append(gpa, offset); | 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,26 +275,26 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) anyerror!void { |
| 275 | } | 275 | } |
| 276 | 276 | ||
| 277 | segment_offset.* = offset; | 277 | segment_offset.* = offset; |
| 278 | offset += segment.size; | 278 | offset += segment.payload.len; |
| 279 | memory_ptr += segment.size; | 279 | memory_ptr += segment.payload.len; |
| 280 | } | 280 | } |
| 281 | if (offset > 0) try f.data_segment_groups.append(gpa, offset); | 281 | if (offset > 0) try f.data_segment_groups.append(gpa, offset); |
| 282 | } | 282 | } |
| 283 | 283 | ||
| 284 | if (shared_memory and any_passive_inits) { | 284 | if (shared_memory and any_passive_inits) { |
| 285 | memory_ptr = pointer_alignment.forward(memory_ptr); | 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 | memory_ptr += 4; | 287 | memory_ptr += 4; |
| 288 | } | 288 | } |
| 289 | 289 | ||
| 290 | if (!place_stack_first and !is_obj) { | 290 | if (!place_stack_first and !is_obj) { |
| 291 | memory_ptr = stack_alignment.forward(memory_ptr); | 291 | memory_ptr = stack_alignment.forward(memory_ptr); |
| 292 | memory_ptr += wasm.base.stack_size; | 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 | memory_ptr = heap_alignment.forward(memory_ptr); | 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 | if (wasm.initial_memory) |initial_memory| { | 299 | if (wasm.initial_memory) |initial_memory| { |
| 300 | if (!mem.isAlignedGeneric(u64, initial_memory, page_size)) { | 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,7 +311,7 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) anyerror!void { |
| 311 | } else { | 311 | } else { |
| 312 | memory_ptr = mem.alignForward(u64, memory_ptr, std.wasm.page_size); | 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 | // In case we do not import memory, but define it ourselves, set the | 316 | // In case we do not import memory, but define it ourselves, set the |
| 317 | // minimum amount of pages on the memory section. | 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,7 +326,7 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) anyerror!void { |
| 326 | diags.addError("maximum memory value {d} insufficient; minimum {d}", .{ max_memory, memory_ptr }); | 326 | diags.addError("maximum memory value {d} insufficient; minimum {d}", .{ max_memory, memory_ptr }); |
| 327 | } | 327 | } |
| 328 | if (max_memory > std.math.maxInt(u32)) { | 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 | if (diags.hasErrors()) return error.LinkFailure; | 331 | if (diags.hasErrors()) return error.LinkFailure; |
| 332 | wasm.memories.limits.max = @intCast(max_memory / page_size); | 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,24 +346,26 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) anyerror!void { |
| 346 | const binary_bytes = &f.binary_bytes; | 346 | const binary_bytes = &f.binary_bytes; |
| 347 | assert(binary_bytes.items.len == 0); | 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 | assert(binary_bytes.items.len == 8); | 350 | assert(binary_bytes.items.len == 8); |
| 351 | 351 | ||
| 352 | const binary_writer = binary_bytes.writer(gpa); | 352 | const binary_writer = binary_bytes.writer(gpa); |
| 353 | 353 | ||
| 354 | // Type section | 354 | // Type section |
| 355 | if (wasm.func_types.items.len != 0) { | 355 | if (wasm.func_types.entries.len != 0) { |
| 356 | const header_offset = try reserveVecSectionHeader(gpa, binary_bytes); | 356 | const header_offset = try reserveVecSectionHeader(gpa, binary_bytes); |
| 357 | log.debug("Writing type section. Count: ({d})", .{wasm.func_types.items.len}); | 357 | log.debug("Writing type section. Count: ({d})", .{wasm.func_types.entries.len}); |
| 358 | for (wasm.func_types.items) |func_type| { | 358 | for (wasm.func_types.keys()) |func_type| { |
| 359 | try leb.writeUleb128(binary_writer, std.wasm.function_type); | 359 | try leb.writeUleb128(binary_writer, std.wasm.function_type); |
| 360 | try leb.writeUleb128(binary_writer, @as(u32, @intCast(func_type.params.len))); | 360 | const params = func_type.params.slice(wasm); |
| 361 | for (func_type.params) |param_ty| { | 361 | try leb.writeUleb128(binary_writer, @as(u32, @intCast(params.len))); |
| 362 | try leb.writeUleb128(binary_writer, std.wasm.valtype(param_ty)); | 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 | const returns = func_type.returns.slice(wasm); |
| 365 | for (func_type.returns) |ret_ty| { | 366 | try leb.writeUleb128(binary_writer, @as(u32, @intCast(returns.len))); |
| 366 | try leb.writeUleb128(binary_writer, std.wasm.valtype(ret_ty)); | 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,19 +374,19 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) anyerror!void { |
| 372 | header_offset, | 374 | header_offset, |
| 373 | .type, | 375 | .type, |
| 374 | @intCast(binary_bytes.items.len - header_offset - header_size), | 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 | section_index += 1; | 379 | section_index += 1; |
| 378 | } | 380 | } |
| 379 | 381 | ||
| 380 | // Import section | 382 | // Import section |
| 381 | const total_imports_len = wasm.function_imports.items.len + wasm.global_imports.items.len + | 383 | const total_imports_len = wasm.function_imports.entries.len + wasm.global_imports.entries.len + |
| 382 | wasm.table_imports.items.len + wasm.memory_imports.items.len + @intFromBool(import_memory); | 384 | wasm.table_imports.entries.len + wasm.memory_imports.items.len + @intFromBool(import_memory); |
| 383 | 385 | ||
| 384 | if (total_imports_len > 0) { | 386 | if (total_imports_len > 0) { |
| 385 | const header_offset = try reserveVecSectionHeader(gpa, binary_bytes); | 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 | const module_name = function_import.module_name.slice(wasm); | 390 | const module_name = function_import.module_name.slice(wasm); |
| 389 | try leb.writeUleb128(binary_writer, @as(u32, @intCast(module_name.len))); | 391 | try leb.writeUleb128(binary_writer, @as(u32, @intCast(module_name.len))); |
| 390 | try binary_writer.writeAll(module_name); | 392 | try binary_writer.writeAll(module_name); |
| ... | @@ -397,7 +399,7 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) anyerror!void { | ... | @@ -397,7 +399,7 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) anyerror!void { |
| 397 | try leb.writeUleb128(binary_writer, function_import.index); | 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 | const module_name = table_import.module_name.slice(wasm); | 403 | const module_name = table_import.module_name.slice(wasm); |
| 402 | try leb.writeUleb128(binary_writer, @as(u32, @intCast(module_name.len))); | 404 | try leb.writeUleb128(binary_writer, @as(u32, @intCast(module_name.len))); |
| 403 | try binary_writer.writeAll(module_name); | 405 | try binary_writer.writeAll(module_name); |
| ... | @@ -424,7 +426,7 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) anyerror!void { | ... | @@ -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 | const module_name = global_import.module_name.slice(wasm); | 430 | const module_name = global_import.module_name.slice(wasm); |
| 429 | try leb.writeUleb128(binary_writer, @as(u32, @intCast(module_name.len))); | 431 | try leb.writeUleb128(binary_writer, @as(u32, @intCast(module_name.len))); |
| 430 | try binary_writer.writeAll(module_name); | 432 | try binary_writer.writeAll(module_name); |
| ... | @@ -504,7 +506,7 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) anyerror!void { | ... | @@ -504,7 +506,7 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) anyerror!void { |
| 504 | const header_offset = try reserveVecSectionHeader(gpa, binary_bytes); | 506 | const header_offset = try reserveVecSectionHeader(gpa, binary_bytes); |
| 505 | 507 | ||
| 506 | for (wasm.output_globals.items) |global| { | 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 | try binary_writer.writeByte(@intFromBool(global.global_type.mutable)); | 510 | try binary_writer.writeByte(@intFromBool(global.global_type.mutable)); |
| 509 | try emitInit(binary_writer, global.init); | 511 | try emitInit(binary_writer, global.init); |
| 510 | } | 512 | } |
| ... | @@ -841,7 +843,7 @@ fn writeCustomSectionHeader(buffer: []u8, offset: u32, size: u32) !void { | ... | @@ -841,7 +843,7 @@ fn writeCustomSectionHeader(buffer: []u8, offset: u32, size: u32) !void { |
| 841 | buffer[offset..][0..buf.len].* = buf; | 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 | // unlike regular section, we don't emit the count | 847 | // unlike regular section, we don't emit the count |
| 846 | const header_size = 1 + 5; | 848 | const header_size = 1 + 5; |
| 847 | try bytes.appendNTimes(gpa, 0, header_size); | 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,12 +1101,12 @@ fn wantSegmentMerge(wasm: *const Wasm, a_index: Wasm.DataSegment.Index, b_index: |
| 1099 | if (a.flags.tls != b.flags.tls) return false; | 1101 | if (a.flags.tls != b.flags.tls) return false; |
| 1100 | if (a.flags.is_passive != b.flags.is_passive) return false; | 1102 | if (a.flags.is_passive != b.flags.is_passive) return false; |
| 1101 | if (a.name == b.name) return true; | 1103 | if (a.name == b.name) return true; |
| 1102 | const a_prefix, _ = splitSegmentName(a.name.slice(wasm)); | 1104 | const a_prefix, _ = splitSegmentName(a.name.slice(wasm).?); |
| 1103 | const b_prefix, _ = splitSegmentName(b.name.slice(wasm)); | 1105 | const b_prefix, _ = splitSegmentName(b.name.slice(wasm).?); |
| 1104 | return a_prefix.len > 0 and mem.eql(u8, a_prefix, b_prefix); | 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 | // section id + fixed leb contents size + fixed leb vector length | 1110 | // section id + fixed leb contents size + fixed leb vector length |
| 1109 | const header_size = 1 + 5 + 5; | 1111 | const header_size = 1 + 5 + 5; |
| 1110 | try bytes.appendNTimes(gpa, 0, header_size); | 1112 | try bytes.appendNTimes(gpa, 0, header_size); |
| ... | @@ -1125,7 +1127,7 @@ fn emitLimits(writer: anytype, limits: std.wasm.Limits) !void { | ... | @@ -1125,7 +1127,7 @@ fn emitLimits(writer: anytype, limits: std.wasm.Limits) !void { |
| 1125 | if (limits.flags.has_max) try leb.writeUleb128(writer, limits.max); | 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 | const module_name = memory_import.module_name.slice(wasm); | 1131 | const module_name = memory_import.module_name.slice(wasm); |
| 1130 | try leb.writeUleb128(writer, @as(u32, @intCast(module_name.len))); | 1132 | try leb.writeUleb128(writer, @as(u32, @intCast(module_name.len))); |
| 1131 | try writer.writeAll(module_name); | 1133 | try writer.writeAll(module_name); |
src/link/Wasm/Object.zig+111-79| ... | @@ -36,7 +36,7 @@ global_imports: RelativeSlice, | ... | @@ -36,7 +36,7 @@ global_imports: RelativeSlice, |
| 36 | table_imports: RelativeSlice, | 36 | table_imports: RelativeSlice, |
| 37 | /// Points into Wasm object_custom_segments | 37 | /// Points into Wasm object_custom_segments |
| 38 | custom_segments: RelativeSlice, | 38 | custom_segments: RelativeSlice, |
| 39 | /// For calculating local section index from `Wasm.SectionIndex`. | 39 | /// For calculating local section index from `Wasm.ObjectSectionIndex`. |
| 40 | local_section_index_base: u32, | 40 | local_section_index_base: u32, |
| 41 | /// Points into Wasm object_init_funcs | 41 | /// Points into Wasm object_init_funcs |
| 42 | init_funcs: RelativeSlice, | 42 | init_funcs: RelativeSlice, |
| ... | @@ -109,10 +109,10 @@ pub const Symbol = struct { | ... | @@ -109,10 +109,10 @@ pub const Symbol = struct { |
| 109 | }, | 109 | }, |
| 110 | data_import: void, | 110 | data_import: void, |
| 111 | global: Wasm.ObjectGlobalIndex, | 111 | global: Wasm.ObjectGlobalIndex, |
| 112 | global_import: Wasm.ObjectGlobalImportIndex, | 112 | global_import: Wasm.GlobalImport.Index, |
| 113 | section: Wasm.ObjectSectionIndex, | 113 | section: Wasm.ObjectSectionIndex, |
| 114 | table: Wasm.ObjectTableIndex, | 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,7 +159,7 @@ pub const ScratchSpace = struct { |
| 159 | } | 159 | } |
| 160 | }; | 160 | }; |
| 161 | 161 | ||
| 162 | fn parse( | 162 | pub fn parse( |
| 163 | wasm: *Wasm, | 163 | wasm: *Wasm, |
| 164 | bytes: []const u8, | 164 | bytes: []const u8, |
| 165 | path: Path, | 165 | path: Path, |
| ... | @@ -181,18 +181,18 @@ fn parse( | ... | @@ -181,18 +181,18 @@ fn parse( |
| 181 | pos += 4; | 181 | pos += 4; |
| 182 | 182 | ||
| 183 | const data_segment_start: u32 = @intCast(wasm.object_data_segments.items.len); | 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 | const functions_start: u32 = @intCast(wasm.object_functions.items.len); | 185 | const functions_start: u32 = @intCast(wasm.object_functions.items.len); |
| 186 | const tables_start: u32 = @intCast(wasm.object_tables.items.len); | 186 | const tables_start: u32 = @intCast(wasm.object_tables.items.len); |
| 187 | const memories_start: u32 = @intCast(wasm.object_memories.items.len); | 187 | const memories_start: u32 = @intCast(wasm.object_memories.items.len); |
| 188 | const globals_start: u32 = @intCast(wasm.object_globals.items.len); | 188 | const globals_start: u32 = @intCast(wasm.object_globals.items.len); |
| 189 | const init_funcs_start: u32 = @intCast(wasm.object_init_funcs.items.len); | 189 | const init_funcs_start: u32 = @intCast(wasm.object_init_funcs.items.len); |
| 190 | const comdats_start: u32 = @intCast(wasm.object_comdats.items.len); | 190 | const comdats_start: u32 = @intCast(wasm.object_comdats.items.len); |
| 191 | const function_imports_start: u32 = @intCast(wasm.object_function_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.items.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.items.len); | 193 | const table_imports_start: u32 = @intCast(wasm.object_table_imports.entries.len); |
| 194 | const local_section_index_base = wasm.object_total_sections; | 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 | ss.clear(); | 197 | ss.clear(); |
| 198 | 198 | ||
| ... | @@ -200,10 +200,9 @@ fn parse( | ... | @@ -200,10 +200,9 @@ fn parse( |
| 200 | var opt_features: ?Wasm.Feature.Set = null; | 200 | var opt_features: ?Wasm.Feature.Set = null; |
| 201 | var saw_linking_section = false; | 201 | var saw_linking_section = false; |
| 202 | var has_tls = false; | 202 | var has_tls = false; |
| 203 | var local_section_index: u32 = 0; | ||
| 204 | var table_count: usize = 0; | 203 | var table_count: usize = 0; |
| 205 | while (pos < bytes.len) : (local_section_index += 1) { | 204 | while (pos < bytes.len) : (wasm.object_total_sections += 1) { |
| 206 | const section_index: Wasm.SectionIndex = @enumFromInt(local_section_index_base + local_section_index); | 205 | const section_index: Wasm.ObjectSectionIndex = @enumFromInt(wasm.object_total_sections); |
| 207 | 206 | ||
| 208 | const section_tag: std.wasm.Section = @enumFromInt(bytes[pos]); | 207 | const section_tag: std.wasm.Section = @enumFromInt(bytes[pos]); |
| 209 | pos += 1; | 208 | pos += 1; |
| ... | @@ -245,7 +244,7 @@ fn parse( | ... | @@ -245,7 +244,7 @@ fn parse( |
| 245 | .strings = flags.strings, | 244 | .strings = flags.strings, |
| 246 | .tls = tls, | 245 | .tls = tls, |
| 247 | .alignment = @enumFromInt(alignment), | 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,13 +256,13 @@ fn parse( |
| 257 | if (symbol_index > ss.symbol_table.items.len) | 256 | if (symbol_index > ss.symbol_table.items.len) |
| 258 | return diags.failParse(path, "init_funcs before symbol table", .{}); | 257 | return diags.failParse(path, "init_funcs before symbol table", .{}); |
| 259 | const sym = &ss.symbol_table.items[symbol_index]; | 258 | const sym = &ss.symbol_table.items[symbol_index]; |
| 260 | if (sym.tag != .function) { | 259 | if (sym.pointee != .function) { |
| 261 | return diags.failParse(path, "init_func symbol '{s}' not a function", .{ | 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 | } else if (sym.flags.undefined) { | 263 | } else if (sym.flags.undefined) { |
| 265 | return diags.failParse(path, "init_func symbol '{s}' is an import", .{ | 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 | func.* = .{ | 268 | func.* = .{ |
| ... | @@ -278,22 +277,23 @@ fn parse( | ... | @@ -278,22 +277,23 @@ fn parse( |
| 278 | const flags, pos = readLeb(u32, bytes, pos); | 277 | const flags, pos = readLeb(u32, bytes, pos); |
| 279 | if (flags != 0) return error.UnexpectedComdatFlags; | 278 | if (flags != 0) return error.UnexpectedComdatFlags; |
| 280 | const symbol_count, pos = readLeb(u32, bytes, pos); | 279 | const symbol_count, pos = readLeb(u32, bytes, pos); |
| 281 | const start_off: u32 = @intCast(wasm.object_comdat_symbols.items.len); | 280 | const start_off: u32 = @intCast(wasm.object_comdat_symbols.len); |
| 282 | for (try wasm.object_comdat_symbols.addManyAsSlice(gpa, symbol_count)) |*symbol| { | 281 | try wasm.object_comdat_symbols.ensureUnusedCapacity(gpa, symbol_count); |
| 282 | for (0..symbol_count) |_| { | ||
| 283 | const kind, pos = readEnum(Wasm.Comdat.Symbol.Type, bytes, pos); | 283 | const kind, pos = readEnum(Wasm.Comdat.Symbol.Type, bytes, pos); |
| 284 | const index, pos = readLeb(u32, bytes, pos); | 284 | const index, pos = readLeb(u32, bytes, pos); |
| 285 | if (true) @panic("TODO rebase index depending on kind"); | 285 | if (true) @panic("TODO rebase index depending on kind"); |
| 286 | symbol.* = .{ | 286 | wasm.object_comdat_symbols.appendAssumeCapacity(.{ |
| 287 | .kind = kind, | 287 | .kind = kind, |
| 288 | .index = index, | 288 | .index = index, |
| 289 | }; | 289 | }); |
| 290 | } | 290 | } |
| 291 | comdat.* = .{ | 291 | comdat.* = .{ |
| 292 | .name = try wasm.internString(name), | 292 | .name = try wasm.internString(name), |
| 293 | .flags = flags, | 293 | .flags = flags, |
| 294 | .symbols = .{ | 294 | .symbols = .{ |
| 295 | .off = start_off, | 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,7 +321,7 @@ fn parse( |
| 321 | const size, pos = readLeb(u32, bytes, pos); | 321 | const size, pos = readLeb(u32, bytes, pos); |
| 322 | 322 | ||
| 323 | symbol.pointee = .{ .data = .{ | 323 | symbol.pointee = .{ .data = .{ |
| 324 | .index = @enumFromInt(data_segment_start + segment_index), | 324 | .segment_index = @enumFromInt(data_segment_start + segment_index), |
| 325 | .segment_offset = segment_offset, | 325 | .segment_offset = segment_offset, |
| 326 | .size = size, | 326 | .size = size, |
| 327 | } }; | 327 | } }; |
| ... | @@ -329,7 +329,7 @@ fn parse( | ... | @@ -329,7 +329,7 @@ fn parse( |
| 329 | }, | 329 | }, |
| 330 | .section => { | 330 | .section => { |
| 331 | const local_section, pos = readLeb(u32, bytes, pos); | 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 | symbol.pointee = .{ .section = section }; | 333 | symbol.pointee = .{ .section = section }; |
| 334 | }, | 334 | }, |
| 335 | 335 | ||
| ... | @@ -337,7 +337,7 @@ fn parse( | ... | @@ -337,7 +337,7 @@ fn parse( |
| 337 | const local_index, pos = readLeb(u32, bytes, pos); | 337 | const local_index, pos = readLeb(u32, bytes, pos); |
| 338 | if (symbol.flags.undefined) { | 338 | if (symbol.flags.undefined) { |
| 339 | symbol.pointee = .{ .function_import = @enumFromInt(local_index) }; | 339 | symbol.pointee = .{ .function_import = @enumFromInt(local_index) }; |
| 340 | if (flags.explicit_name) { | 340 | if (symbol.flags.explicit_name) { |
| 341 | const name, pos = readBytes(bytes, pos); | 341 | const name, pos = readBytes(bytes, pos); |
| 342 | symbol.name = (try wasm.internString(name)).toOptional(); | 342 | symbol.name = (try wasm.internString(name)).toOptional(); |
| 343 | } | 343 | } |
| ... | @@ -351,7 +351,7 @@ fn parse( | ... | @@ -351,7 +351,7 @@ fn parse( |
| 351 | const local_index, pos = readLeb(u32, bytes, pos); | 351 | const local_index, pos = readLeb(u32, bytes, pos); |
| 352 | if (symbol.flags.undefined) { | 352 | if (symbol.flags.undefined) { |
| 353 | symbol.pointee = .{ .global_import = @enumFromInt(global_imports_start + local_index) }; | 353 | symbol.pointee = .{ .global_import = @enumFromInt(global_imports_start + local_index) }; |
| 354 | if (flags.explicit_name) { | 354 | if (symbol.flags.explicit_name) { |
| 355 | const name, pos = readBytes(bytes, pos); | 355 | const name, pos = readBytes(bytes, pos); |
| 356 | symbol.name = (try wasm.internString(name)).toOptional(); | 356 | symbol.name = (try wasm.internString(name)).toOptional(); |
| 357 | } | 357 | } |
| ... | @@ -366,7 +366,7 @@ fn parse( | ... | @@ -366,7 +366,7 @@ fn parse( |
| 366 | const local_index, pos = readLeb(u32, bytes, pos); | 366 | const local_index, pos = readLeb(u32, bytes, pos); |
| 367 | if (symbol.flags.undefined) { | 367 | if (symbol.flags.undefined) { |
| 368 | symbol.pointee = .{ .table_import = @enumFromInt(table_imports_start + local_index) }; | 368 | symbol.pointee = .{ .table_import = @enumFromInt(table_imports_start + local_index) }; |
| 369 | if (flags.explicit_name) { | 369 | if (symbol.flags.explicit_name) { |
| 370 | const name, pos = readBytes(bytes, pos); | 370 | const name, pos = readBytes(bytes, pos); |
| 371 | symbol.name = (try wasm.internString(name)).toOptional(); | 371 | symbol.name = (try wasm.internString(name)).toOptional(); |
| 372 | } | 372 | } |
| ... | @@ -377,7 +377,7 @@ fn parse( | ... | @@ -377,7 +377,7 @@ fn parse( |
| 377 | } | 377 | } |
| 378 | }, | 378 | }, |
| 379 | else => { | 379 | else => { |
| 380 | log.debug("unrecognized symbol type tag: {x}", .{tag}); | 380 | log.debug("unrecognized symbol type tag: {x}", .{@intFromEnum(tag)}); |
| 381 | return error.UnrecognizedSymbolType; | 381 | return error.UnrecognizedSymbolType; |
| 382 | }, | 382 | }, |
| 383 | } | 383 | } |
| ... | @@ -396,14 +396,14 @@ fn parse( | ... | @@ -396,14 +396,14 @@ fn parse( |
| 396 | // "Relocation sections can only target code, data and custom sections." | 396 | // "Relocation sections can only target code, data and custom sections." |
| 397 | const local_section, pos = readLeb(u32, bytes, pos); | 397 | const local_section, pos = readLeb(u32, bytes, pos); |
| 398 | const count, pos = readLeb(u32, bytes, pos); | 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 | log.debug("found {d} relocations for section={d}", .{ count, section }); | 401 | log.debug("found {d} relocations for section={d}", .{ count, section }); |
| 402 | 402 | ||
| 403 | var prev_offset: u32 = 0; | 403 | var prev_offset: u32 = 0; |
| 404 | try wasm.relocations.ensureUnusedCapacity(gpa, count); | 404 | try wasm.object_relocations.ensureUnusedCapacity(gpa, count); |
| 405 | for (0..count) |_| { | 405 | for (0..count) |_| { |
| 406 | const tag: Wasm.Relocation.Tag = @enumFromInt(bytes[pos]); | 406 | const tag: Wasm.ObjectRelocation.Tag = @enumFromInt(bytes[pos]); |
| 407 | pos += 1; | 407 | pos += 1; |
| 408 | const offset, pos = readLeb(u32, bytes, pos); | 408 | const offset, pos = readLeb(u32, bytes, pos); |
| 409 | const index, pos = readLeb(u32, bytes, pos); | 409 | const index, pos = readLeb(u32, bytes, pos); |
| ... | @@ -426,9 +426,10 @@ fn parse( | ... | @@ -426,9 +426,10 @@ fn parse( |
| 426 | .MEMORY_ADDR_TLS_SLEB64, | 426 | .MEMORY_ADDR_TLS_SLEB64, |
| 427 | .FUNCTION_OFFSET_I32, | 427 | .FUNCTION_OFFSET_I32, |
| 428 | .SECTION_OFFSET_I32, | 428 | .SECTION_OFFSET_I32, |
| 429 | .FUNCTION_OFFSET_I64, | ||
| 429 | => { | 430 | => { |
| 430 | const addend: i32, pos = readLeb(i32, bytes, pos); | 431 | const addend: i32, pos = readLeb(i32, bytes, pos); |
| 431 | wasm.relocations.appendAssumeCapacity(.{ | 432 | wasm.object_relocations.appendAssumeCapacity(.{ |
| 432 | .tag = tag, | 433 | .tag = tag, |
| 433 | .offset = offset, | 434 | .offset = offset, |
| 434 | .pointee = .{ .section = ss.symbol_table.items[index].pointee.section }, | 435 | .pointee = .{ .section = ss.symbol_table.items[index].pointee.section }, |
| ... | @@ -436,7 +437,7 @@ fn parse( | ... | @@ -436,7 +437,7 @@ fn parse( |
| 436 | }); | 437 | }); |
| 437 | }, | 438 | }, |
| 438 | .TYPE_INDEX_LEB => { | 439 | .TYPE_INDEX_LEB => { |
| 439 | wasm.relocations.appendAssumeCapacity(.{ | 440 | wasm.object_relocations.appendAssumeCapacity(.{ |
| 440 | .tag = tag, | 441 | .tag = tag, |
| 441 | .offset = offset, | 442 | .offset = offset, |
| 442 | .pointee = .{ .type_index = ss.func_types.items[index] }, | 443 | .pointee = .{ .type_index = ss.func_types.items[index] }, |
| ... | @@ -444,9 +445,19 @@ fn parse( | ... | @@ -444,9 +445,19 @@ fn parse( |
| 444 | }); | 445 | }); |
| 445 | }, | 446 | }, |
| 446 | .FUNCTION_INDEX_LEB, | 447 | .FUNCTION_INDEX_LEB, |
| 448 | .FUNCTION_INDEX_I32, | ||
| 447 | .GLOBAL_INDEX_LEB, | 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 | .tag = tag, | 461 | .tag = tag, |
| 451 | .offset = offset, | 462 | .offset = offset, |
| 452 | .pointee = .{ .symbol_name = ss.symbol_table.items[index].name.unwrap().? }, | 463 | .pointee = .{ .symbol_name = ss.symbol_table.items[index].name.unwrap().? }, |
| ... | @@ -457,7 +468,7 @@ fn parse( | ... | @@ -457,7 +468,7 @@ fn parse( |
| 457 | } | 468 | } |
| 458 | 469 | ||
| 459 | try wasm.object_relocations_table.putNoClobber(gpa, section, .{ | 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 | .len = count, | 472 | .len = count, |
| 462 | }); | 473 | }); |
| 463 | } else if (std.mem.eql(u8, section_name, "target_features")) { | 474 | } else if (std.mem.eql(u8, section_name, "target_features")) { |
| ... | @@ -466,15 +477,15 @@ fn parse( | ... | @@ -466,15 +477,15 @@ fn parse( |
| 466 | const debug_content = bytes[pos..section_end]; | 477 | const debug_content = bytes[pos..section_end]; |
| 467 | pos = section_end; | 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 | try wasm.string_bytes.appendSlice(gpa, debug_content); | 481 | try wasm.string_bytes.appendSlice(gpa, debug_content); |
| 471 | 482 | ||
| 472 | try wasm.object_custom_segments.put(gpa, section_index, .{ | 483 | try wasm.object_custom_segments.put(gpa, section_index, .{ |
| 473 | .data_off = data_off, | 484 | .payload = .{ |
| 474 | .flags = .{ | 485 | .off = data_off, |
| 475 | .data_len = @intCast(debug_content.len), | 486 | .len = @intCast(debug_content.len), |
| 476 | .represented = false, // set when scanning symbol table | ||
| 477 | }, | 487 | }, |
| 488 | .flags = .{}, | ||
| 478 | .section_name = try wasm.internString(section_name), | 489 | .section_name = try wasm.internString(section_name), |
| 479 | }); | 490 | }); |
| 480 | } else { | 491 | } else { |
| ... | @@ -483,7 +494,7 @@ fn parse( | ... | @@ -483,7 +494,7 @@ fn parse( |
| 483 | }, | 494 | }, |
| 484 | .type => { | 495 | .type => { |
| 485 | const func_types_len, pos = readLeb(u32, bytes, pos); | 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 | if (bytes[pos] != std.wasm.function_type) return error.ExpectedFuncType; | 498 | if (bytes[pos] != std.wasm.function_type) return error.ExpectedFuncType; |
| 488 | pos += 1; | 499 | pos += 1; |
| 489 | 500 | ||
| ... | @@ -509,7 +520,7 @@ fn parse( | ... | @@ -509,7 +520,7 @@ fn parse( |
| 509 | try ss.func_imports.append(gpa, .{ | 520 | try ss.func_imports.append(gpa, .{ |
| 510 | .module_name = interned_module_name, | 521 | .module_name = interned_module_name, |
| 511 | .name = interned_name, | 522 | .name = interned_name, |
| 512 | .index = function, | 523 | .function_index = @enumFromInt(function), |
| 513 | }); | 524 | }); |
| 514 | }, | 525 | }, |
| 515 | .memory => { | 526 | .memory => { |
| ... | @@ -527,24 +538,32 @@ fn parse( | ... | @@ -527,24 +538,32 @@ fn parse( |
| 527 | const valtype, pos = readEnum(std.wasm.Valtype, bytes, pos); | 538 | const valtype, pos = readEnum(std.wasm.Valtype, bytes, pos); |
| 528 | const mutable = bytes[pos] == 0x01; | 539 | const mutable = bytes[pos] == 0x01; |
| 529 | pos += 1; | 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 | .module_name = interned_module_name, | 548 | .module_name = interned_module_name, |
| 532 | .name = interned_name, | 549 | .source_location = source_location, |
| 533 | .mutable = mutable, | 550 | .resolution = .unresolved, |
| 534 | .valtype = valtype, | ||
| 535 | }); | 551 | }); |
| 536 | }, | 552 | }, |
| 537 | .table => { | 553 | .table => { |
| 538 | const reftype, pos = readEnum(std.wasm.RefType, bytes, pos); | 554 | const ref_type, pos = readEnum(std.wasm.RefType, bytes, pos); |
| 539 | const limits, pos = readLimits(bytes, pos); | 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 | .module_name = interned_module_name, | 562 | .module_name = interned_module_name, |
| 542 | .name = interned_name, | 563 | .source_location = source_location, |
| 564 | .resolution = .unresolved, | ||
| 543 | .limits_min = limits.min, | 565 | .limits_min = limits.min, |
| 544 | .limits_max = limits.max, | 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,17 +572,25 @@ fn parse( |
| 553 | .function => { | 572 | .function => { |
| 554 | const functions_len, pos = readLeb(u32, bytes, pos); | 573 | const functions_len, pos = readLeb(u32, bytes, pos); |
| 555 | for (try ss.func_type_indexes.addManyAsSlice(gpa, functions_len)) |*func_type_index| { | 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 | .table => { | 579 | .table => { |
| 560 | const tables_len, pos = readLeb(u32, bytes, pos); | 580 | const tables_len, pos = readLeb(u32, bytes, pos); |
| 561 | for (try wasm.object_tables.addManyAsSlice(gpa, tables_len)) |*table| { | 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 | const limits, pos = readLimits(bytes, pos); | 583 | const limits, pos = readLimits(bytes, pos); |
| 564 | table.* = .{ | 584 | table.* = .{ |
| 565 | .reftype = reftype, | 585 | .name = .none, |
| 566 | .limits = limits, | 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,8 +609,13 @@ fn parse( |
| 582 | pos += 1; | 609 | pos += 1; |
| 583 | const expr, pos = try readInit(wasm, bytes, pos); | 610 | const expr, pos = try readInit(wasm, bytes, pos); |
| 584 | global.* = .{ | 611 | global.* = .{ |
| 585 | .valtype = valtype, | 612 | .name = .none, |
| 586 | .mutable = mutable, | 613 | .flags = .{ |
| 614 | .global_type = .{ | ||
| 615 | .valtype = .from(valtype), | ||
| 616 | .mutable = mutable, | ||
| 617 | }, | ||
| 618 | }, | ||
| 587 | .expr = expr, | 619 | .expr = expr, |
| 588 | }; | 620 | }; |
| 589 | } | 621 | } |
| ... | @@ -668,8 +700,6 @@ fn parse( | ... | @@ -668,8 +700,6 @@ fn parse( |
| 668 | } | 700 | } |
| 669 | if (!saw_linking_section) return error.MissingLinkingSection; | 701 | if (!saw_linking_section) return error.MissingLinkingSection; |
| 670 | 702 | ||
| 671 | wasm.object_total_sections = local_section_index_base + local_section_index; | ||
| 672 | |||
| 673 | if (has_tls) { | 703 | if (has_tls) { |
| 674 | const cpu_features = wasm.base.comp.root_mod.resolved_target.result.cpu.features; | 704 | const cpu_features = wasm.base.comp.root_mod.resolved_target.result.cpu.features; |
| 675 | if (!std.Target.wasm.featureSetHas(cpu_features, .atomics)) | 705 | if (!std.Target.wasm.featureSetHas(cpu_features, .atomics)) |
| ... | @@ -770,7 +800,7 @@ fn parse( | ... | @@ -770,7 +800,7 @@ fn parse( |
| 770 | ptr.name = symbol.name; | 800 | ptr.name = symbol.name; |
| 771 | ptr.flags = symbol.flags; | 801 | ptr.flags = symbol.flags; |
| 772 | if (symbol.flags.undefined and symbol.flags.binding == .local) { | 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 | diags.addParseError(path, "local symbol '{s}' references import", .{name}); | 804 | diags.addParseError(path, "local symbol '{s}' references import", .{name}); |
| 775 | } | 805 | } |
| 776 | }, | 806 | }, |
| ... | @@ -779,7 +809,7 @@ fn parse( | ... | @@ -779,7 +809,7 @@ fn parse( |
| 779 | const ptr = i.ptr(wasm); | 809 | const ptr = i.ptr(wasm); |
| 780 | ptr.flags = symbol.flags; | 810 | ptr.flags = symbol.flags; |
| 781 | if (symbol.flags.undefined and symbol.flags.binding == .local) { | 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 | diags.addParseError(path, "local symbol '{s}' references import", .{name}); | 813 | diags.addParseError(path, "local symbol '{s}' references import", .{name}); |
| 784 | } | 814 | } |
| 785 | }, | 815 | }, |
| ... | @@ -806,19 +836,20 @@ fn parse( | ... | @@ -806,19 +836,20 @@ fn parse( |
| 806 | data.flags.no_strip = info.flags.retain; | 836 | data.flags.no_strip = info.flags.retain; |
| 807 | data.flags.alignment = info.flags.alignment; | 837 | data.flags.alignment = info.flags.alignment; |
| 808 | if (data.flags.undefined and data.flags.binding == .local) { | 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 | diags.addParseError(path, "local symbol '{s}' references import", .{name}); | 840 | diags.addParseError(path, "local symbol '{s}' references import", .{name}); |
| 811 | } | 841 | } |
| 812 | } | 842 | } |
| 813 | 843 | ||
| 814 | // Check for indirect function table in case of an MVP object file. | 844 | // Check for indirect function table in case of an MVP object file. |
| 815 | legacy_indirect_function_table: { | 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 | // If there is a symbol for each import table, this is not a legacy object file. | 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 | if (table_count != 0) { | 850 | if (table_count != 0) { |
| 820 | return diags.failParse(path, "expected a table entry symbol for each of the {d} table(s), but instead got {d} symbols.", .{ | 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 | // MVP object files cannot have any table definitions, only | 855 | // MVP object files cannot have any table definitions, only |
| ... | @@ -827,16 +858,16 @@ fn parse( | ... | @@ -827,16 +858,16 @@ fn parse( |
| 827 | if (tables.len > 0) { | 858 | if (tables.len > 0) { |
| 828 | return diags.failParse(path, "table definition without representing table symbols", .{}); | 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 | return diags.failParse(path, "found more than one table import, but no representing table symbols", .{}); | 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 | if (table_import_name != wasm.preloaded_strings.__indirect_function_table) { | 865 | if (table_import_name != wasm.preloaded_strings.__indirect_function_table) { |
| 835 | return diags.failParse(path, "non-indirect function table import '{s}' is missing a corresponding symbol", .{ | 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 | .undefined = true, | 871 | .undefined = true, |
| 841 | .no_strip = true, | 872 | .no_strip = true, |
| 842 | }; | 873 | }; |
| ... | @@ -874,11 +905,11 @@ fn parse( | ... | @@ -874,11 +905,11 @@ fn parse( |
| 874 | }, | 905 | }, |
| 875 | .function_imports = .{ | 906 | .function_imports = .{ |
| 876 | .off = function_imports_start, | 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 | .global_imports = .{ | 910 | .global_imports = .{ |
| 880 | .off = global_imports_start, | 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 | .table_imports = .{ | 914 | .table_imports = .{ |
| 884 | .off = table_imports_start, | 915 | .off = table_imports_start, |
| ... | @@ -894,7 +925,7 @@ fn parse( | ... | @@ -894,7 +925,7 @@ fn parse( |
| 894 | }, | 925 | }, |
| 895 | .custom_segments = .{ | 926 | .custom_segments = .{ |
| 896 | .off = custom_segment_start, | 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 | .local_section_index_base = local_section_index_base, | 930 | .local_section_index_base = local_section_index_base, |
| 900 | }; | 931 | }; |
| ... | @@ -920,7 +951,7 @@ fn parseFeatures( | ... | @@ -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 | pos += 1; | 956 | pos += 1; |
| 926 | const name, pos = readBytes(bytes, pos); | 957 | const name, pos = readBytes(bytes, pos); |
| ... | @@ -935,7 +966,7 @@ fn parseFeatures( | ... | @@ -935,7 +966,7 @@ fn parseFeatures( |
| 935 | std.mem.sortUnstable(Wasm.Feature, feature_buffer, {}, Wasm.Feature.lessThan); | 966 | std.mem.sortUnstable(Wasm.Feature, feature_buffer, {}, Wasm.Feature.lessThan); |
| 936 | 967 | ||
| 937 | return .{ | 968 | return .{ |
| 938 | .fromString(try wasm.internString(@bitCast(feature_buffer))), | 969 | .fromString(try wasm.internString(@ptrCast(feature_buffer))), |
| 939 | pos, | 970 | pos, |
| 940 | }; | 971 | }; |
| 941 | } | 972 | } |
| ... | @@ -966,9 +997,9 @@ fn readEnum(comptime T: type, bytes: []const u8, pos: usize) struct { T, usize } | ... | @@ -966,9 +997,9 @@ fn readEnum(comptime T: type, bytes: []const u8, pos: usize) struct { T, usize } |
| 966 | } | 997 | } |
| 967 | 998 | ||
| 968 | fn readLimits(bytes: []const u8, start_pos: usize) struct { std.wasm.Limits, usize } { | 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 | const min, const max_pos = readLeb(u32, bytes, start_pos + 1); | 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 | return .{ .{ | 1003 | return .{ .{ |
| 973 | .flags = flags, | 1004 | .flags = flags, |
| 974 | .min = min, | 1005 | .min = min, |
| ... | @@ -977,7 +1008,7 @@ fn readLimits(bytes: []const u8, start_pos: usize) struct { std.wasm.Limits, usi | ... | @@ -977,7 +1008,7 @@ fn readLimits(bytes: []const u8, start_pos: usize) struct { std.wasm.Limits, usi |
| 977 | } | 1008 | } |
| 978 | 1009 | ||
| 979 | fn readInit(wasm: *Wasm, bytes: []const u8, pos: usize) !struct { Wasm.Expr, usize } { | 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 | return .{ try wasm.addExpr(bytes[pos..end_pos]), end_pos }; | 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,6 +1022,7 @@ fn skipInit(bytes: []const u8, pos: usize) !usize { |
| 991 | .global_get => readLeb(u32, bytes, pos + 1)[1], | 1022 | .global_get => readLeb(u32, bytes, pos + 1)[1], |
| 992 | else => return error.InvalidInitOpcode, | 1023 | else => return error.InvalidInitOpcode, |
| 993 | }; | 1024 | }; |
| 994 | if (readEnum(std.wasm.Opcode, bytes, end_pos) != .end) return error.InitExprMissingEnd; | 1025 | const op, const final_pos = readEnum(std.wasm.Opcode, bytes, end_pos); |
| 995 | return end_pos + 1; | 1026 | if (op != .end) return error.InitExprMissingEnd; |
| 1027 | return final_pos; | ||
| 996 | } | 1028 | } |