Ast.cpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. #include "Ast.h"
  2. #include "Parser.h"
  3. namespace ast{
  4. // attributes added from chapter 3 of the tutorial
  5. std::unique_ptr<Module> AstObjects::TheModule = std::make_unique<Module>("my cool jit", getGlobalContext());
  6. IRBuilder<> AstObjects::Builder(getGlobalContext());
  7. std::map<std::string, Value *> AstObjects::NamedValues{};
  8. Value *ErrorV(const char *Str) {
  9. parser::Error(Str);
  10. return nullptr;
  11. }
  12. Value *NumberExprAST::codegen() {
  13. return ConstantFP::get(getGlobalContext(), APFloat(Val));
  14. }
  15. Value *VariableExprAST::codegen() {
  16. // Look this variable up in the function.
  17. Value *V = AstObjects::NamedValues[Name];
  18. if (!V)
  19. ErrorV("Unknown variable name");
  20. return V;
  21. }
  22. Value *BinaryExprAST::codegen() {
  23. Value *L = LHS->codegen();
  24. Value *R = RHS->codegen();
  25. if (!L || !R)
  26. return nullptr;
  27. switch (Op) {
  28. case '+':
  29. return AstObjects::Builder.CreateFAdd(L, R, "addtmp");
  30. case '-':
  31. return AstObjects::Builder.CreateFSub(L, R, "subtmp");
  32. case '*':
  33. return AstObjects::Builder.CreateFMul(L, R, "multmp");
  34. case '<':
  35. L = AstObjects::Builder.CreateFCmpULT(L, R, "cmptmp");
  36. // Convert bool 0/1 to double 0.0 or 1.0
  37. return AstObjects::Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()),
  38. "booltmp");
  39. default:
  40. return ErrorV("invalid binary operator");
  41. }
  42. }
  43. Value *CallExprAST::codegen() {
  44. // Look up the name in the global module table.
  45. Function *CalleeF = AstObjects::TheModule->getFunction(Callee);
  46. if (!CalleeF)
  47. return ErrorV("Unknown function referenced");
  48. // If argument mismatch error.
  49. if (CalleeF->arg_size() != Args.size())
  50. return ErrorV("Incorrect # arguments passed");
  51. std::vector<Value *> ArgsV;
  52. for (unsigned i = 0, e = Args.size(); i != e; ++i) {
  53. ArgsV.push_back(Args[i]->codegen());
  54. if (!ArgsV.back())
  55. return nullptr;
  56. }
  57. return AstObjects::Builder.CreateCall(CalleeF, ArgsV, "calltmp");
  58. }
  59. Function *PrototypeAST::codegen() {
  60. // Make the function type: double(double,double) etc.
  61. std::vector<Type *> Doubles(Args.size(), Type::getDoubleTy(getGlobalContext()));
  62. FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()), Doubles, false);
  63. Function *F = Function::Create(FT, Function::ExternalLinkage, Name, AstObjects::TheModule.get());
  64. // Set names for all arguments.
  65. unsigned Idx = 0;
  66. for (auto &Arg : F->args())
  67. Arg.setName(Args[Idx++]);
  68. return F;
  69. }
  70. Function *FunctionAST::codegen() {
  71. // First, check for an existing function from a previous 'extern' declaration.
  72. Function *TheFunction = AstObjects::TheModule->getFunction(Proto->getName());
  73. if (!TheFunction)
  74. TheFunction = Proto->codegen();
  75. if (!TheFunction)
  76. return nullptr;
  77. if (!TheFunction->empty())
  78. return (Function*)ErrorV("Function cannot be redefined.");
  79. // Create a new basic block to start insertion into.
  80. BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction);
  81. AstObjects::Builder.SetInsertPoint(BB);
  82. // Record the function arguments in the NamedValues map.
  83. AstObjects::NamedValues.clear();
  84. for (auto &Arg : TheFunction->args())
  85. AstObjects::NamedValues[Arg.getName()] = &Arg;
  86. if (Value *RetVal = Body->codegen()) {
  87. // Finish off the function.
  88. AstObjects::Builder.CreateRet(RetVal);
  89. // Validate the generated code, checking for consistency.
  90. verifyFunction(*TheFunction);
  91. return TheFunction;
  92. }
  93. // Error reading body, remove function.
  94. TheFunction->eraseFromParent();
  95. return nullptr;
  96. }
  97. }