LLVM рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдПрдХ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рднрд╛рд╖рд╛ рдмрдирд╛рдирд╛ред рднрд╛рдЧ 5: рднрд╛рд╖рд╛ рд╡рд┐рд╕реНрддрд╛рд░: рдирд┐рдпрдВрддреНрд░рдг рдкреНрд░рд╡рд╛рд╣

рдЯреНрдпреВрдЯреЛрд░рд┐рдпрд▓ рдХреЗ рдЕрдзреНрдпрд╛рдп 5 рдореЗрдВ рдЖрдкрдХрд╛ рд╕реНрд╡рд╛рдЧрдд рд╣реИ "рдПрд▓рдПрд▓рд╡реАрдПрдо рдХреЗ рд╕рд╛рде рдПрдХ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рднрд╛рд╖рд╛ рдмрдирд╛рдирд╛"ред рдкрд┐рдЫрд▓реЗ рдЕрдзреНрдпрд╛рдпреЛрдВ ( рдкреНрд░рдердо , рджреНрд╡рд┐рддреАрдп , рддреГрддреАрдп рдФрд░ рдЪрддреБрд░реНрде ) рдиреЗ рд╕рд░рд▓ рдмрд╣реБрд░реВрдкрджрд░реНрд╢рдХ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рднрд╛рд╖рд╛ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдФрд░ рдПрд▓рдПрд▓рд╡реАрдПрдо рдЖрдИрдЖрд░ рдкреАрдврд╝реА рдХреЗ рд▓рд┐рдП рд╕рдорд░реНрдерди рдХреЗ рд╕рдорд╛рд╡реЗрд╢ рдХреЗ рд╕рд╛рде-рд╕рд╛рде рдмрд╛рдж рдХреЗ рдЕрдиреБрдХреВрд▓рди рдФрд░ рдЬреЗрдЖрдИрдЯреА рд╕рдВрдХрд▓рди рдХрд╛ рд╡рд░реНрдгрди рдХрд┐рдпрд╛ред рджреБрд░реНрднрд╛рдЧреНрдп рд╕реЗ, рдЕрдкрдиреЗ рд╡рд░реНрддрдорд╛рди рд╕реНрд╡рд░реВрдк рдореЗрдВ, рдХреИрд▓рд┐рдбреЛрд╕реНрдХреЛрдк рд▓рдЧрднрдЧ рдмреЗрдХрд╛рд░ рд╣реИ: рдЗрд╕рдореЗрдВ рдХреЙрд▓ рдФрд░ рд░рд┐рдЯрд░реНрди рдХреЗ рдЕрдкрд╡рд╛рдж рдХреЗ рд╕рд╛рде рдХреЛрдИ рдирд┐рдпрдВрддреНрд░рдг рдкреНрд░рд╡рд╛рд╣ рдирд╣реАрдВ рд╣реИред рдЗрд╕рдХрд╛ рдорддрд▓рдм рдпрд╣ рд╣реИ рдХрд┐ рдХреЛрдб рдореЗрдВ рдХреЛрдИ рд╕рд╢рд░реНрдд рдХреВрдж рдирд╣реАрдВ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ, рдЬреЛ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рднрд╛рд╖рд╛ рдХреЛ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд░реВрдк рд╕реЗ рд╕реАрдорд┐рдд рдХрд░рддрд╛ рд╣реИред рдЗрд╕ рдЕрдзреНрдпрд╛рдп рдореЗрдВ, рд╣рдо "for" рд▓реВрдк "for" рдПрдХ if/then/else рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдФрд░ рдПрдХ рд╕рд░рд▓ рдЬреЛрдбрд╝рдХрд░ рдмрд╣реБрд░реВрдкрджрд░реНрд╢рдХ рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рдХрд░рддреЗ рд╣реИрдВред

рдЕрдЧрд░ / рдлрд┐рд░ / рдПрд▓реНрд╕


if/then/else рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрд╣реБрд░реВрдкрджрд░реНрд╢рдХ рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рдХрд░рдирд╛ рдПрдХ рдХрд╛рдлреА рд╕рд░рд▓ рдХрд╛рд░реНрдп рд╣реИред рдЗрд╕рдХреЗ рд▓рд┐рдП рд▓реЗрдХреНрд╕рд┐рдХрд▓ рдФрд░ рдкрд╛рд░реНрд╕рд░реНрд╕, рдПрдПрд╕рдЯреАрдПрд╕ рдФрд░ рдХреЛрдб рдЬрдирд░реЗрдЯрд░ рдХреЗ рд▓рд┐рдП рдЗрд╕ "рдирдИ" рдЕрд╡рдзрд╛рд░рдгрд╛ рдХреЗ рд▓рд┐рдП рд╕рдорд░реНрдерди рдЬреЛрдбрд╝рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдпрд╣ рдПрдХ рдЕрдЪреНрдЫрд╛ рдЙрджрд╛рд╣рд░рдг рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рджрд┐рдЦрд╛рддрд╛ рд╣реИ рдХрд┐ рд╕рдордп рдХреЗ рд╕рд╛рде рдПрдХ рднрд╛рд╖рд╛ рдХреЛ "рдирд┐рд░реНрдорд╛рдг" рдХрд░рдирд╛ рдХрд┐рддрдирд╛ рдЖрд╕рд╛рди рд╣реИ, рдзреАрд░реЗ-рдзреАрд░реЗ рдирдП рд╡рд┐рдЪрд╛рд░реЛрдВ рдХреЗ рдЙрднрд░рдиреЗ рдХреЗ рд╕рд╛рде рдЗрд╕рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рд╣реЛрддрд╛ рд╣реИред

рдЗрд╕рд╕реЗ рдкрд╣рд▓реЗ рдХрд┐ рд╣рдо рдЗрд╕ рд╡рд┐рд╕реНрддрд╛рд░ рдХреЛ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ, рд╣рдореЗрдВ рдЕрдВрдд рдореЗрдВ рдХреНрдпрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рдЗрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдФрд░ рд╣рдо рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рд▓рд┐рдЦрдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ:

 def fib(x) if x < 3 then 1 else fib(x-1)+fib(x-2); 

рдмрд╣реБрд░реВрдкрджрд░реНрд╢рдХ рдореЗрдВ, рдкреНрд░рддреНрдпреЗрдХ рдирд┐рд░реНрдорд╛рдг рдПрдХ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рд╣реИред рдЗрд╕ рдкреНрд░рдХрд╛рд░, if/then/else рдХрд┐рд╕реА рдЕрдиреНрдп if/then/else рддрд░рд╣ if/then/else , рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреЛ рдПрдХ рдореВрд▓реНрдп рд╡рд╛рдкрд╕ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред рдЪреВрдВрдХрд┐ рд╣рдо рдореБрдЦреНрдп рд░реВрдк рд╕реЗ рдХрд╛рд░реНрдпрд╛рддреНрдордХ рд░реВрдк рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рд╣рдореЗрдВ рд╢рд░реНрдд рдХреА рдЧрдгрдирд╛ рдХрд░рдиреА рдЪрд╛рд╣рд┐рдП рдФрд░ рдлрд┐рд░ рдЙрд╕рдХреЗ рдореВрд▓реНрдп рдХреЗ рдЖрдзрд╛рд░ рдкрд░ "then" рдпрд╛ "else" рдореВрд▓реНрдп рд╡рд╛рдкрд╕ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред рдпрд╣ рд╕реА-рдПрдХреНрд╕рдкреНрд░реЗрд╢рди "?:" ред

if/then/else рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХрд╛ рд╢рдмреНрджрд╛рд░реНрде рдпрд╣ рд╣реИ рдХрд┐ рдпрд╣ рдПрдХ рдмреВрд▓рд┐рдпрди рдХреЗ рд░реВрдк рдореЗрдВ рд╕реНрдерд┐рддрд┐ рдХрд╛ рдореВрд▓реНрдпрд╛рдВрдХрди рдХрд░рддрд╛ рд╣реИ: 0.0 рдХреЛ рдЧрд▓рдд рдорд╛рдирд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рдмрд╛рдХреА рд╕рдм рд╕рдЪ рд╣реИред рдпрджрд┐ рд╕реНрдерд┐рддрд┐ рд╕рддреНрдп рд╣реИ, рддреЛ рдкрд╣рд▓реЗ рдЙрдкрд╕рд░реНрдЧ рдХрд╛ рдкрд░рд┐рдХрд▓рди рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рд╡рд╛рдкрд╕ рд▓реМрдЯрд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ; рдпрджрд┐ рд╕реНрдерд┐рддрд┐ рдЭреВрдареА рд╣реИ, рддреЛ рджреВрд╕рд░реА рдЙрдкрд╕рдХреНрд░рд┐рдпрддрд╛ рдХреА рдЧрдгрдирд╛ рдХреА рдЬрд╛рддреА рд╣реИ рдФрд░ рд╡рд╛рдкрд╕ рдХрд░ рджреА рдЬрд╛рддреА рд╣реИред рдЪреВрдВрдХрд┐ рдХреИрд▓реАрдбреЛрд╕реНрдХреЛрдк рджреБрд╖реНрдкреНрд░рднрд╛рд╡ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЗрд╕ рд╡реНрдпрд╡рд╣рд╛рд░ рдХреЛ рд╕реБрджреГрдврд╝ рдХрд░рдирд╛ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИред

рдЕрдм рдЬрдм рд╣рдо рдЬрд╛рдирддреЗ рд╣реИрдВ рдХрд┐ рд╣рдо рдХреНрдпрд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рддреЛ рд╣рдо рднрд╛рдЧреЛрдВ рдореЗрдВ рд╕рдордЭрдирд╛ рд╢реБрд░реВ рдХрд░реЗрдВрдЧреЗред

If / then / Else рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╢рд╛рдмреНрджрд┐рдХ рд╡рд┐рд╢реНрд▓реЗрд╖рдХ рдореЗрдВ рд╕реБрдзрд╛рд░

рдпрд╣рд╛рдВ рд╕рдм рдХреБрдЫ рд╕рд░рд▓ рд╣реИред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдЧрдгрдирд╛ рдХреЗ рдЕрдиреБрд░реВрдк рдЯреЛрдХрди рдХреЗ рд▓рд┐рдП рдирдП рдорд╛рди рдЬреЛрдбрд╝реЗрдВ:

  //  tok_if = -6, tok_then = -7, tok_else = -8, 

рдЕрдм рд╣рдо рд╢рд╛рдмреНрджрд┐рдХ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдореЗрдВ рдирдП рдЦреЛрдЬрд╢рдмреНрджреЛрдВ рдХреЛ рдкрд╣рдЪрд╛рдирддреЗ рд╣реИрдВред рдпрд╣ рднреА рд╕рд░рд▓ рд╣реИ:

  ... if (IdentifierStr == "def") return tok_def; if (IdentifierStr == "extern") return tok_extern; 
  if (IdentifierStr == "if") return tok_if; if (IdentifierStr == "then") return tok_then; if (IdentifierStr == "else") return tok_else; 
  return tok_identifier; 


рд╕рдВрд╢реЛрдзрд┐рдд рдПрдПрд╕рдЯреА рдЕрдЧрд░ / рдлрд┐рд░ / рдПрд▓реНрд╕ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП

рдПрдХ рдирдП рдкреНрд░рдХрд╛рд░ рдХреА рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХрд╛ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдПрдХ рдирдпрд╛ рдПрдПрд╕рдЯреА рдиреЛрдб рдЬреЛрдбрд╝реЗрдВ:

 /// IfExprAST -     if/then/else. class IfExprAST : public ExprAST { ExprAST *Cond, *Then, *Else; public: IfExprAST(ExprAST *cond, ExprAST *then, ExprAST *_else) : Cond(cond), Then(then), Else(_else) {} virtual Value *Codegen(); }; 

рдПрдПрд╕рдЯреА рдиреЛрдб рдореЗрдВ рд╡рд┐рднрд┐рдиреНрди рдЙрдкрдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рд╕рдВрдХреЗрдд рд╣реИрдВред

рдпрджрд┐ / рдлрд┐рд░ / Else рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд╛рд░реНрд╕рд░ рдХреЛ рдкрд░рд┐рд╖реНрдХреГрдд рдХрд░рдирд╛

