Index: cfe/trunk/test/Analysis/exploded-graph-rewriter/explorers.dot =================================================================== --- cfe/trunk/test/Analysis/exploded-graph-rewriter/explorers.dot +++ cfe/trunk/test/Analysis/exploded-graph-rewriter/explorers.dot @@ -1,37 +0,0 @@ -// RUN: %exploded_graph_rewriter %s \ -// RUN: | FileCheck %s -check-prefixes=CHECK,BASIC -// RUN: %exploded_graph_rewriter -s %s \ -// RUN: | FileCheck %s -check-prefixes=CHECK,SINGLE - -// FIXME: Substitution doesn't seem to work on Windows. -// UNSUPPORTED: system-windows - -Node0x1 [shape=record,label= - "{{ "node_id": 1, "pointer": "0x1", "has_report": false, "is_sink": false, - "program_state": null, "program_points": []}\l}"]; - -Node0x2 [shape=record,label= - "{{ "node_id": 2, "pointer": "0x2", "has_report": false, "is_sink": false, - "program_state": null, "program_points": []}\l}"]; - -Node0x3 [shape=record,label= - "{{ "node_id": 3, "pointer": "0x3", "has_report": false, "is_sink": false, - "program_state": null, "program_points": []}\l}"]; - -Node0x4 [shape=record,label= - "{{ "node_id": 4, "pointer": "0x4", "has_report": false, "is_sink": false, - "program_state": null, "program_points": []}\l}"]; - -// CHECK: Node0x1 -> Node0x2; -Node0x1 -> Node0x2; - -// BASIC: Node0x1 -> Node0x3; -// SINGLE-NOT: Node0x1 -> Node0x3; -Node0x1 -> Node0x3; - -// CHECK: Node0x2 -> Node0x4; -Node0x2 -> Node0x4; - -// BASIC: Node0x3 -> Node0x4; -// SINGLE-NOT: Node0x3 -> Node0x4; -Node0x3 -> Node0x4; Index: cfe/trunk/test/Analysis/exploded-graph-rewriter/trimmers.dot =================================================================== --- cfe/trunk/test/Analysis/exploded-graph-rewriter/trimmers.dot +++ cfe/trunk/test/Analysis/exploded-graph-rewriter/trimmers.dot @@ -0,0 +1,37 @@ +// RUN: %exploded_graph_rewriter %s \ +// RUN: | FileCheck %s -check-prefixes=CHECK,BASIC +// RUN: %exploded_graph_rewriter -s %s \ +// RUN: | FileCheck %s -check-prefixes=CHECK,SINGLE + +// FIXME: Substitution doesn't seem to work on Windows. +// UNSUPPORTED: system-windows + +Node0x1 [shape=record,label= + "{{ "node_id": 1, "pointer": "0x1", "has_report": false, "is_sink": false, + "program_state": null, "program_points": []}\l}"]; + +Node0x2 [shape=record,label= + "{{ "node_id": 2, "pointer": "0x2", "has_report": false, "is_sink": false, + "program_state": null, "program_points": []}\l}"]; + +Node0x3 [shape=record,label= + "{{ "node_id": 3, "pointer": "0x3", "has_report": false, "is_sink": false, + "program_state": null, "program_points": []}\l}"]; + +Node0x4 [shape=record,label= + "{{ "node_id": 4, "pointer": "0x4", "has_report": false, "is_sink": false, + "program_state": null, "program_points": []}\l}"]; + +// CHECK: Node0x1 -> Node0x2; +Node0x1 -> Node0x2; + +// BASIC: Node0x1 -> Node0x3; +// SINGLE-NOT: Node0x1 -> Node0x3; +Node0x1 -> Node0x3; + +// CHECK: Node0x2 -> Node0x4; +Node0x2 -> Node0x4; + +// BASIC: Node0x3 -> Node0x4; +// SINGLE-NOT: Node0x3 -> Node0x4; +Node0x3 -> Node0x4; Index: cfe/trunk/utils/analyzer/exploded-graph-rewriter.py =================================================================== --- cfe/trunk/utils/analyzer/exploded-graph-rewriter.py +++ cfe/trunk/utils/analyzer/exploded-graph-rewriter.py @@ -882,37 +882,36 @@ visitor.visit_end_of_graph() -# SinglePathExplorer traverses only a single path - the leftmost path -# from the root. Useful when the trimmed graph is still too large -# due to a large amount of equivalent reports. -class SinglePathExplorer(object): - def __init__(self): - super(SinglePathExplorer, self).__init__() +#===-----------------------------------------------------------------------===# +# Trimmers cut out parts of the ExplodedGraph so that to focus on other parts. +# Trimmers can be combined together by applying them sequentially. +#===-----------------------------------------------------------------------===# - def explore(self, graph, visitor): - visitor.visit_begin_graph(graph) - # Keep track of visited nodes in order to avoid loops. - visited = set() +# SinglePathTrimmer keeps only a single path - the leftmost path from the root. +# Useful when the trimmed graph is still too large. +class SinglePathTrimmer(object): + def __init__(self): + super(SinglePathTrimmer, self).__init__() + + def trim(self, graph): + visited_nodes = set() node_id = graph.root_id while True: - visited.add(node_id) + visited_nodes.add(node_id) node = graph.nodes[node_id] - logging.debug('Visiting ' + node_id) - visitor.visit_node(node) - if len(node.successors) == 0: - break - - succ_id = node.successors[0] - succ = graph.nodes[succ_id] - logging.debug('Visiting edge: %s -> %s ' % (node_id, succ_id)) - visitor.visit_edge(node, succ) - if succ_id in visited: + if len(node.successors) > 0: + succ_id = node.successors[0] + succ = graph.nodes[succ_id] + node.successors = [succ_id] + succ.predecessors = [node_id] + if succ_id in visited_nodes: + break + node_id = succ_id + else: break - - node_id = succ_id - - visitor.visit_end_of_graph() + graph.nodes = {node_id: graph.nodes[node_id] + for node_id in visited_nodes} #===-----------------------------------------------------------------------===# @@ -960,10 +959,18 @@ raw_line = raw_line.strip() graph.add_raw_line(raw_line) - explorer = SinglePathExplorer() if args.single_path else BasicExplorer() + trimmers = [] + if args.single_path: + trimmers.append(SinglePathTrimmer()) + + explorer = BasicExplorer() + visitor = DotDumpVisitor(args.diff, args.dark, args.gray, args.topology, args.dump_dot_only) + for trimmer in trimmers: + trimmer.trim(graph) + explorer.explore(graph, visitor)