mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-06 06:33:24 +00:00
[Orc] Add support classes for inspecting and running C++ static ctor/dtors, and
use these to add support for C++ static ctors/dtors to the Orc-lazy JIT in LLI. Replace the trivial_retval_1 regression test - the new 'hello' test is covering strictly more code. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@233885 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
0a4630d104
commit
14ef491582
182
include/llvm/ExecutionEngine/Orc/ExecutionUtils.h
Normal file
182
include/llvm/ExecutionEngine/Orc/ExecutionUtils.h
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
//===-- ExecutionUtils.h - Utilities for executing code in Orc --*- C++ -*-===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// Contains utilities for executing code in Orc.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef LLVM_EXECUTIONENGINE_ORC_EXECUTIONUTILS_H
|
||||||
|
#define LLVM_EXECUTIONENGINE_ORC_EXECUTIONUTILS_H
|
||||||
|
|
||||||
|
#include "JITSymbol.h"
|
||||||
|
#include "llvm/ADT/iterator_range.h"
|
||||||
|
#include "llvm/ADT/StringMap.h"
|
||||||
|
#include "llvm/ExecutionEngine/RuntimeDyld.h"
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
|
||||||
|
class ConstantArray;
|
||||||
|
class GlobalVariable;
|
||||||
|
class Function;
|
||||||
|
class Module;
|
||||||
|
class Value;
|
||||||
|
|
||||||
|
namespace orc {
|
||||||
|
|
||||||
|
/// @brief This iterator provides a convenient way to iterate over the elements
|
||||||
|
/// of an llvm.global_ctors/llvm.global_dtors instance.
|
||||||
|
///
|
||||||
|
/// The easiest way to get hold of instances of this class is to use the
|
||||||
|
/// getConstructors/getDestructors functions.
|
||||||
|
class CtorDtorIterator {
|
||||||
|
public:
|
||||||
|
|
||||||
|
/// @brief Accessor for an element of the global_ctors/global_dtors array.
|
||||||
|
///
|
||||||
|
/// This class provides a read-only view of the element with any casts on
|
||||||
|
/// the function stripped away.
|
||||||
|
struct Element {
|
||||||
|
Element(unsigned Priority, const Function *Func, const Value *Data)
|
||||||
|
: Priority(Priority), Func(Func), Data(Data) {}
|
||||||
|
|
||||||
|
unsigned Priority;
|
||||||
|
const Function *Func;
|
||||||
|
const Value *Data;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @brief Construct an iterator instance. If End is true then this iterator
|
||||||
|
/// acts as the end of the range, otherwise it is the beginning.
|
||||||
|
CtorDtorIterator(const GlobalVariable *GV, bool End);
|
||||||
|
|
||||||
|
/// @brief Test iterators for equality.
|
||||||
|
bool operator==(const CtorDtorIterator &Other) const;
|
||||||
|
|
||||||
|
/// @brief Test iterators for inequality.
|
||||||
|
bool operator!=(const CtorDtorIterator &Other) const;
|
||||||
|
|
||||||
|
/// @brief Pre-increment iterator.
|
||||||
|
CtorDtorIterator& operator++();
|
||||||
|
|
||||||
|
/// @brief Post-increment iterator.
|
||||||
|
CtorDtorIterator operator++(int);
|
||||||
|
|
||||||
|
/// @brief Dereference iterator. The resulting value provides a read-only view
|
||||||
|
/// of this element of the global_ctors/global_dtors list.
|
||||||
|
Element operator*() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const ConstantArray *InitList;
|
||||||
|
unsigned I;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @brief Create an iterator range over the entries of the llvm.global_ctors
|
||||||
|
/// array.
|
||||||
|
iterator_range<CtorDtorIterator> getConstructors(const Module &M);
|
||||||
|
|
||||||
|
/// @brief Create an iterator range over the entries of the llvm.global_ctors
|
||||||
|
/// array.
|
||||||
|
iterator_range<CtorDtorIterator> getDestructors(const Module &M);
|
||||||
|
|
||||||
|
/// @brief Convenience class for recording constructor/destructor names for
|
||||||
|
/// later execution.
|
||||||
|
template <typename JITLayerT>
|
||||||
|
class CtorDtorRunner {
|
||||||
|
public:
|
||||||
|
|
||||||
|
/// @brief Construct a CtorDtorRunner for the given range using the given
|
||||||
|
/// name mangling function.
|
||||||
|
CtorDtorRunner(std::vector<std::string> CtorDtorNames,
|
||||||
|
typename JITLayerT::ModuleSetHandleT H)
|
||||||
|
: CtorDtorNames(std::move(CtorDtorNames)), H(H) {}
|
||||||
|
|
||||||
|
/// @brief Run the recorded constructors/destructors through the given JIT
|
||||||
|
/// layer.
|
||||||
|
bool runViaLayer(JITLayerT &JITLayer) const {
|
||||||
|
typedef void (*CtorDtorTy)();
|
||||||
|
|
||||||
|
bool Error = false;
|
||||||
|
for (const auto &CtorDtorName : CtorDtorNames)
|
||||||
|
if (auto CtorDtorSym = JITLayer.findSymbolIn(H, CtorDtorName, false)) {
|
||||||
|
CtorDtorTy CtorDtor =
|
||||||
|
reinterpret_cast<CtorDtorTy>(
|
||||||
|
static_cast<uintptr_t>(CtorDtorSym.getAddress()));
|
||||||
|
CtorDtor();
|
||||||
|
} else
|
||||||
|
Error = true;
|
||||||
|
return !Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<std::string> CtorDtorNames;
|
||||||
|
typename JITLayerT::ModuleSetHandleT H;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @brief Support class for static dtor execution. For hosted (in-process) JITs
|
||||||
|
/// only!
|
||||||
|
///
|
||||||
|
/// If a __cxa_atexit function isn't found C++ programs that use static
|
||||||
|
/// destructors will fail to link. However, we don't want to use the host
|
||||||
|
/// process's __cxa_atexit, because it will schedule JIT'd destructors to run
|
||||||
|
/// after the JIT has been torn down, which is no good. This class makes it easy
|
||||||
|
/// to override __cxa_atexit (and the related __dso_handle).
|
||||||
|
///
|
||||||
|
/// To use, clients should manually call searchOverrides from their symbol
|
||||||
|
/// resolver. This should generally be done after attempting symbol resolution
|
||||||
|
/// inside the JIT, but before searching the host process's symbol table. When
|
||||||
|
/// the client determines that destructors should be run (generally at JIT
|
||||||
|
/// teardown or after a return from main), the runDestructors method should be
|
||||||
|
/// called.
|
||||||
|
class LocalCXXRuntimeOverrides {
|
||||||
|
public:
|
||||||
|
|
||||||
|
/// Create a runtime-overrides class.
|
||||||
|
template <typename MangleFtorT>
|
||||||
|
LocalCXXRuntimeOverrides(const MangleFtorT &Mangle) {
|
||||||
|
addOverride(Mangle("__dso_handle"), toTargetAddress(&DSOHandleOverride));
|
||||||
|
addOverride(Mangle("__cxa_atexit"), toTargetAddress(&CXAAtExitOverride));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Search overrided symbols.
|
||||||
|
RuntimeDyld::SymbolInfo searchOverrides(const std::string &Name) {
|
||||||
|
auto I = CXXRuntimeOverrides.find(Name);
|
||||||
|
if (I != CXXRuntimeOverrides.end())
|
||||||
|
return RuntimeDyld::SymbolInfo(I->second, JITSymbolFlags::Exported);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Run any destructors recorded by the overriden __cxa_atexit function
|
||||||
|
/// (CXAAtExitOverride).
|
||||||
|
void runDestructors();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
template <typename PtrTy>
|
||||||
|
TargetAddress toTargetAddress(PtrTy* P) {
|
||||||
|
return static_cast<TargetAddress>(reinterpret_cast<uintptr_t>(P));
|
||||||
|
}
|
||||||
|
|
||||||
|
void addOverride(const std::string &Name, TargetAddress Addr) {
|
||||||
|
CXXRuntimeOverrides.insert(std::make_pair(Name, Addr));
|
||||||
|
}
|
||||||
|
|
||||||
|
StringMap<TargetAddress> CXXRuntimeOverrides;
|
||||||
|
|
||||||
|
typedef void (*DestructorPtr)(void*);
|
||||||
|
typedef std::pair<DestructorPtr, void*> CXXDestructorDataPair;
|
||||||
|
typedef std::vector<CXXDestructorDataPair> CXXDestructorDataPairList;
|
||||||
|
CXXDestructorDataPairList DSOHandleOverride;
|
||||||
|
static int CXAAtExitOverride(DestructorPtr Destructor, void *Arg,
|
||||||
|
void *DSOHandle);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // End namespace orc.
|
||||||
|
} // End namespace llvm.
|
||||||
|
|
||||||
|
#endif // LLVM_EXECUTIONENGINE_ORC_EXECUTIONUTILS_H
|
@ -1,5 +1,6 @@
|
|||||||
add_llvm_library(LLVMOrcJIT
|
add_llvm_library(LLVMOrcJIT
|
||||||
CloneSubModule.cpp
|
CloneSubModule.cpp
|
||||||
|
ExecutionUtils.cpp
|
||||||
IndirectionUtils.cpp
|
IndirectionUtils.cpp
|
||||||
OrcMCJITReplacement.cpp
|
OrcMCJITReplacement.cpp
|
||||||
OrcTargetSupport.cpp
|
OrcTargetSupport.cpp
|
||||||
|
102
lib/ExecutionEngine/Orc/ExecutionUtils.cpp
Normal file
102
lib/ExecutionEngine/Orc/ExecutionUtils.cpp
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
//===---- ExecutionUtils.cpp - Utilities for executing functions in Orc ---===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
|
||||||
|
|
||||||
|
#include "llvm/IR/Constants.h"
|
||||||
|
#include "llvm/IR/Function.h"
|
||||||
|
#include "llvm/IR/GlobalVariable.h"
|
||||||
|
#include "llvm/IR/Module.h"
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
namespace orc {
|
||||||
|
|
||||||
|
CtorDtorIterator::CtorDtorIterator(const GlobalVariable *GV, bool End)
|
||||||
|
: InitList(
|
||||||
|
GV ? dyn_cast_or_null<ConstantArray>(GV->getInitializer()) : nullptr),
|
||||||
|
I((InitList && End) ? InitList->getNumOperands() : 0) {
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CtorDtorIterator::operator==(const CtorDtorIterator &Other) const {
|
||||||
|
assert(InitList == Other.InitList && "Incomparable iterators.");
|
||||||
|
return I == Other.I;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CtorDtorIterator::operator!=(const CtorDtorIterator &Other) const {
|
||||||
|
return !(*this == Other);
|
||||||
|
}
|
||||||
|
|
||||||
|
CtorDtorIterator& CtorDtorIterator::operator++() {
|
||||||
|
++I;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
CtorDtorIterator CtorDtorIterator::operator++(int) {
|
||||||
|
CtorDtorIterator Temp = *this;
|
||||||
|
++I;
|
||||||
|
return Temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
CtorDtorIterator::Element CtorDtorIterator::operator*() const {
|
||||||
|
ConstantStruct *CS = dyn_cast<ConstantStruct>(InitList->getOperand(I));
|
||||||
|
assert(CS && "Unrecognized type in llvm.global_ctors/llvm.global_dtors");
|
||||||
|
|
||||||
|
Constant *FuncC = CS->getOperand(1);
|
||||||
|
Function *Func = nullptr;
|
||||||
|
|
||||||
|
// Extract function pointer, pulling off any casts.
|
||||||
|
while (FuncC) {
|
||||||
|
if (Function *F = dyn_cast_or_null<Function>(FuncC)) {
|
||||||
|
Func = F;
|
||||||
|
break;
|
||||||
|
} else if (ConstantExpr *CE = dyn_cast_or_null<ConstantExpr>(FuncC)) {
|
||||||
|
if (CE->isCast())
|
||||||
|
FuncC = dyn_cast_or_null<ConstantExpr>(CE->getOperand(0));
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
// This isn't anything we recognize. Bail out with Func left set to null.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ConstantInt *Priority = dyn_cast<ConstantInt>(CS->getOperand(0));
|
||||||
|
Value *Data = CS->getOperand(2);
|
||||||
|
return Element(Priority->getZExtValue(), Func, Data);
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator_range<CtorDtorIterator> getConstructors(const Module &M) {
|
||||||
|
const GlobalVariable *CtorsList = M.getNamedGlobal("llvm.global_ctors");
|
||||||
|
return make_range(CtorDtorIterator(CtorsList, false),
|
||||||
|
CtorDtorIterator(CtorsList, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator_range<CtorDtorIterator> getDestructors(const Module &M) {
|
||||||
|
const GlobalVariable *DtorsList = M.getNamedGlobal("llvm.global_dtors");
|
||||||
|
return make_range(CtorDtorIterator(DtorsList, false),
|
||||||
|
CtorDtorIterator(DtorsList, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
void LocalCXXRuntimeOverrides::runDestructors() {
|
||||||
|
auto& CXXDestructorDataPairs = DSOHandleOverride;
|
||||||
|
for (auto &P : CXXDestructorDataPairs)
|
||||||
|
P.first(P.second);
|
||||||
|
CXXDestructorDataPairs.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
int LocalCXXRuntimeOverrides::CXAAtExitOverride(DestructorPtr Destructor,
|
||||||
|
void *Arg, void *DSOHandle) {
|
||||||
|
auto& CXXDestructorDataPairs =
|
||||||
|
*reinterpret_cast<CXXDestructorDataPairList*>(DSOHandle);
|
||||||
|
CXXDestructorDataPairs.push_back(std::make_pair(Destructor, Arg));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // End namespace orc.
|
||||||
|
} // End namespace llvm.
|
34
test/ExecutionEngine/OrcLazy/hello.ll
Normal file
34
test/ExecutionEngine/OrcLazy/hello.ll
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
; RUN: lli -jit-kind=orc-lazy %s | FileCheck %s
|
||||||
|
;
|
||||||
|
; CHECK: Hello
|
||||||
|
; CHECK-NEXT: Goodbye
|
||||||
|
|
||||||
|
%class.Foo = type { i8 }
|
||||||
|
|
||||||
|
@f = global %class.Foo zeroinitializer, align 1
|
||||||
|
@__dso_handle = external global i8
|
||||||
|
@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__sub_I_hello.cpp, i8* null }]
|
||||||
|
@str = private unnamed_addr constant [6 x i8] c"Hello\00"
|
||||||
|
@str2 = private unnamed_addr constant [8 x i8] c"Goodbye\00"
|
||||||
|
|
||||||
|
define linkonce_odr void @_ZN3FooD1Ev(%class.Foo* nocapture readnone %this) unnamed_addr align 2 {
|
||||||
|
entry:
|
||||||
|
%puts.i = tail call i32 @puts(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @str2, i64 0, i64 0))
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare i32 @__cxa_atexit(void (i8*)*, i8*, i8*)
|
||||||
|
|
||||||
|
define i32 @main(i32 %argc, i8** nocapture readnone %argv) {
|
||||||
|
entry:
|
||||||
|
ret i32 0
|
||||||
|
}
|
||||||
|
|
||||||
|
define internal void @_GLOBAL__sub_I_hello.cpp() {
|
||||||
|
entry:
|
||||||
|
%puts.i.i.i = tail call i32 @puts(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @str, i64 0, i64 0))
|
||||||
|
%0 = tail call i32 @__cxa_atexit(void (i8*)* bitcast (void (%class.Foo*)* @_ZN3FooD1Ev to void (i8*)*), i8* getelementptr inbounds (%class.Foo, %class.Foo* @f, i64 0, i32 0), i8* @__dso_handle)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare i32 @puts(i8* nocapture readonly)
|
@ -1,26 +0,0 @@
|
|||||||
; RUN: sh -c 'lli -jit-kind=orc-lazy %s; echo $?' | FileCheck %s
|
|
||||||
; CHECK: {{^30$}}
|
|
||||||
define i32 @baz() {
|
|
||||||
entry:
|
|
||||||
ret i32 2
|
|
||||||
}
|
|
||||||
|
|
||||||
define i32 @bar() {
|
|
||||||
entry:
|
|
||||||
%call = call i32 @baz()
|
|
||||||
%mul = mul nsw i32 3, %call
|
|
||||||
ret i32 %mul
|
|
||||||
}
|
|
||||||
|
|
||||||
define i32 @foo() {
|
|
||||||
entry:
|
|
||||||
%call = call i32 @bar()
|
|
||||||
%mul = mul nsw i32 5, %call
|
|
||||||
ret i32 %mul
|
|
||||||
}
|
|
||||||
|
|
||||||
define i32 @main(i32 %argc, i8** %argv) {
|
|
||||||
entry:
|
|
||||||
%call = call i32 @foo()
|
|
||||||
ret i32 %call
|
|
||||||
}
|
|
@ -64,8 +64,6 @@ int llvm::runOrcLazyJIT(std::unique_ptr<Module> M, int ArgC, char* ArgV[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
typedef int (*MainFnPtr)(int, char*[]);
|
typedef int (*MainFnPtr)(int, char*[]);
|
||||||
auto Main = reinterpret_cast<MainFnPtr>(
|
auto Main = OrcLazyJIT::fromTargetAddress<MainFnPtr>(MainSym.getAddress());
|
||||||
static_cast<uintptr_t>(MainSym.getAddress()));
|
|
||||||
|
|
||||||
return Main(ArgC, ArgV);
|
return Main(ArgC, ArgV);
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include "llvm/ADT/Triple.h"
|
#include "llvm/ADT/Triple.h"
|
||||||
#include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h"
|
#include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h"
|
||||||
#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
|
#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
|
||||||
|
#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
|
||||||
#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
|
#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
|
||||||
#include "llvm/ExecutionEngine/Orc/LazyEmittingLayer.h"
|
#include "llvm/ExecutionEngine/Orc/LazyEmittingLayer.h"
|
||||||
#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
|
#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
|
||||||
@ -53,22 +54,68 @@ public:
|
|||||||
CompileLayer(ObjectLayer, orc::SimpleCompiler(*this->TM)),
|
CompileLayer(ObjectLayer, orc::SimpleCompiler(*this->TM)),
|
||||||
LazyEmitLayer(CompileLayer),
|
LazyEmitLayer(CompileLayer),
|
||||||
CCMgr(BuildCallbackMgr(CompileLayer, CCMgrMemMgr, Context)),
|
CCMgr(BuildCallbackMgr(CompileLayer, CCMgrMemMgr, Context)),
|
||||||
CODLayer(LazyEmitLayer, *CCMgr) { }
|
CODLayer(LazyEmitLayer, *CCMgr),
|
||||||
|
CXXRuntimeOverrides([this](const std::string &S) { return mangle(S); }) {}
|
||||||
|
|
||||||
|
~OrcLazyJIT() {
|
||||||
|
// Run any destructors registered with __cxa_atexit.
|
||||||
|
CXXRuntimeOverrides.runDestructors();
|
||||||
|
// Run any IR destructors.
|
||||||
|
for (auto &DtorRunner : IRStaticDestructorRunners)
|
||||||
|
DtorRunner.runViaLayer(CODLayer);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename PtrTy>
|
||||||
|
static PtrTy fromTargetAddress(orc::TargetAddress Addr) {
|
||||||
|
return reinterpret_cast<PtrTy>(static_cast<uintptr_t>(Addr));
|
||||||
|
}
|
||||||
|
|
||||||
ModuleHandleT addModule(std::unique_ptr<Module> M) {
|
ModuleHandleT addModule(std::unique_ptr<Module> M) {
|
||||||
// Attach a data-layout if one isn't already present.
|
// Attach a data-layout if one isn't already present.
|
||||||
if (M->getDataLayout().isDefault())
|
if (M->getDataLayout().isDefault())
|
||||||
M->setDataLayout(*TM->getDataLayout());
|
M->setDataLayout(*TM->getDataLayout());
|
||||||
|
|
||||||
std::vector<std::unique_ptr<Module>> S;
|
// Record the static constructors and destructors. We have to do this before
|
||||||
S.push_back(std::move(M));
|
// we hand over ownership of the module to the JIT.
|
||||||
|
std::vector<std::string> CtorNames, DtorNames;
|
||||||
|
for (auto Ctor : orc::getConstructors(*M))
|
||||||
|
CtorNames.push_back(mangle(Ctor.Func->getName()));
|
||||||
|
for (auto Dtor : orc::getDestructors(*M))
|
||||||
|
DtorNames.push_back(mangle(Dtor.Func->getName()));
|
||||||
|
|
||||||
|
// Symbol resolution order:
|
||||||
|
// 1) Search the JIT symbols.
|
||||||
|
// 2) Check for C++ runtime overrides.
|
||||||
|
// 3) Search the host process (LLI)'s symbol table.
|
||||||
auto FallbackLookup =
|
auto FallbackLookup =
|
||||||
[](const std::string &Name) {
|
[this](const std::string &Name) {
|
||||||
|
|
||||||
|
if (auto Sym = CODLayer.findSymbol(Name, true))
|
||||||
|
return RuntimeDyld::SymbolInfo(Sym.getAddress(), Sym.getFlags());
|
||||||
|
|
||||||
|
if (auto Sym = CXXRuntimeOverrides.searchOverrides(Name))
|
||||||
|
return Sym;
|
||||||
|
|
||||||
if (auto Addr = RTDyldMemoryManager::getSymbolAddressInProcess(Name))
|
if (auto Addr = RTDyldMemoryManager::getSymbolAddressInProcess(Name))
|
||||||
return RuntimeDyld::SymbolInfo(Addr, JITSymbolFlags::Exported);
|
return RuntimeDyld::SymbolInfo(Addr, JITSymbolFlags::Exported);
|
||||||
|
|
||||||
return RuntimeDyld::SymbolInfo(nullptr);
|
return RuntimeDyld::SymbolInfo(nullptr);
|
||||||
};
|
};
|
||||||
return CODLayer.addModuleSet(std::move(S), std::move(FallbackLookup));
|
|
||||||
|
// Add the module to the JIT.
|
||||||
|
std::vector<std::unique_ptr<Module>> S;
|
||||||
|
S.push_back(std::move(M));
|
||||||
|
auto H = CODLayer.addModuleSet(std::move(S), std::move(FallbackLookup));
|
||||||
|
|
||||||
|
// Run the static constructors, and save the static destructor runner for
|
||||||
|
// execution when the JIT is torn down.
|
||||||
|
orc::CtorDtorRunner<CODLayerT> CtorRunner(std::move(CtorNames), H);
|
||||||
|
CtorRunner.runViaLayer(CODLayer);
|
||||||
|
|
||||||
|
IRStaticDestructorRunners.push_back(
|
||||||
|
orc::CtorDtorRunner<CODLayerT>(std::move(DtorNames), H));
|
||||||
|
|
||||||
|
return H;
|
||||||
}
|
}
|
||||||
|
|
||||||
orc::JITSymbol findSymbol(const std::string &Name) {
|
orc::JITSymbol findSymbol(const std::string &Name) {
|
||||||
@ -99,6 +146,9 @@ private:
|
|||||||
LazyEmitLayerT LazyEmitLayer;
|
LazyEmitLayerT LazyEmitLayer;
|
||||||
std::unique_ptr<CompileCallbackMgr> CCMgr;
|
std::unique_ptr<CompileCallbackMgr> CCMgr;
|
||||||
CODLayerT CODLayer;
|
CODLayerT CODLayer;
|
||||||
|
|
||||||
|
orc::LocalCXXRuntimeOverrides CXXRuntimeOverrides;
|
||||||
|
std::vector<orc::CtorDtorRunner<CODLayerT>> IRStaticDestructorRunners;
|
||||||
};
|
};
|
||||||
|
|
||||||
int runOrcLazyJIT(std::unique_ptr<Module> M, int ArgC, char* ArgV[]);
|
int runOrcLazyJIT(std::unique_ptr<Module> M, int ArgC, char* ArgV[]);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user