рдЕрдм рдЬрдм рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рд╢рд╛рдмреНрджрд┐рдХ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдореЗрдВ рдЙрдкрдпреБрдХреНрдд рдЯреЛрдХрди рдФрд░ рдПрдПрд╕рдЯреА рдиреЛрдб рд╣реИ, рддреЛ рдкрд╛рд░реНрд╕рд┐рдВрдЧ рддрд░реНрдХ рдмрд╣реБрдд рд╕рд░рд▓ рд╣реЛрдЧрд╛ред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдПрдХ рдирдП рдкрд╛рд░реНрд╕рд┐рдВрдЧ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддреЗ рд╣реИрдВ:

 /// ifexpr ::= 'if' expression 'then' expression 'else' expression static ExprAST *ParseIfExpr() { getNextToken(); //  if. // . ExprAST *Cond = ParseExpression(); if (!Cond) return 0; if (CurTok != tok_then) return Error("expected then"); getNextToken(); //  then ExprAST *Then = ParseExpression(); if (Then == 0) return 0; if (CurTok != tok_else) return Error("expected else"); getNextToken(); ExprAST *Else = ParseExpression(); if (!Else) return 0; return new IfExprAST(Cond, Then, Else); } 

рдЕрдЧрд▓рд╛, рдЗрд╕реЗ рдПрдХ рдкреНрд░рд╛рдердорд┐рдХ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреЗ рд░реВрдк рдореЗрдВ рдХрдиреЗрдХреНрдЯ рдХрд░реЗрдВ:

 static ExprAST *ParsePrimary() { switch (CurTok) { default: return Error("unknown token when expecting an expression"); case tok_identifier: return ParseIdentifierExpr(); case tok_number: return ParseNumberExpr(); case '(': return ParseParenExpr(); 
  case tok_if: return ParseIfExpr(); 
  } } 


рдПрд▓рдПрд▓рд╡реАрдПрдо рдЖрдИрдЖрд░ рдлреЙрд░ рдЗрдл / рдлрд┐рд░ / рдПрд▓реНрд╕

рдЕрдм рдЬрдм рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдПрд╕рдЯреА рдХреА рдкрд╛рд░реНрд╕рд┐рдВрдЧ рдФрд░ рдмрд┐рд▓реНрдбрд┐рдВрдЧ рд╣реИ, рддреЛ рдЕрдВрддрд┐рдо рднрд╛рдЧ рдПрд▓рдПрд▓рд╡реАрдПрдо рдХреЛрдб рдЬрдирд░реЗрд╢рди рд╕рдкреЛрд░реНрдЯ рдХреЗ рдЕрддрд┐рд░рд┐рдХреНрдд рд╣реЛрдЧрд╛ред if/then/else рдЬреЛрдбрд╝рдиреЗ рдореЗрдВ рдпрд╣ рд╕рдмрд╕реЗ рджрд┐рд▓рдЪрд╕реНрдк рд╣рд┐рд╕реНрд╕рд╛ if/then/else , рдХреНрдпреЛрдВрдХрд┐ рдпрд╣рд╛рдВ рд╣рдо рдирдИ рдЕрд╡рдзрд╛рд░рдгрд╛рдУрдВ рдХреЛ рдкреЗрд╢ рдХрд░реЗрдВрдЧреЗред рдЙрдкрд░реЛрдХреНрдд рдХреЛрдб рдореЗрдВ рд╕рдм рдХреБрдЫ рдкрд┐рдЫрд▓реЗ рдЕрдзреНрдпрд╛рдпреЛрдВ рдореЗрдВ рд╡рд┐рд╕реНрддрд╛рд░ рд╕реЗ рд╡рд░реНрдгрд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред

рдЖрдЗрдП рдПрдХ рд╕рд╛рдзрд╛рд░рдг рдЙрджрд╛рд╣рд░рдг рджреЗрдЦреЗрдВ:

 extern foo(); extern bar(); 
 def baz(x) if x then foo() else bar(); 

рдпрджрд┐ рдЖрдк рдСрдкреНрдЯрд┐рдорд╛рдЗрдЬрд╝реЗрд╢рди рдмрдВрдж рдХрд░ рджреЗрддреЗ рд╣реИрдВ, рддреЛ рдЖрдкрдХреЛ рдХрд╛рд▓реАрджреЛрд╕реНрдХреЛрдк рд╕реЗ рдкреНрд░рд╛рдкреНрдд рд╣реЛрдиреЗ рд╡рд╛рд▓рд╛ рдХреЛрдб рдЬрд▓реНрдж рд╣реА рдорд┐рд▓ рдЬрд╛рдПрдЧрд╛:

 declare double @foo() declare double @bar() define double @baz(double %x) { entry: %ifcond = fcmp one double %x, 0.000000e+00 br i1 %ifcond, label %then, label %else then: ; preds = %entry %calltmp = call double @foo() br label %ifcont else: ; preds = %entry %calltmp1 = call double @bar() br label %ifcont ifcont: ; preds = %else, %then %iftmp = phi double [ %calltmp, %then ], [ %calltmp1, %else ] ret double %iftmp } 

рдирд┐рдпрдВрддреНрд░рдг рдкреНрд░рд╡рд╛рд╣ рдЧреНрд░рд╛рдл рдХреА рдХрд▓реНрдкрдирд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдк рдПрд▓рдПрд▓рд╡реАрдПрдо " рдСрдкреНрдЯ " рдЯреВрд▓ рдХреА рдЙрддреНрдХреГрд╖реНрдЯ рд╡рд┐рд╢реЗрд╖рддрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдпрджрд┐ рдЖрдк рдЗрд╕ LLVM IR рдХреЛ "t.ll" рдореЗрдВ рд░рдЦрддреЗ рд╣реИрдВ рдФрд░ "llvm-as < t.ll | opt -analyze -view-cfg" , рддреЛ рдПрдХ рд╡рд┐рдВрдбреЛ рджрд┐рдЦрд╛рдИ рджреЗрдЧреА рдЬрд┐рд╕рдореЗрдВ рдЖрдк рдЗрд╕ рдЧреНрд░рд╛рдл рдХреЛ рджреЗрдЦреЗрдВрдЧреЗ:

рдЫрд╡рд┐

рдЗрд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХрд╛ рджреВрд╕рд░рд╛ рддрд░реАрдХрд╛ "F->viewCFG()" рдпрд╛ "F->viewCFGOnly()" (рдЬрд╣рд╛рдВ F "Function*" ) рдХреЙрд▓ рдХрд░рдирд╛ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдХреЛрдб рдореЗрдВ рдХреЙрд▓ рдФрд░ recompiling рдпрд╛ рдбреАрдмрдЧрд░ рдореЗрдВ рдХреЙрд▓ рдХрд░рдирд╛ рд╣реИред рдПрд▓рдПрд▓рд╡реАрдПрдо рдореЗрдВ рд╡рд┐рднрд┐рдиреНрди рд░реЗрдЦрд╛рдВрдХрди рдХреА рдХрд▓реНрдкрдирд╛ рдХреЗ рд▓рд┐рдП рдХрдИ рдЙрдкрдпреЛрдЧреА рд╡рд┐рд╢реЗрд╖рддрд╛рдПрдВ рд╣реИрдВред

рдЖрдЗрдП рд╣рдо рдЙрддреНрдкрдиреНрди рдХреЛрдб рдкрд░ рд▓реМрдЯрддреЗ рд╣реИрдВ, рдпрд╣ рдХрд╛рдлреА рд╕рд░рд▓ рд╣реИ: рдЗрдирдкреБрдЯ рдмреНрд▓реЙрдХ рд╕рд╢рд░реНрдд рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ (рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ, "x" ) рдХреА рдЧрдгрдирд╛ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдирд┐рд░реНрджреЗрд╢ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ 0.0 рд╕рд╛рде рдкрд░рд┐рдгрд╛рдо рдХреА рддреБрд▓рдирд╛ рдХрд░рддрд╛ рд╣реИред "fcmp one" "fcmp one" ред рдЗрд╕ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреЗ рдкрд░рд┐рдгрд╛рдо рдХреЗ рдЖрдзрд╛рд░ рдкрд░, рдХреЛрдб рдпрд╛ рддреЛ "then" рдмреНрд▓реЙрдХ рдпрд╛ "else" рдмреНрд▓реЙрдХ рдореЗрдВ рдЬрд╛рддрд╛ рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рд╕рдЪреНрдЪреЗ / рдЭреВрдареЗ рдорд╛рдорд▓реЛрдВ рдХреЗ рд▓рд┐рдП рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рд╣реЛрддреА рд╣реИред

рдПрдХ рдмрд╛рд░ then/else рдмреНрд▓реЙрдХреЛрдВ рдХреЗ рдкреВрд░рд╛ рд╣реЛ рдЬрд╛рдиреЗ рдХреЗ then/else , рдпреЗ рджреЛрдиреЛрдВ рд╢рд╛рдЦрд╛рдПрдБ "ifcont" рдмреНрд▓реЙрдХ рдкрд░ рдЬрд╛рддреА рд╣реИрдВ рддрд╛рдХрд┐ if/then/else рдмрд╛рдж рд╕реНрдерд┐рдд рдХреЛрдб рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХреЗред рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рдХреЗрд╡рд▓ рдПрдХ рдЪреАрдЬ рдЬреЛ рдХрд░рдирд╛ рдмрд╛рдХреА рд╣реИ, рд╡рд╣ рдХреЙрд▓рд┐рдВрдЧ рдлрд╝рдВрдХреНрд╢рди рдкрд░ рд▓реМрдЯрддреА рд╣реИред рдлрд┐рд░ рд╕рд╡рд╛рд▓ рдЙрдарддрд╛ рд╣реИ: рдореБрдЭреЗ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рд╡рд╛рдкрд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреЛрдб рдХреИрд╕реЗ рдкрддрд╛ рдЪрд▓реЗрдЧрд╛?

рдЗрд╕ рдкреНрд░рд╢реНрди рдХреЗ рдЙрддреНрддрд░ рдореЗрдВ рдПрдХ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдПрд╕рдПрд╕рдП рдСрдкрд░реЗрд╢рди: рдСрдкрд░реЗрд╢рди рд╢рд╛рдорд┐рд▓ рд╣реИ Phi Phi ред рдпрджрд┐ рдЖрдк SSA рд╕реЗ рдкрд░рд┐рдЪрд┐рдд рдирд╣реАрдВ рд╣реИрдВ, рддреЛ рд╡рд┐рдХрд┐рдкреАрдбрд┐рдпрд╛ рд▓реЗрдЦ рдПрдХ рдЕрдЪреНрдЫрд╛ рдкрд░рд┐рдЪрдп рд╣реЛрдЧрд╛, рдФрд░ рдЗрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЕрдиреНрдп рдкрд░рд┐рдЪрдпрд╛рддреНрдордХ рд▓реЗрдЦ рд╣реИрдВ рдЬреЛ рдЖрдкрдХреЗ рдкрд╕рдВрджреАрджрд╛ рдЦреЛрдЬ рдЗрдВрдЬрди рджреНрд╡рд╛рд░рд╛ рдЖрд╕рд╛рдиреА рд╕реЗ рдорд┐рд▓ рд╕рдХрддреЗ рд╣реИрдВред рд▓рдШреБ рд╕рдВрд╕реНрдХрд░рдг: Phi рдСрдкрд░реЗрд╢рди рдХреЗ "рдирд┐рд╖реНрдкрд╛рджрди" рдХреЗ рд▓рд┐рдП рдЙрд╕ рдмреНрд▓реЙрдХ рдХреЛ "рдпрд╛рдж" рдХрд░рдирд╛ рдкрдбрд╝рддрд╛ рд╣реИ рдЬрд┐рд╕рд╕реЗ рд╣рдо рдЖрдП рдереЗред рдСрдкрд░реЗрд╢рди Phi рдорд╛рди рдФрд░ рд╕рдВрдмрдВрдзрд┐рдд рдЗрдирдкреБрдЯ рдХрдВрдЯреНрд░реЛрд▓ рдпреВрдирд┐рдЯ рд▓реЗрддрд╛ рд╣реИред рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рдпрджрд┐ рдирд┐рдпрдВрддреНрд░рдг "then" рдмреНрд▓реЙрдХ рд╕реЗ рдЖрддрд╛ рд╣реИ, "then" рдЗрд╕реЗ "calltmp" рдорд╛рди рдорд┐рд▓рддрд╛ рд╣реИред рдпрджрд┐ рдирд┐рдпрдВрддреНрд░рдг "else" рдмреНрд▓реЙрдХ рд╕реЗ рдЖрддрд╛ рд╣реИ, рддреЛ рдЗрд╕реЗ "calltmp1" рдорд╛рди "calltmp1" ред

