| author | |
| committer | |
| log | e475ddb08e4bb3bacbc50bdd26fa83f579783dbb |
| tree | 366a5b3b61c6598b23bc7e8a3551860ba9ac39af |
| parent | 86ed96d9336c06668a727893e41856b2e4fe3d23 |
| signature |
When exporting a data symbol, generate a regular global and use
the data symbol's virtual addres as the value (init) of the global.2 files changed, 26 insertions(+), 42 deletions(-)
src/link/Wasm.zig+8-18| ... | @@ -112,8 +112,6 @@ func_types: std.ArrayListUnmanaged(std.wasm.Type) = .{}, | ... | @@ -112,8 +112,6 @@ func_types: std.ArrayListUnmanaged(std.wasm.Type) = .{}, |
| 112 | functions: std.AutoArrayHashMapUnmanaged(struct { file: ?u16, index: u32 }, std.wasm.Func) = .{}, | 112 | functions: std.AutoArrayHashMapUnmanaged(struct { file: ?u16, index: u32 }, std.wasm.Func) = .{}, |
| 113 | /// Output global section | 113 | /// Output global section |
| 114 | wasm_globals: std.ArrayListUnmanaged(std.wasm.Global) = .{}, | 114 | wasm_globals: std.ArrayListUnmanaged(std.wasm.Global) = .{}, |
| 115 | /// Global symbols for exported data symbols | ||
| 116 | address_globals: std.ArrayListUnmanaged(SymbolLoc) = .{}, | ||
| 117 | /// Memory section | 115 | /// Memory section |
| 118 | memories: std.wasm.Memory = .{ .limits = .{ .min = 0, .max = null } }, | 116 | memories: std.wasm.Memory = .{ .limits = .{ .min = 0, .max = null } }, |
| 119 | /// Output table section | 117 | /// Output table section |
| ... | @@ -880,7 +878,6 @@ pub fn deinit(wasm: *Wasm) void { | ... | @@ -880,7 +878,6 @@ pub fn deinit(wasm: *Wasm) void { |
| 880 | wasm.func_types.deinit(gpa); | 878 | wasm.func_types.deinit(gpa); |
| 881 | wasm.functions.deinit(gpa); | 879 | wasm.functions.deinit(gpa); |
| 882 | wasm.wasm_globals.deinit(gpa); | 880 | wasm.wasm_globals.deinit(gpa); |
| 883 | wasm.address_globals.deinit(gpa); | ||
| 884 | wasm.function_table.deinit(gpa); | 881 | wasm.function_table.deinit(gpa); |
| 885 | wasm.tables.deinit(gpa); | 882 | wasm.tables.deinit(gpa); |
| 886 | wasm.exports.deinit(gpa); | 883 | wasm.exports.deinit(gpa); |
| ... | @@ -1879,8 +1876,13 @@ fn setupExports(wasm: *Wasm) !void { | ... | @@ -1879,8 +1876,13 @@ fn setupExports(wasm: *Wasm) !void { |
| 1879 | break :blk try wasm.string_table.put(wasm.base.allocator, sym_name); | 1876 | break :blk try wasm.string_table.put(wasm.base.allocator, sym_name); |
| 1880 | }; | 1877 | }; |
| 1881 | const exp: types.Export = if (symbol.tag == .data) exp: { | 1878 | const exp: types.Export = if (symbol.tag == .data) exp: { |
| 1882 | const global_index = @intCast(u32, wasm.wasm_globals.items.len + wasm.address_globals.items.len); | 1879 | const atom = wasm.symbol_atom.get(sym_loc).?; |
| 1883 | try wasm.address_globals.append(wasm.base.allocator, sym_loc); | 1880 | const va = atom.getVA(wasm, symbol); |
| 1881 | const global_index = @intCast(u32, wasm.imported_globals_count + wasm.wasm_globals.items.len); | ||
| 1882 | try wasm.wasm_globals.append(wasm.base.allocator, .{ | ||
| 1883 | .global_type = .{ .valtype = .i32, .mutable = false }, | ||
| 1884 | .init = .{ .i32_const = @intCast(i32, va) }, | ||
| 1885 | }); | ||
| 1884 | break :exp .{ | 1886 | break :exp .{ |
| 1885 | .name = export_name, | 1887 | .name = export_name, |
| 1886 | .kind = .global, | 1888 | .kind = .global, |
| ... | @@ -2741,22 +2743,10 @@ fn writeToFile( | ... | @@ -2741,22 +2743,10 @@ fn writeToFile( |
| 2741 | if (wasm.wasm_globals.items.len > 0) { | 2743 | if (wasm.wasm_globals.items.len > 0) { |
| 2742 | const header_offset = try reserveVecSectionHeader(&binary_bytes); | 2744 | const header_offset = try reserveVecSectionHeader(&binary_bytes); |
| 2743 | 2745 | ||
| 2744 | var global_count: u32 = 0; | ||
| 2745 | for (wasm.wasm_globals.items) |global| { | 2746 | for (wasm.wasm_globals.items) |global| { |
| 2746 | try binary_writer.writeByte(std.wasm.valtype(global.global_type.valtype)); | 2747 | try binary_writer.writeByte(std.wasm.valtype(global.global_type.valtype)); |
| 2747 | try binary_writer.writeByte(@boolToInt(global.global_type.mutable)); | 2748 | try binary_writer.writeByte(@boolToInt(global.global_type.mutable)); |
| 2748 | try emitInit(binary_writer, global.init); | 2749 | try emitInit(binary_writer, global.init); |
| 2749 | global_count += 1; | ||
| 2750 | } | ||
| 2751 | |||
| 2752 | for (wasm.address_globals.items) |sym_loc| { | ||
| 2753 | const atom = wasm.symbol_atom.get(sym_loc).?; | ||
| 2754 | try binary_writer.writeByte(std.wasm.valtype(.i32)); | ||
| 2755 | try binary_writer.writeByte(0); // immutable | ||
| 2756 | try emitInit(binary_writer, .{ | ||
| 2757 | .i32_const = @bitCast(i32, atom.offset), | ||
| 2758 | }); | ||
| 2759 | global_count += 1; | ||
| 2760 | } | 2750 | } |
| 2761 | 2751 | ||
| 2762 | try writeVecSectionHeader( | 2752 | try writeVecSectionHeader( |
| ... | @@ -2764,7 +2754,7 @@ fn writeToFile( | ... | @@ -2764,7 +2754,7 @@ fn writeToFile( |
| 2764 | header_offset, | 2754 | header_offset, |
| 2765 | .global, | 2755 | .global, |
| 2766 | @intCast(u32, binary_bytes.items.len - header_offset - header_size), | 2756 | @intCast(u32, binary_bytes.items.len - header_offset - header_size), |
| 2767 | @intCast(u32, global_count), | 2757 | @intCast(u32, wasm.wasm_globals.items.len), |
| 2768 | ); | 2758 | ); |
| 2769 | section_count += 1; | 2759 | section_count += 1; |
| 2770 | } | 2760 | } |
src/link/Wasm/Atom.zig+18-24| ... | @@ -90,24 +90,26 @@ pub fn getFirst(atom: *Atom) *Atom { | ... | @@ -90,24 +90,26 @@ pub fn getFirst(atom: *Atom) *Atom { |
| 90 | return tmp; | 90 | return tmp; |
| 91 | } | 91 | } |
| 92 | 92 | ||
| 93 | /// Unlike `getFirst` this returns the first `*Atom` that was | ||
| 94 | /// produced from Zig code, rather than an object file. | ||
| 95 | /// This is useful for debug sections where we want to extend | ||
| 96 | /// the bytes, and don't want to overwrite existing Atoms. | ||
| 97 | pub fn getFirstZigAtom(atom: *Atom) *Atom { | ||
| 98 | if (atom.file == null) return atom; | ||
| 99 | var tmp = atom; | ||
| 100 | return while (tmp.prev) |prev| { | ||
| 101 | if (prev.file == null) break prev; | ||
| 102 | tmp = prev; | ||
| 103 | } else unreachable; // must allocate an Atom first! | ||
| 104 | } | ||
| 105 | |||
| 106 | /// Returns the location of the symbol that represents this `Atom` | 93 | /// Returns the location of the symbol that represents this `Atom` |
| 107 | pub fn symbolLoc(atom: Atom) Wasm.SymbolLoc { | 94 | pub fn symbolLoc(atom: Atom) Wasm.SymbolLoc { |
| 108 | return .{ .file = atom.file, .index = atom.sym_index }; | 95 | return .{ .file = atom.file, .index = atom.sym_index }; |
| 109 | } | 96 | } |
| 110 | 97 | ||
| 98 | /// Returns the virtual address of the `Atom`. This is the address starting | ||
| 99 | /// from the first entry within a section. | ||
| 100 | pub fn getVA(atom: Atom, wasm: *const Wasm, symbol: *const Symbol) u32 { | ||
| 101 | if (symbol.tag == .function) return atom.offset; | ||
| 102 | std.debug.assert(symbol.tag == .data); | ||
| 103 | const merge_segment = wasm.base.options.output_mode != .Obj; | ||
| 104 | const segment_info = if (atom.file) |object_index| blk: { | ||
| 105 | break :blk wasm.objects.items[object_index].segment_info; | ||
| 106 | } else wasm.segment_info.values(); | ||
| 107 | const segment_name = segment_info[symbol.index].outputName(merge_segment); | ||
| 108 | const segment_index = wasm.data_segments.get(segment_name).?; | ||
| 109 | const segment = wasm.segments.items[segment_index]; | ||
| 110 | return segment.offset + atom.offset; | ||
| 111 | } | ||
| 112 | |||
| 111 | /// Resolves the relocations within the atom, writing the new value | 113 | /// Resolves the relocations within the atom, writing the new value |
| 112 | /// at the calculated offset. | 114 | /// at the calculated offset. |
| 113 | pub fn resolveRelocs(atom: *Atom, wasm_bin: *const Wasm) void { | 115 | pub fn resolveRelocs(atom: *Atom, wasm_bin: *const Wasm) void { |
| ... | @@ -159,7 +161,7 @@ pub fn resolveRelocs(atom: *Atom, wasm_bin: *const Wasm) void { | ... | @@ -159,7 +161,7 @@ pub fn resolveRelocs(atom: *Atom, wasm_bin: *const Wasm) void { |
| 159 | /// The final value must be casted to the correct size. | 161 | /// The final value must be casted to the correct size. |
| 160 | fn relocationValue(atom: Atom, relocation: types.Relocation, wasm_bin: *const Wasm) u64 { | 162 | fn relocationValue(atom: Atom, relocation: types.Relocation, wasm_bin: *const Wasm) u64 { |
| 161 | const target_loc = (Wasm.SymbolLoc{ .file = atom.file, .index = relocation.index }).finalLoc(wasm_bin); | 163 | const target_loc = (Wasm.SymbolLoc{ .file = atom.file, .index = relocation.index }).finalLoc(wasm_bin); |
| 162 | const symbol = target_loc.getSymbol(wasm_bin).*; | 164 | const symbol = target_loc.getSymbol(wasm_bin); |
| 163 | switch (relocation.relocation_type) { | 165 | switch (relocation.relocation_type) { |
| 164 | .R_WASM_FUNCTION_INDEX_LEB => return symbol.index, | 166 | .R_WASM_FUNCTION_INDEX_LEB => return symbol.index, |
| 165 | .R_WASM_TABLE_NUMBER_LEB => return symbol.index, | 167 | .R_WASM_TABLE_NUMBER_LEB => return symbol.index, |
| ... | @@ -190,17 +192,9 @@ fn relocationValue(atom: Atom, relocation: types.Relocation, wasm_bin: *const Wa | ... | @@ -190,17 +192,9 @@ fn relocationValue(atom: Atom, relocation: types.Relocation, wasm_bin: *const Wa |
| 190 | if (symbol.isUndefined()) { | 192 | if (symbol.isUndefined()) { |
| 191 | return 0; | 193 | return 0; |
| 192 | } | 194 | } |
| 193 | |||
| 194 | const merge_segment = wasm_bin.base.options.output_mode != .Obj; | ||
| 195 | const target_atom = wasm_bin.symbol_atom.get(target_loc).?; | 195 | const target_atom = wasm_bin.symbol_atom.get(target_loc).?; |
| 196 | const segment_info = if (target_atom.file) |object_index| blk: { | 196 | const va = @intCast(i32, target_atom.getVA(wasm_bin, symbol)); |
| 197 | break :blk wasm_bin.objects.items[object_index].segment_info; | 197 | return @intCast(u32, va + relocation.addend); |
| 198 | } else wasm_bin.segment_info.values(); | ||
| 199 | const segment_name = segment_info[symbol.index].outputName(merge_segment); | ||
| 200 | const segment_index = wasm_bin.data_segments.get(segment_name).?; | ||
| 201 | const segment = wasm_bin.segments.items[segment_index]; | ||
| 202 | const rel_value = @intCast(i32, target_atom.offset + segment.offset) + relocation.addend; | ||
| 203 | return @intCast(u32, rel_value); | ||
| 204 | }, | 198 | }, |
| 205 | .R_WASM_EVENT_INDEX_LEB => return symbol.index, | 199 | .R_WASM_EVENT_INDEX_LEB => return symbol.index, |
| 206 | .R_WASM_SECTION_OFFSET_I32 => { | 200 | .R_WASM_SECTION_OFFSET_I32 => { |