14c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar//===------ OrcLazyJIT.cpp - Basic Orc-based JIT for lazy execution -------===//
24c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar//
34c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar//                     The LLVM Compiler Infrastructure
44c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar//
54c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar// This file is distributed under the University of Illinois Open Source
64c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar// License. See LICENSE.TXT for details.
74c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar//
84c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar//===----------------------------------------------------------------------===//
94c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar
104c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar#include "OrcLazyJIT.h"
114c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar#include "llvm/ExecutionEngine/Orc/OrcTargetSupport.h"
120c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar#include "llvm/Support/Debug.h"
130c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar#include "llvm/Support/DynamicLibrary.h"
146948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar#include <cstdio>
150c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar#include <system_error>
164c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar
174c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainarusing namespace llvm;
184c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar
190c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainarnamespace {
200c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar
210c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar  enum class DumpKind { NoDump, DumpFuncsToStdOut, DumpModsToStdErr,
220c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar                        DumpModsToDisk };
230c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar
240c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar  cl::opt<DumpKind> OrcDumpKind("orc-lazy-debug",
250c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar                                cl::desc("Debug dumping for the orc-lazy JIT."),
260c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar                                cl::init(DumpKind::NoDump),
270c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar                                cl::values(
280c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar                                  clEnumValN(DumpKind::NoDump, "no-dump",
290c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar                                             "Don't dump anything."),
300c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar                                  clEnumValN(DumpKind::DumpFuncsToStdOut,
310c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar                                             "funcs-to-stdout",
320c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar                                             "Dump function names to stdout."),
330c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar                                  clEnumValN(DumpKind::DumpModsToStdErr,
340c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar                                             "mods-to-stderr",
350c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar                                             "Dump modules to stderr."),
360c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar                                  clEnumValN(DumpKind::DumpModsToDisk,
370c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar                                             "mods-to-disk",
380c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar                                             "Dump modules to the current "
390c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar                                             "working directory. (WARNING: "
400c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar                                             "will overwrite existing files)."),
41cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                                  clEnumValEnd),
42cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                                cl::Hidden);
43cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
44cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  cl::opt<bool> OrcInlineStubs("orc-lazy-inline-stubs",
45cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                               cl::desc("Try to inline stubs"),
46cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                               cl::init(true), cl::Hidden);
470c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar}
480c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar
49cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainarstd::unique_ptr<OrcLazyJIT::CompileCallbackMgr>
50cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga NainarOrcLazyJIT::createCompileCallbackMgr(Triple T) {
514c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar  switch (T.getArch()) {
520c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar    default: return nullptr;
534c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar
544c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar    case Triple::x86_64: {
55cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      typedef orc::LocalJITCompileCallbackManager<orc::OrcX86_64> CCMgrT;
56cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      return llvm::make_unique<CCMgrT>(0);
574c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar    }
584c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar  }
594c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar}
604c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar
61cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga NainarOrcLazyJIT::IndirectStubsManagerBuilder
62cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga NainarOrcLazyJIT::createIndirectStubsMgrBuilder(Triple T) {
63cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  switch (T.getArch()) {
64cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    default: return nullptr;
65cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
66cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    case Triple::x86_64:
67cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      return [](){
68cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar        return llvm::make_unique<
69cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar                       orc::LocalIndirectStubsManager<orc::OrcX86_64>>();
70cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      };
71cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  }
72cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar}
73cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
740c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga NainarOrcLazyJIT::TransformFtor OrcLazyJIT::createDebugDumper() {
750c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar
760c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar  switch (OrcDumpKind) {
770c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar  case DumpKind::NoDump:
786948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar    return [](std::unique_ptr<Module> M) { return M; };
790c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar
800c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar  case DumpKind::DumpFuncsToStdOut:
810c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar    return [](std::unique_ptr<Module> M) {
820c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar      printf("[ ");
830c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar
840c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar      for (const auto &F : *M) {
850c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar        if (F.isDeclaration())
860c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar          continue;
870c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar
880c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar        if (F.hasName()) {
890c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar          std::string Name(F.getName());
900c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar          printf("%s ", Name.c_str());
910c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar        } else
920c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar          printf("<anon> ");
930c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar      }
940c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar
950c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar      printf("]\n");
966948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar      return M;
970c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar    };
980c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar
990c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar  case DumpKind::DumpModsToStdErr:
1000c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar    return [](std::unique_ptr<Module> M) {
1010c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar             dbgs() << "----- Module Start -----\n" << *M
1020c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar                    << "----- Module End -----\n";
1030c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar
1046948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar             return M;
1050c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar           };
1060c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar
1070c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar  case DumpKind::DumpModsToDisk:
1080c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar    return [](std::unique_ptr<Module> M) {
1090c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar             std::error_code EC;
1100c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar             raw_fd_ostream Out(M->getModuleIdentifier() + ".ll", EC,
1110c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar                                sys::fs::F_Text);
1120c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar             if (EC) {
1130c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar               errs() << "Couldn't open " << M->getModuleIdentifier()
1140c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar                      << " for dumping.\nError:" << EC.message() << "\n";
1150c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar               exit(1);
1160c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar             }
1170c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar             Out << *M;
1186948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar             return M;
1190c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar           };
1200c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar  }
1210c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar  llvm_unreachable("Unknown DumpKind");
1220c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar}
1230c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar
1246948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar// Defined in lli.cpp.
1256948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga NainarCodeGenOpt::Level getOptLevel();
1266948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar
127cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
128cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainartemplate <typename PtrTy>
129cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainarstatic PtrTy fromTargetAddress(orc::TargetAddress Addr) {
130cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  return reinterpret_cast<PtrTy>(static_cast<uintptr_t>(Addr));
131cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar}
132cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
1334c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainarint llvm::runOrcLazyJIT(std::unique_ptr<Module> M, int ArgC, char* ArgV[]) {
1340c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar  // Add the program's symbols into the JIT's search space.
1350c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar  if (sys::DynamicLibrary::LoadLibraryPermanently(nullptr)) {
1360c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar    errs() << "Error loading program symbols.\n";
1370c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar    return 1;
1380c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar  }
1390c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar
1400c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar  // Grab a target machine and try to build a factory function for the
1410c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar  // target-specific Orc callback manager.
1426948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar  EngineBuilder EB;
1436948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar  EB.setOptLevel(getOptLevel());
1446948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar  auto TM = std::unique_ptr<TargetMachine>(EB.selectTarget());
145cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  auto CompileCallbackMgr =
146cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    OrcLazyJIT::createCompileCallbackMgr(Triple(TM->getTargetTriple()));
1474c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar
1480c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar  // If we couldn't build the factory function then there must not be a callback
1490c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar  // manager for this target. Bail out.
150cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  if (!CompileCallbackMgr) {
1510c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar    errs() << "No callback manager available for target '"
152cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar           << TM->getTargetTriple().str() << "'.\n";
153cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    return 1;
154cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  }
155cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
156cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  auto IndirectStubsMgrBuilder =
157cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    OrcLazyJIT::createIndirectStubsMgrBuilder(Triple(TM->getTargetTriple()));
158cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar
159cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  // If we couldn't build a stubs-manager-builder for this target then bail out.
160cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  if (!IndirectStubsMgrBuilder) {
161cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    errs() << "No indirect stubs manager available for target '"
162cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar           << TM->getTargetTriple().str() << "'.\n";
1634c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar    return 1;
1644c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar  }
1654c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar
1660c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar  // Everything looks good. Build the JIT.
167cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  OrcLazyJIT J(std::move(TM), std::move(CompileCallbackMgr),
168cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar               std::move(IndirectStubsMgrBuilder),
169cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar               OrcInlineStubs);
1700c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar
1710c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar  // Add the module, look up main and run it.
1724c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar  auto MainHandle = J.addModule(std::move(M));
1734c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar  auto MainSym = J.findSymbolIn(MainHandle, "main");
1744c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar
1754c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar  if (!MainSym) {
1764c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar    errs() << "Could not find main function.\n";
1774c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar    return 1;
1784c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar  }
1794c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar
1804c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar  typedef int (*MainFnPtr)(int, char*[]);
181cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  auto Main = fromTargetAddress<MainFnPtr>(MainSym.getAddress());
1824c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar  return Main(ArgC, ArgV);
1834c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar}
184