diff options
| author | Tim Blazytko <tim.blazytko@rub.de> | 2015-09-03 08:23:13 +0200 |
|---|---|---|
| committer | Tim Blazytko <tim.blazytko@rub.de> | 2015-09-04 16:17:51 +0200 |
| commit | fba7f7fc8c0b6d819305d43cd9c7718e03c33514 (patch) | |
| tree | 4552b58ad6ef63cf69f5618505c23b135ab24f98 | |
| parent | 54a6a2d915ea331a8505bd0dbcfdcacbf0991394 (diff) | |
| download | miasm-fba7f7fc8c0b6d819305d43cd9c7718e03c33514.tar.gz miasm-fba7f7fc8c0b6d819305d43cd9c7718e03c33514.zip | |
DiGraph: added natural loop detection
| -rw-r--r-- | miasm2/core/graph.py | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/miasm2/core/graph.py b/miasm2/core/graph.py index c14a2f68..c9b6234c 100644 --- a/miasm2/core/graph.py +++ b/miasm2/core/graph.py @@ -378,3 +378,55 @@ shape = "box" def walk_depth_first_backward(self, head): """Performs a depth first search on the reversed graph from @head""" return self._walk_generic_first(head, -1, self.predecessors_iter) + + def compute_natural_loops(self, head): + """ + Computes all natural loops in the graph. + + Source: Aho, Alfred V., Lam, Monica S., Sethi, R. and Jeffrey Ullman. + "Compilers: Principles, Techniques, & Tools, Second Edition" + Pearson/Addison Wesley (2007), Chapter 9.6.6 + :param head: head of the graph + :return: yield a tuple of the form (back edge, loop body) + """ + for a, b in self.compute_back_edges(head): + body = self._compute_natural_loop_body(b, a) + yield ((b, a), body) + + def compute_back_edges(self, head): + """ + Computes all back edges from a node to a + dominator in the graph. + :param head: head of graph + :return: yield a back edge + """ + dominators = self.compute_dominators(head) + + # traverse graph + for node in self.walk_depth_first_forward(head): + for successor in self.successors_iter(node): + # check for a back edge to a dominator + if successor in dominators[node]: + edge = (node, successor) + yield edge + + def _compute_natural_loop_body(self, head, leaf): + """ + Computes the body of a natural loop by a depth-first + search on the reversed control flow graph. + :param head: leaf of the loop + :param leaf: header of the loop + :return: set containing loop body + """ + todo = [leaf] + done = {head} + + while todo: + node = todo.pop() + if node in done: + continue + done.add(node) + + for predecessor in self.predecessors_iter(node): + todo.append(predecessor) + return done |