aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm/tools/lli/lli.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/lli/lli.cpp')
-rw-r--r--contrib/llvm/tools/lli/lli.cpp219
1 files changed, 190 insertions, 29 deletions
diff --git a/contrib/llvm/tools/lli/lli.cpp b/contrib/llvm/tools/lli/lli.cpp
index a33c51d77877..1940dbd848cc 100644
--- a/contrib/llvm/tools/lli/lli.cpp
+++ b/contrib/llvm/tools/lli/lli.cpp
@@ -13,18 +13,20 @@
//
//===----------------------------------------------------------------------===//
-#include "OrcLazyJIT.h"
#include "RemoteJITUtils.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Bitcode/BitcodeReader.h"
-#include "llvm/CodeGen/CommandFlags.def"
+#include "llvm/CodeGen/CommandFlags.inc"
#include "llvm/CodeGen/LinkAllCodegenComponents.h"
+#include "llvm/Config/llvm-config.h"
#include "llvm/ExecutionEngine/GenericValue.h"
#include "llvm/ExecutionEngine/Interpreter.h"
#include "llvm/ExecutionEngine/JITEventListener.h"
#include "llvm/ExecutionEngine/MCJIT.h"
#include "llvm/ExecutionEngine/ObjectCache.h"
+#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
+#include "llvm/ExecutionEngine/Orc/LLJIT.h"
#include "llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h"
#include "llvm/ExecutionEngine/OrcMCJITReplacement.h"
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
@@ -33,6 +35,7 @@
#include "llvm/IR/Module.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/TypeBuilder.h"
+#include "llvm/IR/Verifier.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/ObjectFile.h"
@@ -40,18 +43,18 @@
#include "llvm/Support/Debug.h"
#include "llvm/Support/DynamicLibrary.h"
#include "llvm/Support/Format.h"
+#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/ManagedStatic.h"
#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"
#include "llvm/Support/Program.h"
-#include "llvm/Support/Signals.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TargetSelect.h"
+#include "llvm/Support/WithColor.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Instrumentation.h"
#include <cerrno>
@@ -176,6 +179,28 @@ namespace {
cl::desc("Generate software floating point library calls"),
cl::init(false));
+ enum class DumpKind {
+ NoDump,
+ DumpFuncsToStdOut,
+ DumpModsToStdOut,
+ 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::DumpModsToStdOut, "mods-to-stdout",
+ "Dump modules to stdout."),
+ clEnumValN(DumpKind::DumpModsToDisk, "mods-to-disk",
+ "Dump modules to the current "
+ "working directory. (WARNING: "
+ "will overwrite existing files).")),
+ cl::Hidden);
+
ExitOnError ExitOnErr;
}
@@ -295,7 +320,7 @@ static void addCygMingExtraModule(ExecutionEngine &EE, LLVMContext &Context,
CodeGenOpt::Level getOptLevel() {
switch (OptLevel) {
default:
- errs() << "lli: Invalid optimization level.\n";
+ WithColor::error(errs(), "lli") << "invalid optimization level.\n";
exit(1);
case '0': return CodeGenOpt::None;
case '1': return CodeGenOpt::Less;
@@ -312,14 +337,14 @@ static void reportError(SMDiagnostic Err, const char *ProgName) {
exit(1);
}
+int runOrcLazyJIT(LLVMContext &Ctx, std::vector<std::unique_ptr<Module>> Ms,
+ const std::vector<std::string> &Args);
+
//===----------------------------------------------------------------------===//
// main Driver function
//
int main(int argc, char **argv, char * const *envp) {
- sys::PrintStackTraceOnErrorSignal(argv[0]);
- PrettyStackTraceProgram X(argc, argv);
-
- atexit(llvm_shutdown); // Call llvm_shutdown() on exit.
+ InitLLVM X(argc, argv);
if (argc > 1)
ExitOnErr.setBanner(std::string(argv[0]) + ": ");
@@ -358,7 +383,7 @@ int main(int argc, char **argv, char * const *envp) {
Args.push_back(InputFile);
for (auto &Arg : InputArgv)
Args.push_back(Arg);
- return runOrcLazyJIT(std::move(Ms), Args);
+ return runOrcLazyJIT(Context, std::move(Ms), Args);
}
if (EnableCacheManager) {
@@ -378,8 +403,8 @@ int main(int argc, char **argv, char * const *envp) {
std::string ErrorMsg;
EngineBuilder builder(std::move(Owner));
builder.setMArch(MArch);
- builder.setMCPU(MCPU);
- builder.setMAttrs(MAttrs);
+ builder.setMCPU(getCPUStr());
+ builder.setMAttrs(getFeatureList());
if (RelocModel.getNumOccurrences())
builder.setRelocationModel(RelocModel);
if (CMModel.getNumOccurrences())
@@ -407,8 +432,8 @@ int main(int argc, char **argv, char * const *envp) {
builder.setMCJITMemoryManager(
std::unique_ptr<RTDyldMemoryManager>(RTDyldMM));
} else if (RemoteMCJIT) {
- errs() << "error: Remote process execution does not work with the "
- "interpreter.\n";
+ WithColor::error(errs(), argv[0])
+ << "remote process execution does not work with the interpreter.\n";
exit(1);
}
@@ -423,9 +448,10 @@ int main(int argc, char **argv, char * const *envp) {
std::unique_ptr<ExecutionEngine> EE(builder.create());
if (!EE) {
if (!ErrorMsg.empty())
- errs() << argv[0] << ": error creating EE: " << ErrorMsg << "\n";
+ WithColor::error(errs(), argv[0])
+ << "error creating EE: " << ErrorMsg << "\n";
else
- errs() << argv[0] << ": unknown error creating EE!\n";
+ WithColor::error(errs(), argv[0]) << "unknown error creating EE!\n";
exit(1);
}
@@ -496,9 +522,13 @@ int main(int argc, char **argv, char * const *envp) {
JITEventListener::createOProfileJITEventListener());
EE->RegisterJITEventListener(
JITEventListener::createIntelJITEventListener());
+ if (!RemoteMCJIT)
+ EE->RegisterJITEventListener(
+ JITEventListener::createPerfJITEventListener());
if (!NoLazyCompilation && RemoteMCJIT) {
- errs() << "warning: remote mcjit does not support lazy compilation\n";
+ WithColor::warning(errs(), argv[0])
+ << "remote mcjit does not support lazy compilation\n";
NoLazyCompilation = true;
}
EE->DisableLazyCompilation(NoLazyCompilation);
@@ -524,7 +554,8 @@ int main(int argc, char **argv, char * const *envp) {
//
Function *EntryFn = Mod->getFunction(EntryFunc);
if (!EntryFn) {
- errs() << '\'' << EntryFunc << "\' function not found in module.\n";
+ WithColor::error(errs(), argv[0])
+ << '\'' << EntryFunc << "\' function not found in module.\n";
return -1;
}
@@ -537,16 +568,19 @@ int main(int argc, char **argv, char * const *envp) {
// remote JIT on Unix platforms.
if (RemoteMCJIT) {
#ifndef LLVM_ON_UNIX
- errs() << "Warning: host does not support external remote targets.\n"
- << " Defaulting to local execution\n";
+ WithColor::warning(errs(), argv[0])
+ << "host does not support external remote targets.\n";
+ WithColor::note() << "defaulting to local execution\n";
return -1;
#else
if (ChildExecPath.empty()) {
- errs() << "-remote-mcjit requires -mcjit-remote-process.\n";
+ WithColor::error(errs(), argv[0])
+ << "-remote-mcjit requires -mcjit-remote-process.\n";
exit(1);
} else if (!sys::fs::can_execute(ChildExecPath)) {
- errs() << "Unable to find usable child executable: '" << ChildExecPath
- << "'\n";
+ WithColor::error(errs(), argv[0])
+ << "unable to find usable child executable: '" << ChildExecPath
+ << "'\n";
return -1;
}
#endif
@@ -586,10 +620,11 @@ int main(int argc, char **argv, char * const *envp) {
ResultGV.IntVal = APInt(32, Result);
Args.push_back(ResultGV);
EE->runFunction(ExitF, Args);
- errs() << "ERROR: exit(" << Result << ") returned!\n";
+ WithColor::error(errs(), argv[0]) << "exit(" << Result << ") returned!\n";
abort();
} else {
- errs() << "ERROR: exit defined with wrong prototype!\n";
+ WithColor::error(errs(), argv[0])
+ << "exit defined with wrong prototype!\n";
abort();
}
} else {
@@ -602,13 +637,15 @@ int main(int argc, char **argv, char * const *envp) {
// Lanch the remote process and get a channel to it.
std::unique_ptr<FDRawChannel> C = launchRemote();
if (!C) {
- errs() << "Failed to launch remote JIT.\n";
+ WithColor::error(errs(), argv[0]) << "failed to launch remote JIT.\n";
exit(1);
}
// Create a remote target client running over the channel.
+ llvm::orc::ExecutionSession ES;
+ ES.setErrorReporter([&](Error Err) { ExitOnErr(std::move(Err)); });
typedef orc::remote::OrcRemoteTargetClient MyRemote;
- auto R = ExitOnErr(MyRemote::Create(*C, ExitOnErr));
+ auto R = ExitOnErr(MyRemote::Create(*C, ES));
// Create a remote memory manager.
auto RemoteMM = ExitOnErr(R->createRemoteMemoryManager());
@@ -632,8 +669,8 @@ int main(int argc, char **argv, char * const *envp) {
// FIXME: argv and envp handling.
JITTargetAddress Entry = EE->getFunctionAddress(EntryFn->getName().str());
EE->finalizeObject();
- DEBUG(dbgs() << "Executing '" << EntryFn->getName() << "' at 0x"
- << format("%llx", Entry) << "\n");
+ LLVM_DEBUG(dbgs() << "Executing '" << EntryFn->getName() << "' at 0x"
+ << format("%llx", Entry) << "\n");
Result = ExitOnErr(R->callIntVoid(Entry));
// Like static constructors, the remote target MCJIT support doesn't handle
@@ -651,6 +688,130 @@ int main(int argc, char **argv, char * const *envp) {
return Result;
}
+static orc::IRTransformLayer2::TransformFunction 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::DumpModsToStdOut:
+ return [](std::unique_ptr<Module> M) {
+ outs() << "----- 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");
+}
+
+int runOrcLazyJIT(LLVMContext &Ctx, std::vector<std::unique_ptr<Module>> Ms,
+ const std::vector<std::string> &Args) {
+ // Bail out early if no modules loaded.
+ if (Ms.empty())
+ return 0;
+
+ // Add lli's symbols into the JIT's search space.
+ std::string ErrMsg;
+ sys::DynamicLibrary LibLLI =
+ sys::DynamicLibrary::getPermanentLibrary(nullptr, &ErrMsg);
+ if (!LibLLI.isValid()) {
+ errs() << "Error loading lli symbols: " << ErrMsg << ".\n";
+ return 1;
+ }
+
+ const auto &TT = Ms.front()->getTargetTriple();
+ orc::JITTargetMachineBuilder TMD =
+ TT.empty() ? ExitOnErr(orc::JITTargetMachineBuilder::detectHost())
+ : orc::JITTargetMachineBuilder(Triple(TT));
+
+ TMD.setArch(MArch)
+ .setCPU(getCPUStr())
+ .addFeatures(getFeatureList())
+ .setRelocationModel(RelocModel.getNumOccurrences()
+ ? Optional<Reloc::Model>(RelocModel)
+ : None)
+ .setCodeModel(CMModel.getNumOccurrences()
+ ? Optional<CodeModel::Model>(CMModel)
+ : None);
+ auto TM = ExitOnErr(TMD.createTargetMachine());
+ auto DL = TM->createDataLayout();
+ auto ES = llvm::make_unique<orc::ExecutionSession>();
+ auto J =
+ ExitOnErr(orc::LLLazyJIT::Create(std::move(ES), std::move(TM), DL, Ctx));
+
+ auto Dump = createDebugDumper();
+
+ J->setLazyCompileTransform(
+ [&](std::unique_ptr<Module> M) {
+ if (verifyModule(*M, &dbgs())) {
+ dbgs() << "Bad module: " << *M << "\n";
+ exit(1);
+ }
+ return Dump(std::move(M));
+ });
+ J->getMainVSO().setFallbackDefinitionGenerator(
+ orc::DynamicLibraryFallbackGenerator(
+ std::move(LibLLI), DL, [](orc::SymbolStringPtr) { return true; }));
+
+ orc::MangleAndInterner Mangle(J->getExecutionSession(), DL);
+ orc::LocalCXXRuntimeOverrides2 CXXRuntimeOverrides;
+ ExitOnErr(CXXRuntimeOverrides.enable(J->getMainVSO(), Mangle));
+
+ for (auto &M : Ms) {
+ orc::makeAllSymbolsExternallyAccessible(*M);
+ ExitOnErr(J->addLazyIRModule(std::move(M)));
+ }
+
+ ExitOnErr(J->runConstructors());
+
+ auto MainSym = ExitOnErr(J->lookup("main"));
+ typedef int (*MainFnPtr)(int, const char *[]);
+ std::vector<const char *> ArgV;
+ for (auto &Arg : Args)
+ ArgV.push_back(Arg.c_str());
+ auto Main =
+ reinterpret_cast<MainFnPtr>(static_cast<uintptr_t>(MainSym.getAddress()));
+ auto Result = Main(ArgV.size(), (const char **)ArgV.data());
+
+ ExitOnErr(J->runDestructors());
+
+ CXXRuntimeOverrides.runDestructors();
+
+ return Result;
+}
+
std::unique_ptr<FDRawChannel> launchRemote() {
#ifndef LLVM_ON_UNIX
llvm_unreachable("launchRemote not supported on non-Unix platforms");