Imported Upstream version 6.10.0.49

Former-commit-id: 1d6753294b2993e1fbf92de9366bb9544db4189b
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2020-01-16 16:38:04 +00:00
parent d94e79959b
commit 468663ddbb
48518 changed files with 2789335 additions and 61176 deletions

View File

@ -0,0 +1,16 @@
add_llvm_library(LLVMOrcJIT
ExecutionUtils.cpp
IndirectionUtils.cpp
NullResolver.cpp
OrcABISupport.cpp
OrcCBindings.cpp
OrcError.cpp
OrcMCJITReplacement.cpp
RPCUtils.cpp
ADDITIONAL_HEADER_DIRS
${LLVM_MAIN_INCLUDE_DIR}/llvm/ExecutionEngine/Orc
DEPENDS
intrinsics_gen
)

View 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.

View File

@ -0,0 +1,267 @@
//===---- IndirectionUtils.cpp - Utilities for call indirection 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/IndirectionUtils.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Triple.h"
#include "llvm/ExecutionEngine/Orc/OrcABISupport.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include <sstream>
namespace llvm {
namespace orc {
void JITCompileCallbackManager::anchor() {}
void IndirectStubsManager::anchor() {}
std::unique_ptr<JITCompileCallbackManager>
createLocalCompileCallbackManager(const Triple &T,
JITTargetAddress ErrorHandlerAddress) {
switch (T.getArch()) {
default: return nullptr;
case Triple::aarch64: {
typedef orc::LocalJITCompileCallbackManager<orc::OrcAArch64> CCMgrT;
return llvm::make_unique<CCMgrT>(ErrorHandlerAddress);
}
case Triple::x86: {
typedef orc::LocalJITCompileCallbackManager<orc::OrcI386> CCMgrT;
return llvm::make_unique<CCMgrT>(ErrorHandlerAddress);
}
case Triple::x86_64: {
if ( T.getOS() == Triple::OSType::Win32 ) {
typedef orc::LocalJITCompileCallbackManager<orc::OrcX86_64_Win32> CCMgrT;
return llvm::make_unique<CCMgrT>(ErrorHandlerAddress);
} else {
typedef orc::LocalJITCompileCallbackManager<orc::OrcX86_64_SysV> CCMgrT;
return llvm::make_unique<CCMgrT>(ErrorHandlerAddress);
}
}
}
}
std::function<std::unique_ptr<IndirectStubsManager>()>
createLocalIndirectStubsManagerBuilder(const Triple &T) {
switch (T.getArch()) {
default: return nullptr;
case Triple::aarch64:
return [](){
return llvm::make_unique<
orc::LocalIndirectStubsManager<orc::OrcAArch64>>();
};
case Triple::x86:
return [](){
return llvm::make_unique<
orc::LocalIndirectStubsManager<orc::OrcI386>>();
};
case Triple::x86_64:
if (T.getOS() == Triple::OSType::Win32) {
return [](){
return llvm::make_unique<
orc::LocalIndirectStubsManager<orc::OrcX86_64_Win32>>();
};
} else {
return [](){
return llvm::make_unique<
orc::LocalIndirectStubsManager<orc::OrcX86_64_SysV>>();
};
}
}
}
Constant* createIRTypedAddress(FunctionType &FT, JITTargetAddress Addr) {
Constant *AddrIntVal =
ConstantInt::get(Type::getInt64Ty(FT.getContext()), Addr);
Constant *AddrPtrVal =
ConstantExpr::getCast(Instruction::IntToPtr, AddrIntVal,
PointerType::get(&FT, 0));
return AddrPtrVal;
}
GlobalVariable* createImplPointer(PointerType &PT, Module &M,
const Twine &Name, Constant *Initializer) {
auto IP = new GlobalVariable(M, &PT, false, GlobalValue::ExternalLinkage,
Initializer, Name, nullptr,
GlobalValue::NotThreadLocal, 0, true);
IP->setVisibility(GlobalValue::HiddenVisibility);
return IP;
}
void makeStub(Function &F, Value &ImplPointer) {
assert(F.isDeclaration() && "Can't turn a definition into a stub.");
assert(F.getParent() && "Function isn't in a module.");
Module &M = *F.getParent();
BasicBlock *EntryBlock = BasicBlock::Create(M.getContext(), "entry", &F);
IRBuilder<> Builder(EntryBlock);
LoadInst *ImplAddr = Builder.CreateLoad(&ImplPointer);
std::vector<Value*> CallArgs;
for (auto &A : F.args())
CallArgs.push_back(&A);
CallInst *Call = Builder.CreateCall(ImplAddr, CallArgs);
Call->setTailCall();
Call->setAttributes(F.getAttributes());
if (F.getReturnType()->isVoidTy())
Builder.CreateRetVoid();
else
Builder.CreateRet(Call);
}
// Utility class for renaming global values and functions during partitioning.
class GlobalRenamer {
public:
static bool needsRenaming(const Value &New) {
return !New.hasName() || New.getName().startswith("\01L");
}
const std::string& getRename(const Value &Orig) {
// See if we have a name for this global.
{
auto I = Names.find(&Orig);
if (I != Names.end())
return I->second;
}
// Nope. Create a new one.
// FIXME: Use a more robust uniquing scheme. (This may blow up if the user
// writes a "__orc_anon[[:digit:]]* method).
unsigned ID = Names.size();
std::ostringstream NameStream;
NameStream << "__orc_anon" << ID++;
auto I = Names.insert(std::make_pair(&Orig, NameStream.str()));
return I.first->second;
}
private:
DenseMap<const Value*, std::string> Names;
};
static void raiseVisibilityOnValue(GlobalValue &V, GlobalRenamer &R) {
if (V.hasLocalLinkage()) {
if (R.needsRenaming(V))
V.setName(R.getRename(V));
V.setLinkage(GlobalValue::ExternalLinkage);
V.setVisibility(GlobalValue::HiddenVisibility);
}
V.setUnnamedAddr(GlobalValue::UnnamedAddr::None);
assert(!R.needsRenaming(V) && "Invalid global name.");
}
void makeAllSymbolsExternallyAccessible(Module &M) {
GlobalRenamer Renamer;
for (auto &F : M)
raiseVisibilityOnValue(F, Renamer);
for (auto &GV : M.globals())
raiseVisibilityOnValue(GV, Renamer);
for (auto &A : M.aliases())
raiseVisibilityOnValue(A, Renamer);
}
Function* cloneFunctionDecl(Module &Dst, const Function &F,
ValueToValueMapTy *VMap) {
assert(F.getParent() != &Dst && "Can't copy decl over existing function.");
Function *NewF =
Function::Create(cast<FunctionType>(F.getValueType()),
F.getLinkage(), F.getName(), &Dst);
NewF->copyAttributesFrom(&F);
if (VMap) {
(*VMap)[&F] = NewF;
auto NewArgI = NewF->arg_begin();
for (auto ArgI = F.arg_begin(), ArgE = F.arg_end(); ArgI != ArgE;
++ArgI, ++NewArgI)
(*VMap)[&*ArgI] = &*NewArgI;
}
return NewF;
}
void moveFunctionBody(Function &OrigF, ValueToValueMapTy &VMap,
ValueMaterializer *Materializer,
Function *NewF) {
assert(!OrigF.isDeclaration() && "Nothing to move");
if (!NewF)
NewF = cast<Function>(VMap[&OrigF]);
else
assert(VMap[&OrigF] == NewF && "Incorrect function mapping in VMap.");
assert(NewF && "Function mapping missing from VMap.");
assert(NewF->getParent() != OrigF.getParent() &&
"moveFunctionBody should only be used to move bodies between "
"modules.");
SmallVector<ReturnInst *, 8> Returns; // Ignore returns cloned.
CloneFunctionInto(NewF, &OrigF, VMap, /*ModuleLevelChanges=*/true, Returns,
"", nullptr, nullptr, Materializer);
OrigF.deleteBody();
}
GlobalVariable* cloneGlobalVariableDecl(Module &Dst, const GlobalVariable &GV,
ValueToValueMapTy *VMap) {
assert(GV.getParent() != &Dst && "Can't copy decl over existing global var.");
GlobalVariable *NewGV = new GlobalVariable(
Dst, GV.getValueType(), GV.isConstant(),
GV.getLinkage(), nullptr, GV.getName(), nullptr,
GV.getThreadLocalMode(), GV.getType()->getAddressSpace());
NewGV->copyAttributesFrom(&GV);
if (VMap)
(*VMap)[&GV] = NewGV;
return NewGV;
}
void moveGlobalVariableInitializer(GlobalVariable &OrigGV,
ValueToValueMapTy &VMap,
ValueMaterializer *Materializer,
GlobalVariable *NewGV) {
assert(OrigGV.hasInitializer() && "Nothing to move");
if (!NewGV)
NewGV = cast<GlobalVariable>(VMap[&OrigGV]);
else
assert(VMap[&OrigGV] == NewGV &&
"Incorrect global variable mapping in VMap.");
assert(NewGV->getParent() != OrigGV.getParent() &&
"moveGlobalVariable should only be used to move initializers between "
"modules");
NewGV->setInitializer(MapValue(OrigGV.getInitializer(), VMap, RF_None,
nullptr, Materializer));
}
GlobalAlias* cloneGlobalAliasDecl(Module &Dst, const GlobalAlias &OrigA,
ValueToValueMapTy &VMap) {
assert(OrigA.getAliasee() && "Original alias doesn't have an aliasee?");
auto *NewA = GlobalAlias::create(OrigA.getValueType(),
OrigA.getType()->getPointerAddressSpace(),
OrigA.getLinkage(), OrigA.getName(), &Dst);
NewA->copyAttributesFrom(&OrigA);
VMap[&OrigA] = NewA;
return NewA;
}
void cloneModuleFlagsMetadata(Module &Dst, const Module &Src,
ValueToValueMapTy &VMap) {
auto *MFs = Src.getModuleFlagsMetadata();
if (!MFs)
return;
for (auto *MF : MFs->operands())
Dst.addModuleFlag(MapMetadata(MF, VMap));
}
} // End namespace orc.
} // End namespace llvm.

