Ladies_Man

#Codegen Lab2 LLVM IR COMPLETE

Oct 24th, 2016
242
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 16.59 KB | None | 0 0
  1. #include <stdint.h>
  2. #include "llvm/ADT/STLExtras.h"
  3. #include "llvm/IR/IRBuilder.h"
  4. #include "llvm/IR/Module.h"
  5. #include "llvm/IR/Verifier.h"
  6.  
  7. using namespace std;
  8.  
  9. #define TOK_EOF 1
  10. #define TOK_IDENT 2
  11. #define TOK_NUM 3
  12. #define TOK_IF 6
  13. #define TOK_ELSE 7
  14.  
  15. static string IdentifierStr;
  16. static int NumVal;
  17. static int CurToken;
  18.  
  19. static int GetToken() {
  20.  
  21.     static int posCh = ' ';
  22.  
  23.     while (isspace(posCh))
  24.         posCh = getchar();
  25.     if (isalpha(posCh)) {
  26.         IdentifierStr = posCh;
  27.         while (isalnum((posCh = getchar())))
  28.             IdentifierStr += posCh;
  29.  
  30.         if (IdentifierStr == "if")
  31.             return TOK_IF;
  32.         if (IdentifierStr == "else")
  33.             return TOK_ELSE;
  34.  
  35.         return TOK_IDENT;
  36.     }
  37.  
  38.     if (isdigit(posCh)) {
  39.         string NumStr;
  40.         do {
  41.             NumStr += posCh;
  42.             posCh = getchar();
  43.         } while (isdigit(posCh));
  44.  
  45.         NumVal = strtod(NumStr.c_str(), nullptr);
  46.         return TOK_NUM;
  47.     }
  48.  
  49.     if (posCh == EOF)
  50.         return TOK_EOF;
  51.  
  52.     int thisChar = posCh;
  53.     posCh = getchar();
  54.  
  55.     return thisChar;
  56. }
  57.  
  58. void NextToken(){
  59.     CurToken = GetToken();
  60. }
  61.  
  62.  
  63.  
  64.  
  65. //===-----------------------------------------------------===//
  66. //=---                       EXPR                        ---=//
  67. //===-----------------------------------------------------===//
  68. class ExprAST {
  69. public:
  70.     virtual ~ExprAST() {}
  71.     virtual llvm::Value *codegen() = 0;
  72. };
  73.  
  74.  
  75.  
  76. //===-----------------------------------------------------===//
  77. //=---                     NUMBER                        ---=//
  78. //===-----------------------------------------------------===//
  79. class NumberExprAST : public ExprAST {
  80.     int Val;
  81.  
  82. public:
  83.     NumberExprAST(int Val) : Val(Val) {}
  84.     llvm::Value *codegen() override;
  85. };
  86.  
  87.  
  88. //===-----------------------------------------------------===//
  89. //=---                     ASSIGN                        ---=//
  90. //===-----------------------------------------------------===//
  91. class AssignAST : public ExprAST {
  92.     string Name;
  93.     ExprAST *assExpr;
  94. public:
  95.     AssignAST(const string &Name, ExprAST *Expr) {
  96.         this->Name = Name;
  97.         this->assExpr = Expr;
  98.     }
  99.     llvm::Value *codegen() override;
  100. };
  101.  
  102.  
  103. //===-----------------------------------------------------===//
  104. //=---                       VAR                         ---=//
  105. //===-----------------------------------------------------===//
  106. class VariableExprAST : public ExprAST {
  107.     string Name;
  108. public:
  109.     VariableExprAST(const string &Name) : Name(Name) {}
  110.     llvm::Value *codegen() override;
  111. };
  112.  
  113.  
  114. //===-----------------------------------------------------===//
  115. //=---                        IF                         ---=//
  116. //===-----------------------------------------------------===//
  117. class IfExprAST : public ExprAST {
  118.     ExprAST *Cond, *Then, *Else;
  119. public:
  120.     IfExprAST(ExprAST *Cond, ExprAST *Then, ExprAST *Else){
  121.         this->Cond = Cond;
  122.         this->Then = Then;
  123.         this->Else = Else;
  124.     }
  125.     llvm::Value *codegen() override;
  126. };
  127.  
  128.  
  129. //===-----------------------------------------------------===//
  130. //=---                     BINARY                        ---=//
  131. //===-----------------------------------------------------===//
  132. class BinaryExprAST : public ExprAST {
  133.     char Op;
  134.     ExprAST *LHS, *RHS;
  135.  
  136. public:
  137.     BinaryExprAST(char Op, ExprAST *LHS,
  138.                   ExprAST *RHS)
  139.             : Op(Op), LHS(LHS), RHS(RHS) {}
  140.     llvm::Value *codegen() override;
  141. };
  142.  
  143.  
  144.  
  145.  
  146.  
  147. //===---------------------========------------------------===//
  148. //=---                      PARSE                        ---=//
  149. //===---------------------========------------------------===//
  150.  
  151. //создание Абстр Синт Дерева
  152.  
  153. //https://habrahabr.ru/post/120005/
  154.  
  155. static ExprAST *ParseExpression();
  156.  
  157. static ExprAST *ParseNumberExpr() {
  158.     NumberExprAST *Result = new NumberExprAST(NumVal);
  159.     NextToken();
  160.     return Result;
  161. }
  162.  
  163. static ExprAST *ParseParenExpr() {
  164.     NextToken();
  165.     ExprAST *V = ParseExpression();
  166.     if (!V)
  167.         return nullptr;
  168.  
  169.     if (CurToken != ')') {
  170.         printf("%s\n", "expected ')'");
  171.         return nullptr;
  172.     }
  173.     NextToken();
  174.     return V;
  175. }
  176.  
  177. static ExprAST *ParseVarExpr() {
  178.     string Name = IdentifierStr;
  179.  
  180.     NextToken();
  181.  
  182.     if (CurToken != '=') {
  183.         return new VariableExprAST(Name);
  184.     }
  185.  
  186.     NextToken();
  187.  
  188.     ExprAST *varDecl = ParseExpression();
  189.     if (!varDecl) {
  190.         printf("expected expr after \"=\"!");
  191.         return nullptr;
  192.     }
  193.     return new AssignAST(Name, varDecl);
  194. }
  195.  
  196. static ExprAST *ParseIfExpr() {
  197.     NextToken();
  198.     if (CurToken != '(') {
  199.         printf("%s %c %d\n,", "expected '(' after if, no ", CurToken, CurToken);
  200.     }
  201.     NextToken();
  202.     ExprAST *Cond = ParseExpression();
  203.     if (!Cond)
  204.         return nullptr;
  205.  
  206.     if (CurToken != ')') {
  207.         printf("%s %c %d\n,", "expected ')' after if", CurToken, CurToken);
  208.     }
  209.  
  210.     NextToken();
  211.     NextToken();
  212.  
  213.     ExprAST *Then = ParseExpression();
  214.     NextToken();
  215.     ExprAST *Else = ParseExpression();
  216.  
  217.     return new IfExprAST(Cond, Then, Else);
  218. }
  219.  
  220. static ExprAST *ParsePrimary() {
  221.     switch (CurToken) {
  222.         case TOK_IDENT:
  223.             return ParseVarExpr();
  224.         case TOK_NUM:
  225.             return ParseNumberExpr();
  226.         case '(':
  227.             return ParseParenExpr();
  228.         case TOK_IF:
  229.             return ParseIfExpr();
  230.         default:
  231.             printf("unknown token when expecting an expression: %c\n", CurToken);
  232.             return nullptr;
  233.     }
  234. }
  235.  
  236.  
  237. static ExprAST *ParseBinary (ExprAST *expr) {
  238.     ExprAST *LHS = expr;
  239.     while (1) {
  240.         //  printf("parsemath1c: %d",CurToken);
  241.         if (CurToken!='+' && CurToken!='-')
  242.             return LHS;
  243.         char Op = CurToken;
  244.         NextToken();
  245.         //printf("parsemath2c: %d",CurToken);
  246.         ExprAST *RHS = ParsePrimary();
  247.         if (!RHS)
  248.             return nullptr;
  249.         LHS = new BinaryExprAST(Op, LHS, RHS);
  250.     }
  251. }
  252.  
  253. static ExprAST *ParseExpression() {
  254.     ExprAST *expr = ParsePrimary();
  255.     if (!expr) return nullptr;
  256.     return ParseBinary(expr);
  257. }
  258.  
  259.  
  260.  
  261.  
  262.  
  263. //===---------------------========------------------------===//
  264. //=---                    GENERATE                       ---=//
  265. //===---------------------========------------------------===//
  266.  
  267. //https://habrahabr.ru/post/120424/
  268.  
  269. //генерация Intermediate Representation по AST:
  270.  
  271. //определим виртуальные методы кодогенерации (Codegen) для каждого AST-класса
  272. // Метод Codegen() вернёт IR для данного узла AST вместе со всеми зависимыми от него, и все они возвращают объект LLVM Value.
  273. // "Value" является классом, используемым для представления «регистра Static Single Assigment (SSA)» или «Значения SSA» в LLVM.
  274.  
  275. //TheModule является конструкцией, содержащей все функции и глобальные переменные в куске кода.
  276. // В большинстве случаев, это структуры верхнего уровня, которые использует LLVM IR для содержащегося кода.
  277.  
  278. //Объект Builder является вспомогательным объектом, который позволяет генерировать инструкции LLVM
  279.  
  280. //Карта NamedValues отслеживает, какие значения определены в текущей области видимости и каково их LLVM-представление.
  281. // (Другими словами, это таблица символов для кода). В текущей форме в Kaleidoscope, единственное, что может ссылаться —
  282. // это параметры функций. Таким образом, в этой карте при генерации кода для тела функции будут расположены параметры этой функции.
  283.  
  284.  
  285.  
  286. static llvm::Module *MainModule;
  287. static llvm::Function *MainFunction;
  288. static llvm::LLVMContext MainContext;
  289. static llvm::IRBuilder<> Builder(llvm::getGlobalContext());
  290. static map<string, llvm::Value *> NamedValues;
  291.  
  292. llvm::Value *AssignAST::codegen(){
  293.     llvm::Value *v = assExpr->codegen();
  294.     if (!v)
  295.         return nullptr;
  296.  
  297.     llvm::AllocaInst *Alloca = Builder.CreateAlloca(llvm::Type::getInt32Ty(llvm::getGlobalContext()), 0, Name.c_str());
  298.     Builder.CreateStore(v, Alloca);
  299.     llvm::Value *CurVar = Builder.CreateLoad(Alloca);
  300.  
  301.     NamedValues[Name] = Alloca;
  302.     return CurVar;
  303. }
  304.  
  305. llvm::Value *NumberExprAST::codegen() {
  306.     return llvm::ConstantInt::get(llvm::getGlobalContext(), llvm::APInt(32, Val, false));
  307.     //APInt(unsigned numBits, uint64_t val, bool isSigned = false)
  308. }
  309.  
  310. llvm::Value *VariableExprAST::codegen() {
  311.     llvm::Value *V = NamedValues[Name];
  312.     if (!V) {
  313.         printf("unknown variable name\n");
  314.         return nullptr;
  315.     }
  316.     return Builder.CreateLoad(V, Name);
  317. }
  318.  
  319. llvm::Value *BinaryExprAST::codegen() {
  320.     llvm::Value *L = LHS->codegen();
  321.     llvm::Value *R = RHS->codegen();
  322.     if (!L || !R)
  323.         return nullptr;
  324.     switch (Op) {
  325.         case '+':
  326.             return Builder.CreateAdd(L, R, "addtmp");
  327.         case '-':
  328.             return Builder.CreateSub(L, R, "subtmp");
  329.         default:
  330.             printf("%s\n","invalid binary operator");
  331.             return nullptr;
  332.     }
  333.     //IRBuilder знает, куда вставлять вновь созданные инструкции, и всё, что нужно сделать вам —
  334.     // это указать, какие инструкции создавать (например, "CreateFAdd"),
  335.     // какие операнды использовать (в данном случае L и R) и, если требуется, то какое использовать имя для генерируемой инструкции.
  336. }
  337.  
  338. llvm::Value *IfExprAST::codegen() {
  339.     llvm::Value *CondV = Cond->codegen();
  340.     if (!CondV)
  341.         return nullptr;
  342.  
  343.     //https://habrahabr.ru/post/120881/
  344.     // Конвертация условия в булево сравнением с 0.0.
  345.     CondV = Builder.CreateICmpNE(
  346.             CondV, llvm::ConstantInt::get(llvm::getGlobalContext(), llvm::APInt(32, 0, false)), "ifcond");
  347.  
  348.     //Первая строка получает текущий объект Function (формируемой функции).
  349.     // Она получает его, спрашивая Builder о текущем базовом блоке и получая его «родителя» (текущую функцию).
  350.  
  351.     //Затем он создает три блока. Обратите внимание, что он передаёт "TheFunction" в конструктор блока "then".
  352.     // Это вызывает конструктор с автоматической вставкой нового блока в конец указанной функции.
  353.     // Два других блока тоже создаются, но еще не вставлены в функцию.
  354.     llvm::Function *MainFunction = Builder.GetInsertBlock()->getParent();
  355.  
  356.     llvm::BasicBlock *ThenBB = llvm::BasicBlock::Create(llvm::getGlobalContext(), "then", MainFunction);
  357.     llvm::BasicBlock *ElseBB = llvm::BasicBlock::Create(llvm::getGlobalContext(), "else");
  358.     llvm::BasicBlock *MergeBB = llvm::BasicBlock::Create(llvm::getGlobalContext(), "ifcont");
  359.  
  360.     Builder.CreateCondBr(CondV, ThenBB, ElseBB);
  361.  
  362.     // Генерируем значение.
  363.     Builder.SetInsertPoint(ThenBB);
  364.     llvm::Value *ThenV = Then->codegen();
  365.     if (!ThenV) return nullptr;
  366.  
  367.     Builder.CreateBr(MergeBB);
  368.     // Кодогенерация 'Then' может изменить текущий блок, обновляем ThenBB для PHI.
  369.     ThenBB = Builder.GetInsertBlock();
  370.  
  371.     // Генерируем блок else.
  372.     MainFunction->getBasicBlockList().push_back(ElseBB);
  373.     Builder.SetInsertPoint(ElseBB);
  374.     llvm::Value *ElseV = Else->codegen();
  375.     if (!ElseV) return nullptr;
  376.  
  377.     Builder.CreateBr(MergeBB);
  378.     // Кодогенерация 'Else' может изменить текущий блок, обновляем ElseBB для PHI.
  379.     ElseBB = Builder.GetInsertBlock();
  380.  
  381.  
  382.     // Генерация блока слияния.
  383.     MainFunction->getBasicBlockList().push_back(MergeBB);
  384.     Builder.SetInsertPoint(MergeBB);
  385.     llvm::PHINode *PN = Builder.CreatePHI(llvm::Type::getInt32Ty(llvm::getGlobalContext()), 2, "iftmp");
  386.  
  387.     PN->addIncoming(ThenV, ThenBB);
  388.     PN->addIncoming(ElseV, ElseBB);
  389.     return PN;
  390. }
  391.  
  392. static llvm::Value *Parse() {
  393.     NextToken();
  394.  
  395.     ExprAST *expr = nullptr;
  396.     llvm::Value *RetVal = nullptr;
  397.     while (CurToken != TOK_EOF) {
  398.         expr = ParseExpression();
  399.         if (expr) {
  400.             RetVal = expr->codegen();
  401.             if (!RetVal) NextToken();
  402.         } else {
  403.             return nullptr;
  404.         }
  405.     }
  406.  
  407.     return RetVal;
  408. }
  409.  
  410.  
  411. int main() {
  412.     // Создаём модуль, который будет хранить весь код.
  413.     MainModule = new llvm::Module("main", MainContext);
  414.  
  415.     MainFunction = MainModule->getFunction("main");
  416.  
  417.     llvm::FunctionType *FT =
  418.             llvm::FunctionType::get(llvm::Type::getVoidTy(llvm::getGlobalContext()),false);
  419.     MainFunction =
  420.             llvm::Function::Create(FT, llvm::GlobalValue::CommonLinkage, "main", MainModule);
  421.  
  422.     llvm::BasicBlock *BB = llvm::BasicBlock::Create(MainContext, "entry", MainFunction);
  423.     Builder.SetInsertPoint(BB);
  424.  
  425.     llvm::Value *ret = Parse();
  426.     Builder.CreateRet(ret);
  427.     //llvm::verifyFunction(*MainFunction);
  428.  
  429.     // Выводим сгенерированный код.
  430.     MainModule->dump();
  431.  
  432.     return 0;
  433. }
  434.  
  435.  
  436. //Локальные значения обозначаются префиксом %, а глобальные — @.
  437. // Локальные значения также называют регистрами, а LLVM — виртуальной машиной с бесконечным числом регистров.
  438.  
  439. //что из себя представляет LLVM IR.
  440. // В одном предложении его можно охарактеризовать как типизированный трёхадресный код в SSA-форме.
  441.  
  442. //базовые блоки, содержат последовательность инструкций, заканчивающуюся инструкцией-терминатором,
  443. // ЯВНО передающей управление в другой блок.
  444. // Базовые блоки в LLVM обозначаются метками, а терминаторами являются следующие инструкции: br, ret, switch ...
  445.  
  446. //Обратиться к памяти можно только с помощью двух инструкций, названия которых говорят сами за себя: load и store
  447. // Выделение памяти - alloca. Память выделяется на стеке. (malloc - в куче)
  448. // Память, выделенная alloca, автоматически освобождается при выходе из функции при помощи инструкций ret или unwind.
  449. // http://llvm.org/docs/LangRef.html
  450.  
  451.  
  452.  
  453.  
  454.  g++ -g -O3 main.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core` -fno-rtti -o prog
  455. ./prog
  456.  
  457.  
  458.  
  459. a = 2
  460. b = 3
  461. if (a) then
  462. b = 4
  463. else
  464. b = a + 5
  465. d = b
  466. ; ModuleID = 'main'
  467.  
  468. define common void @main() {
  469. entry:
  470.   %a = alloca i32
  471.   store i32 2, i32* %a
  472.   %0 = load i32, i32* %a
  473.   %b = alloca i32
  474.   store i32 3, i32* %b
  475.   %1 = load i32, i32* %b
  476.   %a1 = load i32, i32* %a
  477.   %ifcond = icmp ne i32 %a1, 0
  478.   br i1 %ifcond, label %then, label %else
  479.  
  480. then:                                             ; preds = %entry
  481.   %b2 = alloca i32
  482.   store i32 4, i32* %b2
  483.   %2 = load i32, i32* %b2
  484.   br label %ifcont
  485.  
  486. else:                                             ; preds = %entry
  487.   %a3 = load i32, i32* %a
  488.   %addtmp = add i32 %a3, 5
  489.   %b4 = alloca i32
  490.   store i32 %addtmp, i32* %b4
  491.   %3 = load i32, i32* %b4
  492.   br label %ifcont
  493.  
  494. ifcont:                                           ; preds = %else, %then
  495.   %iftmp = phi i32 [ %2, %then ], [ %3, %else ]
  496.   %b5 = load i32, i32* %b4
  497.   %d = alloca i32
  498.   store i32 %b5, i32* %d
  499.   %4 = load i32, i32* %d
  500.   ret i32 %4
  501. }
Advertisement
Add Comment
Please, Sign In to add comment