рдЕрдм рдЖрдк рд╢рд╛рдпрдж рд╕реЛрдЪрдиреЗ рд▓рдЧреЗ рд╣реИрдВ: тАЬрдЕрд░реЗ рдирд╣реАрдВ! рдЗрд╕рдХрд╛ рдорддрд▓рдм рдпрд╣ рд╣реИ рдХрд┐ рдореЗрд░реЗ рд╕рд░рд▓ рдФрд░ рд╕реБрд░реБрдЪрд┐рдкреВрд░реНрдг рд╕рд╛рдордиреЗ рдХреЗ рдЫреЛрд░ рдХреЛ рдПрд▓рдПрд▓рд╡реАрдПрдо рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдПрд╕рдПрд╕рдП рдлреЙрд░реНрдо рдЙрддреНрдкрдиреНрди рдХрд░рдирд╛ рд╢реБрд░реВ рдХрд░рдирд╛ рд╣реЛрдЧрд╛! " рд╕реМрднрд╛рдЧреНрдп рд╕реЗ, рдпрд╣ рдорд╛рдорд▓рд╛ рдирд╣реАрдВ рд╣реИ, рдФрд░ рд╣рдо рджреГрдврд╝рддрд╛ рд╕реЗ рд╕рд▓рд╛рд╣ рджреЗрддреЗ рд╣реИрдВ рдХрд┐ рдПрд╕рдПрд╕рдП рднрд╡рди рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдХреЛ рдЕрдкрдиреЗ рд╕рд╛рдордиреЗ рдХреЗ рдЫреЛрд░ рдкрд░ рд▓рд╛рдЧреВ рди рдХрд░реЗрдВ рдЬрдм рддрдХ рдХрд┐ рдЗрд╕рдХреЗ рд▓рд┐рдП рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдХрд╛рд░рдг рди рд╣реЛред рд╡реНрдпрд╡рд╣рд╛рд░ рдореЗрдВ, рдФрд╕рдд рдЕрдирд┐рд╡рд╛рд░реНрдп рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рднрд╛рд╖рд╛ рдХреЗ рд▓рд┐рдП рдХреЛрдб рдореЗрдВ рджреЛ рдкреНрд░рдХрд╛рд░ рдХреЗ рдореВрд▓реНрдп рд╣реИрдВ рдЬрд┐рдиреНрд╣реЗрдВ рдлреА рдиреЛрдбреНрд╕ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛ рд╕рдХрддреА рд╣реИ:
  1. рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЪрд░ рдкреНрд░рджрд╛рди рдХрд░рдиреЗ рд╡рд╛рд▓рд╛ рдХреЛрдб: = 1; = + 1; = 1; = + 1;
  2. рдорд╛рди рдЬреЛ рдЖрдкрдХреЗ рдПрдПрд╕рдЯреА рдХреА рд╕рдВрд░рдЪрдирд╛ рдореЗрдВ рдирд┐рд╣рд┐рдд рд╣реИрдВ, рдЬреИрд╕реЗ рдХрд┐ рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ рдлреА рдиреЛрдбред
рдЗрд╕ рдЯреНрдпреВрдЯреЛрд░рд┐рдпрд▓ рдХреЗ рдЕрдзреНрдпрд╛рдп 7 рдореЗрдВ ("рдкрд░рд┐рд╡рд░реНрддрдирд╢реАрд▓ рдЪрд░"), рд╣рдо рдирдВрдмрд░ 1 рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░реЗрдВрдЧреЗред рдЗрд╕ рдмреАрдЪ, рдмрд╕ рдореБрдЭ рдкрд░ рднрд░реЛрд╕рд╛ рдХрд░реЗрдВ рдХрд┐ рдЖрдкрдХреЛ рдЗрд╕ рдорд╛рдорд▓реЗ рдХреЛ рд╕рдВрднрд╛рд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдПрд╕рдПрд╕рдП рдмрдирд╛рдиреЗ рдХреА рдЬрд░реВрд░рдд рдирд╣реАрдВ рд╣реИред рдирдВрдмрд░ 2 рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЗ рдкрд╛рд╕ рдПрдХ рд╡рд┐рдХрд▓реНрдк рд╣реИ: рдЙрди рд╡рд┐рдзрд┐рдпреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ рдЬреЛ рд╣рдо рдирдВрдмрд░ 1 рдХреЗ рд▓рд┐рдП рд╡рд░реНрдгрди рдХрд░рддреЗ рд╣реИрдВ, рдпрд╛ рдЖрдк рд╕реАрдзреЗ рдлреА рдиреЛрдбреНрд╕ рд╕рдореНрдорд┐рд▓рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЕрдЧрд░ рдпрд╣ рдЖрдкрдХреЗ рд▓рд┐рдП рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИред рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рдлреА рдиреЛрдбреНрд╕ рдЙрддреНрдкрдиреНрди рдХрд░рдирд╛ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдмрд╣реБрдд рд╕рд░рд▓ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдордиреЗ рдРрд╕рд╛ рдХрд░рдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛ред

рдареАрдХ рд╣реИ, рдпрд╣ рдХреЛрдб рдЙрддреНрдкрдиреНрди рдХрд░рдиреЗ рдХрд╛ рд╕рдордп рд╣реИ!

рдЕрдЧрд░ / рдлрд┐рд░ / рдХреЗ рд▓рд┐рдП рдХреЛрдб рдЬрдирд░реЗрд╢рди

рдХреЛрдб рдкреАрдврд╝реА рдХреЗ рд▓рд┐рдП, рд╣рдо IfExprAST рд▓рд┐рдП IfExprAST рд╡рд┐рдзрд┐ рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реИрдВ:

 Value *IfExprAST::Codegen() { Value *CondV = Cond->Codegen(); if (CondV == 0) return 0; //       0.0. CondV = Builder.CreateFCmpONE(CondV, ConstantFP::get(getGlobalContext(), APFloat(0.0)), "ifcond"); 

рдпрд╣ рдХреЛрдб рд╕рд░рд▓ рд╣реИ рдФрд░ рдЬреИрд╕рд╛ рд╣рдордиреЗ рдкрд╣рд▓реЗ рджреЗрдЦрд╛ рдерд╛ рд╡реИрд╕рд╛ рд╣реА рд╣реИред рд╣рдо рд╕реНрдерд┐рддрд┐ рдХреЗ рд▓рд┐рдП рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдкреНрд░рд╛рдкреНрдд рдХрд░рддреЗ рд╣реИрдВ, рдФрд░ рдлрд┐рд░ 1-рдмрд┐рдЯ (рдмреВрд▓) рдореВрд▓реНрдп рдХреЗ рд░реВрдк рдореЗрдВ рдЗрд╕рдХреА рд╕рдЪреНрдЪрд╛рдИ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╢реВрдиреНрдп рдХреЗ рд╕рд╛рде рдЗрд╕ рдореВрд▓реНрдп рдХреА рддреБрд▓рдирд╛ рдХрд░рддреЗ рд╣реИрдВред

  Function *TheFunction = Builder.GetInsertBlock()->getParent(); //     then  else.   'then'  //  . BasicBlock *ThenBB = BasicBlock::Create(getGlobalContext(), "then", TheFunction); BasicBlock *ElseBB = BasicBlock::Create(getGlobalContext(), "else"); BasicBlock *MergeBB = BasicBlock::Create(getGlobalContext(), "ifcont"); Builder.CreateCondBr(CondV, ThenBB, ElseBB); 

рдпрд╣ рдХреЛрдб рдЖрдзрд╛рд░ рдмреНрд▓реЙрдХ рдмрдирд╛рддрд╛ рд╣реИ рдЬреЛ if/then/else рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рд╣реИрдВ рдФрд░ рдЙрдкрд░реЛрдХреНрдд рдЙрджрд╛рд╣рд░рдг рдореЗрдВ рдмреНрд▓реЙрдХ рд╕реЗ рдореЗрд▓ рдЦрд╛рддреЗ рд╣реИрдВред рдкрд╣рд▓реА рдкрдВрдХреНрддрд┐ рдХреЛ рд╡рд░реНрддрдорд╛рди Function рдСрдмреНрдЬреЗрдХреНрдЯ (рдЧрдард┐рдд рдлрд╝рдВрдХреНрд╢рди рдХрд╛) рдорд┐рд▓рддрд╛ рд╣реИред рд╡рд╣ Builder рд╕реЗ рд╡рд░реНрддрдорд╛рди рдЖрдзрд╛рд░ рдЗрдХрд╛рдИ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдкреВрдЫрдХрд░ рдФрд░ рдЙрд╕рдХрд╛ "рдореВрд▓" (рд╡рд░реНрддрдорд╛рди рдХрд╛рд░реНрдп) рдкреНрд░рд╛рдкреНрдд рдХрд░ рд▓реЗрддреА рд╣реИред

рд╡рд╣ рдлрд┐рд░ рддреАрди рдмреНрд▓реЙрдХ рдмрдирд╛рддрд╛ рд╣реИред рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдпрд╣ "then" рдмреНрд▓реЙрдХ рдХреЗ "TheFunction" рдХреЛ "TheFunction" рдкрд╛рд╕ рдХрд░рддрд╛ рд╣реИред рдпрд╣ рдирд┐рд░реНрдорд╛рддрд╛ рдХреЛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдЕрдВрдд рдореЗрдВ рдПрдХ рдирдпрд╛ рдмреНрд▓реЙрдХ рд╕рдореНрдорд┐рд▓рд┐рдд рдХрд░рдиреЗ рдХрд╛ рдХрд╛рд░рдг рдмрдирддрд╛ рд╣реИред рджреЛ рдЕрдиреНрдп рдмреНрд▓реЙрдХ рднреА рдмрдирд╛рдП рдЧрдП рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЕрднреА рддрдХ рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ рдирд╣реАрдВ рдбрд╛рд▓реЗ рдЧрдП рд╣реИрдВред

рдмреНрд▓реЙрдХ рдмрдирд╛рдиреЗ рдХреЗ рдмрд╛рдж, рд╣рдо рдПрдХ рд╕рд╢рд░реНрдд рд╢рд╛рдЦрд╛ рдЙрддреНрдкрдиреНрди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдЬреЛ рдЙрдирдХреЗ рдмреАрдЪ рдЪрдпрди рдХрд░рддреА рд╣реИред рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдирдП рдмреНрд▓реЙрдХ рдХрд╛ рдирд┐рд╣рд┐рдд рдирд┐рд░реНрдорд╛рдг IRBuilder рдХреЛ рдкреНрд░рднрд╛рд╡рд┐рдд рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐ рдЕрднреА рднреА рдЙрд╕реА рдмреНрд▓реЙрдХ рдореЗрдВ рд╣реЛрддреА рд╣реИ рдЬреЛ рд╣рдордиреЗ рджрд░реНрдЬ рдХрд┐рдпрд╛ рдерд╛ред рдпрд╣ рднреА рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдпрд╣ "then" рдмреНрд▓реЙрдХ "else" рдмреНрд▓реЙрдХ рдХреЗ рд▓рд┐рдП рдПрдХ рд╢рд╛рдЦрд╛ рдмрдирд╛рддрд╛ рд╣реИ, рд╣рд╛рд▓рд╛рдВрдХрд┐ "else" рдмреНрд▓реЙрдХ рдХреЛ рдЕрднреА рддрдХ рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ рдирд╣реАрдВ рдбрд╛рд▓рд╛ рдЧрдпрд╛ рд╣реИред рд▓реЗрдХрд┐рди рд╕рдм рдХреБрдЫ рдХреНрд░рдо рдореЗрдВ рд╣реИ: рдЖрдЧреЗ рдХреЗ рд▓рд┐рдВрдХ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрд▓рдПрд▓рд╡реАрдПрдо рдХреЗ рд▓рд┐рдП рдпрд╣ рдорд╛рдирдХ рддрд░реАрдХрд╛ рд╣реИред

  //  . Builder.SetInsertPoint(ThenBB); Value *ThenV = Then->Codegen(); if (ThenV == 0) return 0; Builder.CreateBr(MergeBB); // Codegen of 'Then'    ,  ThenBB  PHI. ThenBB = Builder.GetInsertBlock(); 

рд╕рд╢рд░реНрдд рдХреВрдж рдбрд╛рд▓рдиреЗ рдХреЗ рдмрд╛рдж, рд╣рдо рдмрд┐рд▓реНрдбрд░ рдХреЛ "then" рдмреНрд▓реЙрдХ рдореЗрдВ рд╕рдореНрдорд┐рд▓рд┐рдд рдХрд░рдирд╛ рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП "then" ред рд╕рдЦреНрддреА рд╕реЗ рдмреЛрд▓рддреЗ рд╣реБрдП, рдпрд╣ рдХреЙрд▓ рдХрд░реНрд╕рд░ рдХреЛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдмреНрд▓реЙрдХ рдХреЗ рдЕрдВрдд рддрдХ рд▓реЗ рдЬрд╛рддрд╛ рд╣реИред рд╣рд╛рд▓рд╛рдБрдХрд┐, рдЪреВрдВрдХрд┐ "then" рдмреНрд▓реЙрдХ рдЦрд╛рд▓реА рд╣реИ, рдпрд╣ рдмреНрд▓реЙрдХ рдХреА рд╢реБрд░реБрдЖрдд рдореЗрдВ рд╣рдорд╛рд░рд╛ рдЗрдВрд╕рд░реНрдЯ рднреА рдХрд░рддрд╛ рд╣реИред :)