View File

@ -0,0 +1,22 @@
;===- ./lib/ExecutionEngine/MCJIT/LLVMBuild.txt ----------------*- Conf -*--===;
;
; The LLVM Compiler Infrastructure
;
; This file is distributed under the University of Illinois Open Source
; License. See LICENSE.TXT for details.
;
;===------------------------------------------------------------------------===;
;
; This is an LLVMBuild description file for the components in this subdirectory.
;
; For more information on the LLVMBuild system, please see:
;
; http://llvm.org/docs/LLVMBuild.html
;
;===------------------------------------------------------------------------===;
[component_0]
type = Library
name = OrcJIT
parent = ExecutionEngine
required_libraries = Core ExecutionEngine Object RuntimeDyld Support TransformUtils

View File

@ -0,0 +1,26 @@
//===---------- NullResolver.cpp - Reject symbol lookup requests ----------===//
//
// 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/NullResolver.h"
#include "llvm/Support/ErrorHandling.h"
namespace llvm {
namespace orc {
JITSymbol NullResolver::findSymbol(const std::string &Name) {
llvm_unreachable("Unexpected cross-object symbol reference");
}
JITSymbol NullResolver::findSymbolInLogicalDylib(const std::string &Name) {
llvm_unreachable("Unexpected cross-object symbol reference");
}
} // End namespace orc.
} // End namespace llvm.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,128 @@
//===----------- OrcCBindings.cpp - C bindings for the Orc APIs -----------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "OrcCBindingsStack.h"
#include "llvm-c/OrcBindings.h"
using namespace llvm;
LLVMSharedModuleRef LLVMOrcMakeSharedModule(LLVMModuleRef Mod) {
return wrap(new std::shared_ptr<Module>(unwrap(Mod)));
}
void LLVMOrcDisposeSharedModuleRef(LLVMSharedModuleRef SharedMod) {
delete unwrap(SharedMod);
}
LLVMOrcJITStackRef LLVMOrcCreateInstance(LLVMTargetMachineRef TM) {
TargetMachine *TM2(unwrap(TM));
Triple T(TM2->getTargetTriple());
auto CompileCallbackMgr = orc::createLocalCompileCallbackManager(T, 0);
auto IndirectStubsMgrBuilder =
orc::createLocalIndirectStubsManagerBuilder(T);
OrcCBindingsStack *JITStack = new OrcCBindingsStack(
*TM2, std::move(CompileCallbackMgr), IndirectStubsMgrBuilder);
return wrap(JITStack);
}
const char *LLVMOrcGetErrorMsg(LLVMOrcJITStackRef JITStack) {
OrcCBindingsStack &J = *unwrap(JITStack);
return J.getErrorMessage().c_str();
}
void LLVMOrcGetMangledSymbol(LLVMOrcJITStackRef JITStack, char **MangledName,
const char *SymbolName) {
OrcCBindingsStack &J = *unwrap(JITStack);
std::string Mangled = J.mangle(SymbolName);
*MangledName = new char[Mangled.size() + 1];
strcpy(*MangledName, Mangled.c_str());
}
void LLVMOrcDisposeMangledSymbol(char *MangledName) { delete[] MangledName; }
LLVMOrcErrorCode
LLVMOrcCreateLazyCompileCallback(LLVMOrcJITStackRef JITStack,
LLVMOrcTargetAddress *RetAddr,
LLVMOrcLazyCompileCallbackFn Callback,
void *CallbackCtx) {
OrcCBindingsStack &J = *unwrap(JITStack);
return J.createLazyCompileCallback(*RetAddr, Callback, CallbackCtx);
}
LLVMOrcErrorCode LLVMOrcCreateIndirectStub(LLVMOrcJITStackRef JITStack,
const char *StubName,
LLVMOrcTargetAddress InitAddr) {
OrcCBindingsStack &J = *unwrap(JITStack);
return J.createIndirectStub(StubName, InitAddr);
}
LLVMOrcErrorCode LLVMOrcSetIndirectStubPointer(LLVMOrcJITStackRef JITStack,
const char *StubName,
LLVMOrcTargetAddress NewAddr) {
OrcCBindingsStack &J = *unwrap(JITStack);
return J.setIndirectStubPointer(StubName, NewAddr);
}
LLVMOrcErrorCode
LLVMOrcAddEagerlyCompiledIR(LLVMOrcJITStackRef JITStack,
LLVMOrcModuleHandle *RetHandle,
LLVMSharedModuleRef Mod,
LLVMOrcSymbolResolverFn SymbolResolver,
void *SymbolResolverCtx) {
OrcCBindingsStack &J = *unwrap(JITStack);
std::shared_ptr<Module> *M(unwrap(Mod));
return J.addIRModuleEager(*RetHandle, *M, SymbolResolver, SymbolResolverCtx);
}
LLVMOrcErrorCode
LLVMOrcAddLazilyCompiledIR(LLVMOrcJITStackRef JITStack,
LLVMOrcModuleHandle *RetHandle,
LLVMSharedModuleRef Mod,
LLVMOrcSymbolResolverFn SymbolResolver,
void *SymbolResolverCtx) {
OrcCBindingsStack &J = *unwrap(JITStack);
std::shared_ptr<Module> *M(unwrap(Mod));
return J.addIRModuleLazy(*RetHandle, *M, SymbolResolver, SymbolResolverCtx);
}
LLVMOrcErrorCode
LLVMOrcAddObjectFile(LLVMOrcJITStackRef JITStack,
LLVMOrcModuleHandle *RetHandle,
LLVMMemoryBufferRef Obj,
LLVMOrcSymbolResolverFn SymbolResolver,
void *SymbolResolverCtx) {
OrcCBindingsStack &J = *unwrap(JITStack);
std::unique_ptr<MemoryBuffer> O(unwrap(Obj));
return J.addObject(*RetHandle, std::move(O), SymbolResolver,
SymbolResolverCtx);
}
LLVMOrcErrorCode LLVMOrcRemoveModule(LLVMOrcJITStackRef JITStack,
LLVMOrcModuleHandle H) {
OrcCBindingsStack &J = *unwrap(JITStack);
return J.removeModule(H);
}
LLVMOrcErrorCode LLVMOrcGetSymbolAddress(LLVMOrcJITStackRef JITStack,
LLVMOrcTargetAddress *RetAddr,
const char *SymbolName) {
OrcCBindingsStack &J = *unwrap(JITStack);
return J.findSymbolAddress(*RetAddr, SymbolName, true);
}
LLVMOrcErrorCode LLVMOrcDisposeInstance(LLVMOrcJITStackRef JITStack) {
auto *J = unwrap(JITStack);
auto Err = J->shutdown();
delete J;
return Err;
}

