예제 #1
0
        public static IEnumerable <(VariableName, uint)> FindReadCounts(this IBasicBlock block)
        {
            var r = new FindReadVariables();

            r.Visit(block);

            return(r.Counts.Select(a => (a.Key, a.Value)));
        }
예제 #2
0
        private void AddTryStart(IRTransformer tr)
        {
            var tryStartInstrs = new List <IRInstruction>();

            for (var i = 0; i < thisScopes.Length; i++)
            {
                var scope = thisScopes[i];
                if (scope.Type != ScopeType.Try)
                {
                    continue;
                }
                if (scope.GetBasicBlocks().First() != tr.Block)
                {
                    continue;
                }

                // Search for handler/filter
                IBasicBlock handler = null, filter = null;
                SearchForHandlers(tr.RootScope, scope.ExceptionHandler, ref handler, ref filter);
                Debug.Assert(handler != null &&
                             (scope.ExceptionHandler.HandlerType != ExceptionHandlerType.Filter || filter != null));

                // Add instructions
                tryStartInstrs.Add(new IRInstruction(IROpCode.PUSH, new IRBlockTarget(handler)));

                IIROperand tryOperand = null;
                int        ehType;
                if (scope.ExceptionHandler.HandlerType == ExceptionHandlerType.Catch)
                {
                    tryOperand = IRConstant.FromI4((int)tr.VM.Data.GetId(scope.ExceptionHandler.CatchType));
                    ehType     = tr.VM.Runtime.RTFlags.EH_CATCH;
                }
                else if (scope.ExceptionHandler.HandlerType == ExceptionHandlerType.Filter)
                {
                    tryOperand = new IRBlockTarget(filter);
                    ehType     = tr.VM.Runtime.RTFlags.EH_FILTER;
                }
                else if (scope.ExceptionHandler.HandlerType == ExceptionHandlerType.Fault)
                {
                    ehType = tr.VM.Runtime.RTFlags.EH_FAULT;
                }
                else if (scope.ExceptionHandler.HandlerType == ExceptionHandlerType.Finally)
                {
                    ehType = tr.VM.Runtime.RTFlags.EH_FINALLY;
                }
                else
                {
                    throw new InvalidProgramException();
                }

                tryStartInstrs.Add(new IRInstruction(IROpCode.TRY, IRConstant.FromI4(ehType), tryOperand)
                {
                    Annotation = new EHInfo(scope.ExceptionHandler)
                });
            }
            tr.Instructions.InsertRange(0, tryStartInstrs);
        }
예제 #3
0
        public IEdge CreateEdge(IBasicBlock start, IBasicBlock end, EdgeType type)
        {
            var e = new Edge(start, end, type);

            _vertexLookup[start.ID].AddOutgoing(e);
            _vertexLookup[end.ID].AddIncoming(e);

            _edges.Add(e);

            return(e);
        }
예제 #4
0
 static void VisitSuccessorsCore(IBasicBlock basicBlock, HashSet <IBlock> isVisiteds)
 {
     VisitScope(basicBlock, isVisiteds);
     foreach (var successor in basicBlock.Successors.Keys)
     {
         if (!isVisiteds.Add(successor))
         {
             continue;
         }
         VisitSuccessorsCore(successor, isVisiteds);
     }
 }
예제 #5
0
파일: Builder.cs 프로젝트: Chronojam/Yolol
        [NotNull] public static IModel BuildSAT([NotNull] this IBasicBlock block, [NotNull] ITypeAssignments types)
        {
            var ctx    = new Context();
            var solver = ctx.MkSolver();
            var model  = new Model(ctx, solver);

            foreach (var stmt in block.Statements)
            {
                Assert(model, types, stmt);
            }

            return(model);
        }
