Пример #1
0
        /// <summary>
        /// Group input into a set of blocks that can be later arbitraliby schufled.
        /// The method adds necessary branches to make control flow between blocks
        /// explicit and thus order independent.
        /// </summary>
        ///
        public static void SplitToBasicBlocks(ILBlock block, bool reducebranches = false)
        {
            int           nextLabelIndex = 0;
            List <ILNode> basicBlocks    = new List <ILNode>();

            ILLabel      entryLabel = block.Body.FirstOrDefault() as ILLabel ?? ILLabel.Generate("Block_", nextLabelIndex++);
            ILBasicBlock basicBlock = new ILBasicBlock();

            basicBlocks.Add(basicBlock);
            basicBlock.Body.Add(entryLabel);
            block.EntryGoto = new ILExpression(GMCode.B, entryLabel);

            if (block.Body.Count > 0)
            {
                if (block.Body[0] != entryLabel)
                {
                    basicBlock.Body.Add(block.Body[0]);
                }
                for (int i = 1; i < block.Body.Count; i++)
                {
                    ILNode lastNode = block.Body[i - 1];
                    ILNode currNode = block.Body[i];

                    // Start a new basic block if necessary
                    if (currNode is ILLabel ||
                        lastNode.IsConditionalControlFlow() ||
                        lastNode.IsUnconditionalControlFlow())
                    {
                        // Try to reuse the label
                        ILLabel label = currNode as ILLabel ?? ILLabel.Generate("Block_", nextLabelIndex++);

                        // Terminate the last block
                        if (!lastNode.IsUnconditionalControlFlow())
                        {
                            // Explicit branch from one block to other
                            basicBlock.Body.Add(new ILExpression(GMCode.B, label));
                        }

                        // Start the new block
                        basicBlock = new ILBasicBlock();
                        basicBlocks.Add(basicBlock);
                        basicBlock.Body.Add(label);

                        // Add the node to the basic block
                        if (currNode != label)
                        {
                            basicBlock.Body.Add(currNode);
                        }
                    }
                    else
                    {
                        basicBlock.Body.Add(currNode);
                    }
                }
            }

            block.Body = basicBlocks;

            if (reducebranches)
            {
                if (basicBlocks.Count > 0)
                {
                    for (int i = 0; i < block.Body.Count; i++)
                    {
                        ILBasicBlock bb = block.Body[i] as ILBasicBlock;
                        if (bb == null)
                        {
                            continue;
                        }
                        ILLabel trueLabel;
                        ILLabel falseLabel;
                        if (bb.MatchLastAndBr(GMCode.Bf, out falseLabel, out trueLabel))
                        {
                            ILExpression bf = bb.Body[bb.Body.Count - 2] as ILExpression;
                            ILExpression b  = bb.Body[bb.Body.Count - 1] as ILExpression;
                            bf.Code    = GMCode.Bt;
                            b.Operand  = falseLabel;
                            bf.Operand = trueLabel;
                        }
                    }
                }
            }
            return;
        }