From: Lang Hames Date: Sat, 6 Aug 2016 00:54:43 +0000 (+0000) Subject: [ORC] Add (partial) weak symbol support to the CompileOnDemand layer. X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=62a459603c2b9cf219a3102146d285a860f1cef7;p=platform%2Fupstream%2Fllvm.git [ORC] Add (partial) weak symbol support to the CompileOnDemand layer. This adds partial support for weak functions to the CompileOnDemandLayer by modifying the addLogicalModule method to check for existing stub definitions before building a new stub for a weak function. This scheme is sufficient to support ODR definitions, but fails for general weak definitions if strong definition is encountered after the first weak definition. (A more extensive refactor will be required to fully support weak symbols). This patch does *not* add weak symbol support to RuntimeDyld: I hope to add that in the near future. llvm-svn: 277896 --- diff --git a/llvm/include/llvm/ExecutionEngine/JITSymbol.h b/llvm/include/llvm/ExecutionEngine/JITSymbol.h index 138fe6e..9b09689 100644 --- a/llvm/include/llvm/ExecutionEngine/JITSymbol.h +++ b/llvm/include/llvm/ExecutionEngine/JITSymbol.h @@ -59,6 +59,10 @@ public: return (Flags & Common) == Common; } + bool isStrongDefinition() const { + return !isWeak() && !isCommon(); + } + /// @brief Returns true is the Weak flag is set. bool isExported() const { return (Flags & Exported) == Exported; diff --git a/llvm/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h b/llvm/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h index 2f76b84..f3d95e0 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h @@ -281,12 +281,20 @@ private: // Create stub functions. const DataLayout &DL = SrcM.getDataLayout(); { + LMResources.StubsMgr = CreateIndirectStubsManager(); + typename IndirectStubsMgrT::StubInitsMap StubInits; for (auto &F : SrcM) { // Skip declarations. if (F.isDeclaration()) continue; + // Skip weak functions for which we already have definitions. + auto MangledName = mangle(F.getName(), DL); + if (F.hasWeakLinkage() || F.hasLinkOnceLinkage()) + if (auto Sym = LD.findSymbol(MangledName, false)) + continue; + // Record all functions defined by this module. if (CloneStubsIntoPartitions) LMResources.StubsToClone.insert(&F); @@ -295,7 +303,7 @@ private: // and set the compile action to compile the partition containing the // function. auto CCInfo = CompileCallbackMgr.getCompileCallback(); - StubInits[mangle(F.getName(), DL)] = + StubInits[MangledName] = std::make_pair(CCInfo.getAddress(), JITSymbolFlags::fromGlobalValue(F)); CCInfo.setCompileAction([this, &LD, LMH, &F]() { @@ -303,7 +311,6 @@ private: }); } - LMResources.StubsMgr = CreateIndirectStubsManager(); auto EC = LMResources.StubsMgr->createStubs(StubInits); (void)EC; // FIXME: This should be propagated back to the user. Stub creation may @@ -383,8 +390,7 @@ private: // Build a resolver for the globals module and add it to the base layer. auto GVsResolver = createLambdaResolver( [&LD, LMH](const std::string &Name) { - auto &LMResources = LD.getLogicalModuleResources(LMH); - if (auto Sym = LMResources.StubsMgr->findStub(Name, false)) + if (auto Sym = LD.findSymbol(Name, false)) return Sym; auto &LDResolver = LD.getDylibResources().ExternalSymbolResolver; return LDResolver->findSymbolInLogicalDylib(Name); diff --git a/llvm/lib/ExecutionEngine/JITSymbol.cpp b/llvm/lib/ExecutionEngine/JITSymbol.cpp index 91d198b..8769dcf 100644 --- a/llvm/lib/ExecutionEngine/JITSymbol.cpp +++ b/llvm/lib/ExecutionEngine/JITSymbol.cpp @@ -19,7 +19,7 @@ using namespace llvm; JITSymbolFlags llvm::JITSymbolFlags::fromGlobalValue(const GlobalValue &GV) { JITSymbolFlags Flags = JITSymbolFlags::None; - if (GV.hasWeakLinkage()) + if (GV.hasWeakLinkage() || GV.hasLinkOnceLinkage()) Flags |= JITSymbolFlags::Weak; if (GV.hasCommonLinkage()) Flags |= JITSymbolFlags::Common; diff --git a/llvm/test/ExecutionEngine/OrcLazy/Inputs/weak-function-2.ll b/llvm/test/ExecutionEngine/OrcLazy/Inputs/weak-function-2.ll new file mode 100644 index 0000000..dca4f70 --- /dev/null +++ b/llvm/test/ExecutionEngine/OrcLazy/Inputs/weak-function-2.ll @@ -0,0 +1,13 @@ +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-macosx10.12.0" + +; Function Attrs: nounwind ssp uwtable +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/OrcLazy/weak-function.ll b/llvm/test/ExecutionEngine/OrcLazy/weak-function.ll new file mode 100644 index 0000000..86c962e --- /dev/null +++ b/llvm/test/ExecutionEngine/OrcLazy/weak-function.ll @@ -0,0 +1,28 @@ +; RUN: lli -jit-kind=orc-lazy -extra-module %p/Inputs/weak-function-2.ll %s +; +; Check that functions in two different modules agree on the address of weak +; function 'baz' +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-macosx10.12.0" + +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/tools/lli/OrcLazyJIT.cpp b/llvm/tools/lli/OrcLazyJIT.cpp index a36d573..d9cec0c 100644 --- a/llvm/tools/lli/OrcLazyJIT.cpp +++ b/llvm/tools/lli/OrcLazyJIT.cpp @@ -144,8 +144,7 @@ int llvm::runOrcLazyJIT(std::vector> Ms, int ArgC, OrcInlineStubs); // Add the module, look up main and run it. - for (auto &M : Ms) - J.addModule(std::move(M)); + J.addModuleSet(std::move(Ms)); auto MainSym = J.findSymbol("main"); if (!MainSym) { diff --git a/llvm/tools/lli/OrcLazyJIT.h b/llvm/tools/lli/OrcLazyJIT.h index 26be63d..71e0d83 100644 --- a/llvm/tools/lli/OrcLazyJIT.h +++ b/llvm/tools/lli/OrcLazyJIT.h @@ -38,7 +38,7 @@ public: typedef orc::CompileOnDemandLayer CODLayerT; typedef CODLayerT::IndirectStubsManagerBuilderT IndirectStubsManagerBuilder; - typedef CODLayerT::ModuleSetHandleT ModuleHandleT; + typedef CODLayerT::ModuleSetHandleT ModuleSetHandleT; OrcLazyJIT(std::unique_ptr TM, std::unique_ptr CCMgr, @@ -62,18 +62,21 @@ public: DtorRunner.runViaLayer(CODLayer); } - ModuleHandleT addModule(std::unique_ptr M) { - // Attach a data-layout if one isn't already present. - if (M->getDataLayout().isDefault()) - M->setDataLayout(DL); + ModuleSetHandleT addModuleSet(std::vector> Ms) { + // Attach a data-layouts if they aren't already present. + for (auto &M : Ms) + if (M->getDataLayout().isDefault()) + M->setDataLayout(DL); // Record the static constructors and destructors. We have to do this before // we hand over ownership of the module to the JIT. std::vector CtorNames, DtorNames; - for (auto Ctor : orc::getConstructors(*M)) - CtorNames.push_back(mangle(Ctor.Func->getName())); - for (auto Dtor : orc::getDestructors(*M)) - DtorNames.push_back(mangle(Dtor.Func->getName())); + for (auto &M : Ms) { + for (auto Ctor : orc::getConstructors(*M)) + CtorNames.push_back(mangle(Ctor.Func->getName())); + for (auto Dtor : orc::getDestructors(*M)) + DtorNames.push_back(mangle(Dtor.Func->getName())); + } // Symbol resolution order: // 1) Search the JIT symbols. @@ -84,24 +87,18 @@ public: [this](const std::string &Name) -> JITSymbol { if (auto Sym = CODLayer.findSymbol(Name, true)) return Sym; - if (auto Sym = CXXRuntimeOverrides.searchOverrides(Name)) - return Sym; - + return CXXRuntimeOverrides.searchOverrides(Name); + }, + [](const std::string &Name) { if (auto Addr = RTDyldMemoryManager::getSymbolAddressInProcess(Name)) return JITSymbol(Addr, JITSymbolFlags::Exported); - - return JITSymbol(nullptr); - }, - [](const std::string &Name) { return JITSymbol(nullptr); } ); // Add the module to the JIT. - std::vector> S; - S.push_back(std::move(M)); - auto H = CODLayer.addModuleSet(std::move(S), + auto H = CODLayer.addModuleSet(std::move(Ms), llvm::make_unique(), std::move(Resolver)); @@ -119,7 +116,7 @@ public: return CODLayer.findSymbol(mangle(Name), true); } - JITSymbol findSymbolIn(ModuleHandleT H, const std::string &Name) { + JITSymbol findSymbolIn(ModuleSetHandleT H, const std::string &Name) { return CODLayer.findSymbolIn(H, mangle(Name), true); }