View File

@ -0,0 +1,409 @@
//===- OrcCBindingsStack.h - Orc JIT stack for C bindings -----*- C++ -*---===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIB_EXECUTIONENGINE_ORC_ORCCBINDINGSSTACK_H
#define LLVM_LIB_EXECUTIONENGINE_ORC_ORCCBINDINGSSTACK_H
#include "llvm-c/OrcBindings.h"
#include "llvm-c/TargetMachine.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ExecutionEngine/JITSymbol.h"
#include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h"
#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
#include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
#include "llvm/ExecutionEngine/RuntimeDyld.h"
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Mangler.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/CBindingWrapping.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetMachine.h"
#include <algorithm>
#include <cstdint>
#include <functional>
#include <memory>
#include <set>
#include <string>
#include <vector>
namespace llvm {
class OrcCBindingsStack;
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(std::shared_ptr<Module>,
LLVMSharedModuleRef)
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(OrcCBindingsStack, LLVMOrcJITStackRef)
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef)
namespace detail {
class GenericHandle {
public:
virtual ~GenericHandle() = default;
virtual JITSymbol findSymbolIn(const std::string &Name,
bool ExportedSymbolsOnly) = 0;
virtual Error removeModule() = 0;
};
template <typename LayerT> class GenericHandleImpl : public GenericHandle {
public:
GenericHandleImpl(LayerT &Layer, typename LayerT::ModuleHandleT Handle)
: Layer(Layer), Handle(std::move(Handle)) {}
JITSymbol findSymbolIn(const std::string &Name,
bool ExportedSymbolsOnly) override {
return Layer.findSymbolIn(Handle, Name, ExportedSymbolsOnly);
}
Error removeModule() override { return Layer.removeModule(Handle); }
private:
LayerT &Layer;
typename LayerT::ModuleHandleT Handle;
};
template <>
class GenericHandleImpl<orc::RTDyldObjectLinkingLayer>
: public GenericHandle {
private:
using LayerT = orc::RTDyldObjectLinkingLayer;
public:
GenericHandleImpl(LayerT &Layer, typename LayerT::ObjHandleT Handle)
: Layer(Layer), Handle(std::move(Handle)) {}
JITSymbol findSymbolIn(const std::string &Name,
bool ExportedSymbolsOnly) override {
return Layer.findSymbolIn(Handle, Name, ExportedSymbolsOnly);
}
Error removeModule() override { return Layer.removeObject(Handle); }
private:
LayerT &Layer;
typename LayerT::ObjHandleT Handle;
};
template <typename LayerT, typename HandleT>
std::unique_ptr<GenericHandleImpl<LayerT>>
createGenericHandle(LayerT &Layer, HandleT Handle) {
return llvm::make_unique<GenericHandleImpl<LayerT>>(Layer,
std::move(Handle));
}
} // end namespace detail
class OrcCBindingsStack {
public:
using CompileCallbackMgr = orc::JITCompileCallbackManager;
using ObjLayerT = orc::RTDyldObjectLinkingLayer;
using CompileLayerT = orc::IRCompileLayer<ObjLayerT, orc::SimpleCompiler>;
using CODLayerT =
orc::CompileOnDemandLayer<CompileLayerT, CompileCallbackMgr>;
using CallbackManagerBuilder =
std::function<std::unique_ptr<CompileCallbackMgr>()>;
using IndirectStubsManagerBuilder = CODLayerT::IndirectStubsManagerBuilderT;
private:
using OwningObject = object::OwningBinary<object::ObjectFile>;
public:
using ModuleHandleT = unsigned;
OrcCBindingsStack(TargetMachine &TM,
std::unique_ptr<CompileCallbackMgr> CCMgr,
IndirectStubsManagerBuilder IndirectStubsMgrBuilder)
: DL(TM.createDataLayout()), IndirectStubsMgr(IndirectStubsMgrBuilder()),
CCMgr(std::move(CCMgr)),
ObjectLayer(
[]() {
return std::make_shared<SectionMemoryManager>();
}),
CompileLayer(ObjectLayer, orc::SimpleCompiler(TM)),
CODLayer(CompileLayer,
[](Function &F) { return std::set<Function *>({&F}); },
*this->CCMgr, std::move(IndirectStubsMgrBuilder), false),
CXXRuntimeOverrides(
[this](const std::string &S) { return mangle(S); }) {}
LLVMOrcErrorCode shutdown() {
// Run any destructors registered with __cxa_atexit.
CXXRuntimeOverrides.runDestructors();
// Run any IR destructors.
for (auto &DtorRunner : IRStaticDestructorRunners)
if (auto Err = DtorRunner.runViaLayer(*this))
return mapError(std::move(Err));
return LLVMOrcErrSuccess;
}
std::string mangle(StringRef Name) {
std::string MangledName;
{
raw_string_ostream MangledNameStream(MangledName);
Mangler::getNameWithPrefix(MangledNameStream, Name, DL);
}
return MangledName;
}
template <typename PtrTy>
static PtrTy fromTargetAddress(JITTargetAddress Addr) {
return reinterpret_cast<PtrTy>(static_cast<uintptr_t>(Addr));
}
LLVMOrcErrorCode
createLazyCompileCallback(JITTargetAddress &RetAddr,
LLVMOrcLazyCompileCallbackFn Callback,
void *CallbackCtx) {
if (auto CCInfoOrErr = CCMgr->getCompileCallback()) {
auto &CCInfo = *CCInfoOrErr;
CCInfo.setCompileAction([=]() -> JITTargetAddress {
return Callback(wrap(this), CallbackCtx);
});
RetAddr = CCInfo.getAddress();
return LLVMOrcErrSuccess;
} else
return mapError(CCInfoOrErr.takeError());
}
LLVMOrcErrorCode createIndirectStub(StringRef StubName,
JITTargetAddress Addr) {
return mapError(
IndirectStubsMgr->createStub(StubName, Addr, JITSymbolFlags::Exported));
}
LLVMOrcErrorCode setIndirectStubPointer(StringRef Name,
JITTargetAddress Addr) {
return mapError(IndirectStubsMgr->updatePointer(Name, Addr));
}
std::shared_ptr<JITSymbolResolver>
createResolver(LLVMOrcSymbolResolverFn ExternalResolver,
void *ExternalResolverCtx) {
return orc::createLambdaResolver(
[this, ExternalResolver, ExternalResolverCtx](const std::string &Name)
-> JITSymbol {
// Search order:
// 1. JIT'd symbols.
// 2. Runtime overrides.
// 3. External resolver (if present).
if (auto Sym = CODLayer.findSymbol(Name, true))
return Sym;
else if (auto Err = Sym.takeError())
return Sym.takeError();
if (auto Sym = CXXRuntimeOverrides.searchOverrides(Name))
return Sym;
if (ExternalResolver)
return JITSymbol(
ExternalResolver(Name.c_str(), ExternalResolverCtx),
JITSymbolFlags::Exported);
return JITSymbol(nullptr);
},
[](const std::string &Name) -> JITSymbol {
return JITSymbol(nullptr);
});
}
template <typename LayerT>
LLVMOrcErrorCode
addIRModule(ModuleHandleT &RetHandle, LayerT &Layer,
std::shared_ptr<Module> M,
std::unique_ptr<RuntimeDyld::MemoryManager> MemMgr,
LLVMOrcSymbolResolverFn ExternalResolver,
void *ExternalResolverCtx) {
// Attach a data-layout if one isn't already present.
if (M->getDataLayout().isDefault())
M->setDataLayout(DL);
// Record the static constructors and destructors. We have to do this before
// 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()));
// Create the resolver.
auto Resolver = createResolver(ExternalResolver, ExternalResolverCtx);
// Add the module to the JIT.
ModuleHandleT H;
if (auto LHOrErr = Layer.addModule(std::move(M), std::move(Resolver)))
H = createHandle(Layer, *LHOrErr);
else
return mapError(LHOrErr.takeError());
// Run the static constructors, and save the static destructor runner for
// execution when the JIT is torn down.
orc::CtorDtorRunner<OrcCBindingsStack> CtorRunner(std::move(CtorNames), H);
if (auto Err = CtorRunner.runViaLayer(*this))
return mapError(std::move(Err));
IRStaticDestructorRunners.emplace_back(std::move(DtorNames), H);
RetHandle = H;
return LLVMOrcErrSuccess;
}
LLVMOrcErrorCode addIRModuleEager(ModuleHandleT &RetHandle,
std::shared_ptr<Module> M,
LLVMOrcSymbolResolverFn ExternalResolver,
void *ExternalResolverCtx) {
return addIRModule(RetHandle, CompileLayer, std::move(M),
llvm::make_unique<SectionMemoryManager>(),
std::move(ExternalResolver), ExternalResolverCtx);
}
LLVMOrcErrorCode addIRModuleLazy(ModuleHandleT &RetHandle,
std::shared_ptr<Module> M,
LLVMOrcSymbolResolverFn ExternalResolver,
void *ExternalResolverCtx) {
return addIRModule(RetHandle, CODLayer, std::move(M),
llvm::make_unique<SectionMemoryManager>(),
std::move(ExternalResolver), ExternalResolverCtx);
}
LLVMOrcErrorCode removeModule(ModuleHandleT H) {
if (auto Err = GenericHandles[H]->removeModule())
return mapError(std::move(Err));
GenericHandles[H] = nullptr;
FreeHandleIndexes.push_back(H);
return LLVMOrcErrSuccess;
}
LLVMOrcErrorCode addObject(ModuleHandleT &RetHandle,
std::unique_ptr<MemoryBuffer> ObjBuffer,
LLVMOrcSymbolResolverFn ExternalResolver,
void *ExternalResolverCtx) {
if (auto ObjOrErr =
object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef())) {
auto &Obj = *ObjOrErr;
auto OwningObj =
std::make_shared<OwningObject>(std::move(Obj), std::move(ObjBuffer));
// Create the resolver.
auto Resolver = createResolver(ExternalResolver, ExternalResolverCtx);
ModuleHandleT H;
if (auto HOrErr = ObjectLayer.addObject(std::move(OwningObj),
std::move(Resolver)))
H = createHandle(ObjectLayer, *HOrErr);
else
return mapError(HOrErr.takeError());
RetHandle = H;
return LLVMOrcErrSuccess;
} else
return mapError(ObjOrErr.takeError());
}
JITSymbol findSymbol(const std::string &Name,
bool ExportedSymbolsOnly) {
if (auto Sym = IndirectStubsMgr->findStub(Name, ExportedSymbolsOnly))
return Sym;
return CODLayer.findSymbol(mangle(Name), ExportedSymbolsOnly);
}
JITSymbol findSymbolIn(ModuleHandleT H, const std::string &Name,
bool ExportedSymbolsOnly) {
return GenericHandles[H]->findSymbolIn(Name, ExportedSymbolsOnly);
}
LLVMOrcErrorCode findSymbolAddress(JITTargetAddress &RetAddr,
const std::string &Name,
bool ExportedSymbolsOnly) {
RetAddr = 0;
if (auto Sym = findSymbol(Name, ExportedSymbolsOnly)) {
// Successful lookup, non-null symbol:
if (auto AddrOrErr = Sym.getAddress()) {
RetAddr = *AddrOrErr;
return LLVMOrcErrSuccess;
} else
return mapError(AddrOrErr.takeError());
} else if (auto Err = Sym.takeError()) {
// Lookup failure - report error.
return mapError(std::move(Err));
}
// Otherwise we had a successful lookup but got a null result. We already
// set RetAddr to '0' above, so just return success.
return LLVMOrcErrSuccess;
}
const std::string &getErrorMessage() const { return ErrMsg; }
private:
template <typename LayerT, typename HandleT>
unsigned createHandle(LayerT &Layer, HandleT Handle) {
unsigned NewHandle;
if (!FreeHandleIndexes.empty()) {
NewHandle = FreeHandleIndexes.back();
FreeHandleIndexes.pop_back();
GenericHandles[NewHandle] =
detail::createGenericHandle(Layer, std::move(Handle));
return NewHandle;
} else {
NewHandle = GenericHandles.size();
GenericHandles.push_back(
detail::createGenericHandle(Layer, std::move(Handle)));
}
return NewHandle;
}
LLVMOrcErrorCode mapError(Error Err) {
LLVMOrcErrorCode Result = LLVMOrcErrSuccess;
handleAllErrors(std::move(Err), [&](ErrorInfoBase &EIB) {
// Handler of last resort.
Result = LLVMOrcErrGeneric;
ErrMsg = "";
raw_string_ostream ErrStream(ErrMsg);
EIB.log(ErrStream);
});
return Result;
}
DataLayout DL;
SectionMemoryManager CCMgrMemMgr;
std::unique_ptr<orc::IndirectStubsManager> IndirectStubsMgr;
std::unique_ptr<CompileCallbackMgr> CCMgr;
ObjLayerT ObjectLayer;
CompileLayerT CompileLayer;
CODLayerT CODLayer;
std::vector<std::unique_ptr<detail::GenericHandle>> GenericHandles;
std::vector<unsigned> FreeHandleIndexes;
orc::LocalCXXRuntimeOverrides CXXRuntimeOverrides;
std::vector<orc::CtorDtorRunner<OrcCBindingsStack>> IRStaticDestructorRunners;
std::string ErrMsg;
};
} // end namespace llvm
#endif // LLVM_LIB_EXECUTIONENGINE_ORC_ORCCBINDINGSSTACK_H

