1/*******************************************************************\
3 Module: analyses variable-sensitivity variable-sensitivity-dependence-graph
7\*******************************************************************/
33 std::dynamic_pointer_cast<const data_dependency_contextt>(
eval(expr, ns));
35 if(
res->get_data_dependencies().size() > 0)
37 // If the expression was able to be eval'ed to something with data
38 // dependencies, then that's all we need to gather.
39 for(
const auto &
dep :
res->get_data_dependencies())
44 // If the expression could not be eval'ed to something with data
45 // dependencies, then it may have been some sort of compound expression,
46 // so attempt to eval the data dependencies for all the operands, taking
47 // the union of them all.
85 dep_graph !=
nullptr,
"Domains should all be of the same type");
87 // propagate control dependencies across function calls
88 if(from->is_function_call())
96 // edge to function entry point
102 DATA_INVARIANT(s !=
nullptr,
"Domains should all be of the same type");
110 // modify abstract state of return location
131 // Find all the data dependencies in the the 'to' expression
141 // Find all the data dependencies in the the 'to' expression
145 const exprt &rhs = to->assign_rhs();
147 // Handle return value of a 'no body' function
153 if(from->is_function_call())
155 const exprt &
call = from->call_function();
162 goto_functionst::function_mapt::const_iterator it =
167 if(!it->second.body_available())
// body not available
172 else // function not in map
177 else // complex call expression
186 // Just an ordinary assignement
190 else if(to->is_function_call())
193 for(
const auto &arg : args)
198 else if(to->is_goto())
211 // Better Slicing of Programs with Jumps and Switches
212 // Kumar and Horwitz, FASE'02:
213 // "Node N is control dependent on node M iff N postdominates, in
214 // the CFG, one but not all of M's CFG successors."
216 // The "successor" above refers to an immediate successor of M.
218 // Candidates for M for "to" are "from" and all existing control
219 // dependencies on nodes. "from" is added if it is a goto or assume
222 // Add new candidates
224 if(from->is_goto() || from->is_assume())
226 else if(from->is_end_function())
235 // Compute postdominators if needed
242 goto_functionst::function_mapt::const_iterator
f_it =
250 if(
pd_tmp.cfg.size() == 0)
// have we computed the dominators already?
257 // Check all candidates
261 // check all CFG successors of M
262 // special case: assumptions also introduce a control dependency
266 // we could hard-code assume and goto handling here to improve
268 const cfg_post_dominatorst::cfgt::nodet &m =
pd.get_node(
cd);
271 for(
const auto &edge : m.out)
273 const cfg_post_dominatorst::cfgt::nodet &
m_s =
pd.cfg[edge.first];
275 if(
m_s.dominators.find(to) !=
m_s.dominators.end())
289 if(
cd->is_goto() && !
cd->is_backwards_goto())
293 to->location_number >= t->location_number ?
tvt(
false) :
tvt(
true);
309 // add edges to the graph
320 bool changed =
false;
322 // Merge control dependencies
328 // find position to insert
337 // hint points at position that will follow the new element
344 it !=
control_deps.end(),
"Property of branch needed for safety");
347 "Property of loop needed for safety");
350 "Property of loop needed for safety");
365 // Merge control dependency candidates
374 // Merge call control dependencies
383 // Merge call control dependency candidates
409 bool changed =
false;
414 // Handle data dependencies
418 // Merge data dependencies
424 changed |= result.second;
430 cast_b.control_dep_candidates,
432 cast_b.control_dep_call_candidates);
448 // The gathering of the data dependencies for the domain is handled by the
449 // 'transform' and simply relies on the underlying domains with their
450 // data_dependency_context to be correct. Therefore all we need to ensure at
451 // the three way merge is that the underlying variable sensitivity domain
452 // does its three way merge.
471 out <<
"Control dependencies: ";
472 for(control_depst::const_iterator it =
control_deps.begin();
482 out <<
cd->location_number <<
" [" <<
branch <<
"]";
492 out << (*it)->location_number <<
" [UNCONDITIONAL]";
500 out <<
"Data dependencies: ";
507 out <<
dep.first->location_number;
510 for(
auto &expr :
dep.second)
547 link[
"locationNumber"] =
549 link[
"sourceLocation"] =
json(target->source_location());
557 link[
"locationNumber"] =
559 link[
"sourceLocation"] =
json(target->source_location());
567 link[
"locationNumber"] =
569 link[
"sourceLocation"] =
json(
dep.first->source_location());
573 const std::set<exprt> &expr_set =
dep.second;
576 for(
const exprt &e : expr_set)
584 return std::move(graph);
620 auto p = std::make_unique<variable_sensitivity_dependence_domaint>(
624 return std::unique_ptr<statet>(p.release());
647 goto_functions(goto_functions),
662 // add_edge is redundant as the subsequent operations also insert
663 // entries into the edge maps (implicitly)
665 // add_edge(n_from, n_to);
std::shared_ptr< variable_sensitivity_object_factoryt > variable_sensitivity_object_factory_ptrt
void branch(goto_modelt &goto_model, const irep_idt &id)
The common case of history is to only care about where you are now, not how you got there!...
This is the basic interface of the abstract interpreter with default implementations of the core func...
virtual void clear()
Reset the abstract state.
The interface offered by a domain, allows code to manipulate domains without knowing their exact type...
ai_history_baset::trace_ptrt trace_ptrt
goto_programt::const_targett locationt
ai_domain_factory_baset::locationt locationt
An easy factory implementation for histories that don't need parameters.
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
virtual statet & get_state(locationt l)
exprt::operandst argumentst
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Base class for all expressions.
A collection of goto functions.
function_mapt function_map
A generic container class for the GOTO intermediate representation of one function.
instructionst::const_iterator const_targett
instructiont::target_less_than target_less_than
nodet::node_indext node_indext
node_indext add_node(arguments &&... values)
const irep_idt & id() const
jsont & push_back(const jsont &json)
json_arrayt & make_array()
json_objectt & make_object()
The most conventional storage; one domain per location.
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
An expression containing a side effect.
This ensures that all domains are constructed with the node ID that links them to the graph part of t...
variable_sensitivity_object_factory_ptrt object_factory
const vsd_configt configuration
variable_sensitivity_dependence_grapht & dg
std::unique_ptr< statet > make(locationt l) const override
variable_sensitivity_dependence_domain_factoryt(variable_sensitivity_dependence_grapht &_dg, variable_sensitivity_object_factory_ptrt _object_factory, const vsd_configt &_configuration)
control_dep_candidatest control_dep_candidates
void control_dependencies(const irep_idt &from_function, goto_programt::const_targett from, const irep_idt &to_function, goto_programt::const_targett to, variable_sensitivity_dependence_grapht &dep_graph)
control_depst control_deps
void populate_dep_graph(variable_sensitivity_dependence_grapht &, goto_programt::const_targett) const
control_dep_callst control_dep_calls
std::map< goto_programt::const_targett, tvt, goto_programt::target_less_than > control_depst
std::map< goto_programt::const_targett, std::set< exprt >, dependency_ordert > data_depst
std::set< goto_programt::const_targett, goto_programt::target_less_than > control_dep_candidatest
std::set< goto_programt::const_targett, goto_programt::target_less_than > control_dep_callst
control_dep_callst control_dep_call_candidates
void transform(const irep_idt &function_from, trace_ptrt trace_from, const irep_idt &function_to, trace_ptrt trace_to, ai_baset &ai, const namespacet &ns) override
Compute the abstract transformer for a single instruction.
void eval_data_deps(const exprt &expr, const namespacet &ns, data_depst &deps) const
Evaluate an expression and accumulate all the data dependencies involved in the evaluation.
void merge_three_way_function_return(const ai_domain_baset &function_start, const ai_domain_baset &function_end, const namespacet &ns) override
Merges just the things that have changes between "function_start" and "function_end" into "this".
bool merge_control_dependencies(const control_depst &other_control_deps, const control_dep_candidatest &other_control_dep_candidates, const control_dep_callst &other_control_dep_calls, const control_dep_callst &other_control_dep_call_candidates)
bool merge(const variable_sensitivity_domaint &b, trace_ptrt from, trace_ptrt to) override
Computes the join between "this" and "b".
void output(std::ostream &out, const ai_baset &ai, const namespacet &ns) const override
Basic text output of the abstract domain.
void data_dependencies(goto_programt::const_targett from, goto_programt::const_targett to, variable_sensitivity_dependence_grapht &dep_graph, const namespacet &ns)
data_depst domain_data_deps
jsont output_json(const ai_baset &ai, const namespacet &ns) const override
Outputs the current value of the domain.
variable_sensitivity_dependence_grapht(const goto_functionst &goto_functions, const namespacet &_ns, variable_sensitivity_object_factory_ptrt object_factory, const vsd_configt &_configuration, message_handlert &message_handler)
void add_dep(vs_dep_edget::kindt kind, goto_programt::const_targett from, goto_programt::const_targett to)
void transform(const irep_idt &function_from, trace_ptrt trace_from, const irep_idt &function_to, trace_ptrt trace_to, ai_baset &ai, const namespacet &ns) override
Compute the abstract transformer for a single instruction.
virtual void merge_three_way_function_return(const ai_domain_baset &function_start, const ai_domain_baset &function_end, const namespacet &ns)
Merges just the things that have changes between "function_start" and "function_end" into "this".
virtual abstract_object_pointert eval(const exprt &expr, const namespacet &ns) const
virtual bool merge(const variable_sensitivity_domaint &b, trace_ptrt from, trace_ptrt to)
Computes the join between "this" and "b".
bool util_inplace_set_union(std::set< T, Compare, Alloc > &target, const std::set< T, Compare, Alloc > &source)
Compute union of two sets.
Maintain data dependencies as a context in the variable sensitivity domain.
exprt object_factory(const typet &type, const irep_idt base_name, code_blockt &init_code, symbol_table_baset &symbol_table, java_object_factory_parameterst parameters, lifetimet lifetime, const source_locationt &loc, const select_pointer_typet &pointer_type_selector, message_handlert &log)
Similar to gen_nondet_init below, but instead of allocating and non-deterministically initializing th...
std::string from_expr(const namespacet &ns, const irep_idt &identifier, const exprt &expr)
static void json(json_objectT &result, const irep_idt &property_id, const property_infot &property_info)
#define CHECK_RETURN(CONDITION)
#define DATA_INVARIANT(CONDITION, REASON)
This condition should be used to document that assumptions that are made on goto_functions,...
#define INVARIANT(CONDITION, REASON)
This macro uses the wrapper function 'invariant_violated_string'.
side_effect_exprt & to_side_effect_expr(exprt &expr)
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
A total order over targett and const_targett.
A forked and modified version of analyses/dependence_graph.