123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135 |
- // LLVM includes
- #include "llvm/IR/Verifier.h"
- // Local includes
- #include "Ast.h"
- #include "Parser.h"
- namespace ast{
- // attributes added from chapter 3 of the tutorial
- std::unique_ptr<Module> AstObjects::TheModule =
- std::make_unique<Module>("my cool jit", getGlobalContext());
- IRBuilder<> AstObjects::Builder(getGlobalContext());
- std::map<std::string, Value *> AstObjects::NamedValues;
- Value *ErrorV(const char *Str) {
- parser::Error(Str);
- return nullptr;
- }
- Value *NumberExprAST::codegen() {
- return ConstantFP::get(getGlobalContext(), APFloat(Val));
- }
- Value *VariableExprAST::codegen() {
- // Look this variable up in the function.
- Value *V = AstObjects::NamedValues[Name];
- if (!V)
- ErrorV("Unknown variable name");
- return V;
- }
- Value *BinaryExprAST::codegen() {
- Value *L = LHS->codegen();
- Value *R = RHS->codegen();
- if (!L || !R)
- return nullptr;
- switch (Op) {
- case '+':
- return AstObjects::Builder.CreateFAdd(L, R, "addtmp");
- case '-':
- return AstObjects::Builder.CreateFSub(L, R, "subtmp");
- case '*':
- return AstObjects::Builder.CreateFMul(L, R, "multmp");
- case '<':
- L = AstObjects::Builder.CreateFCmpULT(L, R, "cmptmp");
- // Convert bool 0/1 to double 0.0 or 1.0
- return AstObjects::Builder.CreateUIToFP(L,
- Type::getDoubleTy(getGlobalContext()), "booltmp");
- default:
- return ErrorV("invalid binary operator");
- }
- }
- Value *CallExprAST::codegen() {
- // Look up the name in the global module table.
- Function *CalleeF = AstObjects::TheModule->getFunction(Callee);
- if (!CalleeF)
- return ErrorV("Unknown function referenced");
- // If argument mismatch error.
- if (CalleeF->arg_size() != Args.size())
- return ErrorV("Incorrect # arguments passed");
- std::vector<Value *> ArgsV;
- for (unsigned i = 0, e = Args.size(); i != e; ++i) {
- ArgsV.push_back(Args[i]->codegen());
- if (!ArgsV.back())
- return nullptr;
- }
- return AstObjects::Builder.CreateCall(CalleeF, ArgsV, "calltmp");
- }
- Function *PrototypeAST::codegen() {
- // Make the function type: double(double,double) etc.
- std::vector<Type *> Doubles(Args.size(),
- Type::getDoubleTy(getGlobalContext()));
- FunctionType *FT = FunctionType::get(Type::getDoubleTy(
- getGlobalContext()), Doubles, false);
- Function *F = Function::Create(FT, Function::ExternalLinkage, Name,
- AstObjects::TheModule.get());
- // Set names for all arguments.
- unsigned Idx = 0;
- for (auto &Arg : F->args())
- Arg.setName(Args[Idx++]);
- return F;
- }
- const std::string &PrototypeAST::getName() const { return Name; }
- Function *FunctionAST::codegen() {
- // First, check for an existing function from a previous 'extern' declaration.
- Function *TheFunction =
- AstObjects::TheModule->getFunction(Proto->getName());
- if (!TheFunction)
- TheFunction = Proto->codegen();
- if (!TheFunction)
- return nullptr;
- if (!TheFunction->empty())
- return (Function*)ErrorV("Function cannot be redefined.");
- // Create a new basic block to start insertion into.
- BasicBlock *BB = BasicBlock::Create(getGlobalContext(),
- "entry", TheFunction);
- AstObjects::Builder.SetInsertPoint(BB);
- // Record the function arguments in the NamedValues map.
- AstObjects::NamedValues.clear();
- for (auto &Arg : TheFunction->args()) {
- AstObjects::NamedValues[Arg.getName()] = &Arg;
- }
- if (Value *RetVal = Body->codegen()) {
- // Finish off the function.
- AstObjects::Builder.CreateRet(RetVal);
- // Validate the generated code, checking for consistency.
- verifyFunction(*TheFunction);
- return TheFunction;
- }
- // Error reading body, remove function.
- TheFunction->eraseFromParent();
- return nullptr;
- }
- }
|