Skip to content

Commit

Permalink
Revert "[Orc] Directly emit machine code for the x86 resolver block a…
Browse files Browse the repository at this point in the history
…nd trampolines."

This reverts commit r251933.

It broke the build of examples/Kaleidoscope/Orc/fully_lazy/toy.cpp.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@251937 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
espindola committed Nov 3, 2015
1 parent 6ea7358 commit 1b023a3
Show file tree
Hide file tree
Showing 12 changed files with 289 additions and 194 deletions.
3 changes: 2 additions & 1 deletion include/llvm-c/OrcBindings.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ typedef uint64_t (*LLVMOrcLazyCompileCallbackFn)(LLVMOrcJITStackRef JITStack,
* client should not attempt to dispose of the Target Machine, or it will result
* in a double-free.
*/
LLVMOrcJITStackRef LLVMOrcCreateInstance(LLVMTargetMachineRef TM);
LLVMOrcJITStackRef LLVMOrcCreateInstance(LLVMTargetMachineRef TM,
LLVMContextRef Context);

/**
* Mangle the given symbol.
Expand Down
2 changes: 1 addition & 1 deletion include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ class CompileOnDemandLayer {
// Create a callback, associate it with the stub for the function,
// and set the compile action to compile the partition containing the
// function.
auto CCInfo = CompileCallbackMgr.getCompileCallback();
auto CCInfo = CompileCallbackMgr.getCompileCallback(SrcM.getContext());
StubInits[mangle(F.getName(), DL)] =
std::make_pair(CCInfo.getAddress(),
JITSymbolBase::flagsFromGlobalValue(F));
Expand Down
148 changes: 82 additions & 66 deletions include/llvm/ExecutionEngine/Orc/IndirectionUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@
namespace llvm {
namespace orc {

/// @brief Target-independent base class JITCompileCallbackManager.
/// @brief Base class for JITLayer independent aspects of
/// JITCompileCallbackManager.
class JITCompileCallbackManagerBase {
public:

Expand All @@ -53,8 +54,13 @@ class JITCompileCallbackManagerBase {
/// @brief Construct a JITCompileCallbackManagerBase.
/// @param ErrorHandlerAddress The address of an error handler in the target
/// process to be used if a compile callback fails.
JITCompileCallbackManagerBase(TargetAddress ErrorHandlerAddress)
: ErrorHandlerAddress(ErrorHandlerAddress) {}
/// @param NumTrampolinesPerBlock Number of trampolines to emit if there is no
/// available trampoline when getCompileCallback is
/// called.
JITCompileCallbackManagerBase(TargetAddress ErrorHandlerAddress,
unsigned NumTrampolinesPerBlock)
: ErrorHandlerAddress(ErrorHandlerAddress),
NumTrampolinesPerBlock(NumTrampolinesPerBlock) {}

virtual ~JITCompileCallbackManagerBase() {}

Expand Down Expand Up @@ -84,7 +90,7 @@ class JITCompileCallbackManagerBase {
}

/// @brief Reserve a compile callback.
virtual CompileCallbackInfo getCompileCallback() = 0;
virtual CompileCallbackInfo getCompileCallback(LLVMContext &Context) = 0;

/// @brief Get a CompileCallbackInfo for an existing callback.
CompileCallbackInfo getCompileCallbackInfo(TargetAddress TrampolineAddr) {
Expand All @@ -107,6 +113,7 @@ class JITCompileCallbackManagerBase {

protected:
TargetAddress ErrorHandlerAddress;
unsigned NumTrampolinesPerBlock;

typedef std::map<TargetAddress, CompileFtor> TrampolineMapT;
TrampolineMapT ActiveTrampolines;
Expand All @@ -117,96 +124,105 @@ class JITCompileCallbackManagerBase {
};

/// @brief Manage compile callbacks.
template <typename TargetT>
template <typename JITLayerT, typename TargetT>
class JITCompileCallbackManager : public JITCompileCallbackManagerBase {
public:

/// @brief Construct a JITCompileCallbackManager.
/// @param JIT JIT layer to emit callback trampolines, etc. into.
/// @param Context LLVMContext to use for trampoline & resolve block modules.
/// @param ErrorHandlerAddress The address of an error handler in the target
/// process to be used if a compile callback fails.
JITCompileCallbackManager(TargetAddress ErrorHandlerAddress)
: JITCompileCallbackManagerBase(ErrorHandlerAddress) {

/// Set up the resolver block.
std::error_code EC;
ResolverBlock =
sys::OwningMemoryBlock(
sys::Memory::allocateMappedMemory(TargetT::ResolverCodeSize, nullptr,
sys::Memory::MF_READ |
sys::Memory::MF_WRITE, EC));
assert(!EC && "Failed to allocate resolver block");

TargetT::writeResolverCode(static_cast<uint8_t*>(ResolverBlock.base()),
&reenter, this);

EC = sys::Memory::protectMappedMemory(ResolverBlock.getMemoryBlock(),
sys::Memory::MF_READ |
sys::Memory::MF_EXEC);
assert(!EC && "Failed to mprotect resolver block");
/// @param NumTrampolinesPerBlock Number of trampolines to allocate whenever
/// there is no existing callback trampoline.
/// (Trampolines are allocated in blocks for
/// efficiency.)
JITCompileCallbackManager(JITLayerT &JIT, RuntimeDyld::MemoryManager &MemMgr,
LLVMContext &Context,
TargetAddress ErrorHandlerAddress,
unsigned NumTrampolinesPerBlock)
: JITCompileCallbackManagerBase(ErrorHandlerAddress,
NumTrampolinesPerBlock),
JIT(JIT), MemMgr(MemMgr) {
emitResolverBlock(Context);
}

/// @brief Get/create a compile callback with the given signature.
CompileCallbackInfo getCompileCallback() final {
TargetAddress TrampolineAddr = getAvailableTrampolineAddr();
CompileCallbackInfo getCompileCallback(LLVMContext &Context) final {
TargetAddress TrampolineAddr = getAvailableTrampolineAddr(Context);
auto &Compile = this->ActiveTrampolines[TrampolineAddr];
return CompileCallbackInfo(TrampolineAddr, Compile);
}

private:

static TargetAddress reenter(void *CCMgr, void *TrampolineId) {
JITCompileCallbackManager *Mgr =
static_cast<JITCompileCallbackManager*>(CCMgr);
return Mgr->executeCompileCallback(
static_cast<TargetAddress>(
reinterpret_cast<uintptr_t>(TrampolineId)));
std::vector<std::unique_ptr<Module>>
SingletonSet(std::unique_ptr<Module> M) {
std::vector<std::unique_ptr<Module>> Ms;
Ms.push_back(std::move(M));
return Ms;
}

void emitResolverBlock(LLVMContext &Context) {
std::unique_ptr<Module> M(new Module("resolver_block_module",
Context));
TargetT::insertResolverBlock(*M, *this);
auto NonResolver =
createLambdaResolver(
[](const std::string &Name) -> RuntimeDyld::SymbolInfo {
llvm_unreachable("External symbols in resolver block?");
},
[](const std::string &Name) -> RuntimeDyld::SymbolInfo {
llvm_unreachable("Dylib symbols in resolver block?");
});
auto H = JIT.addModuleSet(SingletonSet(std::move(M)), &MemMgr,
std::move(NonResolver));
JIT.emitAndFinalize(H);
auto ResolverBlockSymbol =
JIT.findSymbolIn(H, TargetT::ResolverBlockName, false);
assert(ResolverBlockSymbol && "Failed to insert resolver block");
ResolverBlockAddr = ResolverBlockSymbol.getAddress();
}

TargetAddress getAvailableTrampolineAddr() {
TargetAddress getAvailableTrampolineAddr(LLVMContext &Context) {
if (this->AvailableTrampolines.empty())
grow();
grow(Context);
assert(!this->AvailableTrampolines.empty() &&
"Failed to grow available trampolines.");
TargetAddress TrampolineAddr = this->AvailableTrampolines.back();
this->AvailableTrampolines.pop_back();
return TrampolineAddr;
}

void grow() {
void grow(LLVMContext &Context) {
assert(this->AvailableTrampolines.empty() && "Growing prematurely?");

std::error_code EC;
auto TrampolineBlock =
sys::OwningMemoryBlock(
sys::Memory::allocateMappedMemory(TargetT::PageSize, nullptr,
sys::Memory::MF_READ |
sys::Memory::MF_WRITE, EC));
assert(!EC && "Failed to allocate trampoline block");


unsigned NumTrampolines =
(TargetT::PageSize - TargetT::PointerSize) / TargetT::TrampolineSize;

uint8_t *TrampolineMem = static_cast<uint8_t*>(TrampolineBlock.base());
TargetT::writeTrampolines(TrampolineMem, ResolverBlock.base(),
NumTrampolines);

for (unsigned I = 0; I < NumTrampolines; ++I)
this->AvailableTrampolines.push_back(
static_cast<TargetAddress>(
reinterpret_cast<uintptr_t>(
TrampolineMem + (I * TargetT::TrampolineSize))));

EC = sys::Memory::protectMappedMemory(TrampolineBlock.getMemoryBlock(),
sys::Memory::MF_READ |
sys::Memory::MF_EXEC);
assert(!EC && "Failed to mprotect trampoline block");

TrampolineBlocks.push_back(std::move(TrampolineBlock));
std::unique_ptr<Module> M(new Module("trampoline_block", Context));
auto GetLabelName =
TargetT::insertCompileCallbackTrampolines(*M, ResolverBlockAddr,
this->NumTrampolinesPerBlock,
this->ActiveTrampolines.size());
auto NonResolver =
createLambdaResolver(
[](const std::string &Name) -> RuntimeDyld::SymbolInfo {
llvm_unreachable("External symbols in trampoline block?");
},
[](const std::string &Name) -> RuntimeDyld::SymbolInfo {
llvm_unreachable("Dylib symbols in trampoline block?");
});
auto H = JIT.addModuleSet(SingletonSet(std::move(M)), &MemMgr,
std::move(NonResolver));
JIT.emitAndFinalize(H);
for (unsigned I = 0; I < this->NumTrampolinesPerBlock; ++I) {
std::string Name = GetLabelName(I);
auto TrampolineSymbol = JIT.findSymbolIn(H, Name, false);
assert(TrampolineSymbol && "Failed to emit trampoline.");
this->AvailableTrampolines.push_back(TrampolineSymbol.getAddress());
}
}

sys::OwningMemoryBlock ResolverBlock;
std::vector<sys::OwningMemoryBlock> TrampolineBlocks;
JITLayerT &JIT;
RuntimeDyld::MemoryManager &MemMgr;
TargetAddress ResolverBlockAddr;
};

/// @brief Base class for managing collections of named indirect stubs.
Expand Down
35 changes: 20 additions & 15 deletions include/llvm/ExecutionEngine/Orc/OrcTargetSupport.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,24 +26,29 @@ namespace orc {

class OrcX86_64 {
public:
static const unsigned PageSize = 4096;
static const unsigned PointerSize = 8;
static const unsigned TrampolineSize = 8;
static const unsigned ResolverCodeSize = 0x78;
static const char *ResolverBlockName;

typedef TargetAddress (*JITReentryFn)(void *CallbackMgr,
void *TrampolineId);
/// @brief Insert module-level inline callback asm into module M for the
/// symbols managed by JITResolveCallbackHandler J.
static void insertResolverBlock(Module &M,
JITCompileCallbackManagerBase &JCBM);

/// @brief Write the resolver code into the given memory. The user is be
/// responsible for allocating the memory and setting permissions.
static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,
void *CallbackMgr);
/// @brief Get a label name from the given index.
typedef std::function<std::string(unsigned)> LabelNameFtor;

/// @brief Write the requsted number of trampolines into the given memory,
/// which must be big enough to hold 1 pointer, plus NumTrampolines
/// trampolines.
static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,
unsigned NumTrampolines);
/// @brief Insert the requested number of trampolines into the given module.
/// @param M Module to insert the call block into.
/// @param NumCalls Number of calls to create in the call block.
/// @param StartIndex Optional argument specifying the index suffix to start
/// with.
/// @return A functor that provides the symbol name for each entry in the call
/// block.
///
static LabelNameFtor insertCompileCallbackTrampolines(
Module &M,
TargetAddress TrampolineAddr,
unsigned NumCalls,
unsigned StartIndex = 0);

/// @brief Provide information about stub blocks generated by the
/// makeIndirectStubsBlock function.
Expand Down
10 changes: 6 additions & 4 deletions lib/ExecutionEngine/Orc/OrcCBindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,20 @@

using namespace llvm;

LLVMOrcJITStackRef LLVMOrcCreateInstance(LLVMTargetMachineRef TM) {
LLVMOrcJITStackRef LLVMOrcCreateInstance(LLVMTargetMachineRef TM,
LLVMContextRef Context) {
TargetMachine *TM2(unwrap(TM));
LLVMContext &Ctx = *unwrap(Context);

Triple T(TM2->getTargetTriple());

auto CompileCallbackMgr = OrcCBindingsStack::createCompileCallbackMgr(T);
auto CallbackMgrBuilder = OrcCBindingsStack::createCallbackManagerBuilder(T);
auto IndirectStubsMgrBuilder =
OrcCBindingsStack::createIndirectStubsMgrBuilder(T);

OrcCBindingsStack *JITStack =
new OrcCBindingsStack(*TM2, std::move(CompileCallbackMgr),
IndirectStubsMgrBuilder);
new OrcCBindingsStack(*TM2, Ctx, CallbackMgrBuilder,
IndirectStubsMgrBuilder);

return wrap(JITStack);
}
Expand Down
13 changes: 9 additions & 4 deletions lib/ExecutionEngine/Orc/OrcCBindingsStack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,19 @@

using namespace llvm;

std::unique_ptr<OrcCBindingsStack::CompileCallbackMgr>
OrcCBindingsStack::createCompileCallbackMgr(Triple T) {
OrcCBindingsStack::CallbackManagerBuilder
OrcCBindingsStack::createCallbackManagerBuilder(Triple T) {
switch (T.getArch()) {
default: return nullptr;

case Triple::x86_64: {
typedef orc::JITCompileCallbackManager<orc::OrcX86_64> CCMgrT;
return llvm::make_unique<CCMgrT>(0);
typedef orc::JITCompileCallbackManager<CompileLayerT,
orc::OrcX86_64> CCMgrT;
return [](CompileLayerT &CompileLayer, RuntimeDyld::MemoryManager &MemMgr,
LLVMContext &Context) {
return llvm::make_unique<CCMgrT>(CompileLayer, MemMgr, Context, 0,
64);
};
}
}
}
Expand Down
21 changes: 13 additions & 8 deletions lib/ExecutionEngine/Orc/OrcCBindingsStack.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@ class OrcCBindingsStack {
typedef orc::IRCompileLayer<ObjLayerT> CompileLayerT;
typedef orc::CompileOnDemandLayer<CompileLayerT, CompileCallbackMgr> CODLayerT;

typedef std::function<std::unique_ptr<CompileCallbackMgr>()>
typedef std::function<
std::unique_ptr<CompileCallbackMgr>(CompileLayerT&,
RuntimeDyld::MemoryManager&,
LLVMContext&)>
CallbackManagerBuilder;

typedef CODLayerT::IndirectStubsManagerBuilderT IndirectStubsManagerBuilder;
Expand Down Expand Up @@ -83,18 +86,19 @@ class OrcCBindingsStack {

typedef unsigned ModuleHandleT;

static std::unique_ptr<CompileCallbackMgr> createCompileCallbackMgr(Triple T);
static CallbackManagerBuilder createCallbackManagerBuilder(Triple T);
static IndirectStubsManagerBuilder createIndirectStubsMgrBuilder(Triple T);

OrcCBindingsStack(TargetMachine &TM,
std::unique_ptr<CompileCallbackMgr> CCMgr,
OrcCBindingsStack(TargetMachine &TM, LLVMContext &Context,
CallbackManagerBuilder &BuildCallbackMgr,
IndirectStubsManagerBuilder IndirectStubsMgrBuilder)
: DL(TM.createDataLayout()), CCMgr(std::move(CCMgr)),
: Context(Context), DL(TM.createDataLayout()),
ObjectLayer(),
CompileLayer(ObjectLayer, orc::SimpleCompiler(TM)),
CCMgr(BuildCallbackMgr(CompileLayer, CCMgrMemMgr, Context)),
CODLayer(CompileLayer,
[](Function &F) { std::set<Function*> S; S.insert(&F); return S; },
*this->CCMgr, std::move(IndirectStubsMgrBuilder), false),
*CCMgr, std::move(IndirectStubsMgrBuilder), false),
IndirectStubsMgr(IndirectStubsMgrBuilder()),
CXXRuntimeOverrides([this](const std::string &S) { return mangle(S); }) {}

Expand Down Expand Up @@ -123,7 +127,7 @@ class OrcCBindingsStack {
orc::TargetAddress
createLazyCompileCallback(LLVMOrcLazyCompileCallbackFn Callback,
void *CallbackCtx) {
auto CCInfo = CCMgr->getCompileCallback();
auto CCInfo = CCMgr->getCompileCallback(Context);
CCInfo.setCompileAction(
[=]() -> orc::TargetAddress {
return Callback(wrap(this), CallbackCtx);
Expand Down Expand Up @@ -260,12 +264,13 @@ class OrcCBindingsStack {
return NewHandle;
}

LLVMContext &Context;
DataLayout DL;
SectionMemoryManager CCMgrMemMgr;

std::unique_ptr<CompileCallbackMgr> CCMgr;
ObjLayerT ObjectLayer;
CompileLayerT CompileLayer;
std::unique_ptr<CompileCallbackMgr> CCMgr;
CODLayerT CODLayer;

std::unique_ptr<orc::IndirectStubsManagerBase> IndirectStubsMgr;
Expand Down
Loading

0 comments on commit 1b023a3

Please sign in to comment.