[ORC] Add LLJIT and LLLazyJIT, and replace OrcLazyJIT in LLI with LLLazyJIT.

LLJIT is a prefabricated ORC based JIT class that is meant to be the go-to
replacement for MCJIT. Unlike OrcMCJITReplacement (which will continue to be
supported) it is not API or bug-for-bug compatible, but targets the same
use cases: Simple, non-lazy compilation and execution of LLVM IR.

LLLazyJIT extends LLJIT with support for function-at-a-time lazy compilation,
similar to what was provided by LLVM's original (now long deprecated) JIT APIs.

This commit also contains some simple utility classes (CtorDtorRunner2,
LocalCXXRuntimeOverrides2, JITTargetMachineBuilder) to support LLJIT and
LLLazyJIT.

Both of these classes are works in progress. Feedback from JIT clients is very
welcome!

llvm-svn: 335670
diff --git a/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp b/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp
index f6e6ed6..1389c2c 100644
--- a/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp
@@ -13,10 +13,51 @@
 #include "llvm/IR/Function.h"
 #include "llvm/IR/GlobalVariable.h"
 #include "llvm/IR/Module.h"
+#include "llvm/Support/TargetRegistry.h"
+#include "llvm/Target/TargetMachine.h"
 
 namespace llvm {
 namespace orc {
 
+JITTargetMachineBuilder::JITTargetMachineBuilder(Triple TT)
+    : TT(std::move(TT)) {}
+
+Expected<JITTargetMachineBuilder> JITTargetMachineBuilder::detectHost() {
+  return JITTargetMachineBuilder(Triple(sys::getProcessTriple()));
+}
+
+Expected<std::unique_ptr<TargetMachine>>
+JITTargetMachineBuilder::createTargetMachine() {
+  if (!Arch.empty()) {
+    Triple::ArchType Type = Triple::getArchTypeForLLVMName(Arch);
+
+    if (Type == Triple::UnknownArch)
+      return make_error<StringError>(std::string("Unknown arch: ") + Arch,
+                                     inconvertibleErrorCode());
+  }
+
+  std::string ErrMsg;
+  auto *TheTarget = TargetRegistry::lookupTarget(TT.getTriple(), ErrMsg);
+  if (!TheTarget)
+    return make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode());
+
+  auto *TM =
+      TheTarget->createTargetMachine(TT.getTriple(), CPU, Features.getString(),
+                                     Options, RM, CM, OptLevel, /*JIT*/ true);
+  if (!TM)
+    return make_error<StringError>("Could not allocate target machine",
+                                   inconvertibleErrorCode());
+
+  return std::unique_ptr<TargetMachine>(TM);
+}
+
+JITTargetMachineBuilder &JITTargetMachineBuilder::addFeatures(
+    const std::vector<std::string> &FeatureVec) {
+  for (const auto &F : FeatureVec)
+    Features.AddFeature(F);
+  return *this;
+}
+
 CtorDtorIterator::CtorDtorIterator(const GlobalVariable *GV, bool End)
   : InitList(
       GV ? dyn_cast_or_null<ConstantArray>(GV->getInitializer()) : nullptr),
@@ -68,6 +109,8 @@
 
   ConstantInt *Priority = dyn_cast<ConstantInt>(CS->getOperand(0));
   Value *Data = CS->getNumOperands() == 3 ? CS->getOperand(2) : nullptr;
+  if (!isa<GlobalValue>(Data))
+    Data = nullptr;
   return Element(Priority->getZExtValue(), Func, Data);
 }
 
@@ -83,20 +126,121 @@
                     CtorDtorIterator(DtorsList, true));
 }
 
