Home | History | Annotate | Download | only in lli
      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 
     10 #include "OrcLazyJIT.h"
     11 #include "llvm/ExecutionEngine/Orc/OrcABISupport.h"
     12 #include "llvm/Support/Debug.h"
     13 #include "llvm/Support/DynamicLibrary.h"
     14 #include <cstdio>
     15 #include <system_error>
     16 
     17 using namespace llvm;
     18 
     19 namespace {
     20 
     21   enum class DumpKind { NoDump, DumpFuncsToStdOut, DumpModsToStdErr,
     22                         DumpModsToDisk };
     23 
     24   cl::opt<DumpKind> OrcDumpKind("orc-lazy-debug",
     25                                 cl::desc("Debug dumping for the orc-lazy JIT."),
     26                                 cl::init(DumpKind::NoDump),
     27                                 cl::values(
     28                                   clEnumValN(DumpKind::NoDump, "no-dump",
     29                                              "Don't dump anything."),
     30                                   clEnumValN(DumpKind::DumpFuncsToStdOut,
     31                                              "funcs-to-stdout",
     32                                              "Dump function names to stdout."),
     33                                   clEnumValN(DumpKind::DumpModsToStdErr,
     34                                              "mods-to-stderr",
     35                                              "Dump modules to stderr."),
     36                                   clEnumValN(DumpKind::DumpModsToDisk,
     37                                              "mods-to-disk",
     38                                              "Dump modules to the current "
     39                                              "working directory. (WARNING: "
     40                                              "will overwrite existing files)."),
     41                                   clEnumValEnd),
     42                                 cl::Hidden);
     43 
     44   cl::opt<bool> OrcInlineStubs("orc-lazy-inline-stubs",
     45                                cl::desc("Try to inline stubs"),
     46                                cl::init(true), cl::Hidden);
     47 }
     48 
     49 OrcLazyJIT::TransformFtor OrcLazyJIT::createDebugDumper() {
     50 
     51   switch (OrcDumpKind) {
     52   case DumpKind::NoDump:
     53     return [](std::unique_ptr<Module> M) { return M; };
     54 
     55   case DumpKind::DumpFuncsToStdOut:
     56     return [](std::unique_ptr<Module> M) {
     57       printf("[ ");
     58 
     59       for (const auto &F : *M) {
     60         if (F.isDeclaration())
     61           continue;
     62 
     63         if (F.hasName()) {
     64           std::string Name(F.getName());
     65           printf("%s ", Name.c_str());
     66         } else
     67           printf("<anon> ");
     68       }
     69 
     70       printf("]\n");
     71       return M;
     72     };
     73 
     74   case DumpKind::DumpModsToStdErr:
     75     return [](std::unique_ptr<Module> M) {
     76              dbgs() << "----- Module Start -----\n" << *M
     77                     << "----- Module End -----\n";
     78 
     79              return M;
     80            };
     81 
     82   case DumpKind::DumpModsToDisk:
     83     return [](std::unique_ptr<Module> M) {
     84              std::error_code EC;
     85              raw_fd_ostream Out(M->getModuleIdentifier() + ".ll", EC,
     86                                 sys::fs::F_Text);
     87              if (EC) {
     88                errs() << "Couldn't open " << M->getModuleIdentifier()
     89                       << " for dumping.\nError:" << EC.message() << "\n";
     90                exit(1);
     91              }
     92              Out << *M;
     93              return M;
     94            };
     95   }
     96   llvm_unreachable("Unknown DumpKind");
     97 }
     98 
     99 // Defined in lli.cpp.
    100 CodeGenOpt::Level getOptLevel();
    101 
    102 
    103 template <typename PtrTy>
    104 static PtrTy fromTargetAddress(orc::TargetAddress Addr) {
    105   return reinterpret_cast<PtrTy>(static_cast<uintptr_t>(Addr));
    106 }
    107 
    108 int llvm::runOrcLazyJIT(std::unique_ptr<Module> M, int ArgC, char* ArgV[]) {
    109   // Add the program's symbols into the JIT's search space.
    110   if (sys::DynamicLibrary::LoadLibraryPermanently(nullptr)) {
    111     errs() << "Error loading program symbols.\n";
    112     return 1;
    113   }
    114 
    115   // Grab a target machine and try to build a factory function for the
    116   // target-specific Orc callback manager.
    117   EngineBuilder EB;
    118   EB.setOptLevel(getOptLevel());
    119   auto TM = std::unique_ptr<TargetMachine>(EB.selectTarget());
    120   Triple T(TM->getTargetTriple());
    121   auto CompileCallbackMgr = orc::createLocalCompileCallbackManager(T, 0);
    122 
    123   // If we couldn't build the factory function then there must not be a callback
    124   // manager for this target. Bail out.
    125   if (!CompileCallbackMgr) {
    126     errs() << "No callback manager available for target '"
    127            << TM->getTargetTriple().str() << "'.\n";
    128     return 1;
    129   }
    130 
    131   auto IndirectStubsMgrBuilder = orc::createLocalIndirectStubsManagerBuilder(T);
    132 
    133   // If we couldn't build a stubs-manager-builder for this target then bail out.
    134   if (!IndirectStubsMgrBuilder) {
    135     errs() << "No indirect stubs manager available for target '"
    136            << TM->getTargetTriple().str() << "'.\n";
    137     return 1;
    138   }
    139 
    140   // Everything looks good. Build the JIT.
    141   OrcLazyJIT J(std::move(TM), std::move(CompileCallbackMgr),
    142                std::move(IndirectStubsMgrBuilder),
    143                OrcInlineStubs);
    144 
    145   // Add the module, look up main and run it.
    146   auto MainHandle = J.addModule(std::move(M));
    147   auto MainSym = J.findSymbolIn(MainHandle, "main");
    148 
    149   if (!MainSym) {
    150     errs() << "Could not find main function.\n";
    151     return 1;
    152   }
    153 
    154   typedef int (*MainFnPtr)(int, char*[]);
    155   auto Main = fromTargetAddress<MainFnPtr>(MainSym.getAddress());
    156   return Main(ArgC, ArgV);
    157 }
    158 
    159