Last active
December 5, 2022 15:31
-
-
Save ioperations/0fbe859739fb3a8dbaa26f9daa850652 to your computer and use it in GitHub Desktop.
executor
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
// 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; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
clang++ $(llvm-config --cxxflags --ldflags --libs) fib_jit.cc