/// <summary> /// Removed error/continue edges which we know cannot happen due to type info /// </summary> /// <param name="graph"></param> /// <param name="types"></param> /// <returns></returns> public static IControlFlowGraph TypeDrivenEdgeTrimming(this IControlFlowGraph graph, ITypeAssignments types) { return(graph.Trim(edge => { // Find last statement in previous block var stmt = edge.Start.Statements.LastOrDefault(); var tass = stmt as TypedAssignment; var err = stmt as ErrorStatement; // If type is unassigned we can't make a judgement if (tass?.Type == Execution.Type.Unassigned) { return true; } if (edge.Type == EdgeType.RuntimeError) { // If it's an error statement keep it if (err != null) { return true; } // If there is no statement at all then it can't be an error if (tass == null) { return false; } // Only keep edge if type has an error return tass.Type.HasFlag(Execution.Type.Error); } else { // If it's an error statement remove it if (err != null) { return false; } // If there is no typed assignment we can't judge if (tass == null) { return true; } return tass.Type != Execution.Type.Error; } })); }
/// <summary> /// Remove blocks that cannot be reached from the entry node /// </summary> /// <param name="graph"></param> /// <returns></returns> public static IControlFlowGraph RemoveUnreachableBlocks(this IControlFlowGraph graph) { var reachable = new HashSet <IBasicBlock>(); var queue = new Queue <IBasicBlock>(); void Mark(IBasicBlock block) { if (reachable.Add(block)) { foreach (var edge in block.Outgoing) { queue.Enqueue(edge.End); } } } queue.Enqueue(graph.Vertices.Single(v => v.Type == BasicBlockType.Entry)); while (queue.Count > 0) { Mark(queue.Dequeue()); } return(graph.Trim(reachable.Contains)); }