Skip to content

Instantly share code, notes, and snippets.

@jensb1
Created March 19, 2021 01:04
Show Gist options
  • Save jensb1/69340306768ef40caa3310c296acf552 to your computer and use it in GitHub Desktop.
Save jensb1/69340306768ef40caa3310c296acf552 to your computer and use it in GitHub Desktop.
LLVM Orc v2 - loading separate file
#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