summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/lli
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/lli')
-rw-r--r--contrib/llvm/tools/lli/OrcLazyJIT.cpp153
-rw-r--r--contrib/llvm/tools/lli/OrcLazyJIT.h165
-rw-r--r--contrib/llvm/tools/lli/RemoteMemoryManager.cpp1
-rw-r--r--contrib/llvm/tools/lli/RemoteMemoryManager.h2
-rw-r--r--contrib/llvm/tools/lli/RemoteTargetExternal.h2
-rw-r--r--contrib/llvm/tools/lli/lli.cpp82
6 files changed, 362 insertions, 43 deletions
diff --git a/contrib/llvm/tools/lli/OrcLazyJIT.cpp b/contrib/llvm/tools/lli/OrcLazyJIT.cpp
new file mode 100644
index 0000000..ae276e6
--- /dev/null
+++ b/contrib/llvm/tools/lli/OrcLazyJIT.cpp
@@ -0,0 +1,153 @@
+//===------ OrcLazyJIT.cpp - Basic Orc-based JIT for lazy execution -------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "OrcLazyJIT.h"
+#include "llvm/ExecutionEngine/Orc/OrcTargetSupport.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/DynamicLibrary.h"
+#include <cstdio>
+#include <system_error>
+
+using namespace llvm;
+
+namespace {
+
+ enum class DumpKind { NoDump, DumpFuncsToStdOut, 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::DumpFuncsToStdOut,
+ "funcs-to-stdout",
+ "Dump function names to stdout."),
+ 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<IRDumpLayerT,
+ orc::OrcX86_64> CCMgrT;
+ return [](IRDumpLayerT &IRDumpLayer, RuntimeDyld::MemoryManager &MemMgr,
+ LLVMContext &Context) {
+ return llvm::make_unique<CCMgrT>(IRDumpLayer, MemMgr, Context, 0,
+ 64);
+ };
+ }
+ }
+}
+
+OrcLazyJIT::TransformFtor OrcLazyJIT::createDebugDumper() {
+
+ switch (OrcDumpKind) {
+ case DumpKind::NoDump:
+ return [](std::unique_ptr<Module> M) { return M; };
+
+ case DumpKind::DumpFuncsToStdOut:
+ return [](std::unique_ptr<Module> M) {
+ printf("[ ");
+
+ for (const auto &F : *M) {
+ if (F.isDeclaration())
+ continue;
+
+ if (F.hasName()) {
+ std::string Name(F.getName());
+ printf("%s ", Name.c_str());
+ } else
+ printf("<anon> ");
+ }
+
+ printf("]\n");
+ return M;
+ };
+
+ case DumpKind::DumpModsToStdErr:
+ return [](std::unique_ptr<Module> M) {
+ dbgs() << "----- Module Start -----\n" << *M
+ << "----- Module End -----\n";
+
+ return 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 M;
+ };
+ }
+ llvm_unreachable("Unknown DumpKind");
+}
+
+// Defined in lli.cpp.
+CodeGenOpt::Level getOptLevel();
+
+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)) {
+ errs() << "Error loading program symbols.\n";
+ return 1;
+ }
+
+ // Grab a target machine and try to build a factory function for the
+ // target-specific Orc callback manager.
+ EngineBuilder EB;
+ EB.setOptLevel(getOptLevel());
+ auto TM = std::unique_ptr<TargetMachine>(EB.selectTarget());
+ auto &Context = getGlobalContext();
+ auto CallbackMgrBuilder =
+ OrcLazyJIT::createCallbackManagerBuilder(Triple(TM->getTargetTriple()));
+
+ // If we couldn't build the factory function then there must not be a callback
+ // manager for this target. Bail out.
+ if (!CallbackMgrBuilder) {
+ errs() << "No callback manager available for target '"
+ << TM->getTargetTriple().str() << "'.\n";
+ return 1;
+ }
+
+ // Everything looks good. Build the JIT.
+ OrcLazyJIT J(std::move(TM), Context, CallbackMgrBuilder);
+
+ // Add the module, look up main and run it.
+ auto MainHandle = J.addModule(std::move(M));
+ auto MainSym = J.findSymbolIn(MainHandle, "main");
+
+ if (!MainSym) {
+ errs() << "Could not find main function.\n";
+ return 1;
+ }
+
+ typedef int (*MainFnPtr)(int, char*[]);
+ auto Main = OrcLazyJIT::fromTargetAddress<MainFnPtr>(MainSym.getAddress());
+ return Main(ArgC, ArgV);
+}
diff --git a/contrib/llvm/tools/lli/OrcLazyJIT.h b/contrib/llvm/tools/lli/OrcLazyJIT.h
new file mode 100644
index 0000000..9257225
--- /dev/null
+++ b/contrib/llvm/tools/lli/OrcLazyJIT.h
@@ -0,0 +1,165 @@
+//===--- OrcLazyJIT.h - Basic Orc-based JIT for lazy execution --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Simple Orc-based JIT. Uses the compile-on-demand layer to break up and
+// lazily compile modules.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLI_ORCLAZYJIT_H
+#define LLVM_TOOLS_LLI_ORCLAZYJIT_H
+
+#include "llvm/ADT/Triple.h"
+#include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h"
+#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/ObjectLinkingLayer.h"
+#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
+#include "llvm/IR/LLVMContext.h"
+
+namespace llvm {
+
+class OrcLazyJIT {
+public:
+
+ typedef orc::JITCompileCallbackManagerBase CompileCallbackMgr;
+ typedef orc::ObjectLinkingLayer<> ObjLayerT;
+ typedef orc::IRCompileLayer<ObjLayerT> CompileLayerT;
+ typedef std::function<std::unique_ptr<Module>(std::unique_ptr<Module>)>
+ TransformFtor;
+ typedef orc::IRTransformLayer<CompileLayerT, TransformFtor> IRDumpLayerT;
+ typedef orc::CompileOnDemandLayer<IRDumpLayerT, CompileCallbackMgr> CODLayerT;
+ typedef CODLayerT::ModuleSetHandleT ModuleHandleT;
+
+ typedef std::function<
+ std::unique_ptr<CompileCallbackMgr>(IRDumpLayerT&,
+ RuntimeDyld::MemoryManager&,
+ LLVMContext&)>
+ CallbackManagerBuilder;
+
+ static CallbackManagerBuilder createCallbackManagerBuilder(Triple T);
+
+ OrcLazyJIT(std::unique_ptr<TargetMachine> TM, LLVMContext &Context,
+ CallbackManagerBuilder &BuildCallbackMgr)
+ : TM(std::move(TM)),
+ Mang(this->TM->getDataLayout()),
+ ObjectLayer(),
+ CompileLayer(ObjectLayer, orc::SimpleCompiler(*this->TM)),
+ IRDumpLayer(CompileLayer, createDebugDumper()),
+ CCMgr(BuildCallbackMgr(IRDumpLayer, CCMgrMemMgr, Context)),
+ CODLayer(IRDumpLayer, *CCMgr, false),
+ CXXRuntimeOverrides([this](const std::string &S) { return mangle(S); }) {}
+
+ ~OrcLazyJIT() {
+ // Run any destructors registered with __cxa_atexit.
+ CXXRuntimeOverrides.runDestructors();
+ // Run any IR destructors.
+ for (auto &DtorRunner : IRStaticDestructorRunners)
+ DtorRunner.runViaLayer(CODLayer);
+ }
+
+ template <typename PtrTy>
+ static PtrTy fromTargetAddress(orc::TargetAddress Addr) {
+ return reinterpret_cast<PtrTy>(static_cast<uintptr_t>(Addr));
+ }
+
+ ModuleHandleT addModule(std::unique_ptr<Module> M) {
+ // Attach a data-layout if one isn't already present.
+ if (M->getDataLayout().isDefault())
+ M->setDataLayout(*TM->getDataLayout());
+
+ // Record the static constructors and destructors. We have to do this before
+ // we hand over ownership of the module to the JIT.
+ std::vector<std::string> 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()));
+
+ // Symbol resolution order:
+ // 1) Search the JIT symbols.
+ // 2) Check for C++ runtime overrides.
+ // 3) Search the host process (LLI)'s symbol table.
+ std::shared_ptr<RuntimeDyld::SymbolResolver> Resolver =
+ orc::createLambdaResolver(
+ [this](const std::string &Name) {
+ if (auto Sym = CODLayer.findSymbol(Name, true))
+ return RuntimeDyld::SymbolInfo(Sym.getAddress(),
+ Sym.getFlags());
+ if (auto Sym = CXXRuntimeOverrides.searchOverrides(Name))
+ return Sym;
+
+ if (auto Addr =
+ RTDyldMemoryManager::getSymbolAddressInProcess(Name))
+ return RuntimeDyld::SymbolInfo(Addr, JITSymbolFlags::Exported);
+
+ return RuntimeDyld::SymbolInfo(nullptr);
+ },
+ [](const std::string &Name) {
+ return RuntimeDyld::SymbolInfo(nullptr);
+ }
+ );
+
+ // Add the module to the JIT.
+ std::vector<std::unique_ptr<Module>> S;
+ S.push_back(std::move(M));
+ auto H = CODLayer.addModuleSet(std::move(S), nullptr, std::move(Resolver));
+
+ // Run the static constructors, and save the static destructor runner for
+ // execution when the JIT is torn down.
+ orc::CtorDtorRunner<CODLayerT> CtorRunner(std::move(CtorNames), H);
+ CtorRunner.runViaLayer(CODLayer);
+
+ IRStaticDestructorRunners.emplace_back(std::move(DtorNames), H);
+
+ return H;
+ }
+
+ orc::JITSymbol findSymbol(const std::string &Name) {
+ return CODLayer.findSymbol(mangle(Name), true);
+ }
+
+ orc::JITSymbol findSymbolIn(ModuleHandleT H, const std::string &Name) {
+ return CODLayer.findSymbolIn(H, mangle(Name), true);
+ }
+
+private:
+
+ std::string mangle(const std::string &Name) {
+ std::string MangledName;
+ {
+ raw_string_ostream MangledNameStream(MangledName);
+ Mang.getNameWithPrefix(MangledNameStream, Name);
+ }
+ return MangledName;
+ }
+
+ static TransformFtor createDebugDumper();
+
+ std::unique_ptr<TargetMachine> TM;
+ Mangler Mang;
+ SectionMemoryManager CCMgrMemMgr;
+
+ ObjLayerT ObjectLayer;
+ CompileLayerT CompileLayer;
+ IRDumpLayerT IRDumpLayer;
+ std::unique_ptr<CompileCallbackMgr> CCMgr;
+ CODLayerT CODLayer;
+
+ orc::LocalCXXRuntimeOverrides CXXRuntimeOverrides;
+ std::vector<orc::CtorDtorRunner<CODLayerT>> IRStaticDestructorRunners;
+};
+
+int runOrcLazyJIT(std::unique_ptr<Module> M, int ArgC, char* ArgV[]);
+
+} // end namespace llvm
+
+#endif
diff --git a/contrib/llvm/tools/lli/RemoteMemoryManager.cpp b/contrib/llvm/tools/lli/RemoteMemoryManager.cpp
index 47da8fb..0a16210 100644
--- a/contrib/llvm/tools/lli/RemoteMemoryManager.cpp
+++ b/contrib/llvm/tools/lli/RemoteMemoryManager.cpp
@@ -16,6 +16,7 @@
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
using namespace llvm;
diff --git a/contrib/llvm/tools/lli/RemoteMemoryManager.h b/contrib/llvm/tools/lli/RemoteMemoryManager.h
index 895bcda..5733fa5 100644
--- a/contrib/llvm/tools/lli/RemoteMemoryManager.h
+++ b/contrib/llvm/tools/lli/RemoteMemoryManager.h
@@ -64,7 +64,7 @@ private:
public:
RemoteMemoryManager() : Target(nullptr) {}
- virtual ~RemoteMemoryManager();
+ ~RemoteMemoryManager() override;
uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
unsigned SectionID,
diff --git a/contrib/llvm/tools/lli/RemoteTargetExternal.h b/contrib/llvm/tools/lli/RemoteTargetExternal.h
index bb621f5..afe8570 100644
--- a/contrib/llvm/tools/lli/RemoteTargetExternal.h
+++ b/contrib/llvm/tools/lli/RemoteTargetExternal.h
@@ -106,7 +106,7 @@ public:
void stop() override;
RemoteTargetExternal(std::string &Name) : RemoteTarget(), ChildName(Name) {}
- virtual ~RemoteTargetExternal() {}
+ ~RemoteTargetExternal() override {}
private:
std::string ChildName;
diff --git a/contrib/llvm/tools/lli/lli.cpp b/contrib/llvm/tools/lli/lli.cpp
index 730911b..057841f 100644
--- a/contrib/llvm/tools/lli/lli.cpp
+++ b/contrib/llvm/tools/lli/lli.cpp
@@ -14,6 +14,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/IR/LLVMContext.h"
+#include "OrcLazyJIT.h"
#include "RemoteMemoryManager.h"
#include "RemoteTarget.h"
#include "RemoteTargetExternal.h"
@@ -25,6 +26,7 @@
#include "llvm/ExecutionEngine/JITEventListener.h"
#include "llvm/ExecutionEngine/MCJIT.h"
#include "llvm/ExecutionEngine/ObjectCache.h"
+#include "llvm/ExecutionEngine/OrcMCJITReplacement.h"
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Module.h"
@@ -41,6 +43,7 @@
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/Memory.h"
#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
#include "llvm/Support/PluginLoader.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Process.h"
@@ -64,6 +67,9 @@ using namespace llvm;
#define DEBUG_TYPE "lli"
namespace {
+
+ enum class JITKind { MCJIT, OrcMCJITReplacement, OrcLazy };
+
cl::opt<std::string>
InputFile(cl::desc("<input bitcode>"), cl::Positional, cl::init("-"));
@@ -74,6 +80,20 @@ namespace {
cl::desc("Force interpretation: disable JIT"),
cl::init(false));
+ cl::opt<JITKind> UseJITKind("jit-kind",
+ cl::desc("Choose underlying JIT kind."),
+ cl::init(JITKind::MCJIT),
+ cl::values(
+ clEnumValN(JITKind::MCJIT, "mcjit",
+ "MCJIT"),
+ clEnumValN(JITKind::OrcMCJITReplacement,
+ "orc-mcjit",
+ "Orc-based MCJIT replacement"),
+ clEnumValN(JITKind::OrcLazy,
+ "orc-lazy",
+ "Orc-based lazy JIT."),
+ clEnumValEnd));
+
// The MCJIT supports building for a target address space separate from
// the JIT compilation process. Use a forked process and a copying
// memory manager with IPC to execute using this functionality.
@@ -215,23 +235,6 @@ namespace {
clEnumValN(FloatABI::Hard, "hard",
"Hard float ABI (uses FP registers)"),
clEnumValEnd));
- cl::opt<bool>
-// In debug builds, make this default to true.
-#ifdef NDEBUG
-#define EMIT_DEBUG false
-#else
-#define EMIT_DEBUG true
-#endif
- EmitJitDebugInfo("jit-emit-debug",
- cl::desc("Emit debug information to debugger"),
- cl::init(EMIT_DEBUG));
-#undef EMIT_DEBUG
-
- static cl::opt<bool>
- EmitJitDebugInfoToDisk("jit-emit-debug-to-disk",
- cl::Hidden,
- cl::desc("Emit debug info objfiles to disk"),
- cl::init(false));
}
//===----------------------------------------------------------------------===//
@@ -251,7 +254,7 @@ public:
this->CacheDir[this->CacheDir.size() - 1] != '/')
this->CacheDir += '/';
}
- virtual ~LLIObjectCache() {}
+ ~LLIObjectCache() override {}
void notifyObjectCompiled(const Module *M, MemoryBufferRef Obj) override {
const std::string ModuleID = M->getModuleIdentifier();
@@ -362,6 +365,19 @@ static void addCygMingExtraModule(ExecutionEngine *EE,
EE->addModule(std::move(M));
}
+CodeGenOpt::Level getOptLevel() {
+ switch (OptLevel) {
+ default:
+ errs() << "lli: Invalid optimization level.\n";
+ exit(1);
+ case '0': return CodeGenOpt::None;
+ case '1': return CodeGenOpt::Less;
+ case ' ':
+ case '2': return CodeGenOpt::Default;
+ case '3': return CodeGenOpt::Aggressive;
+ }
+ llvm_unreachable("Unrecognized opt level.");
+}
//===----------------------------------------------------------------------===//
// main Driver function
@@ -395,6 +411,9 @@ int main(int argc, char **argv, char * const *envp) {
return 1;
}
+ if (UseJITKind == JITKind::OrcLazy)
+ return runOrcLazyJIT(std::move(Owner), argc, argv);
+
if (EnableCacheManager) {
std::string CacheName("file:");
CacheName.append(InputFile);
@@ -421,6 +440,7 @@ int main(int argc, char **argv, char * const *envp) {
builder.setEngineKind(ForceInterpreter
? EngineKind::Interpreter
: EngineKind::JIT);
+ builder.setUseOrcMCJITReplacement(UseJITKind == JITKind::OrcMCJITReplacement);
// If we are supposed to override the target triple, do so now.
if (!TargetTriple.empty())
@@ -444,31 +464,11 @@ int main(int argc, char **argv, char * const *envp) {
exit(1);
}
- CodeGenOpt::Level OLvl = CodeGenOpt::Default;
- switch (OptLevel) {
- default:
- errs() << argv[0] << ": invalid optimization level.\n";
- return 1;
- case ' ': break;
- case '0': OLvl = CodeGenOpt::None; break;
- case '1': OLvl = CodeGenOpt::Less; break;
- case '2': OLvl = CodeGenOpt::Default; break;
- case '3': OLvl = CodeGenOpt::Aggressive; break;
- }
- builder.setOptLevel(OLvl);
+ builder.setOptLevel(getOptLevel());
TargetOptions Options;
- Options.UseSoftFloat = GenerateSoftFloatCalls;
if (FloatABIForCalls != FloatABI::Default)
Options.FloatABIType = FloatABIForCalls;
- if (GenerateSoftFloatCalls)
- FloatABIForCalls = FloatABI::Soft;
-
- // Remote target execution doesn't handle EH or debug registration.
- if (!RemoteMCJIT) {
- Options.JITEmitDebugInfo = EmitJitDebugInfo;
- Options.JITEmitDebugInfoToDisk = EmitJitDebugInfoToDisk;
- }
builder.setTargetOptions(Options);
@@ -556,7 +556,7 @@ int main(int argc, char **argv, char * const *envp) {
// If the user specifically requested an argv[0] to pass into the program,
// do it now.
if (!FakeArgv0.empty()) {
- InputFile = FakeArgv0;
+ InputFile = static_cast<std::string>(FakeArgv0);
} else {
// Otherwise, if there is a .bc suffix on the executable strip it off, it
// might confuse the program.
@@ -588,7 +588,7 @@ int main(int argc, char **argv, char * const *envp) {
// function later on to make an explicit call, so get the function now.
Constant *Exit = Mod->getOrInsertFunction("exit", Type::getVoidTy(Context),
Type::getInt32Ty(Context),
- NULL);
+ nullptr);
// Run static constructors.
if (!ForceInterpreter) {
OpenPOWER on IntegriCloud