[lld] r353478 - [WebAssembly] Refactor handling of weak undefined functions. NFC.
Sam Clegg via llvm-commits
llvm-commits at lists.llvm.org
Thu Feb 7 14:42:16 PST 2019
Author: sbc
Date: Thu Feb 7 14:42:16 2019
New Revision: 353478
URL: http://llvm.org/viewvc/llvm-project?rev=353478&view=rev
Log:
[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
Modified:
lld/trunk/docs/WebAssembly.rst
lld/trunk/test/wasm/archive-weak-undefined.ll
lld/trunk/test/wasm/cxx-mangling.ll
lld/trunk/test/wasm/lto/weak-undefined.ll
lld/trunk/test/wasm/undefined-weak-call.ll
lld/trunk/wasm/Driver.cpp
lld/trunk/wasm/SymbolTable.cpp
lld/trunk/wasm/SymbolTable.h
lld/trunk/wasm/Symbols.h
Modified: lld/trunk/docs/WebAssembly.rst
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/docs/WebAssembly.rst?rev=353478&r1=353477&r2=353478&view=diff
==============================================================================
--- lld/trunk/docs/WebAssembly.rst (original)
+++ lld/trunk/docs/WebAssembly.rst Thu Feb 7 14:42:16 2019
@@ -124,6 +124,18 @@ The symbols which are preserved by defau
- Any symbol which is to be exported.
- Any symbol transitively referenced by the above.
+Weak Undefined Functions
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+On native platforms, calls to weak undefined functions end up as calls to the
+null function pointer. With WebAssembly, direct calls must reference a defined
+function (with the correct signature). In order to handle this case the linker
+will generate function a stub containing only the ``unreachable`` instruction
+and use this for any direct references to an undefined weak function.
+
+For example a runtime call to a weak undefined function ``foo`` will up trapping
+on ``unreachable`` inside and linker-generated function called
+``undefined:foo``.
Missing features
----------------
Modified: lld/trunk/test/wasm/archive-weak-undefined.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/archive-weak-undefined.ll?rev=353478&r1=353477&r2=353478&view=diff
==============================================================================
--- lld/trunk/test/wasm/archive-weak-undefined.ll (original)
+++ lld/trunk/test/wasm/archive-weak-undefined.ll Thu Feb 7 14:42:16 2019
@@ -15,5 +15,5 @@ entry:
ret void
}
-; CHECK: Name: undefined function ret32
+; CHECK: Name: 'undefined:ret32'
; CHECK-NOT: Name: ret32
Modified: lld/trunk/test/wasm/cxx-mangling.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/cxx-mangling.ll?rev=353478&r1=353477&r2=353478&view=diff
==============================================================================
--- lld/trunk/test/wasm/cxx-mangling.ll (original)
+++ lld/trunk/test/wasm/cxx-mangling.ll Thu Feb 7 14:42:16 2019
@@ -58,8 +58,8 @@ define void @_start() {
; CHECK-NEXT: - Index: 0
; CHECK-NEXT: Name: __wasm_call_ctors
; CHECK-NEXT: - Index: 1
-; DEMANGLE-NEXT: Name: 'undefined function bar(int)'
-; MANGLE-NEXT: Name: undefined function _Z3bari
+; DEMANGLE-NEXT: Name: 'undefined:bar(int)'
+; MANGLE-NEXT: Name: 'undefined:_Z3bari'
; CHECK-NEXT: - Index: 2
; DEMANGLE-NEXT: Name: 'foo(int)'
; MANGLE-NEXT: Name: _Z3fooi
Modified: lld/trunk/test/wasm/lto/weak-undefined.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/lto/weak-undefined.ll?rev=353478&r1=353477&r2=353478&view=diff
==============================================================================
--- lld/trunk/test/wasm/lto/weak-undefined.ll (original)
+++ lld/trunk/test/wasm/lto/weak-undefined.ll Thu Feb 7 14:42:16 2019
@@ -17,4 +17,4 @@ entry:
ret void
}
-; CHECK: Name: undefined function foo
+; CHECK: Name: 'undefined:foo'
Modified: lld/trunk/test/wasm/undefined-weak-call.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/undefined-weak-call.ll?rev=353478&r1=353477&r2=353478&view=diff
==============================================================================
--- lld/trunk/test/wasm/undefined-weak-call.ll (original)
+++ lld/trunk/test/wasm/undefined-weak-call.ll Thu Feb 7 14:42:16 2019
@@ -110,11 +110,11 @@ define i32 @callWeakFuncs() {
; CHECK-NEXT: - Index: 0
; CHECK-NEXT: Name: __wasm_call_ctors
; CHECK-NEXT: - Index: 1
-; CHECK-NEXT: Name: undefined function weakFunc1
+; CHECK-NEXT: Name: 'undefined:weakFunc1'
; CHECK-NEXT: - Index: 2
-; CHECK-NEXT: Name: undefined function weakFunc2
+; CHECK-NEXT: Name: 'undefined:weakFunc2'
; CHECK-NEXT: - Index: 3
-; CHECK-NEXT: Name: undefined function weakFunc3
+; CHECK-NEXT: Name: 'undefined:weakFunc3'
; CHECK-NEXT: - Index: 4
; CHECK-NEXT: Name: callWeakFuncs
; CHECK-NEXT: ...
Modified: lld/trunk/wasm/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/Driver.cpp?rev=353478&r1=353477&r2=353478&view=diff
==============================================================================
--- lld/trunk/wasm/Driver.cpp (original)
+++ lld/trunk/wasm/Driver.cpp Thu Feb 7 14:42:16 2019
@@ -286,53 +286,6 @@ static StringRef getEntry(opt::InputArgL
return Arg->getValue();
}
-static const uint8_t UnreachableFn[] = {
- 0x03 /* ULEB length */, 0x00 /* ULEB num locals */,
- 0x00 /* opcode unreachable */, 0x0b /* opcode end */
-};
-
-// 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.
-static void handleWeakUndefines() {
- for (Symbol *Sym : Symtab->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.
- std::string SymName = toString(*Sym);
- StringRef DebugName = Saver.save("undefined function " + SymName);
- auto *Func = make<SyntheticFunction>(*Sig, Sym->getName(), DebugName);
- Func->setBody(UnreachableFn);
- // 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);
- Symtab->SyntheticFunctions.emplace_back(Func);
- // Hide our dummy to prevent export.
- uint32_t Flags = WASM_SYMBOL_VISIBILITY_HIDDEN;
- replaceSymbol<DefinedFunction>(Sym, Sym->getName(), Flags, nullptr, Func);
- }
-}
-
// Some Config members do not directly correspond to any particular
// command line options, but computed based on other Config values.
// This function initialize such members. See Config.h for the details
@@ -620,7 +573,7 @@ void LinkerDriver::link(ArrayRef<const c
// Add synthetic dummies for weak undefined functions. Must happen
// after LTO otherwise functions may not yet have signatures.
if (!Config->Relocatable)
- handleWeakUndefines();
+ Symtab->handleWeakUndefines();
if (EntrySym)
EntrySym->setHidden(false);
Modified: lld/trunk/wasm/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/SymbolTable.cpp?rev=353478&r1=353477&r2=353478&view=diff
==============================================================================
--- lld/trunk/wasm/SymbolTable.cpp (original)
+++ lld/trunk/wasm/SymbolTable.cpp Thu Feb 7 14:42:16 2019
@@ -102,7 +102,8 @@ std::pair<Symbol *, bool> SymbolTable::i
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 Na
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);
+ }
+}
Modified: lld/trunk/wasm/SymbolTable.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/SymbolTable.h?rev=353478&r1=353477&r2=353478&view=diff
==============================================================================
--- lld/trunk/wasm/SymbolTable.h (original)
+++ lld/trunk/wasm/SymbolTable.h Thu Feb 7 14:42:16 2019
@@ -79,10 +79,15 @@ public:
DefinedFunction *addSyntheticFunction(StringRef Name, uint32_t Flags,
InputFunction *Function);
+ void handleWeakUndefines();
+
private:
- std::pair<Symbol *, bool> insert(StringRef Name, InputFile *File);
+ std::pair<Symbol *, bool> insert(StringRef Name, const InputFile *File);
std::pair<Symbol *, bool> insertName(StringRef Name);
+ InputFunction *replaceWithUnreachable(Symbol *Sym, const WasmSignature &Sig,
+ StringRef DebugName);
+
// Maps symbol names to index into the SymVector. -1 means that symbols
// is to not yet in the vector but it should have tracing enabled if it is
// ever added.
Modified: lld/trunk/wasm/Symbols.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/Symbols.h?rev=353478&r1=353477&r2=353478&view=diff
==============================================================================
--- lld/trunk/wasm/Symbols.h (original)
+++ lld/trunk/wasm/Symbols.h Thu Feb 7 14:42:16 2019
@@ -76,6 +76,8 @@ public:
// Returns the file from which this symbol was created.
InputFile *getFile() const { return File; }
+ uint32_t getFlags() const { return Flags; }
+
InputChunk *getChunk() const;
// Indicates that the section or import for this symbol will be included in
More information about the llvm-commits
mailing list