diff options
| author | Sam Clegg <sbc@chromium.org> | 2019-02-07 22:42:16 +0000 |
|---|---|---|
| committer | Sam Clegg <sbc@chromium.org> | 2019-02-07 22:42:16 +0000 |
| commit | 230dc11d24626c8a717de5073fef31ea8ea2683f (patch) | |
| tree | d6615c67263009ce81f191b15416fc5a68fe3cfe /lld/wasm/SymbolTable.cpp | |
| parent | 81f859d16940e7b7193c074ee03ff39a79dff901 (diff) | |
| download | bcm5719-llvm-230dc11d24626c8a717de5073fef31ea8ea2683f.tar.gz bcm5719-llvm-230dc11d24626c8a717de5073fef31ea8ea2683f.zip | |
[WebAssembly] Refactor handling of weak undefined functions. NFC.
Also add to the docs.
This is refactor in preparation for https://reviews.llvm.org/D57909
Differential Revision: https://reviews.llvm.org/D57920
llvm-svn: 353478
Diffstat (limited to 'lld/wasm/SymbolTable.cpp')
| -rw-r--r-- | lld/wasm/SymbolTable.cpp | 58 |
1 files changed, 57 insertions, 1 deletions
diff --git a/lld/wasm/SymbolTable.cpp b/lld/wasm/SymbolTable.cpp index 00ee88f662e..35ac2c5a6da 100644 --- a/lld/wasm/SymbolTable.cpp +++ b/lld/wasm/SymbolTable.cpp @@ -102,7 +102,8 @@ std::pair<Symbol *, bool> SymbolTable::insertName(StringRef Name) { return {Sym, true}; } -std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name, InputFile *File) { +std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name, + const InputFile *File) { Symbol *S; bool WasInserted; std::tie(S, WasInserted) = insertName(Name); @@ -442,3 +443,58 @@ bool SymbolTable::addComdat(StringRef Name) { void SymbolTable::trace(StringRef Name) { SymMap.insert({CachedHashStringRef(Name), -1}); } + +static const uint8_t UnreachableFn[] = { + 0x03 /* ULEB length */, 0x00 /* ULEB num locals */, + 0x00 /* opcode unreachable */, 0x0b /* opcode end */ +}; + +// Replace the given symbol body with an unreachable function. +// This is used by handleWeakUndefines in order to generate a callable +// equivalent of an undefined function. +InputFunction *SymbolTable::replaceWithUnreachable(Symbol *Sym, + const WasmSignature &Sig, + StringRef DebugName) { + auto *Func = make<SyntheticFunction>(Sig, Sym->getName(), DebugName); + Func->setBody(UnreachableFn); + SyntheticFunctions.emplace_back(Func); + replaceSymbol<DefinedFunction>(Sym, Sym->getName(), Sym->getFlags(), nullptr, Func); + return Func; +} + +// For weak undefined functions, there may be "call" instructions that reference +// the symbol. In this case, we need to synthesise a dummy/stub function that +// will abort at runtime, so that relocations can still provided an operand to +// the call instruction that passes Wasm validation. +void SymbolTable::handleWeakUndefines() { + for (Symbol *Sym : getSymbols()) { + if (!Sym->isUndefWeak()) + continue; + + const WasmSignature *Sig = nullptr; + + if (auto *FuncSym = dyn_cast<FunctionSymbol>(Sym)) { + // It is possible for undefined functions not to have a signature (eg. if + // added via "--undefined"), but weak undefined ones do have a signature. + assert(FuncSym->Signature); + Sig = FuncSym->Signature; + } else if (auto *LazySym = dyn_cast<LazySymbol>(Sym)) { + // Lazy symbols may not be functions and therefore can have a null + // signature. + Sig = LazySym->Signature; + } + + if (!Sig) + continue; + + // Add a synthetic dummy for weak undefined functions. These dummies will + // be GC'd if not used as the target of any "call" instructions. + StringRef DebugName = Saver.save("undefined:" + toString(*Sym)); + InputFunction* Func = replaceWithUnreachable(Sym, *Sig, DebugName); + // Ensure it compares equal to the null pointer, and so that table relocs + // don't pull in the stub body (only call-operand relocs should do that). + Func->setTableIndex(0); + // Hide our dummy to prevent export. + Sym->setHidden(true); + } +} |

