11
11
#include < util/arith_tools.h>
12
12
#include < util/bitvector_types.h>
13
13
#include < util/expr_util.h>
14
+ #include < util/graph.h>
14
15
#include < util/mathematical_expr.h>
15
16
#include < util/namespace.h>
16
17
#include < util/std_expr.h>
@@ -1712,6 +1713,22 @@ void smv_typecheckt::convert_define(const irep_idt &identifier)
1712
1713
symbol.type =d.value .type ();
1713
1714
}
1714
1715
1716
+ class symbol_collectort :public const_expr_visitort
1717
+ {
1718
+ public:
1719
+ virtual void operator ()(const exprt &expr)
1720
+ {
1721
+ if (expr.id ()==ID_symbol)
1722
+ {
1723
+ const symbol_exprt &symbol_expr=to_symbol_expr (expr);
1724
+ const irep_idt id=symbol_expr.get_identifier ();
1725
+ symbols.insert (id);
1726
+ }
1727
+ }
1728
+
1729
+ std::unordered_set<irep_idt, irep_id_hash> symbols;
1730
+ };
1731
+
1715
1732
/* ******************************************************************\
1716
1733
1717
1734
Function: smv_typecheckt::convert_defines
@@ -1726,15 +1743,71 @@ Function: smv_typecheckt::convert_defines
1726
1743
1727
1744
void smv_typecheckt::convert_defines (exprt::operandst &invar)
1728
1745
{
1729
- for (auto &define_it : define_map)
1746
+ // create graph of definition dependencies
1747
+ typedef size_t node_indext;
1748
+ std::map<irep_idt, node_indext> id_node_index;
1749
+ std::map<node_indext, irep_idt> index_node_id;
1750
+ grapht<graph_nodet<empty_edget>> definition_graph;
1751
+
1752
+ for (const auto &p : define_map) {
1753
+ // for each defined symbol, collect all symbols it depends on
1754
+ symbol_collectort visitor;
1755
+ p.second .value .visit (visitor);
1756
+ if (id_node_index.find (p.first )==id_node_index.end ())
1757
+ {
1758
+ id_node_index[p.first ]=definition_graph.add_node ();
1759
+ index_node_id[id_node_index[p.first ]]=p.first ;
1760
+ }
1761
+ node_indext t=id_node_index[p.first ];
1762
+
1763
+ // for each node t add (t, dep) for each definition dep it depends on
1764
+ for (const auto &id : visitor.symbols )
1765
+ {
1766
+ if (id_node_index.find (id)==id_node_index.end ())
1767
+ {
1768
+ id_node_index[id]=definition_graph.add_node ();
1769
+ index_node_id[id_node_index[id]]=id;
1770
+ }
1771
+ node_indext s=id_node_index[id];
1772
+ definition_graph.add_edge (s, t);
1773
+ }
1774
+ }
1775
+
1776
+ // sort the graph topologically to reduce call depth of `convert_define` and
1777
+ // `typecheck`
1778
+ std::list<node_indext> top_order=definition_graph.topsort ();
1779
+ if (top_order.empty ())
1730
1780
{
1731
- convert_define (define_it.first );
1781
+ // in case no topological order exists, fall back on starting with any
1782
+ // defined symbol
1783
+ warning () << " definiton graph is not a DAG" ;
1784
+ for (define_mapt::iterator it=define_map.begin ();
1785
+ it!=define_map.end ();
1786
+ it++)
1787
+ {
1788
+ convert_define (it->first );
1732
1789
1733
- // generate constraint
1734
- equal_exprt equality{
1735
- symbol_exprt{define_it.first , define_it.second .value .type ()},
1736
- define_it.second .value };
1737
- invar.push_back (equality);
1790
+ // generate constraint
1791
+ equal_exprt equality{symbol_exprt{it->first , it->second .value .type ()},
1792
+ it->second .value };
1793
+ invar.push_back (equality);
1794
+ }
1795
+ }
1796
+ else
1797
+ {
1798
+ for (const auto &idx : top_order)
1799
+ {
1800
+ const irep_idt &id=index_node_id[idx];
1801
+ // skip independent defines
1802
+ if (define_map.find (id)==define_map.end ())
1803
+ continue ;
1804
+ convert_define (id);
1805
+
1806
+ // generate constraint
1807
+ equal_exprt equality{symbol_exprt{id, define_map[id].value .type ()},
1808
+ define_map[id].value };
1809
+ invar.push_back (equality);
1810
+ }
1738
1811
}
1739
1812
}
1740
1813
0 commit comments