View File

@ -0,0 +1,95 @@
//===---------------- OrcError.cpp - Error codes for ORC ------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Error codes for ORC.
//
//===----------------------------------------------------------------------===//
#include "llvm/ExecutionEngine/Orc/OrcError.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ManagedStatic.h"
using namespace llvm;
using namespace llvm::orc;
namespace {
// FIXME: This class is only here to support the transition to llvm::Error. It
// will be removed once this transition is complete. Clients should prefer to
// deal with the Error value directly, rather than converting to error_code.
class OrcErrorCategory : public std::error_category {
public:
const char *name() const noexcept override { return "orc"; }
std::string message(int condition) const override {
switch (static_cast<OrcErrorCode>(condition)) {
case OrcErrorCode::RemoteAllocatorDoesNotExist:
return "Remote allocator does not exist";
case OrcErrorCode::RemoteAllocatorIdAlreadyInUse:
return "Remote allocator Id already in use";
case OrcErrorCode::RemoteMProtectAddrUnrecognized:
return "Remote mprotect call references unallocated memory";
case OrcErrorCode::RemoteIndirectStubsOwnerDoesNotExist:
return "Remote indirect stubs owner does not exist";
case OrcErrorCode::RemoteIndirectStubsOwnerIdAlreadyInUse:
return "Remote indirect stubs owner Id already in use";
case OrcErrorCode::RPCConnectionClosed:
return "RPC connection closed";
case OrcErrorCode::RPCCouldNotNegotiateFunction:
return "Could not negotiate RPC function";
case OrcErrorCode::RPCResponseAbandoned:
return "RPC response abandoned";
case OrcErrorCode::JITSymbolNotFound:
return "JIT symbol not found";
case OrcErrorCode::UnexpectedRPCCall:
return "Unexpected RPC call";
case OrcErrorCode::UnexpectedRPCResponse:
return "Unexpected RPC response";
case OrcErrorCode::UnknownErrorCodeFromRemote:
return "Unknown error returned from remote RPC function "
"(Use StringError to get error message)";
case OrcErrorCode::UnknownResourceHandle:
return "Unknown resource handle";
}
llvm_unreachable("Unhandled error code");
}
};
static ManagedStatic<OrcErrorCategory> OrcErrCat;
}
namespace llvm {
namespace orc {
char JITSymbolNotFound::ID = 0;
std::error_code orcError(OrcErrorCode ErrCode) {
typedef std::underlying_type<OrcErrorCode>::type UT;
return std::error_code(static_cast<UT>(ErrCode), *OrcErrCat);
}
JITSymbolNotFound::JITSymbolNotFound(std::string SymbolName)
: SymbolName(std::move(SymbolName)) {}
std::error_code JITSymbolNotFound::convertToErrorCode() const {
typedef std::underlying_type<OrcErrorCode>::type UT;
return std::error_code(static_cast<UT>(OrcErrorCode::JITSymbolNotFound),
*OrcErrCat);
}
void JITSymbolNotFound::log(raw_ostream &OS) const {
OS << "Could not find symbol '" << SymbolName << "'";
}
const std::string &JITSymbolNotFound::getSymbolName() const {
return SymbolName;
}
}
}

