Skip to content

Instantly share code, notes, and snippets.

@ioperations
Last active December 5, 2022 15:31
Show Gist options
  • Save ioperations/0fbe859739fb3a8dbaa26f9daa850652 to your computer and use it in GitHub Desktop.
Save ioperations/0fbe859739fb3a8dbaa26f9daa850652 to your computer and use it in GitHub Desktop.
executor
// Original URL:
// https://llvm.org/svn/llvm-project/llvm/trunk/examples/HowToUseJIT/HowToUseJIT.cpp
//
//===-- examples/HowToUseJIT/HowToUseJIT.cpp - An example use of the JIT --===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//
//===----------------------------------------------------------------------===//
#include <cstdlib>
#include <memory>
#include <sstream>
#include "llvm/ExecutionEngine/GenericValue.h"
#include "llvm/ExecutionEngine/Interpreter.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Value.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/TimeProfiler.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
using namespace std;
int Fib(int val) {
LLVMContext context;
std::unique_ptr<Module> owner = make_unique<Module>("test", context);
Module* m = owner.get();
// Create a basic block builder with default parameters. The builder
// will automatically append instructions to the basic block `BB'.
auto* fib =
Function::Create(FunctionType::get(Type::getInt32Ty(context),
{Type::getInt32Ty(context)}, false),
Function::ExternalLinkage, "fib",
m); // fib could have name mangle in c++
auto* foo = Function::Create(
FunctionType::get(Type::getInt32Ty(context), {}, false),
Function::ExternalLinkage, "foo",
m); // foo could have name mangle in c++
// fib function body
{
BasicBlock* bb = BasicBlock::Create(context, "EntryBlock", fib);
IRBuilder<> builder(bb);
BasicBlock* trueblock = BasicBlock::Create(context, "trueblock", fib);
BasicBlock* falseblock = BasicBlock::Create(context, "falseblock", fib);
builder.SetInsertPoint(bb);
Value* condition = nullptr;
{ // construt condition
Value* args = fib->arg_begin();
args->setName("i"); // Give it a nice symbolic name for fun.
Value* two = builder.getInt32(2);
condition = builder.CreateICmpSGT(args, two);
}
builder.CreateCondBr(condition, trueblock, falseblock);
{
builder.SetInsertPoint(trueblock);
Value* args = fib->arg_begin();
Value* two = builder.getInt32(2);
Value* sub_res2 = builder.CreateSub(args, two);
CallInst* sub2_call_res = builder.CreateCall(fib, sub_res2);
Value* one = builder.getInt32(1);
Value* sub_res1 = builder.CreateSub(args, one);
CallInst* sub1_call_res = builder.CreateCall(fib, sub_res1);
auto* z = builder.CreateAdd(sub2_call_res, sub1_call_res);
builder.CreateRet(z);
}
{
builder.SetInsertPoint(falseblock);
Value* one = builder.getInt32(1);
builder.CreateRet(one);
}
}
// foo function body
{
BasicBlock* bb = BasicBlock::Create(context, "EntryBlock", foo);
IRBuilder<> builder(bb);
builder.SetInsertPoint(bb);
Value* val_value = builder.getInt32(val);
CallInst* add1_call_res = builder.CreateCall(fib, val_value);
add1_call_res->setTailCall(true);
builder.CreateRet(add1_call_res);
}
// Now we create the JIT.
{
EngineBuilder engine(std::move(owner));
ExecutionEngine* ee = engine.create();
outs() << "IR\n\n" << *m;
outs() << "\n\nRunning foo: ";
outs().flush();
// Call the `foo' function with no arguments:
std::vector<GenericValue> noargs;
GenericValue gv = ee->runFunction(foo, noargs);
// Import result of execution:
outs() << "Result: " << gv.IntVal << "\n";
delete ee;
}
llvm_shutdown();
return 0;
}
function<int(int)> fib = [](int i) -> int {
if (i > 2) {
return fib(i - 1) + fib(i - 2);
}
return 1;
};
int main(int argc, char* argv[]) {
if (argc != 2) {
llvm::errs() << " should have two arguments "
<< "\n";
return 1;
}
int num = 0;
stringstream ss(argv[1]);
if (ss >> num) {
{
InitializeNativeTarget();
LLVMInitializeNativeAsmPrinter();
Fib(num);
}
{ llvm::outs() << "fib(" << num << ") is " << fib(num) << "\n"; }
} else {
llvm::errs() << "cannot convert " << argv[1] << "to int \n";
}
return 0;
}
@ioperations
Copy link
Author

clang++ $(llvm-config --cxxflags --ldflags --libs) fib_jit.cc

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment