// 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 AstObjects::TheModule = std::make_unique("my cool jit", getGlobalContext()); IRBuilder<> AstObjects::Builder(getGlobalContext()); std::map 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 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 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; } 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; } }