View File

@ -0,0 +1,133 @@
//===-------- OrcMCJITReplacement.cpp - Orc-based MCJIT replacement -------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "OrcMCJITReplacement.h"
#include "llvm/ExecutionEngine/GenericValue.h"
namespace {
static struct RegisterJIT {
RegisterJIT() { llvm::orc::OrcMCJITReplacement::Register(); }
} JITRegistrator;
}
extern "C" void LLVMLinkInOrcMCJITReplacement() {}
namespace llvm {
namespace orc {
GenericValue
OrcMCJITReplacement::runFunction(Function *F,
ArrayRef<GenericValue> ArgValues) {
assert(F && "Function *F was null at entry to run()");
void *FPtr = getPointerToFunction(F);
assert(FPtr && "Pointer to fn's code was null after getPointerToFunction");
FunctionType *FTy = F->getFunctionType();
Type *RetTy = FTy->getReturnType();
assert((FTy->getNumParams() == ArgValues.size() ||
(FTy->isVarArg() && FTy->getNumParams() <= ArgValues.size())) &&
"Wrong number of arguments passed into function!");
assert(FTy->getNumParams() == ArgValues.size() &&
"This doesn't support passing arguments through varargs (yet)!");
// Handle some common cases first. These cases correspond to common `main'
// prototypes.
if (RetTy->isIntegerTy(32) || RetTy->isVoidTy()) {
switch (ArgValues.size()) {
case 3:
if (FTy->getParamType(0)->isIntegerTy(32) &&
FTy->getParamType(1)->isPointerTy() &&
FTy->getParamType(2)->isPointerTy()) {
int (*PF)(int, char **, const char **) =
(int (*)(int, char **, const char **))(intptr_t)FPtr;
// Call the function.
GenericValue rv;
rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(),
(char **)GVTOP(ArgValues[1]),
(const char **)GVTOP(ArgValues[2])));
return rv;
}
break;
case 2:
if (FTy->getParamType(0)->isIntegerTy(32) &&
FTy->getParamType(1)->isPointerTy()) {
int (*PF)(int, char **) = (int (*)(int, char **))(intptr_t)FPtr;
// Call the function.
GenericValue rv;
rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(),
(char **)GVTOP(ArgValues[1])));
return rv;
}
break;
case 1:
if (FTy->getNumParams() == 1 && FTy->getParamType(0)->isIntegerTy(32)) {
GenericValue rv;
int (*PF)(int) = (int (*)(int))(intptr_t)FPtr;
rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue()));
return rv;
}
break;
}
}
// Handle cases where no arguments are passed first.
if (ArgValues.empty()) {
GenericValue rv;
switch (RetTy->getTypeID()) {
default:
llvm_unreachable("Unknown return type for function call!");
case Type::IntegerTyID: {
unsigned BitWidth = cast<IntegerType>(RetTy)->getBitWidth();
if (BitWidth == 1)
rv.IntVal = APInt(BitWidth, ((bool (*)())(intptr_t)FPtr)());
else if (BitWidth <= 8)
rv.IntVal = APInt(BitWidth, ((char (*)())(intptr_t)FPtr)());
else if (BitWidth <= 16)
rv.IntVal = APInt(BitWidth, ((short (*)())(intptr_t)FPtr)());
else if (BitWidth <= 32)
rv.IntVal = APInt(BitWidth, ((int (*)())(intptr_t)FPtr)());
else if (BitWidth <= 64)
rv.IntVal = APInt(BitWidth, ((int64_t (*)())(intptr_t)FPtr)());
else
llvm_unreachable("Integer types > 64 bits not supported");
return rv;
}
case Type::VoidTyID:
rv.IntVal = APInt(32, ((int (*)())(intptr_t)FPtr)());
return rv;
case Type::FloatTyID:
rv.FloatVal = ((float (*)())(intptr_t)FPtr)();
return rv;
case Type::DoubleTyID:
rv.DoubleVal = ((double (*)())(intptr_t)FPtr)();
return rv;
case Type::X86_FP80TyID:
case Type::FP128TyID:
case Type::PPC_FP128TyID:
llvm_unreachable("long double not supported yet");
case Type::PointerTyID:
return PTOGV(((void *(*)())(intptr_t)FPtr)());
}
}
llvm_unreachable("Full-featured argument passing not supported yet!");
}
void OrcMCJITReplacement::runStaticConstructorsDestructors(bool isDtors) {
for (auto &M : LocalModules)
ExecutionEngine::runStaticConstructorsDestructors(*M, isDtors);
}
} // End namespace orc.
} // End namespace llvm.

