/////////////////////////////////////////////////////////////// Loops public void GenerateGenericLoop(IEnumerable <SyntaxNode> initializerNodes, IEnumerable <SyntaxNode> iteratorNodes, SyntaxNode conditionalNode, StatementSyntax loopScopeNode, FrontEndContext context) { // Always walk the initializer node statements first if they exists. The contents of this go before any loop block. if (initializerNodes != null) { foreach (var initializerNode in initializerNodes) { WalkAndGetResult(initializerNode); } } // A basic while looks like a header block that always jumps to a condition block. // The condition block will choose to jump either to the loop block or to the merge point. // The loop block will always branch to the continue target unless a break happens which // will branch to the merge block (after the loop). // The continue block will always jump back to the header block. var headerBlock = mFrontEnd.CreateBlock("headerBlock"); var conditionBlock = mFrontEnd.CreateBlock("conditionBlock"); var loopTrueBlock = mFrontEnd.CreateBlock("loop-body"); var continueBlock = mFrontEnd.CreateBlock("continueBlock"); var mergeBlock = mFrontEnd.CreateBlock("after-loop"); // Always jump to the header block mFrontEnd.CreateOp(context.mCurrentBlock, OpInstructionType.OpBranch, null, new List <IShaderIR> { headerBlock }); // The header always jumps to the conditional context.mCurrentFunction.mBlocks.Add(headerBlock); GenerateLoopHeaderBlock(headerBlock, conditionBlock, mergeBlock, continueBlock, context); // The conditional will jump to either the loop body or the merge point (after the loop) context.mCurrentFunction.mBlocks.Add(conditionBlock); GenerateLoopConditionBlock(conditionalNode, conditionBlock, loopTrueBlock, mergeBlock, context); // Walk all of the statements in the loop body and jump to either the merge or continue block context.mCurrentFunction.mBlocks.Add(loopTrueBlock); GenerateLoopStatements(loopScopeNode, loopTrueBlock, mergeBlock, continueBlock, context); // The continue block always just jumps to the header block context.mCurrentFunction.mBlocks.Add(continueBlock); GenerateLoopContinueBlock(iteratorNodes, continueBlock, headerBlock, context); // Afterwards the active block is always the merge point context.mCurrentFunction.mBlocks.Add(mergeBlock); context.mCurrentBlock = mergeBlock; }