mirror of
https://github.com/llvm/llvm-project.git
synced 2025-05-02 00:06:05 +00:00
[WebAssembly] Store function index rather than table index in TABLE_INDEX relocations
Relocations of type R_WEBASSEMBLY_TABLE_INDEX represent places where the table index for a given function is needed. While the value stored in this location is a table index, the index in the relocation entry itself is a function index (the index of the function which is to be called indirectly). This is how is was spec'd originally but the LLVM implementation didn't do this. This makes things a little simpler in the linker since the table in the input file can essentially be ignored that the output table can be created purely based on these relocations. Patch by Nicholas Wilson! Differential Revision: https://reviews.llvm.org/D42080 llvm-svn: 323165
This commit is contained in:
parent
4ce341ffb6
commit
60ec30340f
@ -499,25 +499,44 @@ static const MCSymbolWasm* ResolveSymbol(const MCSymbolWasm& Symbol) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Compute a value to write into the code at the location covered
|
// Compute a value to write into the code at the location covered
|
||||||
// by RelEntry. This value isn't used by the static linker, since
|
// by RelEntry. This value isn't used by the static linker; it just serves
|
||||||
// we have addends; it just serves to make the code more readable
|
// to make the object format more readable and more likely to be directly
|
||||||
// and to make standalone wasm modules directly usable.
|
// useable.
|
||||||
uint32_t
|
uint32_t
|
||||||
WasmObjectWriter::getProvisionalValue(const WasmRelocationEntry &RelEntry) {
|
WasmObjectWriter::getProvisionalValue(const WasmRelocationEntry &RelEntry) {
|
||||||
const MCSymbolWasm *Sym = ResolveSymbol(*RelEntry.Symbol);
|
|
||||||
|
|
||||||
// For undefined symbols, use zero
|
switch (RelEntry.Type) {
|
||||||
if (!Sym->isDefined())
|
case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
|
||||||
return 0;
|
case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
|
||||||
|
// Provitional value is the indirect symbol index
|
||||||
|
if (!IndirectSymbolIndices.count(RelEntry.Symbol))
|
||||||
|
report_fatal_error("symbol not found in table index space: " +
|
||||||
|
RelEntry.Symbol->getName());
|
||||||
|
return IndirectSymbolIndices[RelEntry.Symbol];
|
||||||
|
case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
|
||||||
|
case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB:
|
||||||
|
case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
|
||||||
|
// Provitional value is function/type/global index itself
|
||||||
|
return getRelocationIndexValue(RelEntry);
|
||||||
|
case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
|
||||||
|
case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
|
||||||
|
case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB: {
|
||||||
|
// Provitional value is address of the global
|
||||||
|
const MCSymbolWasm *Sym = ResolveSymbol(*RelEntry.Symbol);
|
||||||
|
// For undefined symbols, use zero
|
||||||
|
if (!Sym->isDefined())
|
||||||
|
return 0;
|
||||||
|
|
||||||
uint32_t GlobalIndex = SymbolIndices[Sym];
|
uint32_t GlobalIndex = SymbolIndices[Sym];
|
||||||
const WasmGlobal& Global = Globals[GlobalIndex - NumGlobalImports];
|
const WasmGlobal& Global = Globals[GlobalIndex - NumGlobalImports];
|
||||||
uint64_t Address = Global.InitialValue + RelEntry.Addend;
|
uint64_t Address = Global.InitialValue + RelEntry.Addend;
|
||||||
|
|
||||||
// Ignore overflow. LLVM allows address arithmetic to silently wrap.
|
// Ignore overflow. LLVM allows address arithmetic to silently wrap.
|
||||||
uint32_t Value = Address;
|
return Address;
|
||||||
|
}
|
||||||
return Value;
|
default:
|
||||||
|
llvm_unreachable("invalid relocation type");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void addData(SmallVectorImpl<char> &DataBytes,
|
static void addData(SmallVectorImpl<char> &DataBytes,
|
||||||
@ -564,32 +583,19 @@ static void addData(SmallVectorImpl<char> &DataBytes,
|
|||||||
DEBUG(dbgs() << "addData -> " << DataBytes.size() << "\n");
|
DEBUG(dbgs() << "addData -> " << DataBytes.size() << "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t WasmObjectWriter::getRelocationIndexValue(
|
uint32_t
|
||||||
const WasmRelocationEntry &RelEntry) {
|
WasmObjectWriter::getRelocationIndexValue(const WasmRelocationEntry &RelEntry) {
|
||||||
switch (RelEntry.Type) {
|
if (RelEntry.Type == wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB) {
|
||||||
case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
|
|
||||||
case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
|
|
||||||
if (!IndirectSymbolIndices.count(RelEntry.Symbol))
|
|
||||||
report_fatal_error("symbol not found in table index space: " +
|
|
||||||
RelEntry.Symbol->getName());
|
|
||||||
return IndirectSymbolIndices[RelEntry.Symbol];
|
|
||||||
case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
|
|
||||||
case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
|
|
||||||
case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
|
|
||||||
case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
|
|
||||||
case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
|
|
||||||
if (!SymbolIndices.count(RelEntry.Symbol))
|
|
||||||
report_fatal_error("symbol not found in function/global index space: " +
|
|
||||||
RelEntry.Symbol->getName());
|
|
||||||
return SymbolIndices[RelEntry.Symbol];
|
|
||||||
case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB:
|
|
||||||
if (!TypeIndices.count(RelEntry.Symbol))
|
if (!TypeIndices.count(RelEntry.Symbol))
|
||||||
report_fatal_error("symbol not found in type index space: " +
|
report_fatal_error("symbol not found in type index space: " +
|
||||||
RelEntry.Symbol->getName());
|
RelEntry.Symbol->getName());
|
||||||
return TypeIndices[RelEntry.Symbol];
|
return TypeIndices[RelEntry.Symbol];
|
||||||
default:
|
|
||||||
llvm_unreachable("invalid relocation type");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!SymbolIndices.count(RelEntry.Symbol))
|
||||||
|
report_fatal_error("symbol not found in function/global index space: " +
|
||||||
|
RelEntry.Symbol->getName());
|
||||||
|
return SymbolIndices[RelEntry.Symbol];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply the portions of the relocation records that we can handle ourselves
|
// Apply the portions of the relocation records that we can handle ourselves
|
||||||
@ -603,35 +609,23 @@ void WasmObjectWriter::applyRelocations(
|
|||||||
RelEntry.Offset;
|
RelEntry.Offset;
|
||||||
|
|
||||||
DEBUG(dbgs() << "applyRelocation: " << RelEntry << "\n");
|
DEBUG(dbgs() << "applyRelocation: " << RelEntry << "\n");
|
||||||
|
uint32_t Value = getProvisionalValue(RelEntry);
|
||||||
|
|
||||||
switch (RelEntry.Type) {
|
switch (RelEntry.Type) {
|
||||||
case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
|
|
||||||
case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
|
case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
|
||||||
case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB:
|
case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB:
|
||||||
case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB: {
|
case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
|
||||||
uint32_t Index = getRelocationIndexValue(RelEntry);
|
case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
|
||||||
WritePatchableSLEB(Stream, Index, Offset);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32: {
|
|
||||||
uint32_t Index = getRelocationIndexValue(RelEntry);
|
|
||||||
WriteI32(Stream, Index, Offset);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB: {
|
|
||||||
uint32_t Value = getProvisionalValue(RelEntry);
|
|
||||||
WritePatchableSLEB(Stream, Value, Offset);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB: {
|
|
||||||
uint32_t Value = getProvisionalValue(RelEntry);
|
|
||||||
WritePatchableLEB(Stream, Value, Offset);
|
WritePatchableLEB(Stream, Value, Offset);
|
||||||
break;
|
break;
|
||||||
}
|
case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
|
||||||
case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32: {
|
case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
|
||||||
uint32_t Value = getProvisionalValue(RelEntry);
|
|
||||||
WriteI32(Stream, Value, Offset);
|
WriteI32(Stream, Value, Offset);
|
||||||
break;
|
break;
|
||||||
}
|
case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
|
||||||
|
case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
|
||||||
|
WritePatchableSLEB(Stream, Value, Offset);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
llvm_unreachable("invalid relocation type");
|
llvm_unreachable("invalid relocation type");
|
||||||
}
|
}
|
||||||
|
@ -34,5 +34,5 @@ declare void @f1(i32) #1
|
|||||||
; CHECK: - Type: DATA
|
; CHECK: - Type: DATA
|
||||||
; CHECK-NEXT: Relocations:
|
; CHECK-NEXT: Relocations:
|
||||||
; CHECK-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_I32
|
; CHECK-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_I32
|
||||||
; CHECK-NEXT: Index: 1
|
; CHECK-NEXT: Index: 0
|
||||||
; CHECK-NEXT: Offset: 0x00000006
|
; CHECK-NEXT: Offset: 0x00000006
|
||||||
|
@ -42,6 +42,6 @@ entry:
|
|||||||
; CHECK: Relocation {
|
; CHECK: Relocation {
|
||||||
; CHECK: Type: R_WEBASSEMBLY_TABLE_INDEX_SLEB (1)
|
; CHECK: Type: R_WEBASSEMBLY_TABLE_INDEX_SLEB (1)
|
||||||
; CHECK: Offset: 0x1E
|
; CHECK: Offset: 0x1E
|
||||||
; CHECK: Index: 0x1
|
; CHECK: Index: 0x2
|
||||||
; CHECK: }
|
; CHECK: }
|
||||||
; CHECK: }
|
; CHECK: }
|
||||||
|
@ -95,7 +95,7 @@ declare void @func3()
|
|||||||
; CHECK-NEXT: Index: 0
|
; CHECK-NEXT: Index: 0
|
||||||
; CHECK-NEXT: Offset: 0x00000004
|
; CHECK-NEXT: Offset: 0x00000004
|
||||||
; CHECK-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_SLEB
|
; CHECK-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_SLEB
|
||||||
; CHECK-NEXT: Index: 1
|
; CHECK-NEXT: Index: 5
|
||||||
; CHECK-NEXT: Offset: 0x0000000F
|
; CHECK-NEXT: Offset: 0x0000000F
|
||||||
; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_SLEB
|
; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_SLEB
|
||||||
; CHECK-NEXT: Index: 0
|
; CHECK-NEXT: Index: 0
|
||||||
@ -107,7 +107,7 @@ declare void @func3()
|
|||||||
; CHECK-NEXT: Index: 2
|
; CHECK-NEXT: Index: 2
|
||||||
; CHECK-NEXT: Offset: 0x0000002C
|
; CHECK-NEXT: Offset: 0x0000002C
|
||||||
; CHECK-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_SLEB
|
; CHECK-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_SLEB
|
||||||
; CHECK-NEXT: Index: 2
|
; CHECK-NEXT: Index: 7
|
||||||
; CHECK-NEXT: Offset: 0x00000037
|
; CHECK-NEXT: Offset: 0x00000037
|
||||||
; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_SLEB
|
; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_SLEB
|
||||||
; CHECK-NEXT: Index: 0
|
; CHECK-NEXT: Index: 0
|
||||||
|
@ -174,7 +174,7 @@ entry:
|
|||||||
; CHECK-NEXT: Index: 1
|
; CHECK-NEXT: Index: 1
|
||||||
; CHECK-NEXT: Offset: 0x0000000F
|
; CHECK-NEXT: Offset: 0x0000000F
|
||||||
; CHECK-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_I32
|
; CHECK-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_I32
|
||||||
; CHECK-NEXT: Index: 2
|
; CHECK-NEXT: Index: 0
|
||||||
; CHECK-NEXT: Offset: 0x00000018
|
; CHECK-NEXT: Offset: 0x00000018
|
||||||
; CHECK-NEXT: Segments:
|
; CHECK-NEXT: Segments:
|
||||||
; CHECK-NEXT: - SectionOffset: 6
|
; CHECK-NEXT: - SectionOffset: 6
|
||||||
|
Loading…
x
Reference in New Issue
Block a user