예제 #6
0
 private void SearchForHandlers(ScopeBlock scope, ExceptionHandler eh, ref IBasicBlock handler, ref IBasicBlock filter)
 {
     if (scope.ExceptionHandler == eh)
     {
         if (scope.Type == ScopeType.Handler)
         {
             handler = scope.GetBasicBlocks().First();
         }
         else if (scope.Type == ScopeType.Filter)
         {
             filter = scope.GetBasicBlocks().First();
         }
     }
     foreach (var child in scope.Children)
     {
         SearchForHandlers(child, eh, ref handler, ref filter);
     }
 }
예제 #7
0
        [NotNull] private static Line ConvertLine([NotNull] IBasicBlock entry)
        {
            var statements = new List <BaseStatement>();

            var e = entry.Outgoing.Single();

            if (e.Type != EdgeType.Continue)
            {
                throw new InvalidOperationException("LineStart block has an invalid edge");
            }

            if (e.End.LineNumber == e.Start.LineNumber)
            {
                RecursiveConvertBlock(e.End, statements);
            }

            return(new Line(new StatementList(statements)));
        }
예제 #8
0
 private static bool SearchBlockInternal(ScopeBlock scope, IBasicBlock target, Stack <ScopeBlock> scopeStack)
 {
     if (scope.Content.Count > 0)
     {
         if (scope.Content.Contains(target))
         {
             scopeStack.Push(scope);
             return(true);
         }
         return(false);
     }
     scopeStack.Push(scope);
     foreach (var child in scope.Children)
     {
         if (SearchBlockInternal(child, target, scopeStack))
         {
             return(true);
         }
     }
     scopeStack.Pop();
     return(false);
 }
예제 #9
0
            public bool Equals(IBasicBlock other)
            {
                if (ReferenceEquals(null, other))
                {
                    return(false);
                }
                if (ReferenceEquals(this, other))
                {
                    return(true);
                }

                if (!ID.Equals(other.ID))
                {
                    return(false);
                }
                if (_statements.Count != other.Statements.Count())
                {
                    return(false);
                }

                return(_statements.Zip(other.Statements, (a, b) => a.Equals(b)).All(a => a));
            }
예제 #10
0
        private void VisitInstr(IRInstrList instrs, IRInstruction instr, ref int index, IRTransformer tr)
        {
            if (instr.OpCode != IROpCode.__LEAVE)
            {
                return;
            }

            var targetScopes = tr.RootScope.SearchBlock(((IRBlockTarget)instr.Operand1).Target);

            var escapeTarget = FindCommonAncestor(thisScopes, targetScopes);
            var leaveInstrs  = new List <IRInstruction>();

            for (var i = thisScopes.Length - 1; i >= 0; i--)
            {
                if (thisScopes[i] == escapeTarget)
                {
                    break;
                }
                if (thisScopes[i].Type != ScopeType.Try)
                {
                    continue;
                }

                IBasicBlock handler = null, filter = null;
                SearchForHandlers(tr.RootScope, thisScopes[i].ExceptionHandler, ref handler, ref filter);
                if (handler == null)
                {
                    throw new InvalidProgramException();
                }

                leaveInstrs.Add(new IRInstruction(IROpCode.LEAVE, new IRBlockTarget(handler))
                {
                    Annotation = new EHInfo(thisScopes[i].ExceptionHandler)
                });
            }
            instr.OpCode = IROpCode.JMP;
            leaveInstrs.Add(instr);
            instrs.Replace(index, leaveInstrs);
        }
        /// <summary>
        /// Find the first instrucion index that is not affected by the junk insertion in the new block.
        /// In other words: it Finds the first instruction in the new block which is identical to instruction
        /// in the original basic block. the identical instruction start an identical sequence of instructions
        /// untill the end of the two blocks.
        /// </summary>
        /// <param name="newBasicBlockBytes">new basic block bytes</param>
        /// <param name="basicBlock">original basic block</param>
        /// <param name="disassemblerFactory">diassembler factory</param>
        /// <returns>the first index of unaffected instruction in the original basic block, or not o value otherwise</returns>
        private uint?CompareDisassembleToOriginal(byte[] newBasicBlockBytes, IBasicBlock basicBlock,
                                                  IDisassemblerFactory disassemblerFactory)
        {
            //disassemble new bytes after junk have been inserted
            var           newAssemblyInstructions = new List <IAssemblyInstructionForTransformation>();
            IDisassembler disasm = disassemblerFactory.Create(newBasicBlockBytes);

            foreach (var instruction in disasm.Disassemble())
            {
                newAssemblyInstructions.Add(instruction);
            }

            //not enought instruction have been decoded right in this block!
            if (newAssemblyInstructions.Count <= 1)
            {
                return(null);
            }

            //compare to original basic block instructions
            //start from index 1 because first instruction is the inserted junk...
            for (int i = 1; i < newAssemblyInstructions.Count(); i++)
            {
                for (int j = 0; j < basicBlock.AssemblyInstructions.Count; j++)
                {
                    //compare instruction until the end if they are equal
                    if (newAssemblyInstructions[i].BytesEquals(basicBlock.AssemblyInstructions[j]))
                    {
                        if (instructionAreIdenticalUntilTheEnd(newAssemblyInstructions, i + 1, basicBlock.AssemblyInstructions, j + 1))
                        {
                            return((uint?)j);
                        }
                    }
                }
            }

            return(null);
        }