View File

@ -0,0 +1,418 @@
//===- OrcMCJITReplacement.h - Orc based MCJIT replacement ------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Orc based MCJIT replacement.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIB_EXECUTIONENGINE_ORC_ORCMCJITREPLACEMENT_H
#define LLVM_LIB_EXECUTIONENGINE_ORC_ORCMCJITREPLACEMENT_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/ExecutionEngine/GenericValue.h"
#include "llvm/ExecutionEngine/JITSymbol.h"
#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
#include "llvm/ExecutionEngine/Orc/LazyEmittingLayer.h"
#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
#include "llvm/ExecutionEngine/RuntimeDyld.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Mangler.h"
#include "llvm/IR/Module.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/Binary.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetMachine.h"
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <map>
#include <memory>
#include <set>
#include <string>
#include <vector>
namespace llvm {
class ObjectCache;
namespace orc {
class OrcMCJITReplacement : public ExecutionEngine {
// OrcMCJITReplacement needs to do a little extra book-keeping to ensure that
// Orc's automatic finalization doesn't kick in earlier than MCJIT clients are
// expecting - see finalizeMemory.
class MCJITReplacementMemMgr : public MCJITMemoryManager {
public:
MCJITReplacementMemMgr(OrcMCJITReplacement &M,
std::shared_ptr<MCJITMemoryManager> ClientMM)
: M(M), ClientMM(std::move(ClientMM)) {}
uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
unsigned SectionID,
StringRef SectionName) override {
uint8_t *Addr =
ClientMM->allocateCodeSection(Size, Alignment, SectionID,
SectionName);
M.SectionsAllocatedSinceLastLoad.insert(Addr);
return Addr;
}
uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
unsigned SectionID, StringRef SectionName,
bool IsReadOnly) override {
uint8_t *Addr = ClientMM->allocateDataSection(Size, Alignment, SectionID,
SectionName, IsReadOnly);
M.SectionsAllocatedSinceLastLoad.insert(Addr);
return Addr;
}
void reserveAllocationSpace(uintptr_t CodeSize, uint32_t CodeAlign,
uintptr_t RODataSize, uint32_t RODataAlign,
uintptr_t RWDataSize,
uint32_t RWDataAlign) override {
return ClientMM->reserveAllocationSpace(CodeSize, CodeAlign,
RODataSize, RODataAlign,
RWDataSize, RWDataAlign);
}
bool needsToReserveAllocationSpace() override {
return ClientMM->needsToReserveAllocationSpace();
}
void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr,
size_t Size) override {
return ClientMM->registerEHFrames(Addr, LoadAddr, Size);
}
void deregisterEHFrames() override {
return ClientMM->deregisterEHFrames();
}
void notifyObjectLoaded(RuntimeDyld &RTDyld,
const object::ObjectFile &O) override {
return ClientMM->notifyObjectLoaded(RTDyld, O);
}
void notifyObjectLoaded(ExecutionEngine *EE,
const object::ObjectFile &O) override {
return ClientMM->notifyObjectLoaded(EE, O);
}
bool finalizeMemory(std::string *ErrMsg = nullptr) override {
// Each set of objects loaded will be finalized exactly once, but since
// symbol lookup during relocation may recursively trigger the
// loading/relocation of other modules, and since we're forwarding all
// finalizeMemory calls to a single underlying memory manager, we need to
// defer forwarding the call on until all necessary objects have been
// loaded. Otherwise, during the relocation of a leaf object, we will end
// up finalizing memory, causing a crash further up the stack when we
// attempt to apply relocations to finalized memory.
// To avoid finalizing too early, look at how many objects have been
// loaded but not yet finalized. This is a bit of a hack that relies on
// the fact that we're lazily emitting object files: The only way you can
// get more than one set of objects loaded but not yet finalized is if
// they were loaded during relocation of another set.
if (M.UnfinalizedSections.size() == 1)
return ClientMM->finalizeMemory(ErrMsg);
return false;
}
private:
OrcMCJITReplacement &M;
std::shared_ptr<MCJITMemoryManager> ClientMM;
};
class LinkingResolver : public JITSymbolResolver {
public:
LinkingResolver(OrcMCJITReplacement &M) : M(M) {}
JITSymbol findSymbol(const std::string &Name) override {
return M.ClientResolver->findSymbol(Name);
}
JITSymbol findSymbolInLogicalDylib(const std::string &Name) override {
if (auto Sym = M.findMangledSymbol(Name))
return Sym;
return M.ClientResolver->findSymbolInLogicalDylib(Name);
}
private:
OrcMCJITReplacement &M;
};
private:
static ExecutionEngine *
createOrcMCJITReplacement(std::string *ErrorMsg,
std::shared_ptr<MCJITMemoryManager> MemMgr,
std::shared_ptr<JITSymbolResolver> Resolver,
std::unique_ptr<TargetMachine> TM) {
return new OrcMCJITReplacement(std::move(MemMgr), std::move(Resolver),
std::move(TM));
}
public:
OrcMCJITReplacement(
std::shared_ptr<MCJITMemoryManager> MemMgr,
std::shared_ptr<JITSymbolResolver> ClientResolver,
std::unique_ptr<TargetMachine> TM)
: ExecutionEngine(TM->createDataLayout()), TM(std::move(TM)),
MemMgr(std::make_shared<MCJITReplacementMemMgr>(*this,
std::move(MemMgr))),
Resolver(std::make_shared<LinkingResolver>(*this)),
ClientResolver(std::move(ClientResolver)), NotifyObjectLoaded(*this),
NotifyFinalized(*this),
ObjectLayer([this]() { return this->MemMgr; }, NotifyObjectLoaded,
NotifyFinalized),
CompileLayer(ObjectLayer, SimpleCompiler(*this->TM)),
LazyEmitLayer(CompileLayer) {}
static void Register() {
OrcMCJITReplacementCtor = createOrcMCJITReplacement;
}
void addModule(std::unique_ptr<Module> M) override {
// If this module doesn't have a DataLayout attached then attach the
// default.
if (M->getDataLayout().isDefault()) {
M->setDataLayout(getDataLayout());
} else {
assert(M->getDataLayout() == getDataLayout() && "DataLayout Mismatch");
}
auto *MPtr = M.release();
ShouldDelete[MPtr] = true;
auto Deleter = [this](Module *Mod) {
auto I = ShouldDelete.find(Mod);
if (I != ShouldDelete.end() && I->second)
delete Mod;
};
LocalModules.push_back(std::shared_ptr<Module>(MPtr, std::move(Deleter)));
cantFail(LazyEmitLayer.addModule(LocalModules.back(), Resolver));
}
void addObjectFile(std::unique_ptr<object::ObjectFile> O) override {
auto Obj =
std::make_shared<object::OwningBinary<object::ObjectFile>>(std::move(O),
nullptr);
cantFail(ObjectLayer.addObject(std::move(Obj), Resolver));
}
void addObjectFile(object::OwningBinary<object::ObjectFile> O) override {
auto Obj =
std::make_shared<object::OwningBinary<object::ObjectFile>>(std::move(O));
cantFail(ObjectLayer.addObject(std::move(Obj), Resolver));
}
void addArchive(object::OwningBinary<object::Archive> A) override {
Archives.push_back(std::move(A));
}
bool removeModule(Module *M) override {
for (auto I = LocalModules.begin(), E = LocalModules.end(); I != E; ++I) {
if (I->get() == M) {
ShouldDelete[M] = false;
LocalModules.erase(I);
return true;
}
}
return false;
}
uint64_t getSymbolAddress(StringRef Name) {
return cantFail(findSymbol(Name).getAddress());
}
JITSymbol findSymbol(StringRef Name) {
return findMangledSymbol(Mangle(Name));
}
void finalizeObject() override {
// This is deprecated - Aim to remove in ExecutionEngine.
// REMOVE IF POSSIBLE - Doesn't make sense for New JIT.
}
void mapSectionAddress(const void *LocalAddress,
uint64_t TargetAddress) override {
for (auto &P : UnfinalizedSections)
if (P.second.count(LocalAddress))
ObjectLayer.mapSectionAddress(P.first, LocalAddress, TargetAddress);
}
uint64_t getGlobalValueAddress(const std::string &Name) override {
return getSymbolAddress(Name);
}
uint64_t getFunctionAddress(const std::string &Name) override {
return getSymbolAddress(Name);
}
void *getPointerToFunction(Function *F) override {
uint64_t FAddr = getSymbolAddress(F->getName());
return reinterpret_cast<void *>(static_cast<uintptr_t>(FAddr));
}
void *getPointerToNamedFunction(StringRef Name,
bool AbortOnFailure = true) override {
uint64_t Addr = getSymbolAddress(Name);
if (!Addr && AbortOnFailure)
llvm_unreachable("Missing symbol!");
return reinterpret_cast<void *>(static_cast<uintptr_t>(Addr));
}
GenericValue runFunction(Function *F,
ArrayRef<GenericValue> ArgValues) override;
void setObjectCache(ObjectCache *NewCache) override {
CompileLayer.getCompiler().setObjectCache(NewCache);
}
void setProcessAllSections(bool ProcessAllSections) override {
ObjectLayer.setProcessAllSections(ProcessAllSections);
}
void runStaticConstructorsDestructors(bool isDtors) override;
private:
JITSymbol findMangledSymbol(StringRef Name) {
if (auto Sym = LazyEmitLayer.findSymbol(Name, false))
return Sym;
if (auto Sym = ClientResolver->findSymbol(Name))
return Sym;
if (auto Sym = scanArchives(Name))
return Sym;
return nullptr;
}
JITSymbol scanArchives(StringRef Name) {
for (object::OwningBinary<object::Archive> &OB : Archives) {
object::Archive *A = OB.getBinary();
// Look for our symbols in each Archive
auto OptionalChildOrErr = A->findSym(Name);
if (!OptionalChildOrErr)
report_fatal_error(OptionalChildOrErr.takeError());
auto &OptionalChild = *OptionalChildOrErr;
if (OptionalChild) {
// FIXME: Support nested archives?
Expected<std::unique_ptr<object::Binary>> ChildBinOrErr =
OptionalChild->getAsBinary();
if (!ChildBinOrErr) {
// TODO: Actually report errors helpfully.
consumeError(ChildBinOrErr.takeError());
continue;
}
std::unique_ptr<object::Binary> &ChildBin = ChildBinOrErr.get();
if (ChildBin->isObject()) {
std::unique_ptr<object::ObjectFile> ChildObj(
static_cast<object::ObjectFile*>(ChildBinOrErr->release()));
auto Obj =
std::make_shared<object::OwningBinary<object::ObjectFile>>(
std::move(ChildObj), nullptr);
cantFail(ObjectLayer.addObject(std::move(Obj), Resolver));
if (auto Sym = ObjectLayer.findSymbol(Name, true))
return Sym;
}
}
}
return nullptr;
}
class NotifyObjectLoadedT {
public:
using LoadedObjInfoListT =
std::vector<std::unique_ptr<RuntimeDyld::LoadedObjectInfo>>;
NotifyObjectLoadedT(OrcMCJITReplacement &M) : M(M) {}
void operator()(RTDyldObjectLinkingLayerBase::ObjHandleT H,
const RTDyldObjectLinkingLayer::ObjectPtr &Obj,
const RuntimeDyld::LoadedObjectInfo &Info) const {
M.UnfinalizedSections[H] = std::move(M.SectionsAllocatedSinceLastLoad);
M.SectionsAllocatedSinceLastLoad = SectionAddrSet();
M.MemMgr->notifyObjectLoaded(&M, *Obj->getBinary());
}
private:
OrcMCJITReplacement &M;
};
class NotifyFinalizedT {
public:
NotifyFinalizedT(OrcMCJITReplacement &M) : M(M) {}
void operator()(RTDyldObjectLinkingLayerBase::ObjHandleT H) {
M.UnfinalizedSections.erase(H);
}
private:
OrcMCJITReplacement &M;
};
std::string Mangle(StringRef Name) {
std::string MangledName;
{
raw_string_ostream MangledNameStream(MangledName);
Mang.getNameWithPrefix(MangledNameStream, Name, getDataLayout());
}
return MangledName;
}
using ObjectLayerT = RTDyldObjectLinkingLayer;
using CompileLayerT = IRCompileLayer<ObjectLayerT, orc::SimpleCompiler>;
using LazyEmitLayerT = LazyEmittingLayer<CompileLayerT>;
std::unique_ptr<TargetMachine> TM;
std::shared_ptr<MCJITReplacementMemMgr> MemMgr;
std::shared_ptr<LinkingResolver> Resolver;
std::shared_ptr<JITSymbolResolver> ClientResolver;
Mangler Mang;
// IMPORTANT: ShouldDelete *must* come before LocalModules: The shared_ptr
// delete blocks in LocalModules refer to the ShouldDelete map, so
// LocalModules needs to be destructed before ShouldDelete.
std::map<Module*, bool> ShouldDelete;
std::vector<std::shared_ptr<Module>> LocalModules;
NotifyObjectLoadedT NotifyObjectLoaded;
NotifyFinalizedT NotifyFinalized;
ObjectLayerT ObjectLayer;
CompileLayerT CompileLayer;
LazyEmitLayerT LazyEmitLayer;
// We need to store ObjLayerT::ObjSetHandles for each of the object sets
// that have been emitted but not yet finalized so that we can forward the
// mapSectionAddress calls appropriately.
using SectionAddrSet = std::set<const void *>;
struct ObjHandleCompare {
bool operator()(ObjectLayerT::ObjHandleT H1,
ObjectLayerT::ObjHandleT H2) const {
return &*H1 < &*H2;
}
};
SectionAddrSet SectionsAllocatedSinceLastLoad;
std::map<ObjectLayerT::ObjHandleT, SectionAddrSet, ObjHandleCompare>
UnfinalizedSections;
std::vector<object::OwningBinary<object::Archive>> Archives;
};
} // end namespace orc
} // end namespace llvm
#endif // LLVM_LIB_EXECUTIONENGINE_ORC_MCJITREPLACEMENT_H

