mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-10-18 10:32:48 +02:00
[JITLink][ORC] Make the LinkGraph available to modifyPassConfig.
This makes the target triple, graph name, and full graph content available when making decisions about how to populate the linker pass pipeline. Also updates the LLJITWithObjectLinkingLayerPlugin example to show more API use, including use of the API changes in this patch.
This commit is contained in:
parent
4a11d40768
commit
d7eedad739
@ -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<const uint8_t *>(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<jitlink::Block *> 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 "<anonymous symbol>" if it doesn't have
|
||||
// one.
|
||||
if (Sym->hasName())
|
||||
outs() << Sym->getName() << "\n";
|
||||
else
|
||||
outs() << "<anonymous symbol>\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<const uint8_t *>(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() << "<anonymous target>\n";
|
||||
}
|
||||
}
|
||||
if (EndAddr % LineWidth != 0)
|
||||
dbgs() << "\n";
|
||||
dbgs() << "\n";
|
||||
outs() << "\n";
|
||||
}
|
||||
}
|
||||
return Error::success();
|
||||
}
|
||||
};
|
||||
|
||||
static cl::opt<std::string>
|
||||
EntryPointName("entry", cl::desc("Symbol to call as main entry point"),
|
||||
cl::init("entry"));
|
||||
|
||||
static cl::list<std::string> 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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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:
|
||||
|
@ -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(
|
||||
|
@ -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<jitlink::JITLinkMemoryManager::Allocation>;
|
||||
|
||||
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<jitlink::EHFrameRegistrar> 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;
|
||||
|
@ -787,7 +787,7 @@ void link_ELF_x86_64(std::unique_ptr<LinkGraph> 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));
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -701,7 +701,7 @@ void link_MachO_arm64(std::unique_ptr<LinkGraph> 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.
|
||||
|
@ -688,7 +688,7 @@ void link_MachO_x86_64(std::unique_ptr<LinkGraph> 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.
|
||||
|
@ -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<std::mutex> Lock(PendingObjsLock);
|
||||
|
@ -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())
|
||||
|
@ -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<MaterializationResponsibility> 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<std::mutex> Lock(EHFramePluginMutex);
|
||||
assert(!InProcessLinks.count(&MR) &&
|
||||
|
@ -821,9 +821,9 @@ Session::Session(std::unique_ptr<TargetProcessControl> 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 {
|
||||
|
Loading…
Reference in New Issue
Block a user