OrcLazyJIT.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. //===------ OrcLazyJIT.cpp - Basic Orc-based JIT for lazy execution -------===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. #include "OrcLazyJIT.h"
  10. #include "llvm/ExecutionEngine/Orc/OrcTargetSupport.h"
  11. #include "llvm/Support/Debug.h"
  12. #include "llvm/Support/DynamicLibrary.h"
  13. #include <cstdio>
  14. #include <system_error>
  15. using namespace llvm;
  16. namespace {
  17. enum class DumpKind { NoDump, DumpFuncsToStdOut, DumpModsToStdErr,
  18. DumpModsToDisk };
  19. cl::opt<DumpKind> OrcDumpKind("orc-lazy-debug",
  20. cl::desc("Debug dumping for the orc-lazy JIT."),
  21. cl::init(DumpKind::NoDump),
  22. cl::values(
  23. clEnumValN(DumpKind::NoDump, "no-dump",
  24. "Don't dump anything."),
  25. clEnumValN(DumpKind::DumpFuncsToStdOut,
  26. "funcs-to-stdout",
  27. "Dump function names to stdout."),
  28. clEnumValN(DumpKind::DumpModsToStdErr,
  29. "mods-to-stderr",
  30. "Dump modules to stderr."),
  31. clEnumValN(DumpKind::DumpModsToDisk,
  32. "mods-to-disk",
  33. "Dump modules to the current "
  34. "working directory. (WARNING: "
  35. "will overwrite existing files)."),
  36. clEnumValEnd));
  37. }
  38. OrcLazyJIT::CallbackManagerBuilder
  39. OrcLazyJIT::createCallbackManagerBuilder(Triple T) {
  40. switch (T.getArch()) {
  41. default: return nullptr;
  42. case Triple::x86_64: {
  43. typedef orc::JITCompileCallbackManager<IRDumpLayerT,
  44. orc::OrcX86_64> CCMgrT;
  45. return [](IRDumpLayerT &IRDumpLayer, RuntimeDyld::MemoryManager &MemMgr,
  46. LLVMContext &Context) {
  47. return llvm::make_unique<CCMgrT>(IRDumpLayer, MemMgr, Context, 0,
  48. 64);
  49. };
  50. }
  51. }
  52. }
  53. OrcLazyJIT::TransformFtor OrcLazyJIT::createDebugDumper() {
  54. switch (OrcDumpKind) {
  55. case DumpKind::NoDump:
  56. return [](std::unique_ptr<Module> M) { return M; };
  57. case DumpKind::DumpFuncsToStdOut:
  58. return [](std::unique_ptr<Module> M) {
  59. printf("[ ");
  60. for (const auto &F : *M) {
  61. if (F.isDeclaration())
  62. continue;
  63. if (F.hasName()) {
  64. std::string Name(F.getName());
  65. printf("%s ", Name.c_str());
  66. } else
  67. printf("<anon> ");
  68. }
  69. printf("]\n");
  70. return M;
  71. };
  72. case DumpKind::DumpModsToStdErr:
  73. return [](std::unique_ptr<Module> M) {
  74. dbgs() << "----- Module Start -----\n" << *M
  75. << "----- Module End -----\n";
  76. return M;
  77. };
  78. case DumpKind::DumpModsToDisk:
  79. return [](std::unique_ptr<Module> M) {
  80. std::error_code EC;
  81. raw_fd_ostream Out(M->getModuleIdentifier() + ".ll", EC,
  82. sys::fs::F_Text);
  83. if (EC) {
  84. errs() << "Couldn't open " << M->getModuleIdentifier()
  85. << " for dumping.\nError:" << EC.message() << "\n";
  86. exit(1);
  87. }
  88. Out << *M;
  89. return M;
  90. };
  91. }
  92. llvm_unreachable("Unknown DumpKind");
  93. }
  94. // Defined in lli.cpp.
  95. CodeGenOpt::Level getOptLevel();
  96. int llvm::runOrcLazyJIT(std::unique_ptr<Module> M, int ArgC, char* ArgV[]) {
  97. // Add the program's symbols into the JIT's search space.
  98. if (sys::DynamicLibrary::LoadLibraryPermanently(nullptr)) {
  99. errs() << "Error loading program symbols.\n";
  100. return 1;
  101. }
  102. // Grab a target machine and try to build a factory function for the
  103. // target-specific Orc callback manager.
  104. EngineBuilder EB;
  105. EB.setOptLevel(getOptLevel());
  106. auto TM = std::unique_ptr<TargetMachine>(EB.selectTarget());
  107. auto &Context = getGlobalContext();
  108. auto CallbackMgrBuilder =
  109. OrcLazyJIT::createCallbackManagerBuilder(Triple(TM->getTargetTriple()));
  110. // If we couldn't build the factory function then there must not be a callback
  111. // manager for this target. Bail out.
  112. if (!CallbackMgrBuilder) {
  113. errs() << "No callback manager available for target '"
  114. << TM->getTargetTriple().str() << "'.\n";
  115. return 1;
  116. }
  117. // Everything looks good. Build the JIT.
  118. OrcLazyJIT J(std::move(TM), Context, CallbackMgrBuilder);
  119. // Add the module, look up main and run it.
  120. auto MainHandle = J.addModule(std::move(M));
  121. auto MainSym = J.findSymbolIn(MainHandle, "main");
  122. if (!MainSym) {
  123. errs() << "Could not find main function.\n";
  124. return 1;
  125. }
  126. typedef int (*MainFnPtr)(int, char*[]);
  127. auto Main = OrcLazyJIT::fromTargetAddress<MainFnPtr>(MainSym.getAddress());
  128. return Main(ArgC, ArgV);
  129. }