View File

@ -0,0 +1,55 @@
//===--------------- RPCUtils.cpp - RPCUtils implementation ---------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// RPCUtils implementation.
//
//===----------------------------------------------------------------------===//
#include "llvm/ExecutionEngine/Orc/RPCUtils.h"
char llvm::orc::rpc::RPCFatalError::ID = 0;
char llvm::orc::rpc::ConnectionClosed::ID = 0;
char llvm::orc::rpc::ResponseAbandoned::ID = 0;
char llvm::orc::rpc::CouldNotNegotiate::ID = 0;
namespace llvm {
namespace orc {
namespace rpc {
std::error_code ConnectionClosed::convertToErrorCode() const {
return orcError(OrcErrorCode::RPCConnectionClosed);
}
void ConnectionClosed::log(raw_ostream &OS) const {
OS << "RPC connection already closed";
}
std::error_code ResponseAbandoned::convertToErrorCode() const {
return orcError(OrcErrorCode::RPCResponseAbandoned);
}
void ResponseAbandoned::log(raw_ostream &OS) const {
OS << "RPC response abandoned";
}
CouldNotNegotiate::CouldNotNegotiate(std::string Signature)
: Signature(std::move(Signature)) {}
std::error_code CouldNotNegotiate::convertToErrorCode() const {
return orcError(OrcErrorCode::RPCCouldNotNegotiateFunction);
}
void CouldNotNegotiate::log(raw_ostream &OS) const {
OS << "Could not negotiate RPC function " << Signature;
}
} // end namespace rpc
} // end namespace orc
} // end namespace llvm