forked from OSchip/llvm-project
115 lines
3.8 KiB
C++
115 lines
3.8 KiB
C++
//===----- KaleidoscopeJIT.h - A simple JIT for Kaleidoscope ----*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Contains a simple JIT definition for use in the kaleidoscope tutorials.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLVM_EXECUTIONENGINE_ORC_KALEIDOSCOPEJIT_H
|
|
#define LLVM_EXECUTIONENGINE_ORC_KALEIDOSCOPEJIT_H
|
|
|
|
#include "llvm/ExecutionEngine/ExecutionEngine.h"
|
|
#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
|
|
#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
|
|
#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
|
|
#include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
|
|
#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
|
|
#include "llvm/IR/Mangler.h"
|
|
#include "llvm/Support/DynamicLibrary.h"
|
|
|
|
namespace llvm {
|
|
namespace orc {
|
|
|
|
class KaleidoscopeJIT {
|
|
public:
|
|
typedef ObjectLinkingLayer<> ObjLayerT;
|
|
typedef IRCompileLayer<ObjLayerT> CompileLayerT;
|
|
typedef CompileLayerT::ModuleSetHandleT ModuleHandleT;
|
|
|
|
KaleidoscopeJIT()
|
|
: TM(EngineBuilder().selectTarget()), DL(TM->createDataLayout()),
|
|
CompileLayer(ObjectLayer, SimpleCompiler(*TM)) {
|
|
llvm::sys::DynamicLibrary::LoadLibraryPermanently(nullptr);
|
|
}
|
|
|
|
TargetMachine &getTargetMachine() { return *TM; }
|
|
|
|
ModuleHandleT addModule(std::unique_ptr<Module> M) {
|
|
// We need a memory manager to allocate memory and resolve symbols for this
|
|
// new module. Create one that resolves symbols by looking back into the
|
|
// JIT.
|
|
auto Resolver = createLambdaResolver(
|
|
[&](const std::string &Name) {
|
|
if (auto Sym = findMangledSymbol(Name))
|
|
return RuntimeDyld::SymbolInfo(Sym.getAddress(), Sym.getFlags());
|
|
return RuntimeDyld::SymbolInfo(nullptr);
|
|
},
|
|
[](const std::string &S) { return nullptr; });
|
|
auto H = CompileLayer.addModuleSet(singletonSet(std::move(M)),
|
|
make_unique<SectionMemoryManager>(),
|
|
std::move(Resolver));
|
|
|
|
ModuleHandles.push_back(H);
|
|
return H;
|
|
}
|
|
|
|
void removeModule(ModuleHandleT H) {
|
|
ModuleHandles.erase(
|
|
std::find(ModuleHandles.begin(), ModuleHandles.end(), H));
|
|
CompileLayer.removeModuleSet(H);
|
|
}
|
|
|
|
JITSymbol findSymbol(const std::string Name) {
|
|
return findMangledSymbol(mangle(Name));
|
|
}
|
|
|
|
private:
|
|
|
|
std::string mangle(const std::string &Name) {
|
|
std::string MangledName;
|
|
{
|
|
raw_string_ostream MangledNameStream(MangledName);
|
|
Mangler::getNameWithPrefix(MangledNameStream, Name, DL);
|
|
}
|
|
return MangledName;
|
|
}
|
|
|
|
template <typename T> static std::vector<T> singletonSet(T t) {
|
|
std::vector<T> Vec;
|
|
Vec.push_back(std::move(t));
|
|
return Vec;
|
|
}
|
|
|
|
JITSymbol findMangledSymbol(const std::string &Name) {
|
|
// Search modules in reverse order: from last added to first added.
|
|
// This is the opposite of the usual search order for dlsym, but makes more
|
|
// sense in a REPL where we want to bind to the newest available definition.
|
|
for (auto H : make_range(ModuleHandles.rbegin(), ModuleHandles.rend()))
|
|
if (auto Sym = CompileLayer.findSymbolIn(H, Name, true))
|
|
return Sym;
|
|
|
|
// If we can't find the symbol in the JIT, try looking in the host process.
|
|
if (auto SymAddr = RTDyldMemoryManager::getSymbolAddressInProcess(Name))
|
|
return JITSymbol(SymAddr, JITSymbolFlags::Exported);
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
std::unique_ptr<TargetMachine> TM;
|
|
const DataLayout DL;
|
|
ObjLayerT ObjectLayer;
|
|
CompileLayerT CompileLayer;
|
|
std::vector<ModuleHandleT> ModuleHandles;
|
|
};
|
|
|
|
} // End namespace orc.
|
|
} // End namespace llvm
|
|
|
|
#endif // LLVM_EXECUTIONENGINE_ORC_KALEIDOSCOPEJIT_H
|