예제 #12
0
            static IReadOnlyDictionary <IBasicBlock, uint> Visit(IBasicBlock block, uint depth, Dictionary <IBasicBlock, uint> depths)
            {
                // If we've already been to this block by a shorter route early exit
                if (depths.TryGetValue(block, out var prevDepth))
                {
                    if (prevDepth < depth)
                    {
                        return(depths);
                    }
                }

                // Discovered this block
                depths[block] = depth;

                // Get edges we care about
                var outs = block.Outgoing.Where(e => (e.Type == EdgeType.Continue || e.Type == EdgeType.ConditionalTrue || e.Type == EdgeType.ConditionalFalse) && e.Start.LineNumber == e.End.LineNumber);

                foreach (var @out in outs)
                {
                    Visit(@out.End, depth + 1, depths);
                }

                return(depths);
            }
예제 #13
0
 public DataFlowGraph(IBasicBlock block, ISingleStaticAssignmentTable ssa)
     : this(ssa)
 {
     // Convert statements
     foreach (var stmt in block.Statements)
     {
         if (stmt is Assignment ass)
         {
             AddAssignment(ass.Left, Add(ass.Right));
         }
         else if (stmt is Conditional con)
         {
             AddConditional(Add(con.Condition));
         }
         else if (stmt is Goto @goto)
         {
             AddGoto(Add(@goto.Destination));
         }
         else
         {
             throw new NotSupportedException(stmt.GetType().Name);
         }
     }
 }
예제 #14
0
 [NotNull] public static IDataFlowGraph DataFlowGraph([NotNull] this IBasicBlock block, [NotNull] ISingleStaticAssignmentTable ssa)
 {
     return(new DataFlowGraph(block, ssa));
 }
