Last active
February 19, 2024 02:12
-
-
Save 38/39e7b514d916ed6fa6a2bba629fdf6ff to your computer and use it in GitHub Desktop.
A Minimal LLVM JIT example for LLVM-5
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
jit-toy: jit-toy.cpp | |
clang++ -g -o $@ $^ $(shell /usr/lib/llvm-5.0/bin/llvm-config --cxxflags --ldflags --system-libs --libs core) |
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/IR/IRBuilder.h> | |
#include <llvm/Support/TargetSelect.h> | |
#include <llvm/ExecutionEngine/ExecutionEngine.h> | |
#include <llvm/ExecutionEngine/JITSymbol.h> | |
#include <llvm/ExecutionEngine/SectionMemoryManager.h> | |
#include <llvm/ExecutionEngine/Orc/CompileUtils.h> | |
#include <llvm/ExecutionEngine/Orc/IRCompileLayer.h> | |
#include <llvm/ExecutionEngine/Orc/LambdaResolver.h> | |
#include <llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h> | |
#include <memory> | |
#include <vector> | |
using namespace llvm; | |
using namespace std; | |
static Module* jit_module = NULL; | |
static LLVMContext context; | |
static IRBuilder<> builder(context); | |
using LinkLayer = orc::RTDyldObjectLinkingLayer; | |
using Compiler = orc::SimpleCompiler; | |
using CompileLayer = orc::IRCompileLayer<LinkLayer, Compiler>; | |
JITSymbol dummy_lookup(const string& name) | |
{ | |
return JITSymbol(NULL); | |
} | |
void code_gen() | |
{ | |
jit_module = new Module("Test JIT Compiler", context); | |
// (double, double, double) | |
std::vector<Type*> param_type(3, Type::getDoubleTy(context)); | |
// double (*)(double, double, double) | |
FunctionType* prototype = FunctionType::get(Type::getDoubleTy(context), param_type, false); | |
Function *func = Function::Create(prototype, Function::ExternalLinkage, "test_func", jit_module); | |
BasicBlock *body = BasicBlock::Create(context, "body", func); | |
builder.SetInsertPoint(body); | |
std::vector<Value*> args; | |
for(auto& arg : func->args()) | |
args.push_back(&arg); | |
Value* temp = builder.CreateFMul(args[0], args[1], "temp"); | |
Value* ret = builder.CreateFMul(args[2], temp, "result"); | |
builder.CreateRet(ret); | |
} | |
int main() | |
{ | |
// Initialization | |
LLVMInitializeNativeTarget(); | |
InitializeNativeTargetAsmPrinter(); | |
TargetMachine* target = EngineBuilder().selectTarget(); | |
// Emit the LLVM IR to the Module | |
code_gen(); | |
// Compile the IR to Machine Code | |
const DataLayout dl = target->createDataLayout(); | |
LinkLayer link_layer([]() { return std::make_shared<SectionMemoryManager>(); }); | |
CompileLayer compile_layer(link_layer, Compiler(*target)); | |
auto jit_module_handle = cantFail(compile_layer.addModule(std::shared_ptr<Module>(jit_module), | |
orc::createLambdaResolver(dummy_lookup, dummy_lookup))); | |
// Run the compiled function ! | |
JITSymbol symbol = compile_layer.findSymbolIn(jit_module_handle, "test_func", false); | |
double (*native_func)(double, double, double) = (decltype(native_func))cantFail(symbol.getAddress()); | |
printf("%lf\n", native_func(3,4,5)); | |
printf("%lf\n", native_func(1,2,3)); | |
delete target; | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment