protected internal virtual ExprAST VisitForExprAST(ForExprAST node) { this.Visit(node.Start); this.Visit(node.End); this.Visit(node.Step); this.Visit(node.Body); return node; }
protected internal virtual ExprAST VisitForExprAST(ForExprAST node) { this.Visit(node.Start); this.Visit(node.End); this.Visit(node.Step); this.Visit(node.Body); return(node); }
protected override ExprAST VisitForExprAST(ForExprAST node) { // 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. this.Visit(node.Start); var startVal = this.valueStack.Pop(); // Make the new basic block for the loop header, inserting after current // block. var preheaderBB = LLVM.GetInsertBlock(this.builder); var function = LLVM.GetBasicBlockParent(preheaderBB); var loopBB = LLVM.AppendBasicBlock(function, "loop"); // Insert an explicit fall through from the current block to the LoopBB. LLVM.BuildBr(this.builder, loopBB); // Start insertion in LoopBB. LLVM.PositionBuilderAtEnd(this.builder, loopBB); // Start the PHI node with an entry for Start. var variable = LLVM.BuildPhi(builder, LLVM.DoubleType(), node.VarName); LLVM.AddIncoming(variable, new [] { startVal }, new [] { preheaderBB }, 1); // 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. LLVMValueRef oldVal; if (this.namedValues.TryGetValue(node.VarName, out oldVal)) { this.namedValues[node.VarName] = variable; } else { this.namedValues.Add(node.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. Visit(node.Body); // Emit the step value. LLVMValueRef stepVal; if (node.Step != null) { Visit(node.Step); stepVal = valueStack.Pop(); } else { // If not specified, use 1.0. stepVal = LLVM.ConstReal(LLVM.DoubleType(), 1.0); } LLVMValueRef nextVar = LLVM.BuildFAdd(builder, variable, stepVal, "nextvar"); // Compute the end condition. Visit(node.End); LLVMValueRef endCond = LLVM.BuildFCmp(builder, LLVMRealPredicate.LLVMRealONE, valueStack.Pop(), LLVM.ConstReal(LLVM.DoubleType(), 0.0), "loopcond"); // Create the "after loop" block and insert it. var loopEndBB = LLVM.GetInsertBlock(builder); var afterBB = LLVM.AppendBasicBlock(function, "afterloop"); // Insert the conditional branch into the end of LoopEndBB. LLVM.BuildCondBr(builder, endCond, loopBB, afterBB); // Any new code will be inserted in AfterBB. LLVM.PositionBuilderAtEnd(builder, afterBB); // Add a new entry to the PHI node for the backedge. LLVM.AddIncoming(variable, new [] { nextVar }, new [] { loopEndBB }, 1); // Restore the unshadowed variable. if (oldVal.Pointer != IntPtr.Zero) { namedValues[node.VarName] = oldVal; } else { namedValues.Remove(node.VarName); } valueStack.Push(LLVM.ConstReal(LLVM.DoubleType(), 0.0)); return(node); }