예제 #15
0
 public ILBlockTarget(IBasicBlock target)
 {
     Target = target;
 }
        public ICode Transform(ICode code, TryTransformInstructionDelegate transformInstructionDelegate,
                               Func <ICodeInMemoryLayout> codeInLayoutFactoryDelegate = null)
        {
            var newInstructionsList        = new List <IAssemblyInstructionForTransformation>();
            var newFunctionsList           = new List <IFunction>();
            var instructionListIterator    = code.AssemblyInstructions.GetEnumerator();
            var lastInstructionInLastBlock = code.Functions.Last().BasicBlocks.Last().AssemblyInstructions.Last();
            IAssemblyInstructionForTransformation previousInstruction = null;
            bool afterInstructionOfLastBlock = false;

            //move to the first instruction
            instructionListIterator.MoveNext();

            //iterate through all functions
            foreach (var function in code.Functions)
            {
                var basicBlockList = new List <IBasicBlock>();
                //iterate through all basic block
                foreach (var basicBlock in function.BasicBlocks)
                {
                    var instructionsListOfBlock = new List <IAssemblyInstructionForTransformation>();
                    foreach (var instructionInBasicBlock in basicBlock.AssemblyInstructions)
                    {
                        bool isInstructionInBasicBlock;
                        bool done = false;

                        //transform instructions from instruction list.
                        //this loop transform:
                        //1. instructions before the basic block which are left to process
                        //2. instructions inside a basic block
                        //3. instructions after the last basic block
                        while (!done)
                        {
                            isInstructionInBasicBlock = instructionListIterator.Current == instructionInBasicBlock;
                            IAssemblyInstructionForTransformation instructionToTransform =
                                instructionListIterator.Current;

                            //perfom the transformation of the instruction
                            List <IAssemblyInstructionForTransformation> transformedInstructionList;
                            var wasTransformed = transformInstructionDelegate(instructionToTransform,
                                                                              isInstructionInBasicBlock ? basicBlock : null,
                                                                              isInstructionInBasicBlock ? function : null,
                                                                              out transformedInstructionList);

                            if (wasTransformed)
                            {
                                if (transformedInstructionList.Count == 0)
                                {
                                    throw new ApplicationException("transformation should return at least one instruction");
                                }

                                if (isInstructionInBasicBlock)
                                {
                                    instructionsListOfBlock.AddRange(transformedInstructionList);
                                }
                                newInstructionsList.AddRange(transformedInstructionList);

                                if (previousInstruction != null)
                                {
                                    transformedInstructionList[0].PreviousInstruction = previousInstruction;
                                    previousInstruction.NextInstruction = transformedInstructionList[0];
                                }

                                if (transformedInstructionList.Count > 1)
                                {
                                    for (int i = 1; i < transformedInstructionList.Count; i++)
                                    {
                                        transformedInstructionList[i].PreviousInstruction = transformedInstructionList[i - 1];
                                        transformedInstructionList[i - 1].NextInstruction = transformedInstructionList[i];
                                    }
                                }

                                previousInstruction = transformedInstructionList.Last();
                            }
                            else
                            {
                                if (isInstructionInBasicBlock)
                                {
                                    instructionsListOfBlock.Add(instructionToTransform);
                                }
                                newInstructionsList.Add(instructionToTransform);
                                if (previousInstruction != null)
                                {
                                    instructionToTransform.PreviousInstruction = previousInstruction;
                                    previousInstruction.NextInstruction        = instructionToTransform;
                                }
                                previousInstruction = instructionToTransform;
                            }

                            //check weather this is the last instruction in the last basic block
                            if (isInstructionInBasicBlock && !afterInstructionOfLastBlock)
                            {
                                //The transformed instruction is now in the end of program
                                //after the last basic block instruction
                                afterInstructionOfLastBlock = (instructionToTransform == lastInstructionInLastBlock);
                            }

                            instructionListIterator.MoveNext();

                            //stop transforming intructions in loop when all instruction in scope are processed
                            done = (isInstructionInBasicBlock ||
                                    instructionListIterator.Current == null);

                            //keep transforming after the last basic block instruction to the end of the program
                            if (afterInstructionOfLastBlock && instructionListIterator.Current != null)
                            {
                                done = false;
                            }
                        }
                    }

                    IBasicBlock newBasicBlock = m_basicBlockFactory.Create(instructionsListOfBlock);
                    basicBlockList.Add(newBasicBlock);
                }

                var newFunction = m_functionFactory.Create(basicBlockList.First().AssemblyInstructions.First(),
                                                           basicBlockList.Last().AssemblyInstructions.Last(),
                                                           basicBlockList);
                newFunctionsList.Add(newFunction);
            }


            //if there is a factory to create a new code in memory layout structure than use it, otherwise use
            //the original code layout in memrory instance
            ICodeInMemoryLayout codeInMemoryLayout = codeInLayoutFactoryDelegate == null ? code.CodeInMemoryLayout:codeInLayoutFactoryDelegate();

            //return m_codeFactory.Create(newInstructionsList, newFunctionsList,codeInMemoryLayout);
            var newcode = m_codeFactory.Create(newInstructionsList, newFunctionsList, codeInMemoryLayout);

            ValidateNewCode(newcode);
            return(newcode);
        }
