def test_inconsistent_merge_vardef(self): G = cfg_model.cfg() entry = G.make_node(stmts.null_stmt()) a = G.make_node('let v := a(P)') b = G.make_node('branch v') c = G.make_node('let w := b(P)') d = G.make_node('branch w') e = G.make_node('let P := e(P)') f = G.make_node('let P := f(P)') e2 = G.make_node(stmts.let_stmt(('$p', ), stmts.parse_expr('0'))) f2 = G.make_node(stmts.let_stmt(('$p', ), stmts.parse_expr('1'))) exit = G.make_node(stmts.null_stmt()) G.make_edge(entry, a) G.make_edge(a, b) G.make_edge(b, c, index=0) G.make_edge(b, f, index=1) G.make_edge(c, d) G.make_edge(d, e, index=0) G.make_edge(d, f, index=1) G.make_edge(e, e2) G.make_edge(f, f2) G.make_edge(e2, exit) G.make_edge(f2, exit) #cfg_view.show(G) rvsdg = cfg2rvsdg.convert(G, ('P', ), ('P', '$p'), ('P', '$p'))
def test_visit(self): G = cfg_model.cfg() entry = G.make_node(stmts.null_stmt()) a = G.make_node(stmt='let p, P := a(P)') head = G.make_node(stmt='branch p') b = G.make_node('let P := b(P)') c = G.make_node('let p, P := c(P)') tail = G.make_node('branch p') d = G.make_node('let P := d(P)') exit = G.make_node(stmts.null_stmt()) G.make_edge(entry, a) G.make_edge(a, head) G.make_edge(head, b) G.make_edge(head, c, index=1) G.make_edge(b, tail) G.make_edge(c, tail) G.make_edge(tail, head) G.make_edge(tail, d, index=1) G.make_edge(d, exit) visited = set() cfg_algorithm.visit((entry, ), (exit, ), lambda x: visited.add(x)) self.assertEqual(visited, set((entry, a, head, b, c, tail, d))) visited = set() cfg_algorithm.visit((head, ), (tail, ), lambda x: visited.add(x)) self.assertEqual(visited, set((head, b, c)))
def test_nested_merge_branch(self): G = cfg_model.cfg() entry = G.make_node(stmts.null_stmt()) a = G.make_node('let x, y := a(P)') b = G.make_node('branch x') c = G.make_node('branch y') d = G.make_node('let P := d(P)') e = G.make_node('let P := e(P)') f = G.make_node('let P := f(P)') g = G.make_node('let P := g(P)') exit = G.make_node(stmts.null_stmt()) G.make_edge(entry, a) G.make_edge(a, b) G.make_edge(b, c, index=0) G.make_edge(b, d, index=1) G.make_edge(c, e, index=0) G.make_edge(c, f, index=1) G.make_edge(d, g) G.make_edge(e, g) G.make_edge(f, g) G.make_edge(g, exit) rvsdg = cfg2rvsdg.convert(G) rvsdg.normalize()
def test_inconsistent_merge_branch(self): G = cfg_model.cfg() entry = G.make_node(stmts.null_stmt()) a = G.make_node('let x, y := a(P)') b = G.make_node('branch x') c = G.make_node('branch y') d = G.make_node('let P := d(P)') e = G.make_node('let P := e(P)') f = G.make_node('let P := f(P)') g = G.make_node('let P := g(P)') h = G.make_node('let P := h(P)') exit = G.make_node(stmts.null_stmt()) G.make_edge(entry, a) G.make_edge(a, b) G.make_edge(b, c, index=0) G.make_edge(b, d, index=1) G.make_edge(c, e, index=0) G.make_edge(c, f, index=1) G.make_edge(d, g) G.make_edge(e, g) G.make_edge(f, h) G.make_edge(g, h) G.make_edge(h, exit) rvsdg = cfg2rvsdg.convert(G) rvsdg.normalize() ref0 = self._inconsistent_merge_branch_refgraph(0) ref1 = self._inconsistent_merge_branch_refgraph(1) #rvsdg_view.show(rvsdg) #rvsdg_view.show(ref1) self.assertTrue(rvsdg == ref0 or rvsdg == ref1)
def test_nico1(self): G = cfg_model.cfg() entry = G.make_node(stmts.null_stmt()) n0 = G.make_node('let v1, v2, v3, v4, v5, v6 := f(P)') n1 = G.make_node('branch v1') n2 = G.make_node('let v2 := 2') n3 = G.make_node('branch v3') n4 = G.make_node('let v4 := 4') n5 = G.make_node('let v5 := 5') n6 = G.make_node('let v6 := 6') n7 = G.make_node('let P := g(v1, v2, v3, v4, v5, v6, P)') exit = G.make_node(stmts.null_stmt()) G.make_edge(entry, n0) G.make_edge(n0, n1) G.make_edge(n1, n2, index=0) G.make_edge(n1, n3, index=1) G.make_edge(n2, n4) G.make_edge(n3, n4, index=0) G.make_edge(n3, n5, index=1) G.make_edge(n4, n6) G.make_edge(n5, n6) G.make_edge(n6, n7) G.make_edge(n7, exit) #cfg_view.show(G) rvsdg = cfg2rvsdg.convert(G) rvsdg.normalize()
def refG(): cfg = cfg_model.cfg() entry = cfg.make_node(stmts.null_stmt()) l = cfg.make_node('let v3 := sub(v1, v2)') exit = cfg.make_node(stmts.null_stmt()) cfg.make_edge(entry, l) cfg.make_edge(l, exit) return cfg
def __init__(self, rvsdg): self.rvsdg = rvsdg self.cfg = cfg_model.cfg() self.entry = self.cfg.make_node(stmts.null_stmt()) self.exit= self.cfg.make_node(stmts.null_stmt()) self.var_mapping = ssa_mapping() self.node_mapping = {} self.extra_edges = {}
def test_strongly_connected_selfloop(self): G = cfg_model.cfg() entry = G.make_node(stmts.null_stmt()) a = G.make_node('branch p') exit = G.make_node(stmts.null_stmt()) G.make_edge(entry, a) G.make_edge(a, a, index=1) G.make_edge(a, exit, index=0) clusters = cfg_algorithm.strongly_connected(G) self.assertEqual(clusters, [set((a, ))])
def test_pseudo_branch(self): G = cfg_model.cfg() entry = G.make_node(stmts.null_stmt()) a = G.make_node('let p := a(P)') b = G.make_node('branch p') c = G.make_node('let P := C(P)') exit = G.make_node(stmts.null_stmt()) G.make_edge(entry, a) G.make_edge(a, b) G.make_edge(b, c) G.make_edge(c, exit) rvsdg = cfg2rvsdg.convert(G)
def refG(): cfg = cfg_model.cfg() entry = cfg.make_node(stmts.null_stmt()) a = cfg.make_node('let v1, z := dec(v1)') b = cfg.make_node('let v2 := sqr(v2)') c = cfg.make_node('branch z') exit = cfg.make_node(stmts.null_stmt()) cfg.make_edge(entry, a) cfg.make_edge(a, b) cfg.make_edge(b, c) cfg.make_edge(c, a, index=1) cfg.make_edge(c, exit, index=0) return cfg
def test_empty_branch(self): G = cfg_model.cfg() entry = G.make_node(stmts.null_stmt()) a = G.make_node('let p := a(P)') b = G.make_node('branch p') c = G.make_node('let P := c(P)') exit = G.make_node(stmts.null_stmt()) G.make_edge(entry, a) G.make_edge(a, b) G.make_edge(b, c, index=0) G.make_edge(b, exit, index=1) G.make_edge(c, exit) rvsdg = cfg2rvsdg.convert(G) rvsdg.normalize()
def refG(): cfg = cfg_model.cfg() entry = cfg.make_node(stmts.null_stmt()) c = cfg.make_node('let r := cmp(v1, v2)') b = cfg.make_node('branch r') alt1 = cfg.make_node('let v3 := add(v1, v2)') alt2 = cfg.make_node('let v3 := sub(v1, v2)') exit = cfg.make_node(stmts.null_stmt()) cfg.make_edge(entry, c) cfg.make_edge(c, b) cfg.make_edge(b, alt1, index=0) cfg.make_edge(b, alt2, index=1) cfg.make_edge(alt1, exit) cfg.make_edge(alt2, exit) return cfg
def test_empty_branch_fail(self): G = cfg_model.cfg() entry = G.make_node(stmts.null_stmt()) a = G.make_node('let v := a(P)') b = G.make_node('branch v') c = G.make_node('let x := 0') d = G.make_node('let w := d(P)') exit = G.make_node(stmts.null_stmt()) G.make_edge(entry, a) G.make_edge(a, b) G.make_edge(b, d, index=0) G.make_edge(b, c, index=1) G.make_edge(c, d) G.make_edge(d, exit) # Test is considered to succeed if w is indeed defined at end # of region, no need to explicitly add expectations here. rvsdg = cfg2rvsdg.convert(G, ('P', ), ('P', 'w'), ('P', 'w'))
def test_linear(self): G = cfg_model.cfg() entry = G.make_node(stmts.null_stmt()) a = G.make_node('let P := a(P)') b = G.make_node('let x := 1') c = G.make_node('let y, z := 2, 3') d = G.make_node('let P := c(P, x, y, z)') exit = G.make_node(stmts.null_stmt()) G.make_edge(entry, a) G.make_edge(a, b) G.make_edge(b, c) G.make_edge(c, d) G.make_edge(d, exit) rvsdg = cfg2rvsdg.convert(G) rvsdg.normalize() ref = self._linear_refgraph() self.assertEquals(rvsdg, ref)
def test_strongly_connected1(self): G = cfg_model.cfg() entry = G.make_node(stmts.null_stmt()) a = G.make_node('branch a') b = G.make_node('let P := b(P)') c = G.make_node('branch c') d = G.make_node('let P := d(P)') exit = G.make_node(stmts.null_stmt()) G.make_edge(entry, a) G.make_edge(a, b) G.make_edge(a, c, index=1) G.make_edge(b, c) G.make_edge(c, b) G.make_edge(c, d, index=1) G.make_edge(d, exit) clusters = cfg_algorithm.strongly_connected(G) self.assertEqual(clusters, [set((b, c))])
def test_simple_branch(self): G = cfg_model.cfg() entry = G.make_node(stmts.null_stmt()) a = G.make_node('let p := a(P)') b = G.make_node('branch p') c = G.make_node('let P := c(P)') d = G.make_node('let P := d(P)') exit = G.make_node(stmts.null_stmt()) G.make_edge(entry, a) G.make_edge(a, b) G.make_edge(b, c, index=0) G.make_edge(b, d, index=1) G.make_edge(c, exit) G.make_edge(d, exit) rvsdg = cfg2rvsdg.convert(G) rvsdg.normalize() ref = self._simple_branch_refgraph() self.assertEquals(rvsdg, ref)
def refG(): cfg = cfg_model.cfg() entry = cfg.make_node(stmts.null_stmt()) a = cfg.make_node('let v2 := sqr(v2)') b = cfg.make_node('let c := cmp(v1, v2)') c = cfg.make_node('branch c') d = cfg.make_node('let r:= mov(v1)') e = cfg.make_node('let r:= mov(v2)') exit = cfg.make_node(stmts.null_stmt()) cfg.make_edge(entry, a) cfg.make_edge(a, b) cfg.make_edge(b, c) cfg.make_edge(c, d, index=0) cfg.make_edge(c, a, index=1) cfg.make_edge(c, e, index=2) cfg.make_edge(d, exit) cfg.make_edge(e, exit) return cfg
def refG(pred): invpred = 1 - pred G = cfg_model.cfg() entry = G.make_node(stmts.null_stmt()) a = G.make_node('let v := a(P)') b = G.make_node('branch v') c = G.make_node('let w := b(P)') d = G.make_node('branch w') e = G.make_node('let P := e(P)') f = G.make_node('let P := f(P)') e2 = G.make_node(stmts.let_stmt(('$r', ), stmts.parse_expr('0'))) f2 = G.make_node(stmts.let_stmt(('$r', ), stmts.parse_expr('1'))) exit = G.make_node(stmts.null_stmt()) letp_1 = G.make_node( stmts.let_stmt(('$p', ), stmts.parse_expr(str(pred)))) letp_2 = G.make_node( stmts.let_stmt(('$p', ), stmts.parse_expr(str(pred)))) letp_3 = G.make_node( stmts.let_stmt(('$p', ), stmts.parse_expr(str(invpred)))) null_23 = G.make_node(stmts.null_stmt()) branchp = G.make_node(stmts.branch_stmt(stmts.var_expr('$p'))) G.make_edge(entry, a) G.make_edge(a, b) G.make_edge(b, c, index=0) G.make_edge(b, letp_1, index=1) G.make_edge(letp_1, branchp) G.make_edge(c, d) G.make_edge(d, e, index=0) G.make_edge(e, letp_3) G.make_edge(d, letp_2, index=1) G.make_edge(letp_2, null_23) G.make_edge(letp_3, null_23) G.make_edge(null_23, branchp) G.make_edge(branchp, f, pred) G.make_edge(f, f2) G.make_edge(f2, exit) G.make_edge(branchp, e2, invpred) G.make_edge(e2, exit) return G
def test_simple_loop(self): G = cfg_model.cfg() entry = G.make_node(stmts.null_stmt()) a = G.make_node('let P := a(P)') b = G.make_node('let p, P := b(P)') c = G.make_node('branch p') d = G.make_node('let P := d(P)') exit = G.make_node(stmts.null_stmt()) G.make_edge(entry, a) G.make_edge(a, b) G.make_edge(b, c) G.make_edge(c, d, index=0) G.make_edge(c, b, index=1) G.make_edge(d, exit) #cfg_view.show(G) #cfg2rvsdg.convert_loops(G, cfg2rvsdg.predicate_generator()) #cfg_view.show(G) rvsdg = cfg2rvsdg.convert(G) rvsdg.normalize()
def _convert_to_cfg(dg): cfg = cfg_model.cfg() cfg_tgt_map = {} cfg_org_map = {} entry = cfg.make_node(stmts.null_stmt()) exit = cfg.make_node(stmts.null_stmt()) for vertex, label in dg.vertex_labels.items(): if label == 'ENTER': cfg_org_map[vertex] = entry continue elif label == 'EXIT': cfg_tgt_map[vertex] = exit continue succs = dg.vertex_outgoing.get(vertex, []) is_branch = len(succs) > 1 if is_branch: n1 = cfg.make_node('let P, p%s := f%s(P)' % (vertex, vertex)) n2 = cfg.make_node('branch p%s' % vertex) cfg.make_edge(n1, n2) cfg_tgt_map[vertex] = n1 cfg_org_map[vertex] = n2 else: n = cfg.make_node('let P := f%s(P)' % vertex) cfg_tgt_map[vertex] = n cfg_org_map[vertex] = n for origin, tgts in dg.vertex_outgoing.items(): for target, label in tgts: n1 = cfg_org_map[origin] n2 = cfg_tgt_map[target] if (n1, n2) in cfg.edges: dummy = cfg.make_node('let P := dummy(P)') cfg.make_edge(dummy, n2, 0) n2 = dummy cfg.make_edge(n1, n2, int(label)) return cfg
def test_strongly_connected2(self): G = cfg_model.cfg() entry = G.make_node(stmts.null_stmt()) a = G.make_node('let p, P := a(P)') head = G.make_node('branch p') b = G.make_node('let P := b(P)') c = G.make_node('let p, P := c(P)') tail = G.make_node('branch p') d = G.make_node('let P := d(P)') exit = G.make_node(stmts.null_stmt()) G.make_edge(entry, a) G.make_edge(a, head) G.make_edge(head, b) G.make_edge(head, c, index=1) G.make_edge(b, tail) G.make_edge(c, tail) G.make_edge(tail, head) G.make_edge(tail, d, index=1) G.make_edge(d, exit) clusters = cfg_algorithm.strongly_connected(G) self.assertEqual(clusters, [set((head, b, c, tail))])
def test_stmt_parse(self): s = stmts.parse_stmt('null') self.assertEquals(stmts.null_stmt(), s) s = stmts.parse_stmt('let a := 1') self.assertEquals(stmts.let_stmt(('a', ), stmts.parse_expr('1')), s) s = stmts.parse_stmt('let a, b := f(x), 1') self.assertEquals( stmts.let_stmt(('a', 'b'), stmts.parse_expr('f(x), 1')), s) s = stmts.parse_stmt('branch 1') self.assertEquals(stmts.branch_stmt(stmts.parse_expr('1')), s)
def test_multi_exit_loop(self): G = cfg_model.cfg() entry = G.make_node(stmts.null_stmt()) a = G.make_node('let P := a(P)') b = G.make_node('let p, P := b(P)') b_ = G.make_node('branch p') c = G.make_node('let p, P := c(P)') c_ = G.make_node('branch p') d = G.make_node('let P := d(P)') exit = G.make_node(stmts.null_stmt()) G.make_edge(entry, a) G.make_edge(a, b) G.make_edge(b, b_) G.make_edge(b_, c, index=0) G.make_edge(b_, d, index=1) G.make_edge(c, c_) G.make_edge(c_, b, index=0) G.make_edge(c_, d, index=1) G.make_edge(d, exit) rvsdg = cfg2rvsdg.convert(G) rvsdg.normalize()
def refG(): cfg = cfg_model.cfg() entry = cfg.make_node(stmts.null_stmt()) a = cfg.make_node('let c := gt(v1, v2)') b = cfg.make_node('branch c') c1 = cfg.make_node('let v1 := sub(v1, v2)') c2 = cfg.make_node('let v2 := sub(v2, v1)') d = cfg.make_node('let c := cmp(v1, v2)') e = cfg.make_node('branch c') exit = cfg.make_node(stmts.null_stmt()) cfg.make_edge(entry, a) cfg.make_edge(a, b) cfg.make_edge(b, c1, index=0) cfg.make_edge(b, c2, index=1) cfg.make_edge(c1, d) cfg.make_edge(c2, d) cfg.make_edge(d, e) cfg.make_edge(e, c1, index=0) cfg.make_edge(e, c2, index=2) cfg.make_edge(e, exit, index=1) return cfg
def test_edge_dominators(self): G = cfg_model.cfg() entry = G.make_node('let p := A(p)') branch = G.make_node('branch p') a = G.make_node(stmts.null_stmt()) b = G.make_node('branch p') c = G.make_node(stmts.null_stmt()) exit = G.make_node(stmts.null_stmt()) e1 = G.make_edge(entry, branch) e2 = G.make_edge(branch, a, 0) e3 = G.make_edge(branch, b, 1) e4 = G.make_edge(branch, exit, 2) e5 = G.make_edge(b, c, 0) e6 = G.make_edge(b, exit, 1) e7 = G.make_edge(c, exit) e8 = G.make_edge(a, exit) N, E = cfg_algorithm.edge_dominators(G, e2) self.assertEqual(set((a, )), N) self.assertEqual(set((e2, e8)), E) I, O = cfg_algorithm.border_edges(N, E) self.assertEqual([e2], I) self.assertEqual([e8], O) N, E = cfg_algorithm.edge_dominators(G, e3) self.assertEqual(set((b, c)), N) self.assertEqual(set((e3, e5, e6, e7)), E) I, O = cfg_algorithm.border_edges(N, E) self.assertEqual([e3], I) self.assertEqual(set((e6, e7)), set(O)) N, E = cfg_algorithm.edge_dominators(G, e4) self.assertEqual(set(), N) self.assertEqual(set((e4, )), E) I, O = cfg_algorithm.border_edges(N, E) self.assertEqual([e4], I) self.assertEqual([e4], O)
def refG(pred): invpred = 1 - pred G = cfg_model.cfg() a = G.make_node('branch p') b = G.make_node('branch p') c = G.make_node('let c := 0') letp_c = G.make_node( stmts.let_stmt(('$p', ), stmts.parse_expr(str(pred)))) letp_d = G.make_node( stmts.let_stmt(('$p', ), stmts.parse_expr(str(pred)))) letp_e = G.make_node( stmts.let_stmt(('$p', ), stmts.parse_expr(str(invpred)))) n = G.make_node(stmts.null_stmt()) d = G.make_node('let d := 0') e = G.make_node('let e := 0') rebranch = G.make_node(stmts.branch_stmt(stmts.var_expr('$p'))) f = G.make_node('let f := 0') empty = G.make_node(stmts.null_stmt()) g = G.make_node('let g := 0') G.make_edge(a, b, 0) G.make_edge(a, c, 1) G.make_edge(b, d, 0) G.make_edge(b, e, 1) G.make_edge(c, letp_c) G.make_edge(d, letp_d) G.make_edge(e, letp_e) G.make_edge(letp_d, n) G.make_edge(letp_e, n) G.make_edge(letp_c, rebranch) G.make_edge(n, rebranch) G.make_edge(rebranch, f, pred) G.make_edge(rebranch, empty, invpred) G.make_edge(f, g) G.make_edge(empty, g) return G
def _pseudo_loop_ref_graph(self, pred, dummy_predicate=False): invpred = 1 - pred G = cfg_model.cfg() entry = G.make_node('let v := a(P)') a = G.make_node('branch v') b = G.make_node('let P := b(P)') if dummy_predicate: bp = G.make_node( stmts.let_stmt(('$p', '$x'), stmts.parse_expr('%d,-1' % invpred))) else: bp = G.make_node( stmts.let_stmt(('$p', ), stmts.parse_expr('%d' % invpred))) c = G.make_node( stmts.let_stmt(( '$p', '$x', ), stmts.parse_expr('%d, 0' % pred))) d = G.make_node( stmts.let_stmt(( '$p', '$x', ), stmts.parse_expr('%d, 1' % pred))) rebranch = G.make_node(stmts.branch_stmt(stmts.var_expr('$p'))) e = G.make_node( stmts.let_stmt(('P', ), stmts.call_expr('e', (stmts.var_expr('$x'), )))) f = G.make_node(stmts.let_stmt(('$p', ), stmts.parse_expr('0'))) g = G.make_node(stmts.let_stmt(('$p', ), stmts.parse_expr('1'))) exit = G.make_node(stmts.null_stmt()) G.make_edge(entry, a) G.make_edge(a, b, 0) G.make_edge(a, c, 1) G.make_edge(a, d, 2) G.make_edge(b, bp) G.make_edge(bp, rebranch) G.make_edge(c, rebranch) G.make_edge(d, rebranch) G.make_edge(rebranch, e, pred) G.make_edge(rebranch, f, invpred) G.make_edge(e, g) G.make_edge(f, exit) G.make_edge(g, exit) return G
def refG(): G = cfg_model.cfg() n = G.make_node('branch p') n1 = G.make_node('branch p') n2 = G.make_node('let c := 0') n11 = G.make_node('let d := 0') n12 = G.make_node('let e := 0') n1c = G.make_node(stmts.null_stmt()) nc = G.make_node('let g := 0') G.make_edge(n, n1, 0) G.make_edge(n, n2, 1) G.make_edge(n1, n11, 0) G.make_edge(n1, n12, 1) G.make_edge(n11, n1c) G.make_edge(n12, n1c) G.make_edge(n1c, nc) G.make_edge(n2, nc) return G
def _make_pseudo_loop_graph(self): G = cfg_model.cfg() entry = G.make_node('let v := a(P)') a = G.make_node('branch v') b = G.make_node('let P := b(P)') c = G.make_node(stmts.let_stmt(('$x', ), stmts.parse_expr('0'))) d = G.make_node(stmts.let_stmt(('$x', ), stmts.parse_expr('1'))) e = G.make_node( stmts.let_stmt(('P', ), stmts.call_expr('e', (stmts.var_expr('$x'), )))) f = G.make_node(stmts.let_stmt(('$p', ), stmts.parse_expr('0'))) g = G.make_node(stmts.let_stmt(('$p', ), stmts.parse_expr('1'))) exit = G.make_node(stmts.null_stmt()) G.make_edge(entry, a) G.make_edge(a, b, 0) G.make_edge(a, c, 1) G.make_edge(a, d, 2) G.make_edge(b, f) G.make_edge(c, e) G.make_edge(d, e) G.make_edge(e, g) G.make_edge(f, exit) G.make_edge(g, exit) return G
import cfg_model import figure import stmts #import cfg_layout G = cfg_model.cfg() entry = G.make_node(stmts.null_stmt()) exit = G.make_node(stmts.null_stmt()) n_if = G.make_node('branch p1') G.make_edge(entry, n_if) n_then = G.make_node('branch p2') G.make_edge(n_if, n_then, index=0) n_else = G.make_node('let a := 1') G.make_edge(n_if, n_else, index=1) n_thenthen = G.make_node('let a := 2') G.make_edge(n_then, n_thenthen, index=0) n_thenelse = G.make_node('let a := 3') G.make_edge(n_then, n_thenelse, index=1) n_close1 = G.make_node('let b := a') G.make_edge(n_else, n_close1) G.make_edge(n_thenelse, n_close1) n_close2 = G.make_node('let b := a') G.make_edge(n_close1, n_close2) G.make_edge(n_thenthen, n_close2) G.make_edge(n_close2, exit) cv = figure.base.canvas() l = figure.digraph.cfg_to_graph_layout(G) cv.add(l) l.layout(0, 0)