From 33c0b6bfcaf7579ec552bf4688da33b41f12847a Mon Sep 17 00:00:00 2001 From: Lang Hames Date: Mon, 8 Aug 2016 22:53:37 +0000 Subject: [PATCH] [RuntimeDyld][Orc][MCJIT] Add partial weak-symbol support to RuntimeDyld. This patch causes RuntimeDyld to check for existing definitions when it encounters weak symbols. If a definition already exists then the new weak definition is discarded. All symbol lookups within a "logical dylib" should now agree on the address of any given weak symbol. This allows the JIT to better match the behavior of the static linker for C++ code. This support is only partial, as it does not allow strong definitions that occur after the first weak definition (in JIT symbol lookup order) to override the previous weak definitions. Support for this will be added in a future patch. llvm-svn: 278065 --- .../ExecutionEngine/Orc/OrcMCJITReplacement.h | 6 +++-- .../RuntimeDyld/RuntimeDyld.cpp | 18 +++++++++++++ .../MCJIT/Inputs/weak-function-2.ll | 9 +++++++ .../ExecutionEngine/MCJIT/weak-function.ll | 26 +++++++++++++++++++ .../OrcMCJIT/Inputs/weak-function-2.ll | 9 +++++++ .../ExecutionEngine/OrcMCJIT/weak-function.ll | 26 +++++++++++++++++++ 6 files changed, 92 insertions(+), 2 deletions(-) create mode 100644 llvm/test/ExecutionEngine/MCJIT/Inputs/weak-function-2.ll create mode 100644 llvm/test/ExecutionEngine/MCJIT/weak-function.ll create mode 100644 llvm/test/ExecutionEngine/OrcMCJIT/Inputs/weak-function-2.ll create mode 100644 llvm/test/ExecutionEngine/OrcMCJIT/weak-function.ll diff --git a/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h b/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h index 805852b4887f..db9c519b8261 100644 --- a/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h +++ b/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h @@ -116,11 +116,13 @@ class OrcMCJITReplacement : public ExecutionEngine { LinkingResolver(OrcMCJITReplacement &M) : M(M) {} JITSymbol findSymbol(const std::string &Name) override { - return M.findMangledSymbol(Name); + return M.ClientResolver->findSymbol(Name); } JITSymbol findSymbolInLogicalDylib(const std::string &Name) override { - return M.ClientResolver->findSymbol(Name); + if (auto Sym = M.findMangledSymbol(Name)) + return Sym; + return M.ClientResolver->findSymbolInLogicalDylib(Name); } private: diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp index 1770525879ed..0c69b1a5160c 100644 --- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp @@ -226,6 +226,24 @@ RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) { // Compute JIT symbol flags. JITSymbolFlags JITSymFlags = JITSymbolFlags::fromObjectSymbol(*I); + // If this is a weak definition, check to see if there's a strong one. + // If there is, skip this symbol (we won't be providing it: the strong + // definition will). If there's no strong definition, make this definition + // strong. + if (JITSymFlags.isWeak()) { + // First check whether there's already a definition in this instance. + // FIXME: Override existing weak definitions with strong ones. + if (GlobalSymbolTable.count(Name)) + continue; + // Then check the symbol resolver to see if there's a definition + // elsewhere in this logical dylib. + if (auto Sym = Resolver.findSymbolInLogicalDylib(Name)) + if (Sym.getFlags().isStrongDefinition()) + continue; + // else + JITSymFlags &= ~JITSymbolFlags::Weak; + } + if (Flags & SymbolRef::SF_Absolute && SymType != object::SymbolRef::ST_File) { uint64_t Addr = 0; diff --git a/llvm/test/ExecutionEngine/MCJIT/Inputs/weak-function-2.ll b/llvm/test/ExecutionEngine/MCJIT/Inputs/weak-function-2.ll new file mode 100644 index 000000000000..a7ff83df0398 --- /dev/null +++ b/llvm/test/ExecutionEngine/MCJIT/Inputs/weak-function-2.ll @@ -0,0 +1,9 @@ +define linkonce_odr i32 @baz() #0 { +entry: + ret i32 0 +} + +define i8* @bar() { +entry: + ret i8* bitcast (i32 ()* @baz to i8*) +} diff --git a/llvm/test/ExecutionEngine/MCJIT/weak-function.ll b/llvm/test/ExecutionEngine/MCJIT/weak-function.ll new file mode 100644 index 000000000000..562d6ade33b3 --- /dev/null +++ b/llvm/test/ExecutionEngine/MCJIT/weak-function.ll @@ -0,0 +1,26 @@ +; RUN: lli -jit-kind=mcjit -extra-module %p/Inputs/weak-function-2.ll %s +; +; Check that functions in two different modules agree on the address of weak +; function 'baz' + +define linkonce_odr i32 @baz() { +entry: + ret i32 0 +} + +define i8* @foo() { +entry: + ret i8* bitcast (i32 ()* @baz to i8*) +} + +declare i8* @bar() + +define i32 @main(i32 %argc, i8** %argv) { +entry: + %call = tail call i8* @foo() + %call1 = tail call i8* @bar() + %cmp = icmp ne i8* %call, %call1 + %conv = zext i1 %cmp to i32 + ret i32 %conv +} + diff --git a/llvm/test/ExecutionEngine/OrcMCJIT/Inputs/weak-function-2.ll b/llvm/test/ExecutionEngine/OrcMCJIT/Inputs/weak-function-2.ll new file mode 100644 index 000000000000..a7ff83df0398 --- /dev/null +++ b/llvm/test/ExecutionEngine/OrcMCJIT/Inputs/weak-function-2.ll @@ -0,0 +1,9 @@ +define linkonce_odr i32 @baz() #0 { +entry: + ret i32 0 +} + +define i8* @bar() { +entry: + ret i8* bitcast (i32 ()* @baz to i8*) +} diff --git a/llvm/test/ExecutionEngine/OrcMCJIT/weak-function.ll b/llvm/test/ExecutionEngine/OrcMCJIT/weak-function.ll new file mode 100644 index 000000000000..db255cdbb2ce --- /dev/null +++ b/llvm/test/ExecutionEngine/OrcMCJIT/weak-function.ll @@ -0,0 +1,26 @@ +; RUN: lli -jit-kind=orc-mcjit -extra-module %p/Inputs/weak-function-2.ll %s +; +; Check that functions in two different modules agree on the address of weak +; function 'baz' + +define linkonce_odr i32 @baz() { +entry: + ret i32 0 +} + +define i8* @foo() { +entry: + ret i8* bitcast (i32 ()* @baz to i8*) +} + +declare i8* @bar() + +define i32 @main(i32 %argc, i8** %argv) { +entry: + %call = tail call i8* @foo() + %call1 = tail call i8* @bar() + %cmp = icmp ne i8* %call, %call1 + %conv = zext i1 %cmp to i32 + ret i32 %conv +} +