Example #1
0
        void createNoBranch(BasicBlock deadCodeBasicBlock)
        {
            // Set the dead code block above some other block.
            var exitBranch = new NoBranchTarget();

            exitBranch.sourceBasicBlock   = deadCodeBasicBlock;
            deadCodeBasicBlock.exitBranch = exitBranch;

            BasicBlock targetBlock = null;

            do
            {
                targetBlock = randomTargetBlock();

                // Skip blocks that already have a "no branch" as entry.
                foreach (var entryBranch in targetBlock.entryBranches)
                {
                    if (entryBranch is NoBranchTarget)
                    {
                        targetBlock = null;
                        break;
                    }
                }
            } while(targetBlock == null);

            targetBlock.entryBranches.Add(exitBranch);
            exitBranch.takenTarget = targetBlock;
        }
        // insert the given new target basic block (given by start and end block) between the given no branch to manipulate
        public void insertBasicBlockBetweenBranch(NoBranchTarget branchToManipulate, BasicBlock newTargetStart, BasicBlock newTargetEnd, UnconditionalBranchTarget exitBranch)
        {
            // get the basic block from that the branch is taken and the basic block to that the branch is taken
            BasicBlock introBasicBlock = branchToManipulate.sourceBasicBlock;
            BasicBlock outroBasicBlock = branchToManipulate.takenTarget;

            this.insertBasicBlockBetweenBranch(introBasicBlock, outroBasicBlock, branchToManipulate, ref branchToManipulate.takenTarget, newTargetStart, newTargetEnd, exitBranch, ref exitBranch.takenTarget);
        }
        // insert the given new target basic block between the given no branch to manipulate
        public void insertBasicBlockBetweenBranch(NoBranchTarget branchToManipulate, BasicBlock newTarget, ConditionalBranchTarget exitBranch, bool useTakenBranch)
        {
            // get the basic block from that the branch is taken and the basic block to that the branch is taken
            BasicBlock introBasicBlock = branchToManipulate.sourceBasicBlock;
            BasicBlock outroBasicBlock = branchToManipulate.takenTarget;

            // check wether to use the taken or not taken part of the exit branch
            if (useTakenBranch)
            {
                this.insertBasicBlockBetweenBranch(introBasicBlock, outroBasicBlock, branchToManipulate, ref branchToManipulate.takenTarget, newTarget, newTarget, exitBranch, ref exitBranch.takenTarget);
            }
            else
            {
                this.insertBasicBlockBetweenBranch(introBasicBlock, outroBasicBlock, branchToManipulate, ref branchToManipulate.takenTarget, newTarget, newTarget, exitBranch, ref exitBranch.notTakenTarget);
            }
        }
        // insert the given new target basic block between the given conditional branch to manipulate
        public void insertBasicBlockBetweenBranch(NoBranchTarget branchToManipulate, BasicBlock newTarget, SwitchBranchTarget exitBranch, int switchTakenBranchIdx)
        {
            // get the basic block from that the branch is taken and the basic block to that the branch is taken
            BasicBlock introBasicBlock = branchToManipulate.sourceBasicBlock;
            BasicBlock outroBasicBlock = branchToManipulate.takenTarget;
            BasicBlock tempTakenTarget = null;

            this.insertBasicBlockBetweenBranch(introBasicBlock, outroBasicBlock, branchToManipulate, ref branchToManipulate.takenTarget, newTarget, newTarget, exitBranch, ref tempTakenTarget);

            // fill switch taken branch list with null when index is out of range
            while (exitBranch.takenTarget.Count() <= switchTakenBranchIdx)
            {
                exitBranch.takenTarget.Add(null);
            }

            exitBranch.takenTarget[switchTakenBranchIdx] = tempTakenTarget;
        }
        // this function splits a basic block on the given index
        public void splitBasicBlock(BasicBlock firstPartBB, int splitIndex)
        {
            // check if the index is out of bounds
            if (splitIndex >= firstPartBB.operations.Count())
            {
                throw new ArgumentException("Index is equal or greater than existing basic block operations.");
            }

            // check if there are at least 2 operations inside the basic block to split
            if (firstPartBB.operations.Count() < 2)
            {
                throw new ArgumentException("Too few operations in basic block for splitting.");
            }

            // create the new basic block that will become the second part of the basic block to split
            BasicBlock secondPartBB = new BasicBlock();

            // move the exit basic blocks to the new created basic block
            // and make the new created basic block the exit of the splitted one
            secondPartBB.exitBranch = firstPartBB.exitBranch;
            secondPartBB.exitBranch.sourceBasicBlock = secondPartBB;
            NoBranchTarget tempExitBranch = new NoBranchTarget();

            tempExitBranch.takenTarget      = secondPartBB;
            tempExitBranch.sourceBasicBlock = firstPartBB;
            firstPartBB.exitBranch          = tempExitBranch;

            // add splitted basic block branch
            // to the entries of the new basic block
            secondPartBB.entryBranches.Add(tempExitBranch);

            // distribute the instructions to the basic blocks
            List <IOperation> previousOperations = new List <IOperation>();
            List <IOperation> nextOperations     = new List <IOperation>();

            for (int operationIdx = 0; operationIdx < firstPartBB.operations.Count(); operationIdx++)
            {
                if (operationIdx < splitIndex)
                {
                    previousOperations.Add(firstPartBB.operations.ElementAt(operationIdx));
                }
                else
                {
                    nextOperations.Add(firstPartBB.operations.ElementAt(operationIdx));
                }
            }
            firstPartBB.operations  = previousOperations;
            secondPartBB.operations = nextOperations;


            // add a semantic id to the new basic block
            if (firstPartBB.semanticId == -1)
            {
                secondPartBB.semanticId = -1;
            }
            else
            {
                int highestSemanticId = 0;
                foreach (BasicBlock tempBB in methodCfg.basicBlocks)
                {
                    if (tempBB.semanticId > highestSemanticId)
                    {
                        highestSemanticId = tempBB.semanticId;
                    }
                }

                secondPartBB.semanticId = highestSemanticId + 1;
            }


            // add new basic block to the cfg
            methodCfg.basicBlocks.Add(secondPartBB);
        }
        // insert the given new target basic block (given by start and end block) between the given conditional branch to manipulate
        public void insertBasicBlockBetweenBranch(ConditionalBranchTarget branchToManipulate, bool manipulateTakenBranch, BasicBlock newTargetStart, BasicBlock newTargetEnd, NoBranchTarget exitBranch)
        {
            // get the basic block from that the branch is taken and the basic block to that the branch is taken
            BasicBlock introBasicBlock = branchToManipulate.sourceBasicBlock;
            BasicBlock outroBasicBlock = null;

            // manipulate the correct branch
            if (manipulateTakenBranch)
            {
                outroBasicBlock = branchToManipulate.takenTarget;
                this.insertBasicBlockBetweenBranch(introBasicBlock, outroBasicBlock, branchToManipulate, ref branchToManipulate.takenTarget, newTargetStart, newTargetEnd, exitBranch, ref exitBranch.takenTarget);
            }
            else
            {
                outroBasicBlock = branchToManipulate.notTakenTarget;
                this.insertBasicBlockBetweenBranch(introBasicBlock, outroBasicBlock, branchToManipulate, ref branchToManipulate.notTakenTarget, newTargetStart, newTargetEnd, exitBranch, ref exitBranch.takenTarget);
            }
        }
        // this function replaces a basic block inside the cfg (oldBasicBlock) with a construction of new basic blocks (newBasicBlockStart and newBasicBlockEnd)
        public void replaceBasicBlock(BasicBlock oldBasicBlock, BasicBlock newBasicBlockStart, BasicBlock newBasicBlockEnd)
        {
            // add new basic blocks to cfg
            this.addBasicBlockToCfgRecursively(newBasicBlockStart);


            // add entry branches that enter the old basic block to the new basic block
            newBasicBlockStart.entryBranches.AddRange(oldBasicBlock.entryBranches);

            // exchange the target of the entry branches from the old basic block to the new one
            foreach (IBranchTarget entryBranch in new List <IBranchTarget>(oldBasicBlock.entryBranches))
            {
                if ((entryBranch as NoBranchTarget) != null)
                {
                    NoBranchTarget tempEntryBranch = (entryBranch as NoBranchTarget);

                    // check sanity of entry branch
                    if (tempEntryBranch.takenTarget != oldBasicBlock)
                    {
                        throw new ArgumentException("Entry branch must have old basic block as target.");
                    }

                    // set new basic block as target
                    tempEntryBranch.takenTarget = newBasicBlockStart;
                }
                else if ((entryBranch as UnconditionalBranchTarget) != null)
                {
                    UnconditionalBranchTarget tempEntryBranch = (entryBranch as UnconditionalBranchTarget);

                    // check sanity of entry branch
                    if (tempEntryBranch.takenTarget != oldBasicBlock)
                    {
                        throw new ArgumentException("Entry branch must have old basic block as target.");
                    }

                    // set new basic block as target
                    tempEntryBranch.takenTarget = newBasicBlockStart;
                }
                else if ((entryBranch as ConditionalBranchTarget) != null)
                {
                    ConditionalBranchTarget tempEntryBranch = (entryBranch as ConditionalBranchTarget);
                    bool sanity = false;

                    // change all branches to the old basic block to the new basic block
                    if (tempEntryBranch.takenTarget == oldBasicBlock)
                    {
                        tempEntryBranch.takenTarget = newBasicBlockStart;
                        sanity = true;
                    }
                    if (tempEntryBranch.notTakenTarget == oldBasicBlock)
                    {
                        tempEntryBranch.notTakenTarget = newBasicBlockStart;
                        sanity = true;
                    }

                    // check sanity of entry branch
                    if (!sanity)
                    {
                        throw new ArgumentException("Entry branch must have old basic block as target.");
                    }
                }
                else if ((entryBranch as SwitchBranchTarget) != null)
                {
                    SwitchBranchTarget tempEntryBranch = (entryBranch as SwitchBranchTarget);
                    bool sanity = false;

                    // change all branches to the old basic block to the new basic block
                    if (tempEntryBranch.notTakenTarget == oldBasicBlock)
                    {
                        tempEntryBranch.notTakenTarget = newBasicBlockStart;
                        sanity = true;
                    }
                    for (int idx = 0; idx < tempEntryBranch.takenTarget.Count(); idx++)
                    {
                        if (tempEntryBranch.takenTarget.ElementAt(idx) == oldBasicBlock)
                        {
                            tempEntryBranch.takenTarget[idx] = newBasicBlockStart;
                            sanity = true;
                        }
                    }

                    // check sanity of entry branch
                    if (!sanity)
                    {
                        throw new ArgumentException("Entry branch must have old basic block as target.");
                    }
                }
                else
                {
                    throw new ArgumentException("Not yet implemented.");
                }

                // remove entry branch from the old basic block entry branches list
                oldBasicBlock.entryBranches.Remove(entryBranch);
            }


            IBranchTarget exitBranch = oldBasicBlock.exitBranch;

            // change the exit branch of the old basic block to be the exit branch of the new one
            exitBranch.sourceBasicBlock = newBasicBlockEnd;
            newBasicBlockEnd.exitBranch = exitBranch;


            // check if the old basic block was the start basic block of the cfg
            // => change it to the new basic block
            if (this.methodCfg.startBasicBlock == oldBasicBlock)
            {
                this.methodCfg.startBasicBlock = newBasicBlockStart;
            }

            // remove old basic block if it still belongs to the cfg
            if (this.methodCfg.basicBlocks.Contains(oldBasicBlock))
            {
                this.methodCfg.basicBlocks.Remove(oldBasicBlock);
            }
        }