[llvm-commits] [llvm] r43547 - /llvm/trunk/docs/tutorial/LangImpl5.html
Chris Lattner
sabre at nondot.org
Tue Oct 30 23:47:39 PDT 2007
Author: lattner
Date: Wed Oct 31 01:47:39 2007
New Revision: 43547
URL: http://llvm.org/viewvc/llvm-project?rev=43547&view=rev
Log:
add the code for expression code that we'll add, though most of the
description is missing.
Modified:
llvm/trunk/docs/tutorial/LangImpl5.html
Modified: llvm/trunk/docs/tutorial/LangImpl5.html
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/tutorial/LangImpl5.html?rev=43547&r1=43546&r2=43547&view=diff
==============================================================================
--- llvm/trunk/docs/tutorial/LangImpl5.html (original)
+++ llvm/trunk/docs/tutorial/LangImpl5.html Wed Oct 31 01:47:39 2007
@@ -473,7 +473,271 @@
<div class="doc_text">
-<p>...</p>
+<p>Now that we know how to add basic control flow constructs to the language,
+we have the tools to add more powerful things. Lets add something more
+aggressive, a 'for' expression:</p>
+
+<div class="doc_code">
+<pre>
+ # print 100 '*' (ascii 42) characters
+ extern putchard(char)
+ for x = 1, x < 100, 1.0 in putchard(42);
+</pre>
+</div>
+
+<p>This expression defines a new variable ("x" in this case) which iterates from
+a starting value, while the condition ("x < 100" in this case) is true,
+incrementing by an optional step value ("1.0" in this case). If the step value
+is omitted, it defaults to 1.0. While the loop is true, it executes its
+body expression. Because we don't have anything better to return, we'll just
+define the loop as always returning 0.0. In the future when we have mutable
+variables, it will get more useful.</p>
+
+<p>As before, lets talk about the changes that we need to Kaleidoscope to
+support this.</p>
+
+</div>
+
+<!-- ======================================================================= -->
+<div class="doc_subsubsection"><a name="forlexer">Lexer Extensions for
+the 'for' Loop</a></div>
+<!-- ======================================================================= -->
+
+<div class="doc_text">
+
+<p>The lexer extensions are the same sort of thing as for if/then/else:</p>
+
+<div class="doc_code">
+<pre>
+ ... in enum Token ...
+ // control
+ tok_if = -6, tok_then = -7, tok_else = -8,
+<b> tok_for = -9, tok_in = -10</b>
+
+ ... 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;
+ <b>if (IdentifierStr == "for") return tok_for;
+ if (IdentifierStr == "in") return tok_in;</b>
+ return tok_identifier;
+</pre>
+</div>
+
+</div>
+
+<!-- ======================================================================= -->
+<div class="doc_subsubsection"><a name="forast">AST Extensions for
+the 'for' Loop</a></div>
+<!-- ======================================================================= -->
+
+<div class="doc_text">
+
+<p>The AST node is similarly simple. It basically boils down to capturing
+the variable name and the consituent expressions in the node.</p>
+
+<div class="doc_code">
+<pre>
+/// ForExprAST - Expression class for 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();
+};
+</pre>
+</div>
+
+</div>
+
+<!-- ======================================================================= -->
+<div class="doc_subsubsection"><a name="forparser">Parser Extensions for
+the 'for' Loop</a></div>
+<!-- ======================================================================= -->
+
+<div class="doc_text">
+
+<p>The parser code is also fairly standard. The only interesting thing here is
+handling of the optional step value. The parser code handles it by checking to
+see if the second comma is present. If not, it sets the step value to null in
+the AST node:</p>
+
+<div class="doc_code">
+<pre>
+/// forexpr ::= 'for' identifer '=' expr ',' expr (',' expr)? 'in' expression
+static ExprAST *ParseForExpr() {
+ getNextToken(); // eat the for.
+
+ if (CurTok != tok_identifier)
+ return Error("expected identifier after for");
+
+ std::string IdName = IdentifierStr;
+ getNextToken(); // eat identifer.
+
+ if (CurTok != '=')
+ return Error("expected '=' after for");
+ getNextToken(); // eat '='.
+
+
+ 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;
+
+ // The step value is optional.
+ ExprAST *Step = 0;
+ if (CurTok == ',') {
+ getNextToken();
+ Step = ParseExpression();
+ if (Step == 0) return 0;
+ }
+
+ if (CurTok != tok_in)
+ return Error("expected 'in' after for");
+ getNextToken(); // eat 'in'.
+
+ ExprAST *Body = ParseExpression();
+ if (Body == 0) return 0;
+
+ return new ForExprAST(IdName, Start, End, Step, Body);
+}
+</pre>
+</div>
+
+</div>
+
+<!-- ======================================================================= -->
+<div class="doc_subsubsection"><a name="forir">LLVM IR for
+the 'for' Loop</a></div>
+<!-- ======================================================================= -->
+
+<div class="doc_text">
+
+<p>Now we get to the good part: the LLVM IR we want to generate for this thing.
+</p>
+
+
+
+</div>
+
+<!-- ======================================================================= -->
+<div class="doc_subsubsection"><a name="forcodegen">Code Generation for
+the 'for' Loop</a></div>
+<!-- ======================================================================= -->
+
+<div class="doc_text">
+
+
+<div class="doc_code">
+<pre>
+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;
+
+ // Make the new basic block for the loop header, inserting after current
+ // block.
+ Function *TheFunction = Builder.GetInsertBlock()->getParent();
+ BasicBlock *PreheaderBB = Builder.GetInsertBlock();
+ BasicBlock *LoopBB = new BasicBlock("loop", TheFunction);
+
+ // Insert an explicit fall through from the current block to the LoopBB.
+ // Start insertion in LoopBB.
+ Builder.CreateBr(LoopBB);
+ Builder.SetInsertPoint(LoopBB);
+
+ // Start the PHI node with an entry for Start.
+ PHINode *Variable = Builder.CreatePHI(Type::DoubleTy, VarName.c_str());
+ Variable->addIncoming(StartVal, PreheaderBB);
+
+ // Within the loop, the variable is defined equal to the PHI node. If it
+ // shadows an existing variable, we have to restore it, so save it now.
+ Value *OldVal = NamedValues[VarName];
+ NamedValues[VarName] = Variable;
+
+ // Emit the body of the loop. This, like any other expr, can change the
+ // current BB. Note that we ignore the value computed by the body, but don't
+ // allow an error.
+ if (Body->Codegen() == 0)
+ return 0;
+
+ // Emit the step value.
+ Value *StepVal;
+ if (Step) {
+ StepVal = Step->Codegen();
+ if (StepVal == 0) return 0;
+ } else {
+ // If not specified, use 1.0.
+ StepVal = ConstantFP::get(Type::DoubleTy, APFloat(1.0));
+ }
+
+ Value *NextVar = Builder.CreateAdd(Variable, StepVal, "nextvar");
+
+ // When evaluating the end condition, the value of the variable is the
+ // incremented value.
+ NamedValues[VarName] = Variable;
+
+
+ // Compute the end condition.
+ Value *EndCond = End->Codegen();
+ if (EndCond == 0) return EndCond;
+
+ // Convert condition to a bool by comparing equal to 0.0.
+ EndCond = Builder.CreateFCmpONE(EndCond,
+ ConstantFP::get(Type::DoubleTy, APFloat(0.0)),
+ "loopcond");
+
+ // Create the "after loop" block and insert it.
+ BasicBlock *LoopEndBB = Builder.GetInsertBlock();
+ BasicBlock *AfterBB = new BasicBlock("afterloop", TheFunction);
+
+ // Insert the conditional branch into the end of LoopEndBB.
+ Builder.CreateCondBr(EndCond, LoopBB, AfterBB);
+
+ // Any new code will be inserted in AfterBB.
+ Builder.SetInsertPoint(AfterBB);
+
+ // Add a new entry to the PHI node for the backedge.
+ Variable->addIncoming(NextVar, LoopEndBB);
+
+ // Restore the unshadowed variable.
+ if (OldVal)
+ NamedValues[VarName] = OldVal;
+ else
+ NamedValues.erase(VarName);
+
+
+ // for expr always returns 0.0.
+ return Constant::getNullValue(Type::DoubleTy);
+}
+</pre>
+</div>
+
</div>
More information about the llvm-commits
mailing list