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:
Derek Schuff 2021-01-15 15:50:41 -08:00
parent e65b9b04cd
commit 187d771d27
21 changed files with 127 additions and 249 deletions

View File

@ -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

View File

@ -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: ]

View File

@ -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

View File

@ -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 ]

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 ]

View File

@ -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

View File

@ -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:

View File

@ -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();
}

View File

@ -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 {

View File

@ -157,7 +157,6 @@ private:
Symbol *createUndefined(const WasmSymbol &sym, bool isCalledDirectly);
bool isExcludedByComdat(InputChunk *chunk) const;
void synthesizeTableSymbols();
std::unique_ptr<WasmObjectFile> wasmObj;
};

View File

@ -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));
}
}

View File

@ -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.

View File

@ -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);

View 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))

View File

@ -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

View File

@ -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());
}

View File

@ -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);

View File

@ -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");