Skip to content

Commit f166bfb

Browse files
committed
Apply topological sort to SMV definitions
1 parent 5dbd3a2 commit f166bfb

File tree

1 file changed

+80
-7
lines changed

1 file changed

+80
-7
lines changed

src/smvlang/smv_typecheck.cpp

Lines changed: 80 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ Author: Daniel Kroening, [email protected]
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
17171734
Function: smv_typecheckt::convert_defines
@@ -1726,15 +1743,71 @@ Function: smv_typecheckt::convert_defines
17261743

17271744
void 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

Comments
 (0)