@@ -11,6 +11,7 @@ Author: Daniel Kroening, kroening@kroening.com
1111#include < util/arith_tools.h>
1212#include < util/bitvector_types.h>
1313#include < util/expr_util.h>
14+ #include < util/graph.h>
1415#include < util/mathematical_expr.h>
1516#include < util/namespace.h>
1617#include < util/std_expr.h>
@@ -1712,6 +1713,22 @@ void smv_typecheckt::convert_define(const irep_idt &identifier)
17121713 symbol.type =d.value .type ();
17131714}
17141715
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+
17151732/* ******************************************************************\
17161733
17171734Function: smv_typecheckt::convert_defines
@@ -1726,15 +1743,71 @@ Function: smv_typecheckt::convert_defines
17261743
17271744void smv_typecheckt::convert_defines (exprt::operandst &invar)
17281745{
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 ())
17301780 {
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 );
17321789
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+ }
17381811 }
17391812}
17401813
0 commit comments