diff --git a/examples/OrcV2Examples/LLJITWithObjectLinkingLayerPlugin/LLJITWithObjectLinkingLayerPlugin.cpp b/examples/OrcV2Examples/LLJITWithObjectLinkingLayerPlugin/LLJITWithObjectLinkingLayerPlugin.cpp index f349ce900e6..34776cb4211 100644 --- a/examples/OrcV2Examples/LLJITWithObjectLinkingLayerPlugin/LLJITWithObjectLinkingLayerPlugin.cpp +++ b/examples/OrcV2Examples/LLJITWithObjectLinkingLayerPlugin/LLJITWithObjectLinkingLayerPlugin.cpp @@ -14,6 +14,7 @@ #include "llvm/ADT/StringMap.h" #include "llvm/ExecutionEngine/JITLink/JITLink.h" #include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h" +#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" #include "llvm/ExecutionEngine/Orc/LLJIT.h" #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" #include "llvm/Support/InitLLVM.h" @@ -51,24 +52,35 @@ public: // defined as lambdas that call the printLinkerGraph method on our // plugin: One to run before the linker applies fixups and another to // run afterwards. - void modifyPassConfig(MaterializationResponsibility &MR, const Triple &TT, + void modifyPassConfig(MaterializationResponsibility &MR, + jitlink::LinkGraph &LG, jitlink::PassConfiguration &Config) override { - Config.PostPrunePasses.push_back([this](jitlink::LinkGraph &G) -> Error { - printLinkGraph(G, "Before fixup:"); - return Error::success(); - }); - Config.PostFixupPasses.push_back([this](jitlink::LinkGraph &G) -> Error { - printLinkGraph(G, "After fixup:"); - return Error::success(); - }); + + outs() << "MyPlugin -- Modifying pass config for " << LG.getName() << " (" + << LG.getTargetTriple().str() << "):\n"; + + // Print sections, symbol names and addresses, and any edges for the + // associated blocks. + Config.PostPrunePasses.push_back(printGraph); + + // Print graph contents before and after fixups: + // + // Config.PostPrunePasses.push_back([this](jitlink::LinkGraph &G) -> Error { + // printLinkGraphContent(G, "Before fixup:"); + // return Error::success(); + // }); + // Config.PostFixupPasses.push_back([this](jitlink::LinkGraph &G) -> Error { + // printLinkGraphContent(G, "After fixup:"); + // return Error::success(); + // }); } void notifyLoaded(MaterializationResponsibility &MR) override { - dbgs() << "Loading object defining " << MR.getSymbols() << "\n"; + outs() << "Loading object defining " << MR.getSymbols() << "\n"; } Error notifyEmitted(MaterializationResponsibility &MR) override { - dbgs() << "Emitted object defining " << MR.getSymbols() << "\n"; + outs() << "Emitted object defining " << MR.getSymbols() << "\n"; return Error::success(); } @@ -84,42 +96,100 @@ public: ResourceKey SrcKey) override {} private: - void printLinkGraph(jitlink::LinkGraph &G, StringRef Title) { + static void printBlockContent(jitlink::Block &B) { constexpr JITTargetAddress LineWidth = 16; - dbgs() << "--- " << Title << "---\n"; + if (B.isZeroFill()) { + outs() << " " << formatv("{0:x16}", B.getAddress()) << ": " + << B.getSize() << " bytes of zero-fill.\n"; + return; + } + + JITTargetAddress InitAddr = B.getAddress() & ~(LineWidth - 1); + JITTargetAddress StartAddr = B.getAddress(); + JITTargetAddress EndAddr = B.getAddress() + B.getSize(); + auto *Data = reinterpret_cast(B.getContent().data()); + + for (JITTargetAddress CurAddr = InitAddr; CurAddr != EndAddr; ++CurAddr) { + if (CurAddr % LineWidth == 0) + outs() << " " << formatv("{0:x16}", CurAddr) << ": "; + if (CurAddr < StartAddr) + outs() << " "; + else + outs() << formatv("{0:x-2}", Data[CurAddr - StartAddr]) << " "; + if (CurAddr % LineWidth == LineWidth - 1) + outs() << "\n"; + } + if (EndAddr % LineWidth != 0) + outs() << "\n"; + } + + static Error printGraph(jitlink::LinkGraph &G) { + + DenseSet BlocksAlreadyVisited; + + outs() << "Graph \"" << G.getName() << "\"\n"; + // Loop over all sections... for (auto &S : G.sections()) { - dbgs() << " section: " << S.getName() << "\n"; - for (auto *B : S.blocks()) { - dbgs() << " block@" << formatv("{0:x16}", B->getAddress()) << ":\n"; + outs() << " Section " << S.getName() << ":\n"; - if (B->isZeroFill()) + // Loop over all symbols in the current section... + for (auto *Sym : S.symbols()) { + + // Print the symbol's address. + outs() << " " << formatv("{0:x16}", Sym->getAddress()) << ": "; + + // Print the symbol's name, or "" if it doesn't have + // one. + if (Sym->hasName()) + outs() << Sym->getName() << "\n"; + else + outs() << "\n"; + + // Get the content block for this symbol. + auto &B = Sym->getBlock(); + + if (BlocksAlreadyVisited.count(&B)) { + outs() << " Block " << formatv("{0:x16}", B.getAddress()) + << " already printed.\n"; continue; + } else + outs() << " Block " << formatv("{0:x16}", B.getAddress()) + << ":\n"; - JITTargetAddress InitAddr = B->getAddress() & ~(LineWidth - 1); - JITTargetAddress StartAddr = B->getAddress(); - JITTargetAddress EndAddr = B->getAddress() + B->getSize(); - auto *Data = reinterpret_cast(B->getContent().data()); + outs() << " Content:\n"; + printBlockContent(B); + BlocksAlreadyVisited.insert(&B); - for (JITTargetAddress CurAddr = InitAddr; CurAddr != EndAddr; - ++CurAddr) { - if (CurAddr % LineWidth == 0) - dbgs() << " " << formatv("{0:x16}", CurAddr) << ": "; - if (CurAddr < StartAddr) - dbgs() << " "; - else - dbgs() << formatv("{0:x-2}", Data[CurAddr - StartAddr]) << " "; - if (CurAddr % LineWidth == LineWidth - 1) - dbgs() << "\n"; + if (!llvm::empty(B.edges())) { + outs() << " Edges:\n"; + for (auto &E : B.edges()) { + outs() << " " + << formatv("{0:x16}", B.getAddress() + E.getOffset()) + << ": kind = " << formatv("{0:d}", E.getKind()) + << ", addend = " << formatv("{0:x}", E.getAddend()) + << ", target = "; + jitlink::Symbol &TargetSym = E.getTarget(); + if (TargetSym.hasName()) + outs() << TargetSym.getName() << "\n"; + else + outs() << "\n"; + } } - if (EndAddr % LineWidth != 0) - dbgs() << "\n"; - dbgs() << "\n"; + outs() << "\n"; } } + return Error::success(); } }; +static cl::opt + EntryPointName("entry", cl::desc("Symbol to call as main entry point"), + cl::init("entry")); + +static cl::list InputObjects(cl::Positional, cl::ZeroOrMore, + cl::desc("input objects")); + int main(int argc, char *argv[]) { // Initialize LLVM. InitLLVM X(argc, argv); @@ -151,17 +221,36 @@ int main(int argc, char *argv[]) { }) .create()); - auto M = ExitOnErr(parseExampleModule(TestMod, "test-module")); + if (!InputObjects.empty()) { - ExitOnErr(J->addIRModule(std::move(M))); + // If we have input objects then reflect process symbols so the input + // objects can do interesting things, like call printf. + J->getMainJITDylib().addGenerator( + ExitOnErr(DynamicLibrarySearchGenerator::GetForCurrentProcess( + J->getDataLayout().getGlobalPrefix()))); + + // Load the input objects. + for (auto InputObject : InputObjects) { + auto ObjBuffer = + ExitOnErr(errorOrToExpected(MemoryBuffer::getFile(InputObject))); + ExitOnErr(J->addObjectFile(std::move(ObjBuffer))); + } + } else { + auto M = ExitOnErr(parseExampleModule(TestMod, "test-module")); + M.withModuleDo([](Module &MP) { + outs() << "No input objects specified. Using demo module:\n" + << MP << "\n"; + }); + ExitOnErr(J->addIRModule(std::move(M))); + } // Look up the JIT'd function, cast it to a function pointer, then call it. - auto EntrySym = ExitOnErr(J->lookup("entry")); + auto EntrySym = ExitOnErr(J->lookup(EntryPointName)); auto *Entry = (int (*)())EntrySym.getAddress(); int Result = Entry(); outs() << "---Result---\n" - << "entry() = " << Result << "\n"; + << EntryPointName << "() = " << Result << "\n"; return 0; } diff --git a/include/llvm/ExecutionEngine/JITLink/JITLink.h b/include/llvm/ExecutionEngine/JITLink/JITLink.h index 539036eb5ef..587d46489a0 100644 --- a/include/llvm/ExecutionEngine/JITLink/JITLink.h +++ b/include/llvm/ExecutionEngine/JITLink/JITLink.h @@ -1377,7 +1377,7 @@ public: /// Called by JITLink to modify the pass pipeline prior to linking. /// The default version performs no modification. - virtual Error modifyPassConfig(const Triple &TT, PassConfiguration &Config); + virtual Error modifyPassConfig(LinkGraph &G, PassConfiguration &Config); private: const JITLinkDylib *JD = nullptr; diff --git a/include/llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h b/include/llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h index 68ffbb4a5ed..1b4ee7b5b1f 100644 --- a/include/llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h +++ b/include/llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h @@ -62,7 +62,8 @@ public: void notifyTransferringResources(ResourceKey DstKey, ResourceKey SrcKey) override; - void modifyPassConfig(MaterializationResponsibility &MR, const Triple &TT, + void modifyPassConfig(MaterializationResponsibility &MR, + jitlink::LinkGraph &LG, jitlink::PassConfiguration &PassConfig) override; private: diff --git a/include/llvm/ExecutionEngine/Orc/MachOPlatform.h b/include/llvm/ExecutionEngine/Orc/MachOPlatform.h index 90e1d4704f3..f04bef161ea 100644 --- a/include/llvm/ExecutionEngine/Orc/MachOPlatform.h +++ b/include/llvm/ExecutionEngine/Orc/MachOPlatform.h @@ -114,7 +114,8 @@ private: public: InitScraperPlugin(MachOPlatform &MP) : MP(MP) {} - void modifyPassConfig(MaterializationResponsibility &MR, const Triple &TT, + void modifyPassConfig(MaterializationResponsibility &MR, + jitlink::LinkGraph &G, jitlink::PassConfiguration &Config) override; LocalDependenciesMap getSyntheticSymbolLocalDependencies( diff --git a/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h b/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h index 27387027529..e26c5089991 100644 --- a/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h +++ b/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h @@ -69,7 +69,7 @@ public: virtual ~Plugin(); virtual void modifyPassConfig(MaterializationResponsibility &MR, - const Triple &TT, + jitlink::LinkGraph &G, jitlink::PassConfiguration &Config) {} // Deprecated. Don't use this in new code. There will be a proper mechanism @@ -171,7 +171,8 @@ public: private: using AllocPtr = std::unique_ptr; - void modifyPassConfig(MaterializationResponsibility &MR, const Triple &TT, + void modifyPassConfig(MaterializationResponsibility &MR, + jitlink::LinkGraph &G, jitlink::PassConfiguration &PassConfig); void notifyLoaded(MaterializationResponsibility &MR); Error notifyEmitted(MaterializationResponsibility &MR, AllocPtr Alloc); @@ -194,7 +195,8 @@ public: EHFrameRegistrationPlugin( ExecutionSession &ES, std::unique_ptr Registrar); - void modifyPassConfig(MaterializationResponsibility &MR, const Triple &TT, + void modifyPassConfig(MaterializationResponsibility &MR, + jitlink::LinkGraph &G, jitlink::PassConfiguration &PassConfig) override; Error notifyEmitted(MaterializationResponsibility &MR) override; Error notifyFailed(MaterializationResponsibility &MR) override; diff --git a/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp b/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp index e43e9608c69..e6872a00e49 100644 --- a/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp +++ b/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp @@ -787,7 +787,7 @@ void link_ELF_x86_64(std::unique_ptr G, Config.PreFixupPasses.push_back(optimizeELF_x86_64_GOTAndStubs); } - if (auto Err = Ctx->modifyPassConfig(G->getTargetTriple(), Config)) + if (auto Err = Ctx->modifyPassConfig(*G, Config)) return Ctx->notifyFailed(std::move(Err)); ELFJITLinker_x86_64::link(std::move(Ctx), std::move(G), std::move(Config)); diff --git a/lib/ExecutionEngine/JITLink/JITLink.cpp b/lib/ExecutionEngine/JITLink/JITLink.cpp index 25b554fcb39..681ef3332f3 100644 --- a/lib/ExecutionEngine/JITLink/JITLink.cpp +++ b/lib/ExecutionEngine/JITLink/JITLink.cpp @@ -311,7 +311,7 @@ LinkGraphPassFunction JITLinkContext::getMarkLivePass(const Triple &TT) const { return LinkGraphPassFunction(); } -Error JITLinkContext::modifyPassConfig(const Triple &TT, +Error JITLinkContext::modifyPassConfig(LinkGraph &G, PassConfiguration &Config) { return Error::success(); } diff --git a/lib/ExecutionEngine/JITLink/MachO_arm64.cpp b/lib/ExecutionEngine/JITLink/MachO_arm64.cpp index 8366e965853..ee624c6bfd1 100644 --- a/lib/ExecutionEngine/JITLink/MachO_arm64.cpp +++ b/lib/ExecutionEngine/JITLink/MachO_arm64.cpp @@ -701,7 +701,7 @@ void link_MachO_arm64(std::unique_ptr G, }); } - if (auto Err = Ctx->modifyPassConfig(G->getTargetTriple(), Config)) + if (auto Err = Ctx->modifyPassConfig(*G, Config)) return Ctx->notifyFailed(std::move(Err)); // Construct a JITLinker and run the link function. diff --git a/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp b/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp index bde4a19e71b..288b303dd67 100644 --- a/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp +++ b/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp @@ -688,7 +688,7 @@ void link_MachO_x86_64(std::unique_ptr G, Config.PreFixupPasses.push_back(optimizeMachO_x86_64_GOTAndStubs); } - if (auto Err = Ctx->modifyPassConfig(G->getTargetTriple(), Config)) + if (auto Err = Ctx->modifyPassConfig(*G, Config)) return Ctx->notifyFailed(std::move(Err)); // Construct a JITLinker and run the link function. diff --git a/lib/ExecutionEngine/Orc/DebugObjectManagerPlugin.cpp b/lib/ExecutionEngine/Orc/DebugObjectManagerPlugin.cpp index 1da87dd3468..4b53d87215c 100644 --- a/lib/ExecutionEngine/Orc/DebugObjectManagerPlugin.cpp +++ b/lib/ExecutionEngine/Orc/DebugObjectManagerPlugin.cpp @@ -432,7 +432,7 @@ void DebugObjectManagerPlugin::notifyMaterializing( } void DebugObjectManagerPlugin::modifyPassConfig( - MaterializationResponsibility &MR, const Triple &TT, + MaterializationResponsibility &MR, LinkGraph &G, PassConfiguration &PassConfig) { // Not all link artifacts have associated debug objects. std::lock_guard Lock(PendingObjsLock); diff --git a/lib/ExecutionEngine/Orc/MachOPlatform.cpp b/lib/ExecutionEngine/Orc/MachOPlatform.cpp index 17b9465a054..b47b5e9d396 100644 --- a/lib/ExecutionEngine/Orc/MachOPlatform.cpp +++ b/lib/ExecutionEngine/Orc/MachOPlatform.cpp @@ -298,7 +298,7 @@ getSectionExtent(jitlink::LinkGraph &G, StringRef SectionName) { } void MachOPlatform::InitScraperPlugin::modifyPassConfig( - MaterializationResponsibility &MR, const Triple &TT, + MaterializationResponsibility &MR, jitlink::LinkGraph &LG, jitlink::PassConfiguration &Config) { if (!MR.getInitializerSymbol()) diff --git a/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp b/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp index 24db73e4cf5..dc3cf87798c 100644 --- a/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp +++ b/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp @@ -218,14 +218,14 @@ public: return [this](LinkGraph &G) { return markResponsibilitySymbolsLive(G); }; } - Error modifyPassConfig(const Triple &TT, PassConfiguration &Config) override { + Error modifyPassConfig(LinkGraph &LG, PassConfiguration &Config) override { // Add passes to mark duplicate defs as should-discard, and to walk the // link graph to build the symbol dependence graph. Config.PrePrunePasses.push_back([this](LinkGraph &G) { return claimOrExternalizeWeakAndCommonSymbols(G); }); - Layer.modifyPassConfig(*MR, TT, Config); + Layer.modifyPassConfig(*MR, LG, Config); Config.PostPrunePasses.push_back( [this](LinkGraph &G) { return computeNamedSymbolDependencies(G); }); @@ -511,10 +511,10 @@ void ObjectLinkingLayer::emit(std::unique_ptr R, } void ObjectLinkingLayer::modifyPassConfig(MaterializationResponsibility &MR, - const Triple &TT, + LinkGraph &G, PassConfiguration &PassConfig) { for (auto &P : Plugins) - P->modifyPassConfig(MR, TT, PassConfig); + P->modifyPassConfig(MR, G, PassConfig); } void ObjectLinkingLayer::notifyLoaded(MaterializationResponsibility &MR) { @@ -583,11 +583,11 @@ EHFrameRegistrationPlugin::EHFrameRegistrationPlugin( : ES(ES), Registrar(std::move(Registrar)) {} void EHFrameRegistrationPlugin::modifyPassConfig( - MaterializationResponsibility &MR, const Triple &TT, + MaterializationResponsibility &MR, LinkGraph &G, PassConfiguration &PassConfig) { PassConfig.PostFixupPasses.push_back(createEHFrameRecorderPass( - TT, [this, &MR](JITTargetAddress Addr, size_t Size) { + G.getTargetTriple(), [this, &MR](JITTargetAddress Addr, size_t Size) { if (Addr) { std::lock_guard Lock(EHFramePluginMutex); assert(!InProcessLinks.count(&MR) && diff --git a/tools/llvm-jitlink/llvm-jitlink.cpp b/tools/llvm-jitlink/llvm-jitlink.cpp index 13d13902421..473afc5f47e 100644 --- a/tools/llvm-jitlink/llvm-jitlink.cpp +++ b/tools/llvm-jitlink/llvm-jitlink.cpp @@ -821,9 +821,9 @@ Session::Session(std::unique_ptr TPC, Error &Err) class JITLinkSessionPlugin : public ObjectLinkingLayer::Plugin { public: JITLinkSessionPlugin(Session &S) : S(S) {} - void modifyPassConfig(MaterializationResponsibility &MR, const Triple &TT, + void modifyPassConfig(MaterializationResponsibility &MR, LinkGraph &G, PassConfiguration &PassConfig) override { - S.modifyPassConfig(TT, PassConfig); + S.modifyPassConfig(G.getTargetTriple(), PassConfig); } Error notifyFailed(MaterializationResponsibility &MR) override {