рдПрдХ рдмрд╛рд░ рдХрд░реНрд╕рд░ рд╕реЗрдЯ рд╣реЛ рдЬрд╛рдиреЗ рдкрд░, рд╣рдо рдПрдПрд╕рдЯреА рд╕реЗ "then" рдХреЗ рд▓рд┐рдП рдХреЛрдб рдХрд╛ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдХрд░рддреЗ рд╣реИрдВред "then" рдмреНрд▓реЙрдХ рдХреЛ рдкреВрд░рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рд╢рд╛рдЦрд╛ рдорд░реНрдЬ рдмреНрд▓реЙрдХ рдореЗрдВ рдмрд┐рдирд╛ рд╢рд░реНрдд рдХреВрдж рдмрдирд╛рддреЗ рд╣реИрдВред рдПрд▓рдПрд▓рд╡реАрдПрдо рдЖрдИрдЖрд░ рдХреЗ рджрд┐рд▓рдЪрд╕реНрдк (рдФрд░ рдмрд╣реБрдд рдорд╣рддреНрд╡рдкреВрд░реНрдг) рдкрд╣рд▓реБрдУрдВ рдореЗрдВ рд╕реЗ рдПрдХ рдпрд╣ рд╣реИ рдХрд┐ рдирд┐рдпрдВрддреНрд░рдг рд░реЗрдЦрд╛ рдЕрдиреБрджреЗрд╢ рдЬреИрд╕реЗ рд░рд┐рдЯрд░реНрди рдпрд╛ рд╢рд╛рдЦрд╛ рдХреЗ рд╕рд╛рде рд╕рднреА рдмреЗрд╕ рдмреНрд▓реЙрдХ рдХреЛ "рд╕рдорд╛рдкреНрдд" рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП ред рдЗрд╕рдХрд╛ рдЕрд░реНрде рд╣реИ рдХрд┐ рдирд┐рдпрдВрддреНрд░рдг рдХрд╛ рдкреВрд░рд╛ рдкреНрд░рд╡рд╛рд╣, рдЬрд┐рд╕рдореЗрдВ рдХрд┐рд╕реА рдЕрдиреНрдп рдХреЛрдб рдкрд░ рдирд┐рдпрдВрддреНрд░рдг рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рд╣реЛрддрд╛ рд╣реИ ( рдПрд▓рдЯреА рдереНрд░реВ ), рдПрд▓рдПрд▓рд╡реАрдЖрд░ рдЖрдИрдЖрд░ рдореЗрдВ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдореМрдЬреВрдж рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рдпрджрд┐ рдЗрд╕ рдирд┐рдпрдо рдХрд╛ рдЙрд▓реНрд▓рдВрдШрди рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рд╕рддреНрдпрд╛рдкрдирдХрд░реНрддрд╛ рдПрдХ рддреНрд░реБрдЯрд┐ рд▓реМрдЯрд╛рдПрдЧрд╛ред

рдЕрдВрддрд┐рдо рдкрдВрдХреНрддрд┐ рдпрд╣рд╛рдБ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИред рдПрдХ рд╢рд╛рдЦрд╛ рдорд░реНрдЬ рдмреНрд▓реЙрдХ рдореЗрдВ Phi рдиреЛрдб рдмрдирд╛рддреЗ рд╕рдордп, рд╣рдореЗрдВ рдмреНрд▓реЙрдХ / рдорд╛рди рдЬреЛрдбрд╝реЗ рдХреЛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП рдЬреЛ рдЗрдВрдЧрд┐рдд рдХрд░рддрд╛ рд╣реИ рдХрд┐ Phi рдХреИрд╕реЗ рдХрд╛рдо рдХрд░реЗрдЧрд╛ред рдпрд╣ рдзреНрдпрд╛рди рд░рдЦрдирд╛ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ рдХрд┐ Phi рдиреЛрдб CFG рдореЗрдВ рдкреНрд░рддреНрдпреЗрдХ рдмреНрд▓реЙрдХ рдкреВрд░реНрд╡рд╡рд░реНрддреА рдХреЗ рд▓рд┐рдП рдПрдХ рдкреНрд░рд╡реЗрд╢ рдмрд┐рдВрджреБ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреА рдЙрдореНрдореАрдж рдХрд░рддрд╛ рд╣реИред рдХреНрдпреЛрдВ, рдХреНрдпрд╛ рд╣рдореЗрдВ рд╡рд░реНрддрдорд╛рди рдмреНрд▓реЙрдХ рддрдм рдорд┐рд▓рддрд╛ рд╣реИ рдЬрдм рд╣рдо рдЗрд╕реЗ рд╕рд┐рд░реНрдл рддрдм рдХреЗ рдкрд╛рдВрдЪ рд▓рд╛рдЗрдиреЛрдВ рдореЗрдВ рд╕реЗрдЯ рдХрд░рддреЗ рд╣реИрдВ? рд╕рдорд╕реНрдпрд╛ рдпрд╣ рд╣реИ рдХрд┐ "then" рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЙрд╕ рдмреНрд▓реЙрдХ рдХреЛ рдмрджрд▓ рд╕рдХрддреА рд╣реИ рдЬреЛ рдмрд┐рд▓реНрдбрд░ рдЙрддреНрдкрдиреНрди рдХрд░рддрд╛ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдпрджрд┐ рдЗрд╕рдореЗрдВ рдирд┐рд╣рд┐рдд "if/then/else" рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рд╣реИред рдЪреВрдВрдХрд┐ Codegen рд▓рд┐рдП рдПрдХ рдкреБрдирд░рд╛рд╡рд░реНрддреА рдХреЙрд▓ рд╡рд░реНрддрдорд╛рди рдмреНрд▓реЙрдХ рдХреЛ рдордирдорд╛рдиреЗ рдврдВрдЧ рд╕реЗ рдмрджрд▓ рд╕рдХрддрд╛ рд╣реИ, рд╣рдореЗрдВ рдЙрд╕ рдХреЛрдб рдХреЗ рд▓рд┐рдП рд╡рд░реНрддрдорд╛рди рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдорд╛рди рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рд╣реЛрдЧрд╛ рдЬреЛ Phi рдиреЛрдб рдореЗрдВ рдмрдирд╛рдпрд╛ рдЬрд╛рдПрдЧрд╛ред

  //   else. TheFunction->getBasicBlockList().push_back(ElseBB); Builder.SetInsertPoint(ElseBB); Value *ElseV = Else->Codegen(); if (ElseV == 0) return 0; Builder.CreateBr(MergeBB); //  'Else'    ,  ElseBB  PHI. ElseBB = Builder.GetInsertBlock(); 

"else" рдмреНрд▓реЙрдХ рдХреЗ рд▓рд┐рдП рдХреЛрдб рдкреАрдврд╝реА "then" рдмреНрд▓реЙрдХ рдХреЗ рд▓рд┐рдП рдХреЛрдб рдкреАрдврд╝реА рдХреЗ рд▓рдЧрднрдЧ рд╕рдорд╛рди рд╣реИред рдПрдХрдорд╛рддреНрд░ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдЕрдВрддрд░ рдкрд╣рд▓реА рдкрдВрдХреНрддрд┐ рдореЗрдВ рд╣реИ, рдЬреЛ рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ "else" рдмреНрд▓реЙрдХ рдХреЛ рдЬреЛрдбрд╝рддрд╛ рд╣реИред рдпрд╛рдж рд░рдЦреЗрдВ рдХрд┐ "else" рдмреНрд▓реЙрдХ рдкрд╣рд▓реЗ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рдерд╛, рд▓реЗрдХрд┐рди рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ рдирд╣реАрдВ рдЬреЛрдбрд╝рд╛ рдЧрдпрд╛ред рдЕрдм рдЬрдм "then" рдФрд░ "else" рдмреНрд▓реЙрдХ рдЙрддреНрдкрдиреНрди рд╣реЛ рдЧрдП рд╣реИрдВ, рддреЛ рд╣рдо рдЙрдирдХреЗ рдорд░реНрдЬ рдХреЛрдб рдХреЗ рд╕рд╛рде рд╕рдорд╛рдкреНрдд рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ:

  //   . TheFunction->getBasicBlockList().push_back(MergeBB); Builder.SetInsertPoint(MergeBB); PHINode *PN = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), 2, "iftmp"); PN->addIncoming(ThenV, ThenBB); PN->addIncoming(ElseV, ElseBB); return PN; } 

рдкрд╣рд▓реА рджреЛ рдкрдВрдХреНрддрд┐рдпрд╛рдБ рдЖрдк рд╕реЗ рдкрд░рд┐рдЪрд┐рдд рд╣реИрдВ: рдкрд╣рд▓рд╛ рдлрд╝рдВрдХреНрд╢рди рдСрдмреНрдЬреЗрдХреНрдЯ рдореЗрдВ "merge" рдмреНрд▓реЙрдХ рдЬреЛрдбрд╝рддрд╛ рд╣реИред рджреВрд╕рд░рд╛ рдмреНрд▓реЙрдХ рд╕рдореНрдорд┐рд▓рди рдХрд░реНрд╕рд░ рдХреЛ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рддрд╛ рд╣реИ рддрд╛рдХрд┐ рдирд╡ рдирд┐рд░реНрдорд┐рдд рдХреЛрдб "merge" рдмреНрд▓реЙрдХ рдореЗрдВ рдлрд┐рдЯ рд╣реЛ рдЬрд╛рдПред рдлрд┐рд░ рд╣рдореЗрдВ PHI рдиреЛрдб рдмрдирд╛рдиреЗ рдФрд░ PHI рд▓рд┐рдП рдмреНрд▓реЙрдХ / рдорд╛рди рдЬреЛрдбрд╝реЗ рд╕реЗрдЯ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред

рдЕрдВрдд рдореЗрдВ, CodeGen рдлрд╝рдВрдХреНрд╢рди Phi рдиреЛрдб рдХреЛ if/then/else рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреЗ рд▓рд┐рдП рдЧрдгрдирд╛ рдХрд┐рдП рдЧрдП рдорд╛рди рдХреЗ рд░реВрдк рдореЗрдВ рд▓реМрдЯрд╛рддрд╛ рд╣реИред рдКрдкрд░ рд╣рдорд╛рд░реЗ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рдпрд╣ рд░рд┐рдЯрд░реНрди рд╡реИрд▓реНрдпреВ рд╢реАрд░реНрд╖-рд╕реНрддрд░реАрдп рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдХреЛрдб рдореЗрдВ рдЬрд╛рдПрдЧрд╛, рдЬреЛ рд░рд┐рдЯрд░реНрди рд╕реНрдЯреЗрдЯрдореЗрдВрдЯ рдмрдирд╛рдПрдЧрд╛ред

рд╕рд╛рдорд╛рдиреНрдп рддреМрд░ рдкрд░, рдЕрдм рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдмрд╣реБрд░реВрдкрджрд░реНрд╢рдХ рдореЗрдВ рд╕рд╢рд░реНрдд рдХреЛрдб рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рд╣реИред рдЗрд╕ рд╡рд┐рд╕реНрддрд╛рд░ рдХреЗ рд╕рд╛рде, рдХреИрд▓реАрдбреЛрд╕реНрдХреЛрдк рдПрдХ рдХрд╛рдлреА рд╡реНрдпрд╛рдкрдХ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рднрд╛рд╖рд╛ рд╣реИ рдЬреЛ рд╕рдВрдЦреНрдпрд╛рддреНрдордХ рдХрд╛рд░реНрдпреЛрдВ рдХреА рдПрдХ рд╡рд┐рд╕реНрддреГрдд рд╢реНрд░реГрдВрдЦрд▓рд╛ рдХреА рдЧрдгрдирд╛ рдХрд░ рд╕рдХрддрд╛ рд╣реИред рдЕрдм рд╣рдо рдПрдХ рдФрд░ рдЙрдкрдпреЛрдЧреА рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдЬреЛрдбрд╝реЗрдВрдЧреЗ рдЬреЛ рдЧреИрд░-рдХрд╛рд░реНрдпрд╛рддреНрдордХ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рднрд╛рд╖рд╛рдУрдВ рд╕реЗ рд╣рдореЗрдВ рдкрд░рд┐рдЪрд┐рдд рд╣реИ ...

