Skip to content

Sort definitions of SMV models to reduce recursion depth in typecheck #234

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/smvlang/parser.y
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

#include "smv_y.tab.h"

#define YYMAXDEPTH 200000
#define YYMAXDEPTH 2000000
#define YYSTYPE_IS_TRIVIAL 1

/*------------------------------------------------------------------------*/
Expand Down
91 changes: 84 additions & 7 deletions src/smvlang/smv_typecheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Author: Daniel Kroening, kroening@kroening.com
#include <util/arith_tools.h>
#include <util/bitvector_types.h>
#include <util/expr_util.h>
#include <util/graph.h>
#include <util/mathematical_expr.h>
#include <util/namespace.h>
#include <util/std_expr.h>
Expand Down Expand Up @@ -1712,6 +1713,22 @@ void smv_typecheckt::convert_define(const irep_idt &identifier)
symbol.type=d.value.type();
}

class symbol_collectort : public const_expr_visitort
{
public:
virtual void operator()(const exprt &expr)
{
if(expr.id() == ID_symbol)
{
const symbol_exprt &symbol_expr = to_symbol_expr(expr);
const irep_idt id = symbol_expr.get_identifier();
symbols.insert(id);
}
}

std::unordered_set<irep_idt, irep_id_hash> symbols;
};

/*******************************************************************\

Function: smv_typecheckt::convert_defines
Expand All @@ -1726,15 +1743,75 @@ Function: smv_typecheckt::convert_defines

void smv_typecheckt::convert_defines(exprt::operandst &invar)
{
for(auto &define_it : define_map)
// create graph of definition dependencies
typedef size_t node_indext;
std::map<irep_idt, node_indext> id_node_index;
std::map<node_indext, irep_idt> index_node_id;
grapht<graph_nodet<empty_edget>> definition_graph;

for(const auto &p : define_map)
{
// for each defined symbol, collect all symbols it depends on
symbol_collectort visitor;
p.second.value.visit(visitor);
if(id_node_index.find(p.first) == id_node_index.end())
{
id_node_index[p.first] = definition_graph.add_node();
index_node_id[id_node_index[p.first]] = p.first;
}
node_indext t = id_node_index[p.first];

// for each node t add (t, dep) for each definition dep it depends on
for(const auto &id : visitor.symbols)
{
if(id_node_index.find(id) == id_node_index.end())
{
id_node_index[id] = definition_graph.add_node();
index_node_id[id_node_index[id]] = id;
}
node_indext s = id_node_index[id];
definition_graph.add_edge(s, t);
}
}

// sort the graph topologically to reduce call depth of `convert_define` and
// `typecheck`
std::list<node_indext> top_order = definition_graph.topsort();
if(top_order.empty())
{
convert_define(define_it.first);
// in case no topological order exists, fall back on starting with any
// defined symbol

// warn if non-empty graph is not a DAG
if(!definition_graph.empty())
warning() << "definiton graph is not a DAG";

for(define_mapt::iterator it = define_map.begin(); it != define_map.end();
it++)
{
convert_define(it->first);

// generate constraint
equal_exprt equality{
symbol_exprt{define_it.first, define_it.second.value.type()},
define_it.second.value};
invar.push_back(equality);
// generate constraint
equal_exprt equality{
symbol_exprt{it->first, it->second.value.type()}, it->second.value};
invar.push_back(equality);
}
}
else
{
for(const auto &idx : top_order)
{
const irep_idt &id = index_node_id[idx];
// skip independent defines
if(define_map.find(id) == define_map.end())
continue;
convert_define(id);

// generate constraint
equal_exprt equality{
symbol_exprt{id, define_map[id].value.type()}, define_map[id].value};
invar.push_back(equality);
}
}
}

Expand Down
Loading