forked from OSchip/llvm-project
Revert "[WebAssembly] Add support for table linking to wasm-ld"
This reverts commit 38dfce706f
.
CI discovered a bug where the table is exported twice: see
D91870
This commit is contained in:
parent
e65b9b04cd
commit
187d771d27
|
@ -22,6 +22,14 @@ _start:
|
|||
# CHECK-NEXT: ReturnTypes: []
|
||||
# CHECK-NEXT: - Type: FUNCTION
|
||||
# CHECK-NEXT: FunctionTypes: [ 0 ]
|
||||
# CHECK-NEXT: - Type: TABLE
|
||||
# CHECK-NEXT: Tables:
|
||||
# CHECK-NEXT: - Index: 0
|
||||
# CHECK-NEXT: ElemType: FUNCREF
|
||||
# CHECK-NEXT: Limits:
|
||||
# CHECK-NEXT: Flags: [ HAS_MAX ]
|
||||
# CHECK-NEXT: Initial: 0x1
|
||||
# CHECK-NEXT: Maximum: 0x1
|
||||
# CHECK-NEXT: - Type: MEMORY
|
||||
# CHECK-NEXT: Memories:
|
||||
# CHECK-NEXT: - Initial: 0x2
|
||||
|
|
|
@ -139,15 +139,15 @@ entry:
|
|||
; RELOC-NEXT: InitFunctions [
|
||||
; RELOC-NEXT: 0 (priority=101)
|
||||
; RELOC-NEXT: 1 (priority=101)
|
||||
; RELOC-NEXT: 15 (priority=101)
|
||||
; RELOC-NEXT: 11 (priority=101)
|
||||
; RELOC-NEXT: 21 (priority=101)
|
||||
; RELOC-NEXT: 11 (priority=202)
|
||||
; RELOC-NEXT: 23 (priority=202)
|
||||
; RELOC-NEXT: 14 (priority=101)
|
||||
; RELOC-NEXT: 10 (priority=101)
|
||||
; RELOC-NEXT: 20 (priority=101)
|
||||
; RELOC-NEXT: 10 (priority=202)
|
||||
; RELOC-NEXT: 22 (priority=202)
|
||||
; RELOC-NEXT: 0 (priority=1001)
|
||||
; RELOC-NEXT: 17 (priority=1001)
|
||||
; RELOC-NEXT: 11 (priority=2002)
|
||||
; RELOC-NEXT: 25 (priority=2002)
|
||||
; RELOC-NEXT: 16 (priority=1001)
|
||||
; RELOC-NEXT: 10 (priority=2002)
|
||||
; RELOC-NEXT: 24 (priority=2002)
|
||||
; RELOC-NEXT: 9 (priority=4000)
|
||||
; RELOC-NEXT: 19 (priority=4000)
|
||||
; RELOC-NEXT: 18 (priority=4000)
|
||||
; RELOC-NEXT: ]
|
||||
|
|
|
@ -35,6 +35,14 @@ entry:
|
|||
; CHECK-NEXT: ReturnTypes: []
|
||||
; CHECK-NEXT: - Type: FUNCTION
|
||||
; CHECK-NEXT: FunctionTypes: [ 0, 1 ]
|
||||
; CHECK-NEXT: - Type: TABLE
|
||||
; CHECK-NEXT: Tables:
|
||||
; CHECK-NEXT: - Index: 0
|
||||
; CHECK-NEXT: ElemType: FUNCREF
|
||||
; CHECK-NEXT: Limits:
|
||||
; CHECK-NEXT: Flags: [ HAS_MAX ]
|
||||
; CHECK-NEXT: Initial: 0x1
|
||||
; CHECK-NEXT: Maximum: 0x1
|
||||
; CHECK-NEXT: - Type: MEMORY
|
||||
; CHECK-NEXT: Memories:
|
||||
; CHECK-NEXT: - Initial: 0x2
|
||||
|
|
|
@ -254,40 +254,40 @@
|
|||
; RELOC-NEXT: - Type: CODE
|
||||
; RELOC-NEXT: Relocations:
|
||||
; RELOC-NEXT: - Type: R_WASM_MEMORY_ADDR_SLEB
|
||||
; RELOC-NEXT: Index: 19
|
||||
; RELOC-NEXT: Index: 18
|
||||
; RELOC-NEXT: Offset: 0x13
|
||||
; RELOC-NEXT: - Type: R_WASM_MEMORY_ADDR_SLEB
|
||||
; RELOC-NEXT: Index: 3
|
||||
; RELOC-NEXT: Offset: 0x1C
|
||||
; RELOC-NEXT: - Type: R_WASM_MEMORY_ADDR_SLEB
|
||||
; RELOC-NEXT: Index: 20
|
||||
; RELOC-NEXT: Index: 19
|
||||
; RELOC-NEXT: Offset: 0x25
|
||||
; RELOC-NEXT: - Type: R_WASM_TABLE_INDEX_SLEB
|
||||
; RELOC-NEXT: Index: 17
|
||||
; RELOC-NEXT: Index: 16
|
||||
; RELOC-NEXT: Offset: 0x2E
|
||||
; RELOC-NEXT: - Type: R_WASM_TABLE_INDEX_SLEB
|
||||
; RELOC-NEXT: Index: 0
|
||||
; RELOC-NEXT: Offset: 0x37
|
||||
; RELOC-NEXT: - Type: R_WASM_TABLE_INDEX_SLEB
|
||||
; RELOC-NEXT: Index: 18
|
||||
; RELOC-NEXT: Index: 17
|
||||
; RELOC-NEXT: Offset: 0x40
|
||||
; RELOC-NEXT: - Type: R_WASM_MEMORY_ADDR_SLEB
|
||||
; RELOC-NEXT: Index: 11
|
||||
; RELOC-NEXT: Index: 10
|
||||
; RELOC-NEXT: Offset: 0x58
|
||||
; RELOC-NEXT: - Type: R_WASM_MEMORY_ADDR_SLEB
|
||||
; RELOC-NEXT: Index: 23
|
||||
; RELOC-NEXT: Index: 22
|
||||
; RELOC-NEXT: Offset: 0x61
|
||||
; RELOC-NEXT: - Type: R_WASM_MEMORY_ADDR_SLEB
|
||||
; RELOC-NEXT: Index: 24
|
||||
; RELOC-NEXT: Index: 23
|
||||
; RELOC-NEXT: Offset: 0x6A
|
||||
; RELOC-NEXT: - Type: R_WASM_TABLE_INDEX_SLEB
|
||||
; RELOC-NEXT: Index: 9
|
||||
; RELOC-NEXT: Index: 8
|
||||
; RELOC-NEXT: Offset: 0x73
|
||||
; RELOC-NEXT: - Type: R_WASM_TABLE_INDEX_SLEB
|
||||
; RELOC-NEXT: Index: 21
|
||||
; RELOC-NEXT: Index: 20
|
||||
; RELOC-NEXT: Offset: 0x7C
|
||||
; RELOC-NEXT: - Type: R_WASM_TABLE_INDEX_SLEB
|
||||
; RELOC-NEXT: Index: 22
|
||||
; RELOC-NEXT: Index: 21
|
||||
; RELOC-NEXT: Offset: 0x85
|
||||
; RELOC-NEXT: Functions:
|
||||
; RELOC-NEXT: - Index: 0
|
||||
|
@ -410,92 +410,87 @@
|
|||
; RELOC-NEXT: Flags: [ ]
|
||||
; RELOC-NEXT: Function: 8
|
||||
; RELOC-NEXT: - Index: 8
|
||||
; RELOC-NEXT: Kind: TABLE
|
||||
; RELOC-NEXT: Name: __indirect_function_table
|
||||
; RELOC-NEXT: Flags: [ VISIBILITY_HIDDEN ]
|
||||
; RELOC-NEXT: Table: 0
|
||||
; RELOC-NEXT: - Index: 9
|
||||
; RELOC-NEXT: Kind: FUNCTION
|
||||
; RELOC-NEXT: Name: colliding_func1
|
||||
; RELOC-NEXT: Flags: [ ]
|
||||
; RELOC-NEXT: Function: 9
|
||||
; RELOC-NEXT: - Index: 10
|
||||
; RELOC-NEXT: - Index: 9
|
||||
; RELOC-NEXT: Kind: FUNCTION
|
||||
; RELOC-NEXT: Name: get_global1B
|
||||
; RELOC-NEXT: Flags: [ ]
|
||||
; RELOC-NEXT: Function: 12
|
||||
; RELOC-NEXT: - Index: 11
|
||||
; RELOC-NEXT: - Index: 10
|
||||
; RELOC-NEXT: Kind: DATA
|
||||
; RELOC-NEXT: Name: colliding_global1
|
||||
; RELOC-NEXT: Flags: [ ]
|
||||
; RELOC-NEXT: Segment: 0
|
||||
; RELOC-NEXT: Offset: 4
|
||||
; RELOC-NEXT: Size: 4
|
||||
; RELOC-NEXT: - Index: 12
|
||||
; RELOC-NEXT: - Index: 11
|
||||
; RELOC-NEXT: Kind: FUNCTION
|
||||
; RELOC-NEXT: Name: get_global2B
|
||||
; RELOC-NEXT: Flags: [ ]
|
||||
; RELOC-NEXT: Function: 13
|
||||
; RELOC-NEXT: - Index: 13
|
||||
; RELOC-NEXT: - Index: 12
|
||||
; RELOC-NEXT: Kind: FUNCTION
|
||||
; RELOC-NEXT: Name: get_global3B
|
||||
; RELOC-NEXT: Flags: [ ]
|
||||
; RELOC-NEXT: Function: 14
|
||||
; RELOC-NEXT: - Index: 14
|
||||
; RELOC-NEXT: - Index: 13
|
||||
; RELOC-NEXT: Kind: FUNCTION
|
||||
; RELOC-NEXT: Name: get_func1B
|
||||
; RELOC-NEXT: Flags: [ ]
|
||||
; RELOC-NEXT: Function: 15
|
||||
; RELOC-NEXT: - Index: 15
|
||||
; RELOC-NEXT: - Index: 14
|
||||
; RELOC-NEXT: Kind: FUNCTION
|
||||
; RELOC-NEXT: Name: get_func2B
|
||||
; RELOC-NEXT: Flags: [ ]
|
||||
; RELOC-NEXT: Function: 16
|
||||
; RELOC-NEXT: - Index: 16
|
||||
; RELOC-NEXT: - Index: 15
|
||||
; RELOC-NEXT: Kind: FUNCTION
|
||||
; RELOC-NEXT: Name: get_func3B
|
||||
; RELOC-NEXT: Flags: [ ]
|
||||
; RELOC-NEXT: Function: 17
|
||||
; RELOC-NEXT: - Index: 17
|
||||
; RELOC-NEXT: - Index: 16
|
||||
; RELOC-NEXT: Kind: FUNCTION
|
||||
; RELOC-NEXT: Name: colliding_func1
|
||||
; RELOC-NEXT: Flags: [ BINDING_LOCAL ]
|
||||
; RELOC-NEXT: Function: 0
|
||||
; RELOC-NEXT: - Index: 18
|
||||
; RELOC-NEXT: - Index: 17
|
||||
; RELOC-NEXT: Kind: FUNCTION
|
||||
; RELOC-NEXT: Name: colliding_func3
|
||||
; RELOC-NEXT: Flags: [ BINDING_LOCAL ]
|
||||
; RELOC-NEXT: Function: 2
|
||||
; RELOC-NEXT: - Index: 19
|
||||
; RELOC-NEXT: - Index: 18
|
||||
; RELOC-NEXT: Kind: DATA
|
||||
; RELOC-NEXT: Name: colliding_global1
|
||||
; RELOC-NEXT: Flags: [ BINDING_LOCAL ]
|
||||
; RELOC-NEXT: Segment: 0
|
||||
; RELOC-NEXT: Size: 4
|
||||
; RELOC-NEXT: - Index: 20
|
||||
; RELOC-NEXT: - Index: 19
|
||||
; RELOC-NEXT: Kind: DATA
|
||||
; RELOC-NEXT: Name: colliding_global3
|
||||
; RELOC-NEXT: Flags: [ BINDING_LOCAL ]
|
||||
; RELOC-NEXT: Segment: 2
|
||||
; RELOC-NEXT: Size: 4
|
||||
; RELOC-NEXT: - Index: 21
|
||||
; RELOC-NEXT: - Index: 20
|
||||
; RELOC-NEXT: Kind: FUNCTION
|
||||
; RELOC-NEXT: Name: colliding_func2
|
||||
; RELOC-NEXT: Flags: [ BINDING_LOCAL ]
|
||||
; RELOC-NEXT: Function: 10
|
||||
; RELOC-NEXT: - Index: 22
|
||||
; RELOC-NEXT: - Index: 21
|
||||
; RELOC-NEXT: Kind: FUNCTION
|
||||
; RELOC-NEXT: Name: colliding_func3
|
||||
; RELOC-NEXT: Flags: [ BINDING_LOCAL ]
|
||||
; RELOC-NEXT: Function: 11
|
||||
; RELOC-NEXT: - Index: 23
|
||||
; RELOC-NEXT: - Index: 22
|
||||
; RELOC-NEXT: Kind: DATA
|
||||
; RELOC-NEXT: Name: colliding_global2
|
||||
; RELOC-NEXT: Flags: [ BINDING_LOCAL ]
|
||||
; RELOC-NEXT: Segment: 1
|
||||
; RELOC-NEXT: Offset: 4
|
||||
; RELOC-NEXT: Size: 4
|
||||
; RELOC-NEXT: - Index: 24
|
||||
; RELOC-NEXT: - Index: 23
|
||||
; RELOC-NEXT: Kind: DATA
|
||||
; RELOC-NEXT: Name: colliding_global3
|
||||
; RELOC-NEXT: Flags: [ BINDING_LOCAL ]
|
||||
|
|
|
@ -41,6 +41,14 @@ define void @_start() {
|
|||
; CHECK: - Type: IMPORT
|
||||
; CHECK-NEXT: Imports:
|
||||
; CHECK-NEXT: - Module: env
|
||||
; CHECK-NEXT: Field: __indirect_function_table
|
||||
; CHECK-NEXT: Kind: TABLE
|
||||
; CHECK-NEXT: Table:
|
||||
; CHECK-NEXT: Index: 0
|
||||
; CHECK-NEXT: ElemType: FUNCREF
|
||||
; CHECK-NEXT: Limits:
|
||||
; CHECK-NEXT: Initial: 0x1
|
||||
; CHECK-NEXT: - Module: env
|
||||
; CHECK-NEXT: Field: __stack_pointer
|
||||
; CHECK-NEXT: Kind: GLOBAL
|
||||
; CHECK-NEXT: GlobalType: I32
|
||||
|
@ -55,14 +63,6 @@ define void @_start() {
|
|||
; CHECK-NEXT: Kind: GLOBAL
|
||||
; CHECK-NEXT: GlobalType: I32
|
||||
; CHECK-NEXT: GlobalMutable: false
|
||||
; CHECK-NEXT: - Module: env
|
||||
; CHECK-NEXT: Field: __indirect_function_table
|
||||
; CHECK-NEXT: Kind: TABLE
|
||||
; CHECK-NEXT: Table:
|
||||
; CHECK-NEXT: Index: 0
|
||||
; CHECK-NEXT: ElemType: FUNCREF
|
||||
; CHECK-NEXT: Limits:
|
||||
; CHECK-NEXT: Initial: 0x1
|
||||
|
||||
; CHECK: - Type: START
|
||||
; CHECK-NEXT: StartFunction: 2
|
||||
|
|
|
@ -54,8 +54,8 @@ Sections:
|
|||
# RELOC-NEXT: - Index: 0
|
||||
# RELOC-NEXT: Kind: SECTION
|
||||
# RELOC-NEXT: Flags: [ BINDING_LOCAL ]
|
||||
# RELOC-NEXT: Section: 1
|
||||
# RELOC-NEXT: Section: 2
|
||||
# RELOC-NEXT: - Index: 1
|
||||
# RELOC-NEXT: Kind: SECTION
|
||||
# RELOC-NEXT: Flags: [ BINDING_LOCAL ]
|
||||
# RELOC-NEXT: Section: 2
|
||||
# RELOC-NEXT: Section: 3
|
||||
|
|
|
@ -69,6 +69,14 @@ declare void @func_external()
|
|||
; CHECK-NEXT: Memory:
|
||||
; CHECK-NEXT: Initial: 0x1
|
||||
; CHECK-NEXT: - Module: env
|
||||
; CHECK-NEXT: Field: __indirect_function_table
|
||||
; CHECK-NEXT: Kind: TABLE
|
||||
; CHECK-NEXT: Table:
|
||||
; CHECK-NEXT: Index: 0
|
||||
; CHECK-NEXT: ElemType: FUNCREF
|
||||
; CHECK-NEXT: Limits:
|
||||
; CHECK-NEXT: Initial: 0x2
|
||||
; CHECK-NEXT: - Module: env
|
||||
; CHECK-NEXT: Field: __stack_pointer
|
||||
; CHECK-NEXT: Kind: GLOBAL
|
||||
; CHECK-NEXT: GlobalType: I32
|
||||
|
@ -87,14 +95,6 @@ declare void @func_external()
|
|||
; CHECK-NEXT: Field: func_external
|
||||
; CHECK-NEXT: Kind: FUNCTION
|
||||
; CHECK-NEXT: SigIndex: 1
|
||||
; CHECK-NEXT: - Module: env
|
||||
; CHECK-NEXT: Field: __indirect_function_table
|
||||
; CHECK-NEXT: Kind: TABLE
|
||||
; CHECK-NEXT: Table:
|
||||
; CHECK-NEXT: Index: 0
|
||||
; CHECK-NEXT: ElemType: FUNCREF
|
||||
; CHECK-NEXT: Limits:
|
||||
; CHECK-NEXT: Initial: 0x2
|
||||
; CHECK-NEXT: - Module: GOT.mem
|
||||
; CHECK-NEXT: Field: indirect_func
|
||||
; CHECK-NEXT: Kind: GLOBAL
|
||||
|
|
|
@ -80,22 +80,17 @@ declare i32 @ret32(i32, i64, i32) local_unnamed_addr
|
|||
; RELOC-NEXT: Segment: 0
|
||||
; RELOC-NEXT: Size: 4
|
||||
; RELOC-NEXT: - Index: 3
|
||||
; RELOC-NEXT: Kind: TABLE
|
||||
; RELOC-NEXT: Name: __indirect_function_table
|
||||
; RELOC-NEXT: Flags: [ VISIBILITY_HIDDEN ]
|
||||
; RELOC-NEXT: Table: 0
|
||||
; RELOC-NEXT: - Index: 4
|
||||
; RELOC-NEXT: Kind: FUNCTION
|
||||
; RELOC-NEXT: Name: call_ret32
|
||||
; RELOC-NEXT: Flags: [ ]
|
||||
; RELOC-NEXT: Function: 3
|
||||
; RELOC-NEXT: - Index: 5
|
||||
; RELOC-NEXT: - Index: 4
|
||||
; RELOC-NEXT: Kind: DATA
|
||||
; RELOC-NEXT: Name: ret32_address
|
||||
; RELOC-NEXT: Flags: [ ]
|
||||
; RELOC-NEXT: Segment: 1
|
||||
; RELOC-NEXT: Size: 4
|
||||
; RELOC-NEXT: - Index: 6
|
||||
; RELOC-NEXT: - Index: 5
|
||||
; RELOC-NEXT: Kind: FUNCTION
|
||||
; RELOC-NEXT: Name: 'signature_mismatch:ret32'
|
||||
; RELOC-NEXT: Flags: [ BINDING_LOCAL ]
|
||||
|
|
|
@ -30,6 +30,14 @@ entry:
|
|||
; CHECK-NEXT: GlobalMutable: true
|
||||
; CHECK-NEXT: - Type: FUNCTION
|
||||
; CHECK-NEXT: FunctionTypes: [ 0 ]
|
||||
; CHECK-NEXT: - Type: TABLE
|
||||
; CHECK-NEXT: Tables:
|
||||
; CHECK-NEXT: - Index: 0
|
||||
; CHECK-NEXT: ElemType: FUNCREF
|
||||
; CHECK-NEXT: Limits:
|
||||
; CHECK-NEXT: Flags: [ HAS_MAX ]
|
||||
; CHECK-NEXT: Initial: 0x1
|
||||
; CHECK-NEXT: Maximum: 0x1
|
||||
; CHECK-NEXT: - Type: MEMORY
|
||||
; CHECK-NEXT: Memories:
|
||||
; CHECK-NEXT: - Initial: 0x0
|
||||
|
|
|
@ -276,11 +276,6 @@ entry:
|
|||
; RELOC-NEXT: Name: call_direct_ptr
|
||||
; RELOC-NEXT: Flags: [ ]
|
||||
; RELOC-NEXT: Function: 5
|
||||
; RELOC-NEXT: - Index: 8
|
||||
; RELOC-NEXT: Kind: TABLE
|
||||
; RELOC-NEXT: Name: __indirect_function_table
|
||||
; RELOC-NEXT: Flags: [ VISIBILITY_HIDDEN ]
|
||||
; RELOC-NEXT: Table: 0
|
||||
; RELOC-NEXT: - Type: CUSTOM
|
||||
; RELOC-NEXT: Name: name
|
||||
; RELOC-NEXT: FunctionNames:
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
#include "Config.h"
|
||||
#include "InputChunks.h"
|
||||
#include "InputGlobal.h"
|
||||
#include "InputTable.h"
|
||||
#include "MarkLive.h"
|
||||
#include "SymbolTable.h"
|
||||
#include "Writer.h"
|
||||
|
@ -788,58 +787,6 @@ static void wrapSymbols(ArrayRef<WrappedSymbol> wrapped) {
|
|||
symtab->wrap(w.sym, w.real, w.wrap);
|
||||
}
|
||||
|
||||
static TableSymbol *createDefinedIndirectFunctionTable(StringRef name) {
|
||||
const uint32_t invalidIndex = -1;
|
||||
WasmLimits limits{0, 0, 0}; // Set by the writer.
|
||||
WasmTableType type{uint8_t(ValType::FUNCREF), limits};
|
||||
WasmTable desc{invalidIndex, type, name};
|
||||
InputTable *table = make<InputTable>(desc, nullptr);
|
||||
uint32_t flags = config->exportTable ? 0 : WASM_SYMBOL_VISIBILITY_HIDDEN;
|
||||
TableSymbol *sym = symtab->addSyntheticTable(name, flags, table);
|
||||
sym->markLive();
|
||||
sym->forceExport = config->exportTable;
|
||||
return sym;
|
||||
}
|
||||
|
||||
static TableSymbol *createUndefinedIndirectFunctionTable(StringRef name) {
|
||||
WasmLimits limits{0, 0, 0}; // Set by the writer.
|
||||
WasmTableType *type = make<WasmTableType>();
|
||||
type->ElemType = uint8_t(ValType::FUNCREF);
|
||||
type->Limits = limits;
|
||||
StringRef module(defaultModule);
|
||||
uint32_t flags = config->exportTable ? 0 : WASM_SYMBOL_VISIBILITY_HIDDEN;
|
||||
flags |= WASM_SYMBOL_UNDEFINED;
|
||||
Symbol *sym =
|
||||
symtab->addUndefinedTable(name, name, module, flags, nullptr, type);
|
||||
sym->markLive();
|
||||
sym->forceExport = config->exportTable;
|
||||
return cast<TableSymbol>(sym);
|
||||
}
|
||||
|
||||
static TableSymbol *resolveIndirectFunctionTable() {
|
||||
// Even though we may not need a table, if the user explicitly specified
|
||||
// --import-table or --export-table, ensure a table is residualized.
|
||||
if (config->importTable)
|
||||
return createUndefinedIndirectFunctionTable(functionTableName);
|
||||
if (config->exportTable)
|
||||
return createDefinedIndirectFunctionTable(functionTableName);
|
||||
|
||||
// Otherwise, check to the symtab to find the indirect function table.
|
||||
if (Symbol *sym = symtab->find(functionTableName)) {
|
||||
if (sym->isLive()) {
|
||||
if (auto *t = dyn_cast<TableSymbol>(sym)) {
|
||||
return t->isDefined()
|
||||
? t
|
||||
: createDefinedIndirectFunctionTable(functionTableName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// An indirect function table will only be present in the symbol table if
|
||||
// needed by a reloc; if we get here, we don't need one.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
|
||||
WasmOptTable parser;
|
||||
opt::InputArgList args = parser.parse(argsArr.slice(1));
|
||||
|
@ -1029,12 +976,6 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
|
|||
// Do size optimizations: garbage collection
|
||||
markLive();
|
||||
|
||||
// Provide the indirect funciton table if needed.
|
||||
WasmSym::indirectFunctionTable = resolveIndirectFunctionTable();
|
||||
|
||||
if (errorCount())
|
||||
return;
|
||||
|
||||
// Write the result to the file.
|
||||
writeResult();
|
||||
}
|
||||
|
|
|
@ -310,71 +310,6 @@ static void setRelocs(const std::vector<T *> &chunks,
|
|||
}
|
||||
}
|
||||
|
||||
// Since LLVM 12, we expect that if an input file defines or uses a table, it
|
||||
// declares the tables using symbols and records each use with a relocation.
|
||||
// This way when the linker combines inputs, it can collate the tables used by
|
||||
// the inputs, assigning them distinct table numbers, and renumber all the uses
|
||||
// as appropriate. At the same time, the linker has special logic to build the
|
||||
// indirect function table if it is needed.
|
||||
//
|
||||
// However, object files produced by LLVM 11 and earlier neither write table
|
||||
// symbols nor record relocations, and yet still use tables via call_indirect,
|
||||
// and via function pointer bitcasts. We can detect these object files, as they
|
||||
// declare tables as imports or define them locally, but don't have table
|
||||
// symbols. synthesizeTableSymbols serves as a shim when loading these older
|
||||
// input files, defining the missing symbols to allow the indirect function
|
||||
// table to be built.
|
||||
//
|
||||
// Table uses in these older files won't be relocated, as they have no
|
||||
// relocations. In practice this isn't a problem, as these object files
|
||||
// typically just declare a single table named __indirect_function_table and
|
||||
// having table number 0, so relocation would be idempotent anyway.
|
||||
void ObjFile::synthesizeTableSymbols() {
|
||||
uint32_t tableNumber = 0;
|
||||
const WasmGlobalType *globalType = nullptr;
|
||||
const WasmEventType *eventType = nullptr;
|
||||
const WasmSignature *signature = nullptr;
|
||||
if (wasmObj->getNumImportedTables()) {
|
||||
for (const auto &import : wasmObj->imports()) {
|
||||
if (import.Kind == WASM_EXTERNAL_TABLE) {
|
||||
auto *info = make<WasmSymbolInfo>();
|
||||
info->Name = import.Field;
|
||||
info->Kind = WASM_SYMBOL_TYPE_TABLE;
|
||||
info->ImportModule = import.Module;
|
||||
info->ImportName = import.Field;
|
||||
info->Flags = WASM_SYMBOL_UNDEFINED;
|
||||
info->Flags |= WASM_SYMBOL_NO_STRIP;
|
||||
info->ElementIndex = tableNumber++;
|
||||
LLVM_DEBUG(dbgs() << "Synthesizing symbol for table import: "
|
||||
<< info->Name << "\n");
|
||||
auto *wasmSym = make<WasmSymbol>(*info, globalType, &import.Table,
|
||||
eventType, signature);
|
||||
symbols.push_back(createUndefined(*wasmSym, false));
|
||||
// Because there are no TABLE_NUMBER relocs in this case, we can't
|
||||
// compute accurate liveness info; instead, just mark the symbol as
|
||||
// always live.
|
||||
symbols.back()->markLive();
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const auto &table : tables) {
|
||||
auto *info = make<llvm::wasm::WasmSymbolInfo>();
|
||||
// Empty name.
|
||||
info->Kind = WASM_SYMBOL_TYPE_TABLE;
|
||||
info->Flags = WASM_SYMBOL_BINDING_LOCAL;
|
||||
info->Flags |= WASM_SYMBOL_VISIBILITY_HIDDEN;
|
||||
info->Flags |= WASM_SYMBOL_NO_STRIP;
|
||||
info->ElementIndex = tableNumber++;
|
||||
LLVM_DEBUG(dbgs() << "Synthesizing symbol for table definition: "
|
||||
<< info->Name << "\n");
|
||||
auto *wasmSym = make<WasmSymbol>(*info, globalType, &table->getType(),
|
||||
eventType, signature);
|
||||
symbols.push_back(createDefined(*wasmSym));
|
||||
// Mark live, for the same reasons as for imported tables.
|
||||
symbols.back()->markLive();
|
||||
}
|
||||
}
|
||||
|
||||
void ObjFile::parse(bool ignoreComdats) {
|
||||
// Parse a memory buffer as a wasm file.
|
||||
LLVM_DEBUG(dbgs() << "Parsing object: " << toString(this) << "\n");
|
||||
|
@ -489,11 +424,8 @@ void ObjFile::parse(bool ignoreComdats) {
|
|||
|
||||
// Populate `Symbols` based on the symbols in the object.
|
||||
symbols.reserve(wasmObj->getNumberOfSymbols());
|
||||
bool haveTableSymbol = false;
|
||||
for (const SymbolRef &sym : wasmObj->symbols()) {
|
||||
const WasmSymbol &wasmSym = wasmObj->getWasmSymbol(sym.getRawDataRefImpl());
|
||||
if (wasmSym.isTypeTable())
|
||||
haveTableSymbol = true;
|
||||
if (wasmSym.isDefined()) {
|
||||
// createDefined may fail if the symbol is comdat excluded in which case
|
||||
// we fall back to creating an undefined symbol
|
||||
|
@ -505,13 +437,6 @@ void ObjFile::parse(bool ignoreComdats) {
|
|||
size_t idx = symbols.size();
|
||||
symbols.push_back(createUndefined(wasmSym, isCalledDirectly[idx]));
|
||||
}
|
||||
|
||||
// As a stopgap measure while implementing table support, if the object file
|
||||
// has table definitions or imports but no table symbols, synthesize symbols
|
||||
// for those tables. Mark as NO_STRIP to ensure they reach the output file,
|
||||
// even if there are no TABLE_NUMBER relocs against them.
|
||||
if (!haveTableSymbol)
|
||||
synthesizeTableSymbols();
|
||||
}
|
||||
|
||||
bool ObjFile::isExcludedByComdat(InputChunk *chunk) const {
|
||||
|
|
|
@ -157,7 +157,6 @@ private:
|
|||
Symbol *createUndefined(const WasmSymbol &sym, bool isCalledDirectly);
|
||||
|
||||
bool isExcludedByComdat(InputChunk *chunk) const;
|
||||
void synthesizeTableSymbols();
|
||||
|
||||
std::unique_ptr<WasmObjectFile> wasmObj;
|
||||
};
|
||||
|
|
|
@ -177,9 +177,6 @@ void markLive() {
|
|||
for (InputGlobal *g : symtab->syntheticGlobals)
|
||||
if (!g->live)
|
||||
message("removing unused section " + toString(g));
|
||||
for (InputTable *t : symtab->syntheticTables)
|
||||
if (!t->live)
|
||||
message("removing unused section " + toString(t));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -270,18 +270,6 @@ DefinedGlobal *SymbolTable::addOptionalGlobalSymbols(StringRef name,
|
|||
return replaceSymbol<DefinedGlobal>(s, name, flags, nullptr, global);
|
||||
}
|
||||
|
||||
DefinedTable *SymbolTable::addSyntheticTable(StringRef name, uint32_t flags,
|
||||
InputTable *table) {
|
||||
LLVM_DEBUG(dbgs() << "addSyntheticTable: " << name << " -> " << table
|
||||
<< "\n");
|
||||
Symbol *s = find(name);
|
||||
assert(!s || s->isUndefined());
|
||||
if (!s)
|
||||
s = insertName(name).first;
|
||||
syntheticTables.emplace_back(table);
|
||||
return replaceSymbol<DefinedTable>(s, name, flags, nullptr, table);
|
||||
}
|
||||
|
||||
static bool shouldReplace(const Symbol *existing, InputFile *newFile,
|
||||
uint32_t newFlags) {
|
||||
// If existing symbol is undefined, replace it.
|
||||
|
|
|
@ -93,8 +93,6 @@ public:
|
|||
DefinedData *addOptionalDataSymbol(StringRef name, uint64_t value = 0);
|
||||
DefinedGlobal *addOptionalGlobalSymbols(StringRef name, uint32_t flags,
|
||||
InputGlobal *global);
|
||||
DefinedTable *addSyntheticTable(StringRef name, uint32_t flags,
|
||||
InputTable *global);
|
||||
|
||||
void handleSymbolVariants();
|
||||
void handleWeakUndefines();
|
||||
|
@ -105,7 +103,6 @@ public:
|
|||
std::vector<BitcodeFile *> bitcodeFiles;
|
||||
std::vector<InputFunction *> syntheticFunctions;
|
||||
std::vector<InputGlobal *> syntheticGlobals;
|
||||
std::vector<InputTable *> syntheticTables;
|
||||
|
||||
private:
|
||||
std::pair<Symbol *, bool> insert(StringRef name, const InputFile *file);
|
||||
|
|
|
@ -91,7 +91,6 @@ UndefinedGlobal *WasmSym::tableBase;
|
|||
DefinedData *WasmSym::definedTableBase;
|
||||
UndefinedGlobal *WasmSym::memoryBase;
|
||||
DefinedData *WasmSym::definedMemoryBase;
|
||||
TableSymbol *WasmSym::indirectFunctionTable;
|
||||
|
||||
WasmSymbolType Symbol::getWasmType() const {
|
||||
if (isa<FunctionSymbol>(this))
|
||||
|
|
|
@ -568,11 +568,6 @@ struct WasmSym {
|
|||
// Used in PIC code for offset of global data
|
||||
static UndefinedGlobal *memoryBase;
|
||||
static DefinedData *definedMemoryBase;
|
||||
|
||||
// __indirect_function_table
|
||||
// Used as an address space for function pointers, with each function that is
|
||||
// used as a function pointer being allocated a slot.
|
||||
static TableSymbol *indirectFunctionTable;
|
||||
};
|
||||
|
||||
// A buffer class that is large enough to hold any Symbol-derived
|
||||
|
|
|
@ -92,11 +92,20 @@ void TypeSection::writeBody() {
|
|||
writeSig(bodyOutputStream, *sig);
|
||||
}
|
||||
|
||||
ImportSection::ImportSection() : SyntheticSection(llvm::wasm::WASM_SEC_IMPORT) {
|
||||
// FIXME: Remove when we treat __indirect_function_table as any other symbol.
|
||||
if (config->importTable) {
|
||||
numImportedTables++;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t ImportSection::getNumImports() const {
|
||||
assert(isSealed);
|
||||
uint32_t numImports = importedSymbols.size() + gotSymbols.size();
|
||||
if (config->importMemory)
|
||||
++numImports;
|
||||
if (config->importTable)
|
||||
++numImports;
|
||||
return numImports;
|
||||
}
|
||||
|
||||
|
@ -145,6 +154,17 @@ void ImportSection::writeBody() {
|
|||
writeImport(os, import);
|
||||
}
|
||||
|
||||
if (config->importTable) {
|
||||
uint32_t tableSize = config->tableBase + out.elemSec->numEntries();
|
||||
WasmImport import;
|
||||
import.Module = defaultModule;
|
||||
import.Field = functionTableName;
|
||||
import.Kind = WASM_EXTERNAL_TABLE;
|
||||
import.Table.ElemType = WASM_TYPE_FUNCREF;
|
||||
import.Table.Limits = {0, tableSize, 0};
|
||||
writeImport(os, import);
|
||||
}
|
||||
|
||||
for (const Symbol *sym : importedSymbols) {
|
||||
WasmImport import;
|
||||
if (auto *f = dyn_cast<UndefinedFunction>(sym)) {
|
||||
|
@ -210,9 +230,26 @@ void FunctionSection::addFunction(InputFunction *func) {
|
|||
}
|
||||
|
||||
void TableSection::writeBody() {
|
||||
bool hasIndirectFunctionTable = !config->importTable;
|
||||
|
||||
uint32_t tableCount = inputTables.size();
|
||||
if (hasIndirectFunctionTable)
|
||||
tableCount++;
|
||||
|
||||
raw_ostream &os = bodyOutputStream;
|
||||
|
||||
writeUleb128(os, inputTables.size(), "table count");
|
||||
writeUleb128(os, tableCount, "table count");
|
||||
|
||||
if (hasIndirectFunctionTable) {
|
||||
uint32_t tableSize = config->tableBase + out.elemSec->numEntries();
|
||||
WasmLimits limits;
|
||||
if (config->growableTable)
|
||||
limits = {0, tableSize, 0};
|
||||
else
|
||||
limits = {WASM_LIMITS_FLAG_HAS_MAX, tableSize, tableSize};
|
||||
writeTableType(os, WasmTableType{WASM_TYPE_FUNCREF, limits});
|
||||
}
|
||||
|
||||
for (const InputTable *table : inputTables)
|
||||
writeTableType(os, table->getType());
|
||||
}
|
||||
|
|
|
@ -98,7 +98,7 @@ protected:
|
|||
|
||||
class ImportSection : public SyntheticSection {
|
||||
public:
|
||||
ImportSection() : SyntheticSection(llvm::wasm::WASM_SEC_IMPORT) {}
|
||||
ImportSection();
|
||||
bool isNeeded() const override { return getNumImports() > 0; }
|
||||
void writeBody() override;
|
||||
void addImport(Symbol *sym);
|
||||
|
@ -150,7 +150,16 @@ class TableSection : public SyntheticSection {
|
|||
public:
|
||||
TableSection() : SyntheticSection(llvm::wasm::WASM_SEC_TABLE) {}
|
||||
|
||||
bool isNeeded() const override { return inputTables.size() > 0; };
|
||||
bool isNeeded() const override {
|
||||
// The linker currently always writes an indirect function table to the
|
||||
// output, so unless the indirect function table is imported, we need a
|
||||
// table section. FIXME: Treat __indirect_function_table as a normal
|
||||
// symbol, and only residualize a table section as needed.
|
||||
if (!config->importTable)
|
||||
return true;
|
||||
return inputTables.size() > 0;
|
||||
}
|
||||
|
||||
void writeBody() override;
|
||||
void addTable(InputTable *table);
|
||||
|
||||
|
|
|
@ -745,19 +745,6 @@ void Writer::createCommandExportWrappers() {
|
|||
}
|
||||
}
|
||||
|
||||
static void finalizeIndirectFunctionTable() {
|
||||
if (!WasmSym::indirectFunctionTable)
|
||||
return;
|
||||
|
||||
uint32_t tableSize = config->tableBase + out.elemSec->numEntries();
|
||||
WasmLimits limits = {0, tableSize, 0};
|
||||
if (WasmSym::indirectFunctionTable->isDefined() && !config->growableTable) {
|
||||
limits.Flags |= WASM_LIMITS_FLAG_HAS_MAX;
|
||||
limits.Maximum = limits.Initial;
|
||||
}
|
||||
WasmSym::indirectFunctionTable->setLimits(limits);
|
||||
}
|
||||
|
||||
static void scanRelocations() {
|
||||
for (ObjFile *file : symtab->objectFiles) {
|
||||
LLVM_DEBUG(dbgs() << "scanRelocations: " << file->getName() << "\n");
|
||||
|
@ -805,9 +792,6 @@ void Writer::assignIndexes() {
|
|||
out.tableSec->addTable(table);
|
||||
}
|
||||
|
||||
for (InputTable *table : symtab->syntheticTables)
|
||||
out.tableSec->addTable(table);
|
||||
|
||||
out.globalSec->assignIndexes();
|
||||
}
|
||||
|
||||
|
@ -1357,8 +1341,6 @@ void Writer::run() {
|
|||
|
||||
log("-- scanRelocations");
|
||||
scanRelocations();
|
||||
log("-- finalizeIndirectFunctionTable");
|
||||
finalizeIndirectFunctionTable();
|
||||
log("-- createSyntheticInitFunctions");
|
||||
createSyntheticInitFunctions();
|
||||
log("-- assignIndexes");
|
||||
|
|
Loading…
Reference in New Issue