[Orc] Add an Orc layer for applying arbitrary transforms to IR, use it to add

debugging output to the LLI orc-lazy JIT, and update the orc-lazy "hello.ll"
test to actually test for lazy compilation.

llvm-svn: 234805
This commit is contained in:
Lang Hames 2015-04-13 22:12:54 +00:00
parent 3e1d483e0e
commit cd3fd83c3a
4 changed files with 194 additions and 9 deletions

View File

@ -0,0 +1,101 @@
//===----- IRTransformLayer.h - Run all IR through a functor ----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Run all IR passed in through a user supplied functor.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_EXECUTIONENGINE_ORC_IRTRANSFORMLAYER_H
#define LLVM_EXECUTIONENGINE_ORC_IRTRANSFORMLAYER_H
#include "JITSymbol.h"
namespace llvm {
namespace orc {
/// @brief IR mutating layer.
///
/// This layer accepts sets of LLVM IR Modules (via addModuleSet). It
/// immediately applies the user supplied functor to each module, then adds
/// the set of transformed modules to the layer below.
template <typename BaseLayerT, typename TransformFtor>
class IRTransformLayer {
public:
/// @brief Handle to a set of added modules.
typedef typename BaseLayerT::ModuleSetHandleT ModuleSetHandleT;
/// @brief Construct an IRTransformLayer with the given BaseLayer
IRTransformLayer(BaseLayerT &BaseLayer,
TransformFtor Transform = TransformFtor())
: BaseLayer(BaseLayer), Transform(std::move(Transform)) {}
/// @brief Apply the transform functor to each module in the module set, then
/// add the resulting set of modules to the base layer, along with the
/// memory manager and symbol resolver.
///
/// @return A handle for the added modules.
template <typename ModuleSetT, typename MemoryManagerPtrT,
typename SymbolResolverPtrT>
ModuleSetHandleT addModuleSet(ModuleSetT Ms,
MemoryManagerPtrT MemMgr,
SymbolResolverPtrT Resolver) {
for (auto I = Ms.begin(), E = Ms.end(); I != E; ++I)
*I = Transform(std::move(*I));
return BaseLayer.addModuleSet(std::move(Ms), std::move(MemMgr),
std::move(Resolver));
}
/// @brief Remove the module set associated with the handle H.
void removeModuleSet(ModuleSetHandleT H) { BaseLayer.removeModuleSet(H); }
/// @brief Search for the given named symbol.
/// @param Name The name of the symbol to search for.
/// @param ExportedSymbolsOnly If true, search only for exported symbols.
/// @return A handle for the given named symbol, if it exists.
JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
return BaseLayer.findSymbol(Name, ExportedSymbolsOnly);
}
/// @brief Get the address of the given symbol in the context of the set of
/// modules represented by the handle H. This call is forwarded to the
/// base layer's implementation.
/// @param H The handle for the module set to search in.
/// @param Name The name of the symbol to search for.
/// @param ExportedSymbolsOnly If true, search only for exported symbols.
/// @return A handle for the given named symbol, if it is found in the
/// given module set.
JITSymbol findSymbolIn(ModuleSetHandleT H, const std::string &Name,
bool ExportedSymbolsOnly) {
return BaseLayer.findSymbolIn(H, Name, ExportedSymbolsOnly);
}
/// @brief Immediately emit and finalize the module set represented by the
/// given handle.
/// @param H Handle for module set to emit/finalize.
void emitAndFinalize(ModuleSetHandleT H) {
BaseLayer.emitAndFinalize(H);
}
/// @brief Access the transform functor directly.
TransformFtor& getTransform() { return Transform; }
/// @brief Access the mumate functor directly.
const TransformFtor& getTransform() const { return Transform; }
private:
BaseLayerT &BaseLayer;
TransformFtor Transform;
};
} // End namespace orc.
} // End namespace llvm.
#endif // LLVM_EXECUTIONENGINE_ORC_IRTRANSFORMLAYER_H

View File

@ -1,7 +1,8 @@
; RUN: lli -jit-kind=orc-lazy %s | FileCheck %s
; RUN: lli -jit-kind=orc-lazy -orc-lazy-debug=funcs-to-stderr %s | FileCheck %s
;
; CHECK: Hello
; CHECK-NEXT: Goodbye
; CHECK: [ main$orc_body ]
; CHECK: Goodbye
%class.Foo = type { i8 }

View File