рдкрд╛рд╢ рдХреЗ рд▓рд┐рдП


рдЕрдм рдЬрдм рд╣рдо рдЬрд╛рдирддреЗ рд╣реИрдВ рдХрд┐ рднрд╛рд╖рд╛ рдкрд░ рдмреБрдирд┐рдпрд╛рджреА рдирд┐рдпрдВрддреНрд░рдг рд╕рдВрд░рдЪрдирд╛рдУрдВ рдХреЛ рдХреИрд╕реЗ рдЬреЛрдбрд╝рд╛ рдЬрд╛рдП, рддреЛ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдЕрдзрд┐рдХ рд╢рдХреНрддрд┐рд╢рд╛рд▓реА рдЪреАрдЬреЗрдВ рдЬреЛрдбрд╝рдиреЗ рдХрд╛ рдПрдХ рдЙрдкрдХрд░рдг рд╣реИред рдЖрдЗрдП рдХреБрдЫ рдФрд░ рдЖрдХреНрд░рд╛рдордХ рдЬреЛрдбрд╝рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реЗрдВ - рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ "for" :

  extern putchard(char) 
  def printstar(n) for i = 1, i < n, 1.0 in putchard(42); # ascii 42 = '*' #  100  '*' printstar(100); 

рдпрд╣ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдПрдХ рдирдП рдЪрд░ (рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, "i" ) рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддреА рд╣реИ рдЬреЛ рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдореВрд▓реНрдп рд╕реЗ рддрдм рддрдХ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдХрд░рддрд╛ рд╣реИ рдЬрдм рддрдХ рдХрд┐ рд╕реНрдерд┐рддрд┐ (рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, "i < n" ) рд╕рд╣реА рд╣реЛ рдЬрд╛рддреА рд╣реИ, рдХрджрдо рдХреЗ рдореВрд▓реНрдп рд╕реЗ рдмрдврд╝ рдЬрд╛рддреА рд╣реИ (рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, "1.0" )ред рдпрджрд┐ рдЪрд░рдг рдорд╛рди рдЫреЛрдбрд╝рд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ рдпрд╣ 1.0 ред рд▓реВрдк рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреЗ рдЕрдкрдиреЗ рд╢рд░реАрд░ рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рддрд╛ рд╣реИред рдЪреВрдВрдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рд▓реМрдЯрдиреЗ рдХреЗ рд▓рд┐рдП рдХреБрдЫ рднреА рдмреЗрд╣рддрд░ рдирд╣реАрдВ рд╣реИ, рд╣рдо рдмрд╕ рдкрд╛рд╢ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддреЗ рд╣реИрдВ рдЬреИрд╕реЗ рдХрд┐ рд╣рдореЗрд╢рд╛ 0.0 ред рдмрд╛рдж рдореЗрдВ, рдЬрдм рд╣рдо рдЙрддреНрдкрд░рд┐рд╡рд░реНрддрдиреАрдп рдЪрд░ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ, рддреЛ рдпрд╣ рдЕрдзрд┐рдХ рдЙрдкрдпреЛрдЧреА рд╣реЛрдЧрд╛ред

рдкрд┐рдЫрд▓реЗ рдорд╛рдорд▓реЗ рдХреА рддрд░рд╣, рдЙрди рдмрджрд▓рд╛рд╡реЛрдВ рдкрд░ рднреА рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ, рдЬрд┐рдирдХреА рд╣рдореЗрдВ рдХрд▓реАрджреЛрд╕реНрдХреЛрдк рдХреЛ рдЪрдХреНрд░ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рдиреЗ рдХреА рдЬрд░реВрд░рдд рд╣реИ, рднрд╛рдЧреЛрдВ рдореЗрдВред

рд▓реВрдкрд┐рдХрд▓ рд╡рд┐рд╢реНрд▓реЗрд╖рдХ рдХреЛ 'рд▓реВрдк' рдХреЗ рд▓рд┐рдП рд╕рдкреЛрд░реНрдЯ рдХрд░рдирд╛

рд▓реЗрдХреНрд╕рд┐рдХрд▓ рдПрдирд╛рд▓рд╛рдЗрдЬрд░ рдХреЛ рдЙрд╕реА рддрд░рд╣ рд╕реЗ рд╕рдкреНрд▓реАрдореЗрдВрдЯ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬрд┐рд╕ рддрд░рд╣ рд╕реЗ if/then/else :

  ...   Token ... //  tok_if = -6, tok_then = -7, tok_else = -8, 
  tok_for = -9, tok_in = -10 
 ... in gettok ... if (IdentifierStr == "def") return tok_def; if (IdentifierStr == "extern") return tok_extern; if (IdentifierStr == "if") return tok_if; if (IdentifierStr == "then") return tok_then; if (IdentifierStr == "else") return tok_else; 
  if (IdentifierStr == "for") return tok_for; if (IdentifierStr == "in") return tok_in; 
  return tok_identifier; 


'рдкрд╛рд╢' рдХреЗ рд▓рд┐рдП рд╕рдорд░реНрдерди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдВрд╢реЛрдзрд┐рдд рдПрдПрд╕рдЯреА

рдПрдПрд╕рдЯреА рдиреЛрдб рднреА рд╕рд░рд▓ рд╣реИред рдпрд╣ рдЕрдкрдиреЗ рдиреЛрдбреНрд╕ рдореЗрдВ рдЪрд░ рдирд╛рдо рдФрд░ рд▓реВрдк рдмреЙрдбреА рдХреА рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рддрд╛ рд╣реИред

 /// ForExprAST -     for/in. class ForExprAST : public ExprAST { std::string VarName; ExprAST *Start, *End, *Step, *Body; public: ForExprAST(const std::string &varname, ExprAST *start, ExprAST *end, ExprAST *step, ExprAST *body) : VarName(varname), Start(start), End(end), Step(step), Body(body) {} virtual Value *Codegen(); }; 


'рдлреЙрд░ тАЩрд▓реВрдк рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд╛рд░реНрд╕рд░ рдХреЛ рдкрд░рд┐рд╖реНрдХреГрдд рдХрд░рдирд╛

рдкрд╛рд░реНрд╕рд░ рдХреЛрдб рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрди рднреА рдмрд╣реБрдд рдорд╛рдирдХ рд╣реИрдВред рдпрд╣рд╛рдВ рдПрдХрдорд╛рддреНрд░ рджрд┐рд▓рдЪрд╕реНрдк рдмрд┐рдВрджреБ рд╡реИрдХрд▓реНрдкрд┐рдХ рдХрджрдо рдореВрд▓реНрдп рдХрд╛ рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рд╣реИред рдкрд╛рд░реНрд╕рд░ рдЗрд╕реЗ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рддрд╛ рд╣реИ, рдпрд╣ рджреЗрдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдЬрд╛рдБрдЪрддрд╛ рд╣реИ рдХрд┐ рдХреНрдпрд╛ рджреВрд╕рд░рд╛ рдЕрд▓реНрдкрд╡рд┐рд░рд╛рдо рдореМрдЬреВрдж рд╣реИред рдпрджрд┐ рдирд╣реАрдВ, рддреЛ рдпрд╣ AST рдиреЛрдб рдореЗрдВ null рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЪрд░рдг рдорд╛рди рд╕реЗрдЯ рдХрд░рддрд╛ рд╣реИ:

 /// forexpr ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression static ExprAST *ParseForExpr() { getNextToken(); //  for. if (CurTok != tok_identifier) return Error("expected identifier after for"); std::string IdName = IdentifierStr; getNextToken(); //  . if (CurTok != '=') return Error("expected '=' after for"); getNextToken(); //  '='. ExprAST *Start = ParseExpression(); if (Start == 0) return 0; if (CurTok != ',') return Error("expected ',' after for start value"); getNextToken(); ExprAST *End = ParseExpression(); if (End == 0) return 0; //   . ExprAST *Step = 0; if (CurTok == ',') { getNextToken(); Step = ParseExpression(); if (Step == 0) return 0; } if (CurTok != tok_in) return Error("expected 'in' after for"); getNextToken(); //  'in'. ExprAST *Body = ParseExpression(); if (Body == 0) return 0; return new ForExprAST(IdName, Start, End, Step, Body); } 


LLVM IR 'рд▓реВрдк' рдХреЗ рд▓рд┐рдП

рдЕрдм рд╣рдо рджрд┐рд▓рдЪрд╕реНрдк рд╣рд┐рд╕реНрд╕реЗ рдкрд░ рдЖрдЧреЗ рдмрдврд╝реЗрдВрдЧреЗ: рд╣рдо LLVM IR рдХреА рдкреАрдврд╝реА рдХреЛ рдЖрдЧреЗ рдмрдврд╝рд╛рдПрдВрдЧреЗред рд╣рдорд╛рд░реЗ рдЙрдкрд░реЛрдХреНрдд рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рдпрд╣ рдПрд▓рдПрд▓рд╡реАрдПрдо рдЖрдИрдЖрд░ (рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдпрд╣ рдбрдВрдк рдЕрдиреБрдХреВрд▓рди рдЕрдХреНрд╖рдорддрд╛ рдХреЗ рд╕рд╛рде рд╕реНрдкрд╖реНрдЯрддрд╛ рдХреЗ рд▓рд┐рдП рдЙрддреНрдкрдиреНрди рд╣реЛрддрд╛ рд╣реИ)

 declare double @putchard(double) define double @printstar(double %n) { entry: ; initial value = 1.0 (inlined into phi) br label %loop loop: ; preds = %loop, %entry %i = phi double [ 1.000000e+00, %entry ], [ %nextvar, %loop ] ;  %calltmp = call double @putchard(double 4.200000e+01) ;  %nextvar = fadd double %i, 1.000000e+00 ;  %cmptmp = fcmp ult double %i, %n %booltmp = uitofp i1 %cmptmp to double %loopcond = fcmp one double %booltmp, 0.000000e+00 br i1 %loopcond, label %loop, label %afterloop afterloop: ; preds = %loop ; loop always returns 0.0 ret double 0.000000e+00 } 

рдЗрд╕ рд▓реВрдк рдореЗрдВ рд╡реЗ рд╕рднреА рдирд┐рд░реНрдорд╛рдг рд╢рд╛рдорд┐рд▓ рд╣реИрдВ рдЬреЛ рд╣рдордиреЗ рдкрд╣рд▓реЗ рджреЗрдЦреЗ рдереЗ: phi рдиреЛрдб, рдХрдИ рднрд╛рд╡ рдФрд░ рдХреБрдЫ рдмреБрдирд┐рдпрд╛рджреА рдмреНрд▓реЙрдХред рдЖрдЗрдП рджреЗрдЦреЗрдВ рдХрд┐ рдпрд╣ рдПрдХ рд╕рд╛рде рдХреИрд╕реЗ рдлрд┐рдЯ рдмреИрдарддрд╛ рд╣реИред

'рд▓реВрдк' рдХреЗ рд▓рд┐рдП рдХреЛрдб рдЬрдирд░реЗрд╢рди

