Remove access to the DataLayout in the TargetMachine
[oota-llvm.git] / tools / lli / OrcLazyJIT.cpp
index 0e4e2a579b68e5547aeeced73b28c1556da598dd..718b3903822215cd2f942e988768a439b0841d11 100644 (file)
 
 #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<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 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[]) {
-  auto TM = std::unique_ptr<TargetMachine>(EngineBuilder().selectTarget());
+  // 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() << "'.\n";
+           << TM->getTargetTriple().str() << "'.\n";
     return 1;
   }
 
-  OrcLazyJIT J(std::move(TM), Context, CallbackMgrBuilder);
+  // Everything looks good. Build the JIT.
+  auto &DL = M->getDataLayout();
+  OrcLazyJIT J(std::move(TM), DL, Context, CallbackMgrBuilder);
 
+  // Add the module, look up main and run it.
   auto MainHandle = J.addModule(std::move(M));
   auto MainSym = J.findSymbolIn(MainHandle, "main");
 
@@ -51,8 +149,6 @@ int llvm::runOrcLazyJIT(std::unique_ptr<Module> M, int ArgC, char* ArgV[]) {
   }
 
   typedef int (*MainFnPtr)(int, char*[]);
-  auto Main = reinterpret_cast<MainFnPtr>(
-                static_cast<uintptr_t>(MainSym.getAddress()));
-
+  auto Main = OrcLazyJIT::fromTargetAddress<MainFnPtr>(MainSym.getAddress());
   return Main(ArgC, ArgV);
 }