r333302 - Convert clang-interpreter to ORC JIT API

Stephane Sezer via cfe-commits cfe-commits at lists.llvm.org
Fri May 25 13:23:42 PDT 2018


Author: sas
Date: Fri May 25 13:23:42 2018
New Revision: 333302

URL: http://llvm.org/viewvc/llvm-project?rev=333302&view=rev
Log:
Convert clang-interpreter to ORC JIT API

Summary: This mostly re-uses code from the KaleidoscopeJIT example.

Reviewers: ddunbar, lhames

Reviewed By: lhames

Subscribers: mgrang, alexshap, mgorny, xiaobai, cfe-commits

Differential Revision: https://reviews.llvm.org/D45897

Removed:
    cfe/trunk/examples/clang-interpreter/Invoke.cpp
    cfe/trunk/examples/clang-interpreter/Invoke.h
    cfe/trunk/examples/clang-interpreter/Manager.cpp
    cfe/trunk/examples/clang-interpreter/Manager.h
Modified:
    cfe/trunk/examples/clang-interpreter/CMakeLists.txt
    cfe/trunk/examples/clang-interpreter/main.cpp

Modified: cfe/trunk/examples/clang-interpreter/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/examples/clang-interpreter/CMakeLists.txt?rev=333302&r1=333301&r2=333302&view=diff
==============================================================================
--- cfe/trunk/examples/clang-interpreter/CMakeLists.txt (original)
+++ cfe/trunk/examples/clang-interpreter/CMakeLists.txt Fri May 25 13:23:42 2018
@@ -12,8 +12,6 @@ set(LLVM_LINK_COMPONENTS
 
 add_clang_executable(clang-interpreter
   main.cpp
-  Invoke.cpp
-  Manager.cpp
   )
 
 add_dependencies(clang-interpreter

Removed: cfe/trunk/examples/clang-interpreter/Invoke.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/examples/clang-interpreter/Invoke.cpp?rev=333301&view=auto
==============================================================================
--- cfe/trunk/examples/clang-interpreter/Invoke.cpp (original)
+++ cfe/trunk/examples/clang-interpreter/Invoke.cpp (removed)
@@ -1,31 +0,0 @@
-//==-- examples/clang-interpreter/Invoke.cpp - Clang C Interpreter Example -==//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "Invoke.h"
-
-#include <iostream>
-#include <stdexcept>
-
-namespace interpreter {
-
-int TryIt(llvm::ExecutionEngine *EE, llvm::Function *EntryFn,
-          const std::vector<std::string> &Args, char *const *EnvP,
-          Invoker Invoke) {
-  int Res = -1;
-  try {
-    Res = Invoke(EE, EntryFn, Args, EnvP);
-  } catch (const std::exception &E) {
-    std::cout << "Caught '" << E.what() << "'\n";
-  } catch (...) {
-    std::cout << "Unknown exception\n";
-  }
-  return Res;
-}
-
-}

Removed: cfe/trunk/examples/clang-interpreter/Invoke.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/examples/clang-interpreter/Invoke.h?rev=333301&view=auto
==============================================================================
--- cfe/trunk/examples/clang-interpreter/Invoke.h (original)
+++ cfe/trunk/examples/clang-interpreter/Invoke.h (removed)
@@ -1,34 +0,0 @@
-//===-- examples/clang-interpreter/Invoke.h - Clang C Interpreter Example -===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef CLANG_EXAMPLE_INTERPRETER_INVOKE_H
-#define CLANG_EXAMPLE_INTERPRETER_INVOKE_H
-
-namespace llvm {
-  class ExecutionEngine;
-  class Function;
-}
-
-#include <string>
-#include <vector>
-
-namespace interpreter {
-
-typedef std::vector<std::string> InvokeArgs;
-
-typedef int (*Invoker)(llvm::ExecutionEngine *EE, llvm::Function *EntryFn,
-                       const InvokeArgs &Args, char *const *EnvP);
-
-int TryIt(llvm::ExecutionEngine *EE, llvm::Function *EntryFn,
-          const InvokeArgs &Args, char *const *EnvP,
-          Invoker Invoke);
-
-} // interpreter
-
-#endif // CLANG_EXAMPLE_INTERPRETER_INVOKE_H

Removed: cfe/trunk/examples/clang-interpreter/Manager.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/examples/clang-interpreter/Manager.cpp?rev=333301&view=auto
==============================================================================
--- cfe/trunk/examples/clang-interpreter/Manager.cpp (original)
+++ cfe/trunk/examples/clang-interpreter/Manager.cpp (removed)
@@ -1,328 +0,0 @@
-//==-- examples/clang-interpreter/Manager.cpp - Clang C Interpreter Example -=//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "Manager.h"
-
-#ifdef CLANG_INTERPRETER_WIN_EXCEPTIONS
-#include "llvm/Support/DynamicLibrary.h"
-
-#define WIN32_LEAN_AND_MEAN
-#define NOGDI
-#define NOMINMAX
-#include <windows.h>
-#endif
-
-namespace interpreter {
-
-using namespace llvm;
-
-void SingleSectionMemoryManager::Block::Reset(uint8_t *Ptr, uintptr_t Size) {
-  assert(Ptr != nullptr && "Bad allocation");
-  Addr = Ptr;
-  End = Ptr ? Ptr + Size : nullptr;
-}
-
-uint8_t *SingleSectionMemoryManager::Block::Next(uintptr_t Size,
-                                                 unsigned Alignment) {
-  uintptr_t Out = (uintptr_t)Addr;
-
-  // Align the out pointer properly
-  if (!Alignment)
-    Alignment = 16;
-  Out = (Out + Alignment - 1) & ~(uintptr_t)(Alignment - 1);
-
-  // RuntimeDyld should have called reserveAllocationSpace with an amount that
-  // will fit all required alignemnts...but assert on this to make sure.
-  assert((Out + Size) <= (uintptr_t)End && "Out of bounds");
-
-  // Set the next Addr to deliver at the end of this one.
-  Addr = (uint8_t *)(Out + Size);
-  return (uint8_t *)Out;
-}
-
-uint8_t *SingleSectionMemoryManager::allocateCodeSection(uintptr_t Size,
-                                                         unsigned Align,
-                                                         unsigned ID,
-                                                         StringRef Name) {
-  return Code.Next(Size, Align);
-}
-
-uint8_t *SingleSectionMemoryManager::allocateDataSection(
-    uintptr_t Size, unsigned Align, unsigned ID, StringRef Name, bool RO) {
-  return RO ? ROData.Next(Size, Align) : RWData.Next(Size, Align);
-}
-
-void SingleSectionMemoryManager::reserveAllocationSpace(
-    uintptr_t CodeSize, uint32_t CodeAlign, uintptr_t ROSize, uint32_t ROAlign,
-    uintptr_t RWSize, uint32_t RWAlign) {
-  // FIXME: Ideally this should be one contiguous block, with Code, ROData,
-  // and RWData pointing to sub-blocks within, but setting the correct
-  // permissions for that wouldn't work unless we over-allocated to have each
-  // Block.Base aligned on a page boundary.
-  const unsigned SecID = 0;
-  Code.Reset(SectionMemoryManager::allocateCodeSection(CodeSize, CodeAlign,
-                                                       SecID, "code"),
-             CodeSize);
-
-  ROData.Reset(SectionMemoryManager::allocateDataSection(ROSize, ROAlign, SecID,
-                                                         "rodata", true/*RO*/),
-               ROSize);
-
-  RWData.Reset(SectionMemoryManager::allocateDataSection(RWSize, RWAlign, SecID,
-                                                         "rwdata", false/*RO*/),
-               RWSize);
-
-#ifdef CLANG_INTERPRETER_WIN_EXCEPTIONS
-  ImageBase =
-      (uintptr_t)std::min(std::min(Code.Addr, ROData.Addr), RWData.Addr);
-#endif
-}
-
-#ifdef CLANG_INTERPRETER_WIN_EXCEPTIONS
-
-// Map an "ImageBase" to a range of adresses that can throw.
-//
-class SEHFrameHandler {
-  typedef SingleSectionMemoryManager::EHFrameInfos EHFrameInfos;
-  typedef std::vector<std::pair<DWORD, DWORD>> ImageRanges;
-  typedef std::map<uintptr_t, ImageRanges> ImageBaseMap;
-  ImageBaseMap m_Map;
-
-  static void MergeRanges(ImageRanges &Ranges);
-  uintptr_t FindEHFrame(uintptr_t Caller);
-
-public:
-  static __declspec(noreturn) void __stdcall RaiseSEHException(void *, void *);
-  void RegisterEHFrames(uintptr_t ImageBase, const EHFrameInfos &Frames,
-                        bool Block = true);
-  void DeRegisterEHFrames(uintptr_t ImageBase, const EHFrameInfos &Frames);
-};
-
-// Merge overlaping ranges for faster searching with throwing PC
-void SEHFrameHandler::MergeRanges(ImageRanges &Ranges) {
-  std::sort(Ranges.begin(), Ranges.end());
-
-  ImageRanges Merged;
-  ImageRanges::iterator It = Ranges.begin();
-  auto Current = *(It)++;
-  while (It != Ranges.end()) {
-    if (Current.second + 1 < It->first) {
-      Merged.push_back(Current);
-      Current = *(It);
-    } else
-      Current.second = std::max(Current.second, It->second);
-    ++It;
-  }
-  Merged.emplace_back(Current);
-  Ranges.swap(Merged);
-}
-
-// Find the "ImageBase" for Caller/PC who is throwing an exception
-uintptr_t SEHFrameHandler::FindEHFrame(uintptr_t Caller) {
-  for (auto &&Itr : m_Map) {
-    const uintptr_t ImgBase = Itr.first;
-    for (auto &&Rng : Itr.second) {
-      if (Caller >= (ImgBase + Rng.first) && Caller <= (ImgBase + Rng.second))
-        return ImgBase;
-    }
-  }
-  return 0;
-}
-
-// Register a range of adresses for a single section that
-void SEHFrameHandler::RegisterEHFrames(uintptr_t ImageBase,
-                                       const EHFrameInfos &Frames, bool Block) {
-  if (Frames.empty())
-    return;
-  assert(m_Map.find(ImageBase) == m_Map.end());
-
-  ImageBaseMap::mapped_type &Ranges = m_Map[ImageBase];
-  ImageRanges::value_type *BlockRange = nullptr;
-  if (Block) {
-    // Merge all unwind adresses into a single contiguous block for faster
-    // searching later.
-    Ranges.emplace_back(std::numeric_limits<DWORD>::max(),
-                        std::numeric_limits<DWORD>::min());
-    BlockRange = &Ranges.back();
-  }
-
-  for (auto &&Frame : Frames) {
-    assert(m_Map.find(DWORD64(Frame.Addr)) == m_Map.end() &&
-           "Runtime function should not be a key!");
-
-    PRUNTIME_FUNCTION RFunc = reinterpret_cast<PRUNTIME_FUNCTION>(Frame.Addr);
-    const size_t N = Frame.Size / sizeof(RUNTIME_FUNCTION);
-    if (BlockRange) {
-      for (PRUNTIME_FUNCTION It = RFunc, End = RFunc + N; It < End; ++It) {
-        BlockRange->first = std::min(BlockRange->first, It->BeginAddress);
-        BlockRange->second = std::max(BlockRange->second, It->EndAddress);
-      }
-    } else {
-      for (PRUNTIME_FUNCTION It = RFunc, End = RFunc + N; It < End; ++It)
-        Ranges.emplace_back(It->BeginAddress, It->EndAddress);
-    }
-
-    ::RtlAddFunctionTable(RFunc, N, ImageBase);
-  }
-
-  if (!Block)
-    MergeRanges(Ranges); // Initial sort and merge
-}
-
-void SEHFrameHandler::DeRegisterEHFrames(uintptr_t ImageBase,
-                                         const EHFrameInfos &Frames) {
-  if (Frames.empty())
-    return;
-
-  auto Itr = m_Map.find(ImageBase);
-  if (Itr != m_Map.end()) {
-    // Remove the ImageBase from lookup
-    m_Map.erase(Itr);
-
-    // Unregister all the PRUNTIME_FUNCTIONs
-    for (auto &&Frame : Frames)
-      ::RtlDeleteFunctionTable(reinterpret_cast<PRUNTIME_FUNCTION>(Frame.Addr));
-  }
-}
-
-// FIXME: Rather than this static and overriding _CxxThrowException via
-// DynamicLibrary::AddSymbol, a better route would be to transform the call
-// to _CxxThrowException(Arg0, Arg1) -> RaiseSEHException(Arg0, Arg1, this)
-// where 'this' is the SingleSectionMemoryManager instance.  This could probably
-// be done with clang, and definitely possible by injecting an llvm-IR function
-// into the module with the name '_CxxThrowException'
-//
-static SEHFrameHandler sFrameHandler;
-
-void SingleSectionMemoryManager::deregisterEHFrames() {
-  sFrameHandler.DeRegisterEHFrames(ImageBase, EHFrames);
-  EHFrameInfos().swap(EHFrames);
-}
-
-bool SingleSectionMemoryManager::finalizeMemory(std::string *ErrMsg) {
-  sFrameHandler.RegisterEHFrames(ImageBase, EHFrames);
-  ImageBase = 0;
-  return SectionMemoryManager::finalizeMemory(ErrMsg);
-}
-
-SingleSectionMemoryManager::SingleSectionMemoryManager() {
-  // Override Windows _CxxThrowException to call into our local version that
-  // can throw to and from the JIT.
-  sys::DynamicLibrary::AddSymbol(
-      "_CxxThrowException",
-      (void *)(uintptr_t)&SEHFrameHandler::RaiseSEHException);
-}
-
-// Adapted from VisualStudio/VC/crt/src/vcruntime/throw.cpp
-#ifdef _WIN64
-#define _EH_RELATIVE_OFFSETS 1
-#endif
-// The NT Exception # that we use
-#define EH_EXCEPTION_NUMBER ('msc' | 0xE0000000)
-// The magic # identifying this version
-#define EH_MAGIC_NUMBER1 0x19930520
-#define EH_PURE_MAGIC_NUMBER1 0x01994000
-// Number of parameters in exception record
-#define EH_EXCEPTION_PARAMETERS 4
-
-// A generic exception record
-struct EHExceptionRecord {
-  DWORD ExceptionCode;
-  DWORD ExceptionFlags;               // Flags determined by NT
-  _EXCEPTION_RECORD *ExceptionRecord; // Extra exception record (unused)
-  void *ExceptionAddress;             // Address at which exception occurred
-  DWORD NumberParameters; // No. of parameters = EH_EXCEPTION_PARAMETERS
-  struct EHParameters {
-    DWORD magicNumber;            // = EH_MAGIC_NUMBER1
-    void *pExceptionObject;       // Pointer to the actual object thrown
-    struct ThrowInfo *pThrowInfo; // Description of thrown object
-#if _EH_RELATIVE_OFFSETS
-    DWORD64 pThrowImageBase; // Image base of thrown object
-#endif
-  } params;
-};
-
-__declspec(noreturn) void __stdcall
-SEHFrameHandler::RaiseSEHException(void *CxxExcept, void *Info) {
-  uintptr_t Caller;
-  static_assert(sizeof(Caller) == sizeof(PVOID), "Size mismatch");
-
-  USHORT Frames = CaptureStackBackTrace(1, 1, (PVOID *)&Caller, NULL);
-  assert(Frames && "No frames captured");
-  (void)Frames;
-
-  const DWORD64 BaseAddr = sFrameHandler.FindEHFrame(Caller);
-  if (BaseAddr == 0)
-    _CxxThrowException(CxxExcept, (_ThrowInfo *)Info);
-
-  // A generic exception record
-  EHExceptionRecord Exception = {
-      EH_EXCEPTION_NUMBER,      // Exception number
-      EXCEPTION_NONCONTINUABLE, // Exception flags (we don't do resume)
-      nullptr,                  // Additional record (none)
-      nullptr,                  // Address of exception (OS fills in)
-      EH_EXCEPTION_PARAMETERS,  // Number of parameters
-      {EH_MAGIC_NUMBER1, CxxExcept, (struct ThrowInfo *)Info,
-#if _EH_RELATIVE_OFFSETS
-       BaseAddr
-#endif
-      }};
-
-// const ThrowInfo* pTI = (const ThrowInfo*)Info;
-
-#ifdef THROW_ISWINRT
-  if (pTI && (THROW_ISWINRT((*pTI)))) {
-    // The pointer to the ExceptionInfo structure is stored sizeof(void*)
-    // infront of each WinRT Exception Info.
-    ULONG_PTR *EPtr = *reinterpret_cast<ULONG_PTR **>(CxxExcept);
-    EPtr--;
-
-    WINRTEXCEPTIONINFO **ppWei = reinterpret_cast<WINRTEXCEPTIONINFO **>(EPtr);
-    pTI = (*ppWei)->throwInfo;
-    (*ppWei)->PrepareThrow(ppWei);
-  }
-#endif
-
-  // If the throw info indicates this throw is from a pure region,
-  // set the magic number to the Pure one, so only a pure-region
-  // catch will see it.
-  //
-  // Also use the Pure magic number on Win64 if we were unable to
-  // determine an image base, since that was the old way to determine
-  // a pure throw, before the TI_IsPure bit was added to the FuncInfo
-  // attributes field.
-  if (Info != nullptr) {
-#ifdef THROW_ISPURE
-    if (THROW_ISPURE(*pTI))
-      Exception.params.magicNumber = EH_PURE_MAGIC_NUMBER1;
-#if _EH_RELATIVE_OFFSETS
-    else
-#endif // _EH_RELATIVE_OFFSETS
-#endif // THROW_ISPURE
-
-    // Not quite sure what this is about, but pThrowImageBase can never be 0
-    // here, as that is used to mark when an "ImageBase" was not found.
-#if 0 && _EH_RELATIVE_OFFSETS
-    if (Exception.params.pThrowImageBase == 0)
-      Exception.params.magicNumber = EH_PURE_MAGIC_NUMBER1;
-#endif // _EH_RELATIVE_OFFSETS
-  }
-
-// Hand it off to the OS:
-#if defined(_M_X64) && defined(_NTSUBSET_)
-  RtlRaiseException((PEXCEPTION_RECORD)&Exception);
-#else
-  RaiseException(Exception.ExceptionCode, Exception.ExceptionFlags,
-                 Exception.NumberParameters, (PULONG_PTR)&Exception.params);
-#endif
-}
-
-#endif // CLANG_INTERPRETER_WIN_EXCEPTIONS
-
-} // namespace interpreter

Removed: cfe/trunk/examples/clang-interpreter/Manager.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/examples/clang-interpreter/Manager.h?rev=333301&view=auto
==============================================================================
--- cfe/trunk/examples/clang-interpreter/Manager.h (original)
+++ cfe/trunk/examples/clang-interpreter/Manager.h (removed)
@@ -1,59 +0,0 @@
-//===-- examples/clang-interpreter/Manager.h - Clang C Interpreter Example -==//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef CLANG_EXAMPLE_INTERPRETER_MANAGER_H
-#define CLANG_EXAMPLE_INTERPRETER_MANAGER_H
-
-#include "llvm/ExecutionEngine/SectionMemoryManager.h"
-
-#if defined(_WIN32) && defined(_WIN64)
-#define CLANG_INTERPRETER_COFF_FORMAT
-#define CLANG_INTERPRETER_WIN_EXCEPTIONS
-#endif
-
-namespace interpreter {
-
-class SingleSectionMemoryManager : public llvm::SectionMemoryManager {
-  struct Block {
-    uint8_t *Addr = nullptr, *End = nullptr;
-    void Reset(uint8_t *Ptr, uintptr_t Size);
-    uint8_t *Next(uintptr_t Size, unsigned Alignment);
-  };
-  Block Code, ROData, RWData;
-
-public:
-  uint8_t *allocateCodeSection(uintptr_t Size, unsigned Align, unsigned ID,
-                               llvm::StringRef Name) final;
-
-  uint8_t *allocateDataSection(uintptr_t Size, unsigned Align, unsigned ID,
-                               llvm::StringRef Name, bool RO) final;
-
-  void reserveAllocationSpace(uintptr_t CodeSize, uint32_t CodeAlign,
-                              uintptr_t ROSize, uint32_t ROAlign,
-                              uintptr_t RWSize, uint32_t RWAlign) final;
-
-  bool needsToReserveAllocationSpace() override { return true; }
-
-#ifdef CLANG_INTERPRETER_WIN_EXCEPTIONS
-  using llvm::SectionMemoryManager::EHFrameInfos;
-
-  SingleSectionMemoryManager();
-
-  void deregisterEHFrames() override;
-
-  bool finalizeMemory(std::string *ErrMsg) override;
-
-private:
-  uintptr_t ImageBase = 0;
-#endif
-};
-
-}
-
-#endif // CLANG_EXAMPLE_INTERPRETER_MANAGER_H

Modified: cfe/trunk/examples/clang-interpreter/main.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/examples/clang-interpreter/main.cpp?rev=333302&r1=333301&r2=333302&view=diff
==============================================================================
--- cfe/trunk/examples/clang-interpreter/main.cpp (original)
+++ cfe/trunk/examples/clang-interpreter/main.cpp Fri May 25 13:23:42 2018
@@ -7,11 +7,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "Invoke.h"
-#include "Manager.h"
-
-#include "clang/CodeGen/CodeGenAction.h"
 #include "clang/Basic/DiagnosticOptions.h"
+#include "clang/CodeGen/CodeGenAction.h"
 #include "clang/Driver/Compilation.h"
 #include "clang/Driver/Driver.h"
 #include "clang/Driver/Tool.h"
@@ -21,7 +18,12 @@
 #include "clang/Frontend/TextDiagnosticPrinter.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ExecutionEngine/ExecutionEngine.h"
-#include "llvm/ExecutionEngine/MCJIT.h"
+#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
+#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
+#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
+#include "llvm/ExecutionEngine/SectionMemoryManager.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/Mangler.h"
 #include "llvm/IR/Module.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Host.h"
@@ -29,29 +31,11 @@
 #include "llvm/Support/Path.h"
 #include "llvm/Support/TargetSelect.h"
 #include "llvm/Support/raw_ostream.h"
+#include "llvm/Target/TargetMachine.h"
 
 using namespace clang;
 using namespace clang::driver;
 
-namespace interpreter {
-
-static llvm::ExecutionEngine *
-createExecutionEngine(std::unique_ptr<llvm::Module> M, std::string *ErrorStr) {
-  llvm::EngineBuilder EB(std::move(M));
-  EB.setErrorStr(ErrorStr);
-  EB.setMemoryManager(llvm::make_unique<SingleSectionMemoryManager>());
-  llvm::ExecutionEngine *EE = EB.create();
-  EE->finalizeObject();
-  return EE;
-}
-
-// Invoked from a try/catch block in invoke.cpp.
-//
-static int Invoke(llvm::ExecutionEngine *EE, llvm::Function *EntryFn,
-          const std::vector<std::string> &Args, char *const *EnvP) {
-  return EE->runFunctionAsMain(EntryFn, Args, EnvP);
-}
-
 // This function isn't referenced outside its translation unit, but it
 // can't use the "static" keyword because its address is used for
 // GetMainExecutable (since some platforms don't support taking the
@@ -61,13 +45,76 @@ std::string GetExecutablePath(const char
   return llvm::sys::fs::getMainExecutable(Argv0, MainAddr);
 }
 
-} // namespace interpreter
+namespace llvm {
+namespace orc {
+
+class SimpleJIT {
+private:
+  ExecutionSession ES;
+  std::shared_ptr<SymbolResolver> Resolver;
+  std::unique_ptr<TargetMachine> TM;
+  const DataLayout DL;
+  RTDyldObjectLinkingLayer ObjectLayer;
+  IRCompileLayer<decltype(ObjectLayer), SimpleCompiler> CompileLayer;
+
+public:
+  SimpleJIT()
+      : Resolver(createLegacyLookupResolver(
+            ES,
+            [this](const std::string &Name) -> JITSymbol {
+              if (auto Sym = CompileLayer.findSymbol(Name, false))
+                return Sym;
+              else if (auto Err = Sym.takeError())
+                return std::move(Err);
+              if (auto SymAddr =
+                      RTDyldMemoryManager::getSymbolAddressInProcess(Name))
+                return JITSymbol(SymAddr, JITSymbolFlags::Exported);
+              return nullptr;
+            },
+            [](Error Err) { cantFail(std::move(Err), "lookupFlags failed"); })),
+        TM(EngineBuilder().selectTarget()), DL(TM->createDataLayout()),
+        ObjectLayer(ES,
+                    [this](VModuleKey) {
+                      return RTDyldObjectLinkingLayer::Resources{
+                          std::make_shared<SectionMemoryManager>(), Resolver};
+                    }),
+        CompileLayer(ObjectLayer, SimpleCompiler(*TM)) {
+    llvm::sys::DynamicLibrary::LoadLibraryPermanently(nullptr);
+  }
+
+  const TargetMachine &getTargetMachine() const { return *TM; }
 
-int main(int argc, const char **argv, char * const *envp) {
+  VModuleKey addModule(std::unique_ptr<Module> M) {
+    // Add the module to the JIT with a new VModuleKey.
+    auto K = ES.allocateVModule();
+    cantFail(CompileLayer.addModule(K, std::move(M)));
+    return K;
+  }
+
+  JITSymbol findSymbol(const StringRef &Name) {
+    std::string MangledName;
+    raw_string_ostream MangledNameStream(MangledName);
+    Mangler::getNameWithPrefix(MangledNameStream, Name, DL);
+    return CompileLayer.findSymbol(MangledNameStream.str(), true);
+  }
+
+  JITTargetAddress getSymbolAddress(const StringRef &Name) {
+    return cantFail(findSymbol(Name).getAddress());
+  }
+
+  void removeModule(VModuleKey K) {
+    cantFail(CompileLayer.removeModule(K));
+  }
+};
+
+} // end namespace orc
+} // end namespace llvm
+
+int main(int argc, const char **argv) {
   // This just needs to be some symbol in the binary; C++ doesn't
   // allow taking the address of ::main however.
-  void *MainAddr = (void*) (intptr_t) interpreter::GetExecutablePath;
-  std::string Path = interpreter::GetExecutablePath(argv[0], MainAddr);
+  void *MainAddr = (void*) (intptr_t) GetExecutablePath;
+  std::string Path = GetExecutablePath(argv[0], MainAddr);
   IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
   TextDiagnosticPrinter *DiagClient =
     new TextDiagnosticPrinter(llvm::errs(), &*DiagOpts);
@@ -83,7 +130,7 @@ int main(int argc, const char **argv, ch
   if (T.isOSBinFormatCOFF())
     T.setObjectFormat(llvm::Triple::ELF);
 #endif
-	
+
   Driver TheDriver(Path, T.str(), Diags);
   TheDriver.setTitle("clang interpreter");
   TheDriver.setCheckInputsExist(false);
@@ -158,29 +205,14 @@ int main(int argc, const char **argv, ch
   llvm::InitializeNativeTargetAsmPrinter();
 
   int Res = 255;
-  if (std::unique_ptr<llvm::Module> Module = Act->takeModule()) {
-    llvm::Function *EntryFn = Module->getFunction("main");
-    if (!EntryFn) {
-      llvm::errs() << "'main' function not found in module.\n";
-      return Res;
-    }
-
-    std::string Error;
-    std::unique_ptr<llvm::ExecutionEngine> EE(
-        interpreter::createExecutionEngine(std::move(Module), &Error));
-    if (!EE) {
-      llvm::errs() << "unable to make execution engine: " << Error << "\n";
-      return Res;
-    }
-
-    interpreter::InvokeArgs Args;
-    for (int I = 1; I < argc; ++I)
-      Args.push_back(argv[I]);
-
-    if (Clang.getLangOpts().CPlusPlus)
-      Res = interpreter::TryIt(EE.get(), EntryFn, Args, envp, interpreter::Invoke);
-    else
-      Res = interpreter::Invoke(EE.get(), EntryFn, Args, envp);
+  std::unique_ptr<llvm::Module> Module = Act->takeModule();
+
+  if (Module) {
+    llvm::orc::SimpleJIT J;
+    auto H = J.addModule(std::move(Module));
+    auto Main = (int(*)(...))J.getSymbolAddress("main");
+    Res = Main();
+    J.removeModule(H);
   }
 
   // Shutdown.




More information about the cfe-commits mailing list