summaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorStephane Sezer <sas@cd80.net>2018-05-25 20:23:42 +0000
committerStephane Sezer <sas@cd80.net>2018-05-25 20:23:42 +0000
commit19379d6c2a67a04e7290b5edaf3b3508ff29b671 (patch)
treed1c0a026f8ffa1665c2249472990555abc599a3e /examples
parent113c3c71564da1103f79dec2076b6ba59fd859d9 (diff)
downloadclang-19379d6c2a67a04e7290b5edaf3b3508ff29b671.tar.gz
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 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@333302 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'examples')
-rw-r--r--examples/clang-interpreter/CMakeLists.txt2
-rw-r--r--examples/clang-interpreter/Invoke.cpp31
-rw-r--r--examples/clang-interpreter/Invoke.h34
-rw-r--r--examples/clang-interpreter/Manager.cpp328
-rw-r--r--examples/clang-interpreter/Manager.h59
-rw-r--r--examples/clang-interpreter/main.cpp136
6 files changed, 84 insertions, 506 deletions
diff --git a/examples/clang-interpreter/CMakeLists.txt b/examples/clang-interpreter/CMakeLists.txt
index 0d132807c4..5b4a6e8086 100644
--- a/examples/clang-interpreter/CMakeLists.txt
+++ b/examples/clang-interpreter/CMakeLists.txt
@@ -12,8 +12,6 @@ set(LLVM_LINK_COMPONENTS
add_clang_executable(clang-interpreter
main.cpp
- Invoke.cpp
- Manager.cpp
)
add_dependencies(clang-interpreter
diff --git a/examples/clang-interpreter/Invoke.cpp b/examples/clang-interpreter/Invoke.cpp
deleted file mode 100644
index 90afa0146b..0000000000
--- a/examples/clang-interpreter/Invoke.cpp
+++ /dev/null
@@ -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;
-}
-
-}
diff --git a/examples/clang-interpreter/Invoke.h b/examples/clang-interpreter/Invoke.h
deleted file mode 100644
index 33942534fd..0000000000
--- a/examples/clang-interpreter/Invoke.h
+++ /dev/null
@@ -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
diff --git a/examples/clang-interpreter/Manager.cpp b/examples/clang-interpreter/Manager.cpp
deleted file mode 100644
index 6c83b9d6f0..0000000000
--- a/examples/clang-interpreter/Manager.cpp
+++ /dev/null
@@ -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
diff --git a/examples/clang-interpreter/Manager.h b/examples/clang-interpreter/Manager.h
deleted file mode 100644
index 013bbbccfd..0000000000
--- a/examples/clang-interpreter/Manager.h
+++ /dev/null
@@ -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
diff --git a/examples/clang-interpreter/main.cpp b/examples/clang-interpreter/main.cpp
index 5c5e335cb5..3f87be29a9 100644
--- a/examples/clang-interpreter/main.cpp
+++ b/examples/clang-interpreter/main.cpp
@@ -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 *Argv0, void *MainAddr) {
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, char * const *envp) {
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, char * const *envp) {
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.