예제 #17
0
 protected override void FormatBasicBlockCore(IBasicBlock basicBlock)
 {
     FormatBasicBlockImpl((BasicBlock)basicBlock);
 }
예제 #18
0
 static bool IsDirectBranch(IBasicBlock bb)
 {
     return(bb.FlowType == FlowControl.Branch && (bb.FlowAnnotation & (FlowControl.Leave | FlowControl.Indirect)) == 0);
 }
예제 #19
0
 public ILBlockTarget(IBasicBlock target) => this.Target = target;
예제 #20
0
파일: BbRefDict.cs 프로젝트: xuan2261/Zexil
 int IDictionary <IBasicBlock, int> .this[IBasicBlock key] {
     get => this[(TBasicBlock)key];
예제 #21
0
 private void AddFallthrough(IMutableControlFlowGraph cfg, IBasicBlock source, int currentLineNumber, EdgeType type = EdgeType.Continue)
 {
     cfg.CreateEdge(source, GetLineEntryBlock(cfg, currentLineNumber == _maxLines ? 1 : currentLineNumber + 1), type);
 }
        private bool TryGenerateJunkInstruction(IBasicBlock basicBlock,
                                                IJunkBytesProvider junkBytesProvider,
                                                IStatistics statistics,
                                                out IAssemblyInstructionForTransformation junkInstruction)
        {
            junkInstruction = null;
            bool retVal = false;

            //get junk bytes
            byte[] junkBytes = junkBytesProvider.GetJunkBytes();
            if (junkBytes == null)
            {
                throw new NullReferenceException(nameof(junkBytes));
            }

            //get basic block bytes
            byte[] basicBlockBytes = basicBlock.GetAllBytes();

            //the size of the junk we try to insert
            uint junkBytesSize = (uint)junkBytes.Count();

            //the inde of the most far insruction that has been syncronized
            uint mostFarSyncInstructionIdx = 0;
            //the partial instruction that causes the synchronization to be far as possible
            uint bestPartialInstructionSize = 0;

            //check what sub array of the inserted junk causes the most of confusion
            //so instruction are disassembled not correctly as far as possible
            while (junkBytesSize > 0)
            {
                uint   sizeOfNewBytesArray = basicBlock.NumberOfBytes + junkBytesSize;
                byte[] newBasicBlockBytes  = new byte[sizeOfNewBytesArray];

                //copy junk bytes and then basic block bytes
                Array.Copy(junkBytes, newBasicBlockBytes, junkBytesSize);
                basicBlockBytes.CopyTo(newBasicBlockBytes, junkBytesSize);

                //the index of first identical disassembled instruction to original
                uint?indexOfFirstIdenticalInstruction = CompareDisassembleToOriginal(newBasicBlockBytes, basicBlock,
                                                                                     m_disassemblerFactory);

                //in case that there is no even one instruction that synchronizes, so try another sequence
                //because the parsing error can not proceed to the next block
                if (!indexOfFirstIdenticalInstruction.HasValue)
                {
                    junkBytesSize--;
                    continue;
                }

                if (indexOfFirstIdenticalInstruction.Value > mostFarSyncInstructionIdx)
                {
                    mostFarSyncInstructionIdx  = indexOfFirstIdenticalInstruction.Value;
                    bestPartialInstructionSize = junkBytesSize;
                }

                junkBytesSize--;
            }

            //update basic block with the instruction that causes the synchronization to be as far as
            //possible
            if (mostFarSyncInstructionIdx > 0)
            {
                byte[] junkBytesSelected = new byte[bestPartialInstructionSize];
                for (int i = 0; i < bestPartialInstructionSize; i++)
                {
                    junkBytesSelected[i] = junkBytes[i];
                }

                var disasm = m_disassemblerFactory.Create(junkBytesSelected);
                junkInstruction       = disasm.Disassemble().First();
                junkInstruction.IsNew = true;

                statistics.IncrementMissinterpretedInstructions(mostFarSyncInstructionIdx);
                statistics.IncrementJunkInstructions(1, (uint)junkInstruction.Length);
                retVal = true;
            }

            return(retVal);
        }
예제 #23
0
 public Edge(IBasicBlock start, IBasicBlock end, EdgeType type)
 {
     Start = start;
     End   = end;
     Type  = type;
 }
예제 #24
0
 protected override string FormatBlockId(IBasicBlock basicBlock)
 {
     return($"BLK_{((BasicBlock)basicBlock).OriginalOffset:X4}");
 }
예제 #25
0
        public IReadOnlyList <IBasicBlock> Parse(IAssemblyInstructionForTransformation firstInstruction,
                                                 IAssemblyInstructionForTransformation lastInstruction, Dictionary <ulong, ulong> jumpTargetAddresses)
        {
            if (firstInstruction == null)
            {
                throw new ArgumentNullException(nameof(firstInstruction));
            }
            if (lastInstruction == null)
            {
                throw new ArgumentNullException(nameof(lastInstruction));
            }
            if (jumpTargetAddresses == null)
            {
                throw new ArgumentNullException(nameof(jumpTargetAddresses));
            }
            if (firstInstruction.Offset >= lastInstruction.Offset)
            {
                throw new ArgumentException("first argument address should be less then last argument address", "firstInstruction");
            }

            List <IBasicBlock> basicBlocks = new List <IBasicBlock>();
            var currrentInstruction        = firstInstruction;

            while (currrentInstruction.Offset <= lastInstruction.Offset)
            {
                //find the basic block epilog
                var basicBlockEpilog = BasicBlockEpilogParser.Parse(currrentInstruction,
                                                                    lastInstruction.Offset, jumpTargetAddresses);

                //no epilog was found, for example because the code examined is not a function or ends when the whole code section ends...
                if (basicBlockEpilog == null)
                {
                    break;
                }

                //initialize the assembly instructions of the current basic block being parsed.
                var assemblyInstructions = new List <IAssemblyInstructionForTransformation>()
                {
                    currrentInstruction
                };

                //Add all instruction in between the current and epilog instruction of the basic block
                if (currrentInstruction != basicBlockEpilog)
                {
                    currrentInstruction = currrentInstruction.NextInstruction;
                    while (currrentInstruction != null &&  //may not be possible to happen
                           currrentInstruction != basicBlockEpilog)
                    {
                        assemblyInstructions.Add(currrentInstruction);
                        currrentInstruction = currrentInstruction.NextInstruction;
                    }

                    //add epilog instruction
                    assemblyInstructions.Add(basicBlockEpilog);
                }

                IBasicBlock basicBlock = BasicBlockFactory.Create(assemblyInstructions);
                basicBlocks.Add(basicBlock);
                currrentInstruction = currrentInstruction.NextInstruction;
            }
            return(basicBlocks);
        }
예제 #26
0
 /// <summary />
 protected virtual string FormatSuccessors(IBasicBlock basicBlock)
 {
     return(string.Join(", ", basicBlock.Successors.Keys.Select(t => FormatBlockId(t))));
 }
예제 #27
0
        [CanBeNull] private static IBasicBlock FindCommonSubsequentBlock([NotNull] IBasicBlock a, [NotNull] IBasicBlock b)
        {
            IReadOnlyDictionary <IBasicBlock, uint> Visit(IBasicBlock block, uint depth, Dictionary <IBasicBlock, uint> depths)
            {
                // If we've already been to this block by a shorter route early exit
                if (depths.TryGetValue(block, out var prevDepth))
                {
                    if (prevDepth < depth)
                    {
                        return(depths);
                    }
                }

                // Discovered this block
                depths[block] = depth;

                // Get edges we care about
                var outs = block.Outgoing.Where(e => (e.Type == EdgeType.Continue || e.Type == EdgeType.ConditionalTrue || e.Type == EdgeType.ConditionalFalse) && e.Start.LineNumber == e.End.LineNumber);

                foreach (var @out in outs)
                {
                    Visit(@out.End, depth + 1, depths);
                }

                return(depths);
            }

            var ad = Visit(a, 0, new Dictionary <IBasicBlock, uint>());
            var bd = Visit(b, 0, new Dictionary <IBasicBlock, uint>());

            return(ad.Where(x => bd.ContainsKey(x.Key)).OrderBy(x => x.Value).FirstOrDefault().Key);
        }
예제 #28
0
        [NotNull] public static StatementList Visit([NotNull] this BaseTreeVisitor visitor, [NotNull] IBasicBlock block)
        {
            var result = visitor.Visit(new Program(new Line[] { new Line(new StatementList(block.Statements)) }));

            return(result.Lines.Single().Statements);
        }
예제 #29
0
        /// <summary>
        /// Convert a basic block, recursively convert linked blocks on the same line which are not the stop block
        /// </summary>
        /// <param name="block"></param>
        /// <param name="output"></param>
        /// <param name="stop"></param>
        private static void RecursiveConvertBlock([NotNull] IBasicBlock block, [NotNull] List <BaseStatement> output, [CanBeNull] IBasicBlock stop = null)
        {
            if (stop != null && stop.ID.Equals(block.ID))
            {
                return;
            }

            // Copy statements from this block into output
            output.AddRange(block.Statements);

            // if a block is empty there's nothing more to do
            if (!block.Statements.Any())
            {
                return;
            }

            // If we've jumped away there's nothing more to convert on this line
            if (block.Statements.Last() is Goto)
            {
                return;
            }

            // Serialize if statement
            if (block.Statements.Last() is Conditional con)
            {
                // Remove `Conditional` node, we'll replace with an `if`
                output.RemoveAt(output.Count - 1);

                // Find conditional edges leaving this block
                var trueEdge  = block.Outgoing.Single(a => a.Type == EdgeType.ConditionalTrue);
                var falseEdge = block.Outgoing.Single(a => a.Type == EdgeType.ConditionalFalse);

                // There are four possible cases:
                // - True/False branches both eventually pass on control flow to a common block (continueWith is common block)
                // - True jumps away, False is effectively the rest of the line (continueWith is false branch)
                // - False jumps away, True is effectively the rest of the line (continueWith is true branch)
                // - Both jump away, this is the end of the line (continueWith is null)

                // Try to find the first common block on this line
                var common = FindCommonSubsequentBlock(trueEdge.End, falseEdge.End);

                if (common != null)
                {
                    // Serialize both branches up to common block
                    var trueStmts = new List <BaseStatement>();
                    RecursiveConvertBlock(trueEdge.End, trueStmts, common);

                    var falseStmts = new List <BaseStatement>();
                    RecursiveConvertBlock(falseEdge.End, falseStmts, common);

                    output.Add(new If(con.Condition, new StatementList(trueStmts), new StatementList(falseStmts)));
                }
                else
                {
                    var trueStmts = new List <BaseStatement>();
                    RecursiveConvertBlock(trueEdge.End, trueStmts);

                    var falseStmts = new List <BaseStatement>();
                    RecursiveConvertBlock(falseEdge.End, falseStmts);

                    output.Add(new If(con.Condition, new StatementList(trueStmts), new StatementList(falseStmts)));
                    return;
                }

                // Continue on with rest of the line
                RecursiveConvertBlock(common, output, stop);
            }

            // Try to continue to the next block
            var e = block.Outgoing.SingleOrDefault(a => a.Type == EdgeType.Continue);

            if (e != null && e.Type == EdgeType.Continue && e.End.LineNumber == block.LineNumber && e.End != stop)
            {
                RecursiveConvertBlock(e.End, output, stop);
            }
        }
예제 #30
0
 private static IBasicBlock?FindCommonSubsequentBlock(IBasicBlock a, IBasicBlock b)
 {