Codegen рдкрд╣рд▓рд╛ рднрд╛рдЧ рдмрд╣реБрдд рд╕рд░рд▓ рд╣реИ: рд╣рдореЗрдВ рдмрд╕ рд▓реВрдк рдХреЗ рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдореВрд▓реНрдп рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдорд┐рд▓рддреА рд╣реИ:

 Value *ForExprAST::Codegen() { // Emit the start code first, without 'variable' in scope. Value *StartVal = Start->Codegen(); if (StartVal == 0) return 0; 

рдЕрдЧрд▓рд╛ рдХрджрдо рд▓реВрдк рдмреЙрдбреА рдХреА рд╢реБрд░реБрдЖрдд рдХреЗ рд▓рд┐рдП рдПрд▓рдПрд▓рд╡реАрдПрдо рдмреЗрд╕ рдпреВрдирд┐рдЯ рдмрдирд╛рдирд╛ рд╣реИред рдЙрдкрд░реЛрдХреНрдд рдорд╛рдорд▓реЗ рдореЗрдВ, рд▓реВрдк рдХрд╛ рдкреВрд░рд╛ рд╢рд░реАрд░ рдПрдХ рдмреНрд▓реЙрдХ рд╣реЛрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╛рдж рд░рдЦреЗрдВ рдХрд┐ рдмреЙрдбреА рдХреЛрдб рдореЗрдВ рд╣реА рдХрдИ рдмреНрд▓реЙрдХ рд╢рд╛рдорд┐рд▓ рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдпрджрд┐ рдЗрд╕рдореЗрдВ рднрд╛рд╡ рд╣реИрдВ if/then/else рдпрд╛ if/then/else for/in )ред

  //       ,    //  . Function *TheFunction = Builder.GetInsertBlock()->getParent(); BasicBlock *PreheaderBB = Builder.GetInsertBlock(); BasicBlock *LoopBB = BasicBlock::Create(getGlobalContext(), "loop", TheFunction); //        LoopBB. Builder.CreateBr(LoopBB); 

рдпрд╣ рдХреЛрдб рдЙрд╕реА рдХреЗ рд╕рдорд╛рди рд╣реИ, рдЬрд┐рд╕реЗ рд╣рдордиреЗ if/then/else рджреЗрдЦрд╛ рдерд╛ if/then/else ред рд╣рдореЗрдВ рд╡рд╣ рдмреНрд▓реЙрдХ рдпрд╛рдж рд╣реИ рдЬрд┐рд╕рдореЗрдВ рд╕реЗ рд╣рдо рд▓реВрдк рдореЗрдВ рдЖрдП рд╣реИрдВ, рдХреНрдпреЛрдВрдХрд┐ рд╣рдореЗрдВ Phi рдиреЛрдб рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЗрд╕рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреАред рдлрд┐рд░ рд╣рдо рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдмреНрд▓реЙрдХ рдмрдирд╛рддреЗ рд╣реИрдВ рдЬреЛ рдЪрдХреНрд░ рд╢реБрд░реВ рдХрд░рддрд╛ рд╣реИ, рдФрд░ рджреЛ рдмреНрд▓реЙрдХреЛрдВ рдХреЗ рдмреАрдЪ рдмрд┐рдирд╛ рд╢рд░реНрдд рд╕рдВрдХреНрд░рдордг рдкреИрджрд╛ рдХрд░рддрд╛ рд╣реИред

  //    LoopBB. Builder.SetInsertPoint(LoopBB); //   PHI    Start. PHINode *Variable = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), 2, VarName.c_str()); Variable->addIncoming(StartVal, PreheaderBB); 

рдЕрдм "preheader" рд▓реВрдк рдХреЗ рд▓рд┐рдП "preheader" рд╣реЗрдбрд░ рд╕реЗрдЯ рд╣реЛ рдЧрдпрд╛ рд╣реИ, рд╣рдо рд▓реВрдк рдмреЙрдбреА рдХреЛрдб рдЬрдирд░реЗрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдЧреЗ рдмрдврд╝рддреЗ рд╣реИрдВред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдо рдХрд░реНрд╕рд░ рдХреЛ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рд▓реВрдк рд╡реЗрд░рд┐рдПрдмрд▓ рдХреЗ рд▓рд┐рдП PHI рдиреЛрдб рдмрдирд╛рддреЗ рд╣реИрдВред рдЪреВрдВрдХрд┐ рд╣рдо рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдореВрд▓реНрдп рдЬрд╛рдирддреЗ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рд╣рдо рдЗрд╕реЗ Phi рдиреЛрдб рдореЗрдВ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВред рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ Phi рдХреЛ рдЕрдВрддрддрдГ рджреВрд╕рд░рд╛ рдореВрд▓реНрдп рдорд┐рд▓реЗрдЧрд╛, рд▓реЗрдХрд┐рди рд╣рдо рдЕрднреА рднреА рдЗрд╕реЗ рд╕реЗрдЯ рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ (рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдЕрднреА рддрдХ рдореМрдЬреВрдж рдирд╣реАрдВ рд╣реИ!)ред

  //       PHI.    //  ,     ,  . Value *OldVal = NamedValues[VarName]; NamedValues[VarName] = Variable; //   . ,      ,   //   .  ,    , //  ,     . if (Body->Codegen() == 0) return 0; 

рдЕрдм рдХреЛрдб рдЕрдзрд┐рдХ рджрд┐рд▓рдЪрд╕реНрдк рд╣реЛрддрд╛ рдЬрд╛ рд░рд╣рд╛ рд╣реИред рд╣рдорд╛рд░рд╛ "for" рд▓реВрдк рдЪрд░рд┐рддреНрд░ рддрд╛рд▓рд┐рдХрд╛ рдореЗрдВ рдПрдХ рдирдпрд╛ рдЪрд░ рдкреЗрд╢ рдХрд░рддрд╛ рд╣реИред рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рд╣рдорд╛рд░реА рдкреНрд░рддреАрдХ рддрд╛рд▓рд┐рдХрд╛ рдореЗрдВ рдлрд╝рдВрдХреНрд╢рди рддрд░реНрдХ рдпрд╛ рд▓реВрдк рдЪрд░ рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВред рдЗрд╕рд╕реЗ рдкрд╣рд▓реЗ рдХрд┐ рд╣рдо рд▓реВрдк рдмреЙрдбреА рдХреЛрдб рдЬрдирд░реЗрдЯ рдХрд░реЗрдВ, рд╣рдо рд▓реВрдк рд╡реИрд░рд┐рдПрдмрд▓ рдХреЛ рдЙрд╕рдХреЗ рдирд╛рдо рдХреЗ рд╡рд░реНрддрдорд╛рди рдорд╛рди рдХреЗ рд░реВрдк рдореЗрдВ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВред рдХреГрдкрдпрд╛ рдзреНрдпрд╛рди рджреЗрдВ - рдпрд╣ рдХрд╛рдлреА рд╕рдВрднрд╡ рд╣реИ рдХрд┐ рдмрд╛рд╣рд░реА рджрд╛рдпрд░реЗ рдореЗрдВ рдПрдХ рд╣реА рдирд╛рдо рдХреЗ рд╕рд╛рде рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдПрдХ рдЪрд░ рд╣реИред рдЖрдк рдЗрд╕реЗ рдЖрд╕рд╛рдиреА рд╕реЗ рдПрдХ рддреНрд░реБрдЯрд┐ рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ (рдПрдХ рддреНрд░реБрдЯрд┐ рдлреЗрдВрдХреЗрдВ рдФрд░ рдпрджрд┐ null рдкрд╣рд▓реЗ рд╕реЗ рд╣реА VarName рдХреЗ рд▓рд┐рдП рдПрдХ рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐ рд╣реИ), рд▓реЗрдХрд┐рди рд╣рдо рдЪрд░ рдХреЗ рдУрд╡рд░рд▓реИрдк рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдВрдЧреЗред рдЙрдЪрд┐рдд рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рд▓рд┐рдП, рд╣рдо OldVal рдореЗрдВ рдПрдХ рд╕рдВрднрд╛рд╡рд┐рдд рдУрд╡рд░рд▓реИрдкрд┐рдВрдЧ рдорд╛рди OldVal (рдЬреЛ рдЕрддрд┐рд╡реНрдпрд╛рдкреА рдЪрд░ рдирд╣реАрдВ рд╣реЛрдиреЗ рдкрд░ null рд╣реЛрдЧрд╛)ред

рдкреНрд░рддреАрдХ рддрд╛рд▓рд┐рдХрд╛ рдореЗрдВ рд▓реВрдк рдЪрд░ рд╕реЗрдЯ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рдХреЛрдб рдХреЛ рдкреБрди: рд╢рд░реАрд░ рдореЗрдВ рдЙрддреНрдкрдиреНрди рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдпрд╣ рд╢рд░реАрд░ рдХреЛ рд▓реВрдк рд╡реЗрд░рд┐рдПрдмрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ: рдЗрд╕рдХрд╛ рдХреЛрдИ рднреА рд╕рдВрджрд░реНрдн рд╕реНрд╡рд╛рднрд╛рд╡рд┐рдХ рд░реВрдк рд╕реЗ рдкреНрд░рддреАрдХ рддрд╛рд▓рд┐рдХрд╛ рдореЗрдВ рд╣реИред

  //   . Value *StepVal; if (Step) { StepVal = Step->Codegen(); if (StepVal == 0) return 0; } else { //   ,  1.0. StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0)); } Value *NextVar = Builder.CreateFAdd(Variable, StepVal, "nextvar"); 

рдЬрдм рд╢рд░реАрд░ рдЙрддреНрдкрдиреНрди рд╣реЛрддрд╛ рд╣реИ, рддреЛ рд╣рдо рдЪрд░рдг рдорд╛рди рдЬреЛрдбрд╝рдХрд░ рдпрд╛ 1.0рдЕрдЧрд░ рдпрд╣ рд╕реЗрдЯ рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИ, рддреЛ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдЪрд░ рдХреЗ рдЕрдЧрд▓реЗ рдореВрд▓реНрдп рдХреА рдЧрдгрдирд╛ рдХрд░рддреЗ рд╣реИрдВ ред "NextVar"рд▓реВрдк рдХреЗ рдЕрдЧрд▓реЗ рдЪрд░рдг рдореЗрдВ рд▓реВрдк рд╡реЗрд░рд┐рдПрдмрд▓ рдХрд╛ рдорд╛рди рд╣реИред

  //      . Value *EndCond = End->Codegen(); if (EndCond == 0) return EndCond; //       0.0. EndCond = Builder.CreateFCmpONE(EndCond, ConstantFP::get(getGlobalContext(), APFloat(0.0)), "loopcond"); 

рдЕрдВрдд рдореЗрдВ, рд╣рдо рдпрд╣ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд▓реВрдк рдХреЗ рдирд┐рдХрд╛рд╕ рдорд╛рди рдХреА рдЧрдгрдирд╛ рдХрд░рддреЗ рд╣реИрдВ рдХрд┐ рдХреНрдпрд╛ рд▓реВрдк рдкреВрд░рд╛ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рдпрд╣ рд▓рдЧрднрдЧ рд╕реНрдерд┐рддрд┐ рдореЗрдВ рдЧрдгрдирд╛ рдХреЗ рд╕рдорд╛рди рд╣реИ if/then/elseред

  //   " "   . BasicBlock *LoopEndBB = Builder.GetInsertBlock(); BasicBlock *AfterBB = BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction); //      LoopEndBB. Builder.CreateCondBr(EndCond, LoopBB, AfterBB); //       AfterBB. Builder.SetInsertPoint(AfterBB); 

рд▓реВрдк рдХреЗ рдкреВрд░реНрдг рд╢рд░реАрд░ рдХреЛрдб рдХреЗ рд╕рд╛рде, рд╣рдореЗрдВ рдХреЗрд╡рд▓ рдЗрд╕рдХреЗ рд▓рд┐рдП рдирд┐рдпрдВрддреНрд░рдг рдкреНрд░рд╡рд╛рд╣ рдХреЛ рдкреВрд░рд╛ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдпрд╣ рдХреЛрдб рдмреНрд▓реЙрдХ рдХреЗ рдЕрдВрдд (рдиреЛрдб рдХреЗ рд▓рд┐рдП phi) рдХреЛ рдпрд╛рдж рдХрд░рддрд╛ рд╣реИ , рдФрд░ рдлрд┐рд░ рд▓реВрдк рд╕реЗ рдмрд╛рд╣рд░ рдирд┐рдХрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдмреНрд▓реЙрдХ рдмрдирд╛рддрд╛ рд╣реИ ( "afterloop")ред рдмрд╛рд╣рд░ рдирд┐рдХрд▓рдиреЗ рдХреА рд╕реНрдерд┐рддрд┐ рдХреЗ рдореВрд▓реНрдп рдХреЗ рдЖрдзрд╛рд░ рдкрд░, рдпрд╣ рдПрдХ рд╕рд╢рд░реНрдд рд╕рдВрдХреНрд░рдордг рдмрдирд╛рддрд╛ рд╣реИ рдЬреЛ рдЪрдХреНрд░ рдХреЛ рдлрд┐рд░ рд╕реЗ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рдпрд╛ рдЪрдХреНрд░ рд╕реЗ рдмрд╛рд╣рд░ рдирд┐рдХрд▓рдиреЗ рдХреЗ рдмреАрдЪ рдЪреБрдирддрд╛ рд╣реИред рдХрд┐рд╕реА рднреА рдмрд╛рдж рдХреЗ рдХреЛрдб рдХреЛ рдмреНрд▓реЙрдХ рдореЗрдВ рдЬреЛрдбрд╝рд╛ рдЬрд╛рддрд╛ рд╣реИ "afterloop", рдЗрд╕рд▓рд┐рдП рд╣рдо рд╕рдореНрдорд┐рд▓рди рдХрд░реНрд╕рд░ рдХреЛ рдмрд┐рд▓реНрдХреБрд▓ рд╡рд╣реАрдВ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рддреЗ рд╣реИрдВред

  //      PHI. Variable->addIncoming(NextVar, LoopEndBB); //   . if (OldVal) NamedValues[VarName] = OldVal; else NamedValues.erase(VarName); //  for   0.0. return Constant::getNullValue(Type::getDoubleTy(getGlobalContext())); } 

