Beispiel #1
0
    public static (ControlFlowGraph, string) Decompile(ControlFlowGraph graph)
    {
        if (graph == null)
        {
            throw new ArgumentNullException(nameof(graph));
        }
        foreach (var index in graph.GetDfsPostOrder())
        {
            var children = graph.Children(index);
            if (children.Length != 1 || children[0] == index)
            {
                continue;
            }

            // If the node is the target of a back-edge then leave it alone: it's probably an empty loop-header node
            if (graph.GetBackEdges().Any(x => x.end == index))
            {
                continue;
            }

            int child = children[0];
            // Func<string> vis = () => graph.ToVis().AddPointer("index", index).AddPointer("child", child).ToString(); // For VS Code debug visualisation

            var childsParents = graph.Parents(child);
            var grandChildren = graph.Children(child);

            if (childsParents.Length != 1 || grandChildren.Length > 1)
            {
                continue; // Is a jump target from somewhere else as well - can't combine
            }
            if (grandChildren.Length == 1 && (grandChildren[0] == index || grandChildren[0] == child))
            {
                continue; // Loops around, not a sequence
            }
            var node      = graph.Nodes[index];
            var childNode = graph.Nodes[child];

            var updated = graph
                          .RemoveNode(child)
                          .ReplaceNode(index, Emit.Seq(node, childNode));

            foreach (var grandChild in grandChildren)
            {
                updated = updated.AddEdge(index, grandChild, graph.GetEdgeLabel(child, grandChild));
            }

            return(updated, $"Reduce sequence (node {index}, child {child})");
        }

        return(graph, null);
    }
Beispiel #2
0
    public static (ControlFlowGraph, string) Decompile(ControlFlowGraph graph /*, RecordFunc recordFunc = null*/)
    {
        if (graph == null)
        {
            throw new ArgumentNullException(nameof(graph));
        }
        var regions = graph.GetAllSeseRegions();

        // Do smallest regions first, as they may be nested in a larger one
        foreach (var(region, regionEntry, regionExit) in regions.OrderBy(x => x.nodes.Count))
        {
            if (regionEntry == graph.EntryIndex)
            {
                continue; // Don't try and reduce the 'sequence' of start node -> actual entry point nodes when there's only one entry
            }

            /* Func<string> vis = () => // For VS Code debug visualisation
             * {
             *   var d = graph.ToVis();
             *   foreach(var n in d.Nodes)
             *      if (region.Contains(int.Parse(n.Id, CultureInfo.InvariantCulture)))
             *          n.Color = "#4040b0";
             *   return d.ToString();
             * }; */
            bool containsOther = regions.Any(x => x.nodes != region && !x.nodes.Except(region).Any());
            if (containsOther)
            {
                continue;
            }

            // If either end is a loop header then leave it alone and let the loop rule handle it.
            if (graph.GetBackEdges().Any(x => x.end == regionEntry || x.end == regionExit))
            {
                continue;
            }

            var cut = graph.Cut(region, regionEntry, regionExit);

            if (cut.Cut.IsCyclic()) // Loop reduction comes later
            {
                continue;
            }

            return(cut.Merge(ReduceSese(cut.Cut)), Description);
        }

        return(graph, null);
    }
    public static (ControlFlowGraph, string) Decompile(ControlFlowGraph graph)
    {
        var(reachability, reachableCount) = graph.Reverse().GetReachability(graph.ExitIndex);
        if (reachableCount == graph.ActiveNodeCount)
        {
            return(graph, null);
        }

        var acyclic         = graph.RemoveBackEdges();
        var distances       = acyclic.GetLongestPaths(acyclic.EntryIndex);
        int longestDistance = 0;
        int winner          = -1;

        for (int i = 0; i < graph.NodeCount; i++)
        {
            if (graph.Nodes[i] == null || reachability[i]) // Only consider nodes that can't reach the exit
            {
                continue;
            }

            if (distances[i] <= longestDistance)
            {
                continue;
            }
            longestDistance = distances[i];
            winner          = i;
        }

        if (winner == -1)
        {
            return(graph, null);
        }

        foreach (var backEdge in graph.GetBackEdges().Where(x => x.start == winner))
        {
            return(graph.AddEdge(backEdge.end, graph.ExitIndex, CfgEdge.LoopSuccessor), Description);
        }

        return(graph.AddEdge(winner, graph.ExitIndex, CfgEdge.DisjointGraphFixup), Description);
    }
Beispiel #4
0
        internal static string GetGraphInformation(ControlFlowGraph cfg)
        {
            var str = new StringBuilder();

            str.AppendLine("Доминаторы:");
            var domTree = new DominatorTree().GetDominators(cfg);

            foreach (var pair in domTree)
            {
                foreach (var x in pair.Value)
                {
                    str.AppendLine($"{cfg.VertexOf(x)} dom {cfg.VertexOf(pair.Key)}");
                }
                str.AppendLine("----------------");
            }


            str.AppendLine("\r\nКлассификация ребер:");

            foreach (var pair in cfg.ClassifiedEdges)
            {
                str.AppendLine($"{ pair }");
            }

            str.AppendLine("\r\nОбходы графа:");

            str.AppendLine($"Прямой: { string.Join(" -> ", cfg.PreOrderNumeration) }");
            str.AppendLine($"Обратный: { string.Join(" -> ", cfg.PostOrderNumeration) }");

            str.AppendLine($"\r\nГлубинное остовное дерево:");
            foreach (var x in cfg.DepthFirstSpanningTree)
            {
                str.AppendLine($"({x.from} - > {x.to})");
            }

            var backEdges = cfg.GetBackEdges();

            if (backEdges.Count > 0)
            {
                str.AppendLine("\r\nОбратные ребра:");
                foreach (var x in backEdges)
                {
                    str.AppendLine($"({cfg.VertexOf(x.Item1)}, {cfg.VertexOf(x.Item2)})");
                }
            }
            else
            {
                str.AppendLine("\r\nОбратных ребер нет");
            }


            var answ = cfg.IsReducibleGraph() ? "Граф приводим" : "Граф неприводим";

            str.AppendLine($"\r\n{answ}");

            if (cfg.IsReducibleGraph())
            {
                var natLoops = NaturalLoop.GetAllNaturalLoops(cfg);
                if (natLoops.Count > 0)
                {
                    str.AppendLine($"\r\nЕстественные циклы:");
                    foreach (var x in natLoops)
                    {
                        if (x.Count == 0)
                        {
                            continue;
                        }
                        for (var i = 0; i < x.Count; i++)
                        {
                            str.AppendLine($"Номер блока: {i}");
                            foreach (var xfrom in x[i].GetInstructions())
                            {
                                str.AppendLine(xfrom.ToString());
                            }
                        }
                        str.AppendLine();
                        str.AppendLine("-------------");
                    }
                }
                else
                {
                    str.AppendLine($"\r\nЕстественных циклов нет");
                }
            }
            else
            {
                str.AppendLine($"\r\nНевозможно определить естественные циклы, т.к. граф неприводим");
            }

            return(str.ToString());
        }