-void LocalCXXRuntimeOverrides::runDestructors() {
+void CtorDtorRunner2::add(iterator_range<CtorDtorIterator> CtorDtors) {
+  if (CtorDtors.begin() == CtorDtors.end())
+    return;
+
+  MangleAndInterner Mangle(
+      V.getExecutionSession(),
+      (*CtorDtors.begin()).Func->getParent()->getDataLayout());
+
+  for (const auto &CtorDtor : CtorDtors) {
+    assert(CtorDtor.Func && CtorDtor.Func->hasName() &&
+           "Ctor/Dtor function must be named to be runnable under the JIT");
+
+    if (CtorDtor.Data && cast<GlobalValue>(CtorDtor.Data)->isDeclaration()) {
+      dbgs() << "  Skipping because why now?\n";
+      continue;
+    }
+
+    CtorDtorsByPriority[CtorDtor.Priority].push_back(
+        Mangle(CtorDtor.Func->getName()));
+  }
+}
+
+Error CtorDtorRunner2::run() {
+  using CtorDtorTy = void (*)();
+
+  SymbolNameSet Names;
+
+  for (auto &KV : CtorDtorsByPriority) {
+    for (auto &Name : KV.second) {
+      auto Added = Names.insert(Name).second;
+      (void)Added;
+      assert(Added && "Ctor/Dtor names clashed");
+    }
+  }
+
+  if (auto CtorDtorMap = lookup({&V}, std::move(Names))) {
+    for (auto &KV : CtorDtorsByPriority) {
+      for (auto &Name : KV.second) {
+        assert(CtorDtorMap->count(Name) && "No entry for Name");
+        auto CtorDtor = reinterpret_cast<CtorDtorTy>(
+            static_cast<uintptr_t>((*CtorDtorMap)[Name].getAddress()));
+        CtorDtor();
+      }
+    }
+    return Error::success();
+  } else
+    return CtorDtorMap.takeError();
+
+  CtorDtorsByPriority.clear();
+}
+
+void LocalCXXRuntimeOverridesBase::runDestructors() {
   auto& CXXDestructorDataPairs = DSOHandleOverride;
   for (auto &P : CXXDestructorDataPairs)
     P.first(P.second);
   CXXDestructorDataPairs.clear();
 }
 
-int LocalCXXRuntimeOverrides::CXAAtExitOverride(DestructorPtr Destructor,
-                                                void *Arg, void *DSOHandle) {
+int LocalCXXRuntimeOverridesBase::CXAAtExitOverride(DestructorPtr Destructor,
+                                                    void *Arg,
+                                                    void *DSOHandle) {
   auto& CXXDestructorDataPairs =
     *reinterpret_cast<CXXDestructorDataPairList*>(DSOHandle);
   CXXDestructorDataPairs.push_back(std::make_pair(Destructor, Arg));
   return 0;
 }
 
+Error LocalCXXRuntimeOverrides2::enable(VSO &V, MangleAndInterner &Mangle) {
+  SymbolMap RuntimeInterposes(
+      {{Mangle("__dso_handle"),
+        JITEvaluatedSymbol(toTargetAddress(&DSOHandleOverride),
+                           JITSymbolFlags::Exported)},
+       {Mangle("__cxa_atexit"),
+        JITEvaluatedSymbol(toTargetAddress(&CXAAtExitOverride),
+                           JITSymbolFlags::Exported)}});
+
+  return V.define(absoluteSymbols(std::move(RuntimeInterposes)));
+}
+
+DynamicLibraryFallbackGenerator::DynamicLibraryFallbackGenerator(
+    sys::DynamicLibrary Dylib, const DataLayout &DL, SymbolPredicate Allow)
+    : Dylib(std::move(Dylib)), Allow(std::move(Allow)),
+      GlobalPrefix(DL.getGlobalPrefix()) {}
+
+SymbolNameSet DynamicLibraryFallbackGenerator::
+operator()(VSO &V, const SymbolNameSet &Names) {
+  orc::SymbolNameSet Added;
+  orc::SymbolMap NewSymbols;
+
+  bool HasGlobalPrefix = (GlobalPrefix != '\0');
+
+  for (auto &Name : Names) {
+    if (!Allow(Name) || (*Name).empty())
+      continue;
+
+    if (HasGlobalPrefix && (*Name).front() != GlobalPrefix)
+      continue;
+
+    std::string Tmp((*Name).data() + (HasGlobalPrefix ? 1 : 0), (*Name).size());
+    if (void *Addr = Dylib.getAddressOfSymbol(Tmp.c_str())) {
+      Added.insert(Name);
+      NewSymbols[Name] = JITEvaluatedSymbol(
+          static_cast<JITTargetAddress>(reinterpret_cast<uintptr_t>(Addr)),
+          JITSymbolFlags::Exported);
+    }
+  }
+
+  // Add any new symbols to V. Since the fallback generator is only called for
+  // symbols that are not already defined, this will never trigger a duplicate
+  // definition error, so we can wrap this call in a 'cantFail'.
+  if (!NewSymbols.empty())
+    cantFail(V.define(absoluteSymbols(std::move(NewSymbols))));
+
+  return Added;
+}
+
 } // End namespace orc.
 } // End namespace llvm.