Created
March 19, 2021 01:04
-
-
Save jensb1/69340306768ef40caa3310c296acf552 to your computer and use it in GitHub Desktop.
LLVM Orc v2 - loading separate file
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "llvm/ADT/StringExtras.h" | |
#include "llvm/ADT/Triple.h" | |
#include "llvm/Bitcode/BitcodeReader.h" | |
#include "llvm/CodeGen/CommandFlags.h" | |
#include "llvm/CodeGen/LinkAllCodegenComponents.h" | |
#include "llvm/Config/llvm-config.h" | |
#include "llvm/ExecutionEngine/GenericValue.h" | |
#include "llvm/ExecutionEngine/JITEventListener.h" | |
#include "llvm/ExecutionEngine/ObjectCache.h" | |
#include "llvm/ExecutionEngine/Orc/DebugUtils.h" | |
#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" | |
#include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h" | |
#include "llvm/ExecutionEngine/Orc/LLJIT.h" | |
#include "llvm/ExecutionEngine/Orc/MachOPlatform.h" | |
#include "llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h" | |
#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h" | |
#include "llvm/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.h" | |
#include "llvm/ExecutionEngine/SectionMemoryManager.h" | |
#include "llvm/IR/IRBuilder.h" | |
#include "llvm/IR/LLVMContext.h" | |
#include "llvm/IR/Module.h" | |
#include "llvm/IR/Type.h" | |
#include "llvm/IR/Verifier.h" | |
#include "llvm/IRReader/IRReader.h" | |
#include "llvm/Object/Archive.h" | |
#include "llvm/Object/ObjectFile.h" | |
#include "llvm/Support/CommandLine.h" | |
#include "llvm/Support/Debug.h" | |
#include "llvm/Support/DynamicLibrary.h" | |
#include "llvm/Support/Format.h" | |
#include "llvm/Support/InitLLVM.h" | |
#include "llvm/Support/ManagedStatic.h" | |
#include "llvm/Support/MathExtras.h" | |
#include "llvm/Support/Memory.h" | |
#include "llvm/Support/MemoryBuffer.h" | |
#include "llvm/Support/Path.h" | |
#include "llvm/Support/PluginLoader.h" | |
#include "llvm/Support/Process.h" | |
#include "llvm/Support/Program.h" | |
#include "llvm/Support/SourceMgr.h" | |
#include "llvm/Support/TargetSelect.h" | |
#include "llvm/Support/WithColor.h" | |
#include "llvm/Support/raw_ostream.h" | |
#include "llvm/Transforms/Instrumentation.h" | |
#include <cerrno> | |
#include <string> | |
#include <iostream> | |
#include <fstream> | |
#include <streambuf> | |
using namespace llvm; | |
using namespace llvm::orc; | |
ExitOnError ExitOnErr; | |
inline llvm::Expected<llvm::orc::ThreadSafeModule> | |
parseExampleModule(const llvm::DataLayout &layout, llvm::StringRef Source, llvm::StringRef Name) { | |
using namespace llvm; | |
using namespace llvm::orc; | |
auto Ctx = std::make_unique<LLVMContext>(); | |
SMDiagnostic Err; | |
auto M = parseIR(MemoryBufferRef(Source, Name), Err, *Ctx); | |
M->setDataLayout(layout); | |
if (!M) { | |
std::string ErrMsg; | |
{ | |
raw_string_ostream ErrStream(ErrMsg); | |
Err.print("", ErrStream); | |
} | |
return make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode()); | |
} | |
return ThreadSafeModule(std::move(M), std::move(Ctx)); | |
} | |
Expected<orc::ThreadSafeModule> | |
loadModule(StringRef Path, orc::ThreadSafeContext TSCtx) { | |
SMDiagnostic Err; | |
std::cout << "parsing file: " << Path.data() << std::endl; | |
auto M = parseIRFile(Path, Err, *TSCtx.getContext()); | |
if (!M) { | |
std::string ErrMsg; | |
{ | |
raw_string_ostream ErrMsgStream(ErrMsg); | |
Err.print("lli", ErrMsgStream); | |
} | |
return make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode()); | |
} | |
M->setModuleIdentifier("file:" + M->getModuleIdentifier()); | |
return orc::ThreadSafeModule(std::move(M), std::move(TSCtx)); | |
} | |
static void exitOnLazyCallThroughFailure() { exit(1); } | |
static std::function<void(Module &)> createDebugDumper() { | |
return [](Module &M) { | |
printf("[ "); | |
for (const auto &F : M) { | |
if (F.isDeclaration()) | |
continue; | |
if (F.hasName()) { | |
std::string Name(std::string(F.getName())); | |
printf("%s ", Name.c_str()); | |
} else | |
printf("<anon> "); | |
} | |
printf("]\n"); | |
}; | |
return [](Module &M) { | |
outs() << "----- Module Start -----\n" << M << "----- Module End -----\n"; | |
}; | |
} | |
int main(int argc, char *argv[]) { | |
InitLLVM X(argc, argv); | |
// If we have a native target, initialize it to ensure it is linked in and | |
// usable by the JIT. | |
std::cout << "1" << std::endl; | |
InitializeNativeTarget(); | |
InitializeNativeTargetAsmPrinter(); | |
InitializeNativeTargetAsmParser(); | |
// Parse the main module. | |
orc::ThreadSafeContext TSCtx(std::make_unique<LLVMContext>()); | |
auto MainModule = ExitOnErr(loadModule(StringRef(argv[1]), TSCtx)); | |
// Get TargetTriple and DataLayout from the main module if they're explicitly | |
// set. | |
std::cout << "2" << std::endl; | |
Optional<Triple> TT; | |
Optional<DataLayout> DL; | |
MainModule.withModuleDo([&](Module &M) { | |
if (!M.getTargetTriple().empty()) | |
TT = Triple(M.getTargetTriple()); | |
if (!M.getDataLayout().isDefault()) | |
DL = M.getDataLayout(); | |
}); | |
orc::LLLazyJITBuilder Builder; | |
std::cout << "3" << std::endl; | |
Builder.setJITTargetMachineBuilder( | |
TT ? orc::JITTargetMachineBuilder(*TT) | |
: ExitOnErr(orc::JITTargetMachineBuilder::detectHost())); | |
std::cout << "4" << std::endl; | |
TT = Builder.getJITTargetMachineBuilder()->getTargetTriple(); | |
if (DL) | |
Builder.setDataLayout(DL); | |
std::cout << "4.0" << std::endl; | |
/* | |
if (!codegen::getMArch().empty()) | |
Builder.getJITTargetMachineBuilder()->getTargetTriple().setArchName( | |
codegen::getMArch()); | |
std::cout << "4.1" << std::endl; | |
Builder.getJITTargetMachineBuilder() | |
->setCPU(codegen::getCPUStr()) | |
.addFeatures(codegen::getFeatureList()) | |
.setRelocationModel(codegen::getExplicitRelocModel()) | |
.setCodeModel(codegen::getExplicitCodeModel()); | |
*/ | |
std::cout << "4.2" << std::endl; | |
Builder.setLazyCompileFailureAddr( | |
pointerToJITTargetAddress(exitOnLazyCallThroughFailure)); | |
Builder.setNumCompileThreads(0); | |
auto J = ExitOnErr(Builder.create()); | |
std::cout << "5" << std::endl; | |
if (TT->isOSBinFormatELF()) | |
static_cast<llvm::orc::RTDyldObjectLinkingLayer &>(J->getObjLinkingLayer()) | |
.registerJITEventListener( | |
*JITEventListener::createGDBRegistrationListener()); | |
std::cout << "6" << std::endl; | |
auto Dump = createDebugDumper(); | |
J->getIRTransformLayer().setTransform( | |
[&](orc::ThreadSafeModule TSM, | |
const orc::MaterializationResponsibility &R) { | |
TSM.withModuleDo([&](Module &M) { | |
if (verifyModule(M, &dbgs())) { | |
dbgs() << "Bad module: " << &M << "\n"; | |
exit(1); | |
} | |
Dump(M); | |
}); | |
return TSM; | |
}); | |
std::cout << "7" << std::endl; | |
orc::MangleAndInterner Mangle(J->getExecutionSession(), J->getDataLayout()); | |
J->getMainJITDylib().addGenerator( | |
ExitOnErr(orc::DynamicLibrarySearchGenerator::GetForCurrentProcess( | |
J->getDataLayout().getGlobalPrefix(), | |
[MainName = Mangle("main")](const orc::SymbolStringPtr &Name) { | |
return Name != MainName; | |
}))); | |
// Run any static constructors. | |
ExitOnErr(J->initialize(J->getMainJITDylib())); | |
std::cout << "8" << std::endl; | |
// Run main. | |
auto MainSym = ExitOnErr(J->lookup("main")); | |
std::vector<std::string> Args; | |
Args.push_back("test"); | |
std::cout << "9" << std::endl; | |
typedef int (*MainFnPtr)(int, char *[]); | |
/* | |
auto Result = orc::runAsMain( | |
jitTargetAddressToFunction<MainFnPtr>(MainSym.getAddress()), Args); | |
*/ | |
// Run destructors. | |
ExitOnErr(J->deinitialize(J->getMainJITDylib())); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment