authorgravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2022-10-08 11:00:07+02:00
committergravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-10-08 17:23:13+02:00
log7f508480f49b78817bf67579a8810d4499cbbc13
treed1f9dbed875ae37d2ebf5997cc0d2cde9e3bdfa0
parentfa9327ac051031be21b6ccb494f31585d0b68915

wasm-linker: convert relocation addend to i32

Addends in relocations are signed integers as theoretically it could be a negative number. As Atom's offsets are relative to their parent section, the relocation value should still result in a postive number. For this reason, the final result is stored as an unsigned integer. Also, rather than using `null` for relocations that do not support addends. We set the value to 0 for those that do not support addends, and have to call `addendIsPresent` to determine if an addend exists or not. This means each Relocation costs 4 bytes less than before, saving memory while linking.

5 files changed, 14 insertions(+), 11 deletions(-)

src/arch/wasm/Emit.zig+1-1
......@@ -413,7 +413,7 @@ fn emitMemAddress(emit: *Emit, inst: Mir.Inst.Index) !void {
413413 .offset = mem_offset,
414414 .index = mem.pointer,
415415 .relocation_type = if (is_wasm32) .R_WASM_MEMORY_ADDR_LEB else .R_WASM_MEMORY_ADDR_LEB64,
416 .addend = mem.offset,
416 .addend = @intCast(i32, mem.offset),
417417 });
418418 }
419419}
src/link/Wasm.zig+4-4
......@@ -1080,7 +1080,7 @@ pub fn getDeclVAddr(
10801080 .index = target_symbol_index,
10811081 .offset = @intCast(u32, reloc_info.offset),
10821082 .relocation_type = if (is_wasm32) .R_WASM_MEMORY_ADDR_I32 else .R_WASM_MEMORY_ADDR_I64,
1083 .addend = reloc_info.addend,
1083 .addend = @intCast(i32, reloc_info.addend),
10841084 });
10851085 }
10861086 // we do not know the final address at this point,
......@@ -2001,7 +2001,7 @@ fn populateErrorNameTable(wasm: *Wasm) !void {
20012001 .index = names_symbol_index,
20022002 .relocation_type = .R_WASM_MEMORY_ADDR_I32,
20032003 .offset = offset,
2004 .addend = addend,
2004 .addend = @intCast(i32, addend),
20052005 });
20062006 atom.size += @intCast(u32, slice_ty.abiSize(wasm.base.options.target));
20072007 addend += len;
......@@ -3433,7 +3433,7 @@ fn emitCodeRelocations(
34333433 try leb.writeULEB128(writer, offset);
34343434 try leb.writeULEB128(writer, symbol_index);
34353435 if (relocation.relocation_type.addendIsPresent()) {
3436 try leb.writeULEB128(writer, relocation.addend orelse 0);
3436 try leb.writeILEB128(writer, relocation.addend);
34373437 }
34383438 log.debug("Emit relocation: {}", .{relocation});
34393439 }
......@@ -3483,7 +3483,7 @@ fn emitDataRelocations(
34833483 try leb.writeULEB128(writer, offset);
34843484 try leb.writeULEB128(writer, symbol_index);
34853485 if (relocation.relocation_type.addendIsPresent()) {
3486 try leb.writeULEB128(writer, relocation.addend orelse 0);
3486 try leb.writeILEB128(writer, relocation.addend);
34873487 }
34883488 log.debug("Emit relocation: {}", .{relocation});
34893489 }
src/link/Wasm/Atom.zig+6-3
......@@ -194,12 +194,14 @@ fn relocationValue(atom: Atom, relocation: types.Relocation, wasm_bin: *const Wa
194194 const segment_name = segment_info[symbol.index].outputName(merge_segment);
195195 const segment_index = wasm_bin.data_segments.get(segment_name).?;
196196 const segment = wasm_bin.segments.items[segment_index];
197 return target_atom.offset + segment.offset + (relocation.addend orelse 0);
197 const rel_value = @intCast(i32, target_atom.offset + segment.offset) + relocation.addend;
198 return @intCast(u32, rel_value);
198199 },
199200 .R_WASM_EVENT_INDEX_LEB => return symbol.index,
200201 .R_WASM_SECTION_OFFSET_I32 => {
201202 const target_atom = wasm_bin.symbol_atom.get(target_loc).?;
202 return target_atom.offset + (relocation.addend orelse 0);
203 const rel_value = @intCast(i32, target_atom.offset) + relocation.addend;
204 return @intCast(u32, rel_value);
203205 },
204206 .R_WASM_FUNCTION_OFFSET_I32 => {
205207 const target_atom = wasm_bin.symbol_atom.get(target_loc).?;
......@@ -214,7 +216,8 @@ fn relocationValue(atom: Atom, relocation: types.Relocation, wasm_bin: *const Wa
214216 if (current_atom == target_atom) break;
215217 current_atom = current_atom.next.?;
216218 }
217 return target_atom.offset + offset + (relocation.addend orelse 0);
219 const rel_value = @intCast(i32, target_atom.offset + offset) + relocation.addend;
220 return @intCast(u32, rel_value);
218221 },
219222 }
220223}
src/link/Wasm/Object.zig+1-1
......@@ -606,7 +606,7 @@ fn Parser(comptime ReaderType: type) type {
606606 .relocation_type = rel_type_enum,
607607 .offset = try leb.readULEB128(u32, reader),
608608 .index = try leb.readULEB128(u32, reader),
609 .addend = if (rel_type_enum.addendIsPresent()) try leb.readULEB128(u32, reader) else null,
609 .addend = if (rel_type_enum.addendIsPresent()) try leb.readILEB128(i32, reader) else 0,
610610 };
611611 log.debug("Found relocation: type({s}) offset({d}) index({d}) addend({?d})", .{
612612 @tagName(relocation.relocation_type),
src/link/Wasm/types.zig+2-2
......@@ -12,8 +12,8 @@ pub const Relocation = struct {
1212 /// When the type is `R_WASM_TYPE_INDEX_LEB`, it represents the index of the type.
1313 index: u32,
1414 /// Addend to add to the address.
15 /// This field is only non-null for `R_WASM_MEMORY_ADDR_*`, `R_WASM_FUNCTION_OFFSET_I32` and `R_WASM_SECTION_OFFSET_I32`.
16 addend: ?u32 = null,
15 /// This field is only non-zero for `R_WASM_MEMORY_ADDR_*`, `R_WASM_FUNCTION_OFFSET_I32` and `R_WASM_SECTION_OFFSET_I32`.
16 addend: i32 = 0,
1717
1818 /// All possible relocation types currently existing.
1919 /// This enum is exhaustive as the spec is WIP and new types