Exemplo n.º 1
0
        /////////////////////////////////////////////////////////////// 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;
        }