|
#include <iostream> |
|
#include "llvm/ADT/APFloat.h" |
|
#include "llvm/ADT/STLExtras.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/LLVMContext.h" |
|
#include "llvm/IR/Module.h" |
|
#include "llvm/IR/Type.h" |
|
#include "llvm/IR/Verifier.h" |
|
#include "llvm/Passes/PassBuilder.h" |
|
#include "llvm/Passes/StandardInstrumentations.h" |
|
|
|
using namespace llvm; |
|
|
|
static std::unique_ptr<LLVMContext> TheContext; |
|
static std::unique_ptr<Module> TheModule; |
|
static std::unique_ptr<IRBuilder<>> Builder; |
|
|
|
/// ExprAST - Base class for all expression nodes. |
|
class ExprAST { |
|
public: |
|
virtual ~ExprAST() = default; |
|
virtual Value *codegen() = 0; |
|
}; |
|
|
|
/// NumberExprAST - Expression class for numeric literals like "1.0". |
|
class NumberExprAST : public ExprAST { |
|
double Val; |
|
|
|
public: |
|
NumberExprAST(double Val) : Val(Val) {} |
|
Value *codegen() override; |
|
}; |
|
|
|
Value *NumberExprAST::codegen() { |
|
return ConstantFP::get(*TheContext, APFloat(Val)); |
|
} |
|
|
|
|
|
int main() { |
|
TheContext = std::make_unique<LLVMContext>(); |
|
TheModule = std::make_unique<Module>("my cool jit", *TheContext); |
|
Builder = std::make_unique<IRBuilder<>>(*TheContext); |
|
|
|
Type *doublety = Type::getDoubleTy(*TheContext); |
|
FunctionType *FT = FunctionType::get(doublety, std::vector{doublety}, false); |
|
Function *TheFunction = Function::Create(FT, Function::ExternalLinkage, "main", *TheModule); |
|
BasicBlock *bb = BasicBlock::Create(*TheContext, "my basic block", TheFunction); |
|
Builder->SetInsertPoint(bb); |
|
|
|
NumberExprAST two(2); |
|
Value *two_val = two.codegen(); |
|
Value *arg = TheFunction->args().begin(); |
|
arg->setName("x"); |
|
Value *b = Builder->CreateFAdd(two_val, arg); |
|
Value *c = Builder->CreateFAdd(arg, two_val); |
|
Value *d = Builder->CreateFAdd(b, c); |
|
Builder->CreateRet(d); |
|
|
|
// copied from https://llvm.org/docs/NewPassManager.html |
|
|
|
// Create the analysis managers. |
|
// These must be declared in this order so that they are destroyed in the |
|
// correct order due to inter-analysis-manager references. |
|
LoopAnalysisManager LAM; |
|
FunctionAnalysisManager FAM; |
|
CGSCCAnalysisManager CGAM; |
|
ModuleAnalysisManager MAM; |
|
|
|
// Create the new pass manager builder. |
|
// Take a look at the PassBuilder constructor parameters for more |
|
// customization, e.g. specifying a TargetMachine or various debugging |
|
// options. |
|
PassBuilder PB; |
|
|
|
// Register all the basic analyses with the managers. |
|
PB.registerModuleAnalyses(MAM); |
|
PB.registerCGSCCAnalyses(CGAM); |
|
PB.registerFunctionAnalyses(FAM); |
|
PB.registerLoopAnalyses(LAM); |
|
PB.crossRegisterProxies(LAM, FAM, CGAM, MAM); |
|
|
|
// Create the pass manager. |
|
// This one corresponds to a typical -O2 optimization pipeline. |
|
ModulePassManager MPM = PB.buildPerModuleDefaultPipeline(OptimizationLevel::O2); |
|
|
|
// Optimize the IR! |
|
MPM.run(*TheModule, MAM); |
|
// end copy |
|
|
|
|
|
if (verifyFunction(*TheFunction)) { |
|
std::cout << "LLVM was unhappy\n"; |
|
} else { |
|
TheFunction->print(outs()); |
|
} |
|
} |