рдЕрдВрддрд┐рдо рдХреЛрдб рд╕рдлрд╛рдИ рдХрд░рддрд╛ рд╣реИ: рдЕрдм рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рдореВрд▓реНрдп рд╣реИ "NextVar"рдФрд░ рд╣рдо PHI рдиреЛрдб рдореЗрдВ рд╢рд╛рдорд┐рд▓ рд▓реВрдк рдорд╛рди рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВред рдЙрд╕рдХреЗ рдмрд╛рдж, рд╣рдо рд▓реВрдк рд╡реИрд░рд┐рдПрдмрд▓ рдХреЛ рдкреНрд░рддреАрдХ рддрд╛рд▓рд┐рдХрд╛ рд╕реЗ рд╣рдЯрд╛рддреЗ рд╣реИрдВ, рддрд╛рдХрд┐ рд▓реВрдк рдХреЗ рдмрд╛рдж рдпрд╣ рдЧреБрдВрдЬрд╛рдЗрд╢ рдореЗрдВ рди рд╣реЛред рдЕрдВрдд рдореЗрдВ, рд▓реВрдк рдХреЗ рд▓рд┐рдП рдЙрддреНрдкрдиреНрди рдХреЛрдб рд╣рдореЗрд╢рд╛ рд▓реМрдЯрддрд╛ рд╣реИ 0.0, рдЗрд╕рд▓рд┐рдП рд╣рдо рд╡рд╣рд╛рдВ рд╕реЗ рд▓реМрдЯрддреЗ рд╣реИрдВ ForExprAST::Codegenред

рдпрд╣ рдЯреНрдпреВрдЯреЛрд░рд┐рдпрд▓ рдореЗрдВ рдЕрдзреНрдпрд╛рдп рдХрд╛ рд╕рдорд╛рдкрди рдХрд░рддрд╛ рд╣реИ, "Kaleidoscope рдХреЗ рд▓рд┐рдП рдПрдХ рдирд┐рдпрдВрддреНрд░рдг рдкреНрд░рд╡рд╛рд╣ рдЬреЛрдбрд╝рдирд╛ред" рдЗрд╕ рдЕрдзреНрдпрд╛рдп рдореЗрдВ, рд╣рдордиреЗ LLVM IR рдХреЗ рдХреБрдЫ рдкрд╣рд▓реБрдУрдВ рдкрд░ рдзреНрдпрд╛рди рджрд┐рдпрд╛, рдЬрд┐рдиреНрд╣реЗрдВ рдлреНрд░рдВрдЯ-рдПрдВрдб рдбреЗрд╡рд▓рдкрд░реНрд╕ рдХреЛ рдЬрд╛рдирдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИред рд╣рдорд╛рд░реА рдЧрд╛рдерд╛ рдХреЗ рдЕрдЧрд▓реЗ рдЕрдзреНрдпрд╛рдп рдореЗрдВ, рд╣рдо рдереЛрдбрд╝рд╛ рдкрд╛рдЧрд▓ рд╣реЛрдВрдЧреЗ рдФрд░ рдЕрдкрдиреА рдЧрд░реАрдм, рдирд┐рд░реНрджреЛрд╖ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рднрд╛рд╖рд╛ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛-рдкрд░рд┐рднрд╛рд╖рд┐рдд рдСрдкрд░реЗрдЯрд░ рдЬреЛрдбрд╝реЗрдВрдЧреЗред

рдкреВрд░реНрдг рдХреЛрдб рд╕реВрдЪреА


рдпрд╣рд╛рдБ рдХреЛрдб рдХреА рдПрдХ рдкреВрд░реА рд╕реВрдЪреА рджреА рдЧрдИ рд╣реИ, рдЬреЛ рднрд╛рд╡реЛрдВ рджреНрд╡рд╛рд░рд╛ рд╡рд┐рд╕реНрддрд╛рд░рд┐рдд рд╣реИ if/then/elseрдФрд░ for... рдЗрд╕ рдкреНрд░рдХрд╛рд░ рд╣реИ:

#
g++ -g toy.cpp `llvm-config --cppflags --ldflags --libs core jit native` -O3 -o toy
#
./toy