@ -9,26 +9,101 @@
#include "OrcLazyJIT.h"
#include "llvm/ExecutionEngine/Orc/OrcTargetSupport.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/DynamicLibrary.h"
#include <system_error>
using namespace llvm;
namespace {
enum class DumpKind { NoDump, DumpFuncsToStdErr, DumpModsToStdErr,
DumpModsToDisk };
cl::opt<DumpKind> OrcDumpKind("orc-lazy-debug",
cl::desc("Debug dumping for the orc-lazy JIT."),
cl::init(DumpKind::NoDump),
cl::values(
clEnumValN(DumpKind::NoDump, "no-dump",
"Don't dump anything."),
clEnumValN(DumpKind::DumpFuncsToStdErr,
"funcs-to-stderr",
"Dump function names to stderr."),
clEnumValN(DumpKind::DumpModsToStdErr,
"mods-to-stderr",
"Dump modules to stderr."),
clEnumValN(DumpKind::DumpModsToDisk,
"mods-to-disk",
"Dump modules to the current "
"working directory. (WARNING: "
"will overwrite existing files)."),
clEnumValEnd));
}
OrcLazyJIT::CallbackManagerBuilder
OrcLazyJIT::createCallbackManagerBuilder(Triple T) {
switch (T.getArch()) {
default: return nullptr;
case Triple::x86_64: {
typedef orc::JITCompileCallbackManager<CompileLayerT,
typedef orc::JITCompileCallbackManager<IRDumpLayerT,
orc::OrcX86_64> CCMgrT;
return [](CompileLayerT &CompileLayer, RuntimeDyld::MemoryManager &MemMgr,
return [](IRDumpLayerT &IRDumpLayer, RuntimeDyld::MemoryManager &MemMgr,
LLVMContext &Context) {
return make_unique<CCMgrT>(CompileLayer, MemMgr, Context, 0, 64);
return make_unique<CCMgrT>(IRDumpLayer, MemMgr, Context, 0, 64);
};
}
}
}
OrcLazyJIT::TransformFtor OrcLazyJIT::createDebugDumper() {
switch (OrcDumpKind) {
case DumpKind::NoDump:
return [](std::unique_ptr<Module> M) { return std::move(M); };
case DumpKind::DumpFuncsToStdErr:
return [](std::unique_ptr<Module> M) {
dbgs() << "[ ";
for (const auto &F : *M) {
if (F.isDeclaration())
continue;
if (F.hasName())
dbgs() << F.getName() << " ";
else
dbgs() << "<anon> ";
}
dbgs() << "]\n";
return std::move(M);
};
case DumpKind::DumpModsToStdErr:
return [](std::unique_ptr<Module> M) {
dbgs() << "----- Module Start -----\n" << *M
<< "----- Module End -----\n";
return std::move(M);
};
case DumpKind::DumpModsToDisk:
return [](std::unique_ptr<Module> M) {
std::error_code EC;
raw_fd_ostream Out(M->getModuleIdentifier() + ".ll", EC,
sys::fs::F_Text);
if (EC) {
errs() << "Couldn't open " << M->getModuleIdentifier()
<< " for dumping.\nError:" << EC.message() << "\n";
exit(1);
}
Out << *M;
return std::move(M);
};
}
}
int llvm::runOrcLazyJIT(std::unique_ptr<Module> M, int ArgC, char* ArgV[]) {
// Add the program's symbols into the JIT's search space.
if (sys::DynamicLibrary::LoadLibraryPermanently(nullptr)) {

View File

@ -20,6 +20,7 @@
#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
#include "llvm/ExecutionEngine/Orc/IRTransformLayer.h"
#include "llvm/ExecutionEngine/Orc/LazyEmittingLayer.h"
#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
@ -33,13 +34,16 @@ public:
typedef orc::JITCompileCallbackManagerBase CompileCallbackMgr;
typedef orc::ObjectLinkingLayer<> ObjLayerT;
typedef orc::IRCompileLayer<ObjLayerT> CompileLayerT;
typedef orc::LazyEmittingLayer<CompileLayerT> LazyEmitLayerT;
typedef std::function<std::unique_ptr<Module>(std::unique_ptr<Module>)>
TransformFtor;
typedef orc::IRTransformLayer<CompileLayerT, TransformFtor> IRDumpLayerT;
typedef orc::LazyEmittingLayer<IRDumpLayerT> LazyEmitLayerT;
typedef orc::CompileOnDemandLayer<LazyEmitLayerT,
CompileCallbackMgr> CODLayerT;
typedef CODLayerT::ModuleSetHandleT ModuleHandleT;
typedef std::function<
std::unique_ptr<CompileCallbackMgr>(CompileLayerT&,
std::unique_ptr<CompileCallbackMgr>(IRDumpLayerT&,
RuntimeDyld::MemoryManager&,
LLVMContext&)>
CallbackManagerBuilder;
@ -52,8 +56,9 @@ public:
Mang(this->TM->getDataLayout()),
ObjectLayer(),
CompileLayer(ObjectLayer, orc::SimpleCompiler(*this->TM)),
LazyEmitLayer(CompileLayer),
CCMgr(BuildCallbackMgr(CompileLayer, CCMgrMemMgr, Context)),
IRDumpLayer(CompileLayer, createDebugDumper()),
LazyEmitLayer(IRDumpLayer),
CCMgr(BuildCallbackMgr(IRDumpLayer, CCMgrMemMgr, Context)),
CODLayer(LazyEmitLayer, *CCMgr),
CXXRuntimeOverrides([this](const std::string &S) { return mangle(S); }) {}
@ -137,12 +142,15 @@ private:
return MangledName;
}
static TransformFtor createDebugDumper();
std::unique_ptr<TargetMachine> TM;
Mangler Mang;
SectionMemoryManager CCMgrMemMgr;
ObjLayerT ObjectLayer;
CompileLayerT CompileLayer;
IRDumpLayerT IRDumpLayer;
LazyEmitLayerT LazyEmitLayer;
std::unique_ptr<CompileCallbackMgr> CCMgr;
CODLayerT CODLayer;