コード例 #1
0
        /// <summary>
        /// Replaces nodes with an error statement and an error edge with an empty node and a continue edge
        /// </summary>
        /// <param name="cfg"></param>
        /// <returns></returns>
        public static IControlFlowGraph NormalizeErrors(this IControlFlowGraph cfg)
        {
            var todo = new HashSet <IBasicBlock>();

            // Remove the error statements and save blocks to remove edges from
            cfg = cfg.Modify((a, b) => {
                if (!a.Statements.Any())
                {
                    return;
                }

                var toCopy = a.Statements;
                if ((a.Statements.Last() is ErrorStatement) && a.Outgoing.Count() == 1 && a.Outgoing.Single().Type == EdgeType.RuntimeError)
                {
                    toCopy = a.Statements.Take(a.Statements.Count() - 1);
                    todo.Add(b);
                }

                foreach (var stmt in toCopy)
                {
                    b.Add(stmt);
                }
            });

            // Copy graph, replacing edges as necessary
            return(cfg.Modify((e, c) => {
                c(e.Start, e.End, todo.Contains(e.Start) ? EdgeType.Continue : e.Type);
            }));
        }
コード例 #2
0
        /// <summary>
        /// Merge together basic blocks on the same line connected only by a continue edge
        /// </summary>
        /// <param name="cfg"></param>
        /// <returns></returns>
        public static IControlFlowGraph MergeAdjacentBasicBlocks(this IControlFlowGraph cfg)
        {
            // This keeps looping until it finds no work to do
            while (true)
            {
                // Find all candidates for merging
                var candidates = (from vertex in cfg.Vertices
                                  where vertex.Type == BasicBlockType.Basic
                                  where vertex.Outgoing.Count() == 1
                                  let outgoing = vertex.Outgoing.Single()
                                                 where outgoing.Type == EdgeType.Continue
                                                 where outgoing.End.LineNumber == vertex.LineNumber
                                                 where outgoing.End.Type == BasicBlockType.Basic
                                                 where outgoing.End.Incoming.Count() == 1
                                                 select(vertex, outgoing.End));

                // Select a single candidate pair (A -> B), if there is no work then exit now
                var work = candidates.FirstOrDefault();
                if (work == default)
                {
                    return(cfg);
                }

                // Move all the items from the A into B, leaving A empty
                cfg = cfg.Modify((a, b) => {
                    if (a.ID == work.End.ID)
                    {
                        work.vertex.CopyTo(b);
                        a.CopyTo(b);
                    }
                    else if (a.ID != work.vertex.ID)
                    {
                        a.CopyTo(b);
                    }
                });

                // Remove all empty blocks
                cfg = cfg.RemoveEmptyBlocks();
            }
        }