рдФрд░ рдХреЛрдб рд╣реА:

 #include "llvm/DerivedTypes.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/ExecutionEngine/JIT.h" #include "llvm/LLVMContext.h" #include "llvm/Module.h" #include "llvm/PassManager.h" #include "llvm/Analysis/Verifier.h" #include "llvm/Analysis/Passes.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetSelect.h" #include "llvm/Transforms/Scalar.h" #include "llvm/Support/IRBuilder.h" #include <cstdio> #include <string> #include <map> #include <vector> using namespace llvm; //===----------------------------------------------------------------------===// // Lexer ( ) //===----------------------------------------------------------------------===// //     [0-255],   , //       enum Token { tok_eof = -1, //  ( ) tok_def = -2, tok_extern = -3, //  ( : , ) tok_identifier = -4, tok_number = -5, //   tok_if = -6, tok_then = -7, tok_else = -8, tok_for = -9, tok_in = -10 }; static std::string IdentifierStr; // ,  tok_identifier static double NumVal; // ,  tok_number /// gettok -       . static int gettok() { static int LastChar = ' '; //  . while (isspace(LastChar)) LastChar = getchar(); if (isdigit(LastChar) || LastChar == '.') { // : [0-9.]+ IdentifierStr = LastChar; while (isalnum((LastChar = getchar()))) IdentifierStr += LastChar; if (IdentifierStr == "def") return tok_def; if (IdentifierStr == "extern") return tok_extern; if (IdentifierStr == "if") return tok_if; if (IdentifierStr == "then") return tok_then; if (IdentifierStr == "else") return tok_else; if (IdentifierStr == "for") return tok_for; if (IdentifierStr == "in") return tok_in; return tok_identifier; } if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+ std::string NumStr; do { NumStr += LastChar; LastChar = getchar(); } while (isdigit(LastChar) || LastChar == '.'); NumVal = strtod(NumStr.c_str(), 0); return tok_number; } if (LastChar == '#') { //     do LastChar = getchar(); while (LastChar != EOF && LastChar != '\n' && LastChar != '\r'); if (LastChar != EOF) return gettok(); } //   . if (LastChar == EOF) return tok_eof; //         ASCII int ThisChar = LastChar; LastChar = getchar(); return ThisChar; } //===----------------------------------------------------------------------===// // Abstract Syntax Tree (     ) //===----------------------------------------------------------------------===// /// ExprAST -      . class ExprAST { public: virtual ~ExprAST() {} virtual Value *Codegen() = 0; }; /// NumberExprAST -       (, "1.0"). class NumberExprAST : public ExprAST { double Val; public: NumberExprAST(double val) : Val(val) {} virtual Value *Codegen(); }; /// VariableExprAST -      (, "a"). class VariableExprAST : public ExprAST { std::string Name; public: VariableExprAST(const std::string &name) : Name(name) {} virtual Value *Codegen(); }; /// BinaryExprAST -      . class BinaryExprAST : public ExprAST { char Op; ExprAST *LHS, *RHS; public: BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) : Op(op), LHS(lhs), RHS(rhs) {} virtual Value *Codegen(); }; /// CallExprAST -      . class CallExprAST : public ExprAST { std::string Callee; std::vector<ExprAST*> Args; public: CallExprAST(const std::string &callee, std::vector<ExprAST*> &args) : Callee(callee), Args(args) {} virtual Value *Codegen(); }; /// IfExprAST -     if/then/else. class IfExprAST : public ExprAST { ExprAST *Cond, *Then, *Else; public: IfExprAST(ExprAST *cond, ExprAST *then, ExprAST *_else) : Cond(cond), Then(then), Else(_else) {} virtual Value *Codegen(); }; /// ForExprAST -     for/in. class ForExprAST : public ExprAST { std::string VarName; ExprAST *Start, *End, *Step, *Body; public: ForExprAST(const std::string &varname, ExprAST *start, ExprAST *end, ExprAST *step, ExprAST *body) : VarName(varname), Start(start), End(end), Step(step), Body(body) {} virtual Value *Codegen(); }; /// PrototypeAST -    ""  , ///        (,  , ///    ). class PrototypeAST { std::string Name; std::vector<std::string> Args; public: PrototypeAST(const std::string &name, const std::vector<std::string> &args) : Name(name), Args(args) {} Function *Codegen(); }; /// FunctionAST -     class FunctionAST { PrototypeAST *Proto; ExprAST *Body; public: FunctionAST(PrototypeAST *proto, ExprAST *body) : Proto(proto), Body(body) {} Function *Codegen(); }; //===----------------------------------------------------------------------===// // Parser (   ) //===----------------------------------------------------------------------===// /// CurTok/getNextToken -    . CurTok -   /// ,  . getNextToken     ///     CurTok. static int CurTok; static int getNextToken() { return CurTok = gettok(); } /// BinopPrecedence -      static std::map<char, int> BinopPrecedence; /// GetTokPrecedence -     . static int GetTokPrecedence() { if (!isascii(CurTok)) return -1; // ,     . int TokPrec = BinopPrecedence[CurTok]; if (TokPrec <= 0) return -1; return TokPrec; } /// Error* -       . ExprAST *Error(const char *Str) { fprintf(stderr, "Error: %s\n", Str);return 0;} PrototypeAST *ErrorP(const char *Str) { Error(Str); return 0; } FunctionAST *ErrorF(const char *Str) { Error(Str); return 0; } static ExprAST *ParseExpression(); /// identifierexpr /// ::= identifier /// ::= identifier '(' expression* ')' static ExprAST *ParseIdentifierExpr() { std::string IdName = IdentifierStr; getNextToken(); //  . if (CurTok != '(') //  . return new VariableExprAST(IdName); //  . getNextToken(); //  ( std::vector<ExprAST*> Args; if (CurTok != ')') { while (1) { ExprAST *Arg = ParseExpression(); if (!Arg) return 0; Args.push_back(Arg); if (CurTok == ')') break; if (CurTok != ',') return Error("Expected ')' or ',' in argument list"); getNextToken(); } } //  ')'. getNextToken(); return new CallExprAST(IdName, Args); } /// numberexpr ::= number static ExprAST *ParseNumberExpr() { ExprAST *Result = new NumberExprAST(NumVal); getNextToken(); //   return Result; } /// parenexpr ::= '(' expression ')' static ExprAST *ParseParenExpr() { getNextToken(); //  (. ExprAST *V = ParseExpression(); if (!V) return 0; if (CurTok != ')') return Error("expected ')'"); getNextToken(); //  ). return V; } /// ifexpr ::= 'if' expression 'then' expression 'else' expression static ExprAST *ParseIfExpr() { getNextToken(); //  if. // . ExprAST *Cond = ParseExpression(); if (!Cond) return 0; if (CurTok != tok_then) return Error("expected then"); getNextToken(); //  then ExprAST *Then = ParseExpression(); if (Then == 0) return 0; if (CurTok != tok_else) return Error("expected else"); getNextToken(); ExprAST *Else = ParseExpression(); if (!Else) return 0; return new IfExprAST(Cond, Then, Else); } /// forexpr ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression static ExprAST *ParseForExpr() { getNextToken(); //  for. if (CurTok != tok_identifier) return Error("expected identifier after for"); std::string IdName = IdentifierStr; getNextToken(); //  . if (CurTok != '=') return Error("expected '=' after for"); getNextToken(); //  '='. ExprAST *Start = ParseExpression(); if (Start == 0) return 0; if (CurTok != ',') return Error("expected ',' after for start value"); getNextToken(); ExprAST *End = ParseExpression(); if (End == 0) return 0; //   . ExprAST *Step = 0; if (CurTok == ',') { getNextToken(); Step = ParseExpression(); if (Step == 0) return 0; } if (CurTok != tok_in) return Error("expected 'in' after for"); getNextToken(); //  'in'. ExprAST *Body = ParseExpression(); if (Body == 0) return 0; return new ForExprAST(IdName, Start, End, Step, Body); } /// primary /// ::= identifierexpr /// ::= numberexpr /// ::= parenexpr /// ::= ifexpr /// ::= forexpr static ExprAST *ParsePrimary() { switch (CurTok) { default: return Error("unknown token when expecting an expression"); case tok_identifier: return ParseIdentifierExpr(); case tok_number: return ParseNumberExpr(); case '(': return ParseParenExpr(); case tok_if: return ParseIfExpr(); case tok_for: return ParseForExpr(); } } /// binoprhs /// ::= ('+' primary)* static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { //    ,    while (1) { int TokPrec = GetTokPrecedence(); //           , //  ,    if (TokPrec < ExprPrec) return LHS; // ,  ,    . int BinOp = CurTok; getNextToken(); //    //       ExprAST *RHS = ParsePrimary(); if (!RHS) return 0; //  BinOp   RHS  ,    RHS, //      RHS  LHS. int NextPrec = GetTokPrecedence(); if (TokPrec < NextPrec) { RHS = ParseBinOpRHS(TokPrec+1, RHS); if (RHS == 0) return 0; } //  LHS/RHS. LHS = new BinaryExprAST(BinOp, LHS, RHS); } } /// expression /// ::= primary binoprhs /// static ExprAST *ParseExpression() { ExprAST *LHS = ParsePrimary(); if (!LHS) return 0; return ParseBinOpRHS(0, LHS); } /// prototype /// ::= id '(' id* ')' static PrototypeAST *ParsePrototype() { if (CurTok != tok_identifier) return ErrorP("Expected function name in prototype"); //    . std::string FnName = IdentifierStr; getNextToken(); if (CurTok != '(') return ErrorP("Expected '(' in prototype"); std::vector<std::string> ArgNames; while (getNextToken() == tok_identifier) ArgNames.push_back(IdentifierStr); if (CurTok != ')') return ErrorP("Expected ')' in prototype"); //  . getNextToken(); //  ')'. return new PrototypeAST(FnName, ArgNames); } /// definition ::= 'def' prototype expression static FunctionAST *ParseDefinition() { getNextToken(); //  def. PrototypeAST *Proto = ParsePrototype(); if (Proto == 0) return 0; if (ExprAST *E = ParseExpression()) return new FunctionAST(Proto, E); return 0; } /// toplevelexpr ::= expression static FunctionAST *ParseTopLevelExpr() { if (ExprAST *E = ParseExpression()) { //   . PrototypeAST *Proto = new PrototypeAST("", std::vector<std::string>()); return new FunctionAST(Proto, E); } return 0; } /// external ::= 'extern' prototype static PrototypeAST *ParseExtern() { getNextToken(); //  extern. return ParsePrototype(); } //===----------------------------------------------------------------------===// // Code Generation () //===----------------------------------------------------------------------===// static Module *TheModule; static IRBuilder<> Builder(getGlobalContext()); static std::map<std::string, Value*> NamedValues; static FunctionPassManager *TheFPM; Value *ErrorV(const char *Str) { Error(Str); return 0; } Value *NumberExprAST::Codegen() { return ConstantFP::get(getGlobalContext(), APFloat(Val)); } Value *VariableExprAST::Codegen() { //      . Value *V = NamedValues[Name]; return V ? V : ErrorV("Unknown variable name"); } Value *BinaryExprAST::Codegen() { Value *L = LHS->Codegen(); Value *R = RHS->Codegen(); if (L == 0 || R == 0) return 0; switch (Op) { case '+': return Builder.CreateFAdd(L, R, "addtmp"); case '-': return Builder.CreateFSub(L, R, "subtmp"); case '*': return Builder.CreateFMul(L, R, "multmp"); case '<': L = Builder.CreateFCmpULT(L, R, "cmptmp"); //   0  1   0.0  1.0 return Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()), "booltmp"); default: return ErrorV("invalid binary operator"); } } Value *CallExprAST::Codegen() { //      . Function *CalleeF = TheModule->getFunction(Callee); if (CalleeF == 0) return ErrorV("Unknown function referenced"); //    . 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() == 0) return 0; } return Builder.CreateCall(CalleeF, ArgsV.begin(), ArgsV.end(), "calltmp"); } Value *IfExprAST::Codegen() { Value *CondV = Cond->Codegen(); if (CondV == 0) return 0; //       0.0. CondV = Builder.CreateFCmpONE(CondV, ConstantFP::get(getGlobalContext(), APFloat(0.0)), "ifcond"); Function *TheFunction = Builder.GetInsertBlock()->getParent(); //     then  else.   'then'  //  . BasicBlock *ThenBB = BasicBlock::Create(getGlobalContext(), "then", TheFunction); BasicBlock *ElseBB = BasicBlock::Create(getGlobalContext(), "else"); BasicBlock *MergeBB = BasicBlock::Create(getGlobalContext(), "ifcont"); Builder.CreateCondBr(CondV, ThenBB, ElseBB); //  . Builder.SetInsertPoint(ThenBB); Value *ThenV = Then->Codegen(); if (ThenV == 0) return 0; Builder.CreateBr(MergeBB); //  'Then'    ,  ThenBB  PHI. ThenBB = Builder.GetInsertBlock(); //   else. TheFunction->getBasicBlockList().push_back(ElseBB); Builder.SetInsertPoint(ElseBB); Value *ElseV = Else->Codegen(); if (ElseV == 0) return 0; Builder.CreateBr(MergeBB); //  'Else'    ,  ElseBB  PHI. ElseBB = Builder.GetInsertBlock(); //   . TheFunction->getBasicBlockList().push_back(MergeBB); Builder.SetInsertPoint(MergeBB); PHINode *PN = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), 2, "iftmp"); PN->addIncoming(ThenV, ThenBB); PN->addIncoming(ElseV, ElseBB); return PN; } Value *ForExprAST::Codegen() { // Output this as: // ... // start = startexpr // goto loop // loop: // variable = phi [start, loopheader], [nextvariable, loopend] // ... // bodyexpr // ... // loopend: // step = stepexpr // nextvariable = variable + step // endcond = endexpr // br endcond, loop, endloop // outloop: // Emit the start code first, without 'variable' in scope. Value *StartVal = Start->Codegen(); if (StartVal == 0) return 0; //       ,    //  . Function *TheFunction = Builder.GetInsertBlock()->getParent(); BasicBlock *PreheaderBB = Builder.GetInsertBlock(); BasicBlock *LoopBB = BasicBlock::Create(getGlobalContext(), "loop", TheFunction); //         LoopBB. Builder.CreateBr(LoopBB); //    LoopBB. Builder.SetInsertPoint(LoopBB); //   PHI    Start. PHINode *Variable = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), 2, VarName.c_str()); Variable->addIncoming(StartVal, PreheaderBB); //       PHI.    //  ,     ,  . Value *OldVal = NamedValues[VarName]; NamedValues[VarName] = Variable; //   . ,      ,   //   .  ,    , //  ,     . if (Body->Codegen() == 0) return 0; //   . Value *StepVal; if (Step) { StepVal = Step->Codegen(); if (StepVal == 0) return 0; } else { //   ,  1.0. StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0)); } Value *NextVar = Builder.CreateFAdd(Variable, StepVal, "nextvar"); //      . Value *EndCond = End->Codegen(); if (EndCond == 0) return EndCond; //       0.0. EndCond = Builder.CreateFCmpONE(EndCond, ConstantFP::get(getGlobalContext(), APFloat(0.0)), "loopcond"); //   " "   . BasicBlock *LoopEndBB = Builder.GetInsertBlock(); BasicBlock *AfterBB = BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction); //      LoopEndBB. Builder.CreateCondBr(EndCond, LoopBB, AfterBB); //       AfterBB. Builder.SetInsertPoint(AfterBB); //      PHI. Variable->addIncoming(NextVar, LoopEndBB); //   . if (OldVal) NamedValues[VarName] = OldVal; else NamedValues.erase(VarName); //  for   0.0. return Constant::getNullValue(Type::getDoubleTy(getGlobalContext())); } Function *PrototypeAST::Codegen() { //   : double(double,double)  .. std::vector<const Type*> Doubles(Args.size(), Type::getDoubleTy(getGlobalContext())); FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()), Doubles, false); Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule); //   (F)     ,     'Name'. //     ,      . if (F->getName() != Name) { //   ,      . F->eraseFromParent(); F = TheModule->getFunction(Name); //   (F)   , . if (!F->empty()) { ErrorF("redefinition of function"); return 0; } //   (F)    , . if (F->arg_size() != Args.size()) { ErrorF("redefinition of function with different # args"); return 0; } } //     . unsigned Idx = 0; for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size(); ++AI, ++Idx) { AI->setName(Args[Idx]); //      . NamedValues[Args[Idx]] = AI; } return F; } Function *FunctionAST::Codegen() { NamedValues.clear(); Function *TheFunction = Proto->Codegen(); if (TheFunction == 0) return 0; //      . BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction); Builder.SetInsertPoint(BB); if (Value *RetVal = Body->Codegen()) { //  . Builder.CreateRet(RetVal); //   ,    (). verifyFunction(*TheFunction); //  . TheFPM->run(*TheFunction); return TheFunction; } //  ,   . TheFunction->eraseFromParent(); return 0; } //===----------------------------------------------------------------------===// // Top-Level parsing (  )   JIT //===----------------------------------------------------------------------===// static ExecutionEngine *TheExecutionEngine; static void HandleDefinition() { if (FunctionAST *F = ParseDefinition()) { if (Function *LF = F->Codegen()) { fprintf(stderr, "Read function definition:"); LF->dump(); } } else { //      . getNextToken(); } } static void HandleExtern() { if (PrototypeAST *P = ParseExtern()) { if (Function *F = P->Codegen()) { fprintf(stderr, "Read extern: "); F->dump(); } } else { //      . getNextToken(); } } static void HandleTopLevelExpression() { //      . if (FunctionAST *F = ParseTopLevelExpr()) { if (Function *LF = F->Codegen()) { // JIT-,   . void *FPtr = TheExecutionEngine->getPointerToFunction(LF); //     ( ,  double), //       . double (*FP)() = (double (*)())(intptr_t)FPtr; fprintf(stderr, "Evaluated to %f\n", FP()); } } else { //      . getNextToken(); } } /// top ::= definition | external | expression | ';' static void MainLoop() { while (1) { fprintf(stderr, "ready> "); switch (CurTok) { case tok_eof: return; case ';': getNextToken(); break; //     . case tok_def: HandleDefinition(); break; case tok_extern: HandleExtern(); break; default: HandleTopLevelExpression(); break; } } } //===----------------------------------------------------------------------===// // "" ,     //   ("extern")   . //===----------------------------------------------------------------------===// /// putchard -        0. extern "C" double putchard(double X) { putchar((char)X); return 0; } //===----------------------------------------------------------------------===// // Main driver code (  ) //===----------------------------------------------------------------------===// int main() { InitializeNativeTarget(); LLVMContext &Context = getGlobalContext(); //    . // 1 -  . BinopPrecedence['<'] = 10; BinopPrecedence['+'] = 20; BinopPrecedence['-'] = 20; BinopPrecedence['*'] = 40; //  . // Prime the first token. fprintf(stderr, "ready> "); getNextToken(); //  ,     . TheModule = new Module("my cool jit", Context); //  JIT.     . std::string ErrStr; TheExecutionEngine = EngineBuilder(TheModule).setErrorStr(&ErrStr).create(); if (!TheExecutionEngine) { fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str()); exit(1); } FunctionPassManager OurFPM(TheModule); //   .     ,  //       . OurFPM.add(new TargetData(*TheExecutionEngine->getTargetData())); //   AliasAnalysis  GVN. OurFPM.add(createBasicAliasAnalysisPass()); //   "peephole"  "bit-twiddling". OurFPM.add(createInstructionCombiningPass()); //  . OurFPM.add(createReassociatePass()); //   . OurFPM.add(createGVNPass()); //     (    ..). OurFPM.add(createCFGSimplificationPass()); OurFPM.doInitialization(); //   ,     . TheFPM = &OurFPM; //    " ". MainLoop(); TheFPM = 0; //   . TheModule->dump(); return 0; } 

Source: https://habr.com/ru/post/In120881/


All Articles