1/*******************************************************************\
3Module: Field-Sensitive Program Dependence Analysis, Litvak et al.,
6Author: Michael Tautschnig
10\*******************************************************************/
27 // An abstract state at location `to` may be non-bottom even if
28 // `merge(..., `to`) has not been called so far. This is due to the special
29 // handling of function entry edges (see transform()).
32 // For computing the data dependencies, we would not need a fixpoint
33 // computation. The data dependencies at a location are computed from the
34 // result of the reaching definitions analysis at that location
35 // (in data_dependencies()). Thus, we only need to set the data dependencies
36 // part of an abstract state at a certain location once.
58 // Better Slicing of Programs with Jumps and Switches
59 // Kumar and Horwitz, FASE'02:
60 // "Node N is control dependent on node M iff N postdominates, in
61 // the CFG, one but not all of M's CFG successors."
63 // The "successor" above refers to an immediate successor of M.
65 // When computing the control dependencies of a node N (i.e., "to"
66 // being N), candidates for M are all control statements (gotos or
67 // assumes) from which there is a path in the CFG to N.
71 if(from->is_goto() || from->is_assume())
73 else if(from->is_end_function())
87 // Check all candidates
91 // check all CFG successors of M
92 // special case: assumptions also introduce a control dependency
96 // we could hard-code assume and goto handling here to improve
98 const cfg_post_dominatorst::cfgt::nodet &m =
102 for(
const auto &edge : m.out)
104 // Could use pd.dominates(to, control_dep_candidate) but this would impose
105 // another dominator node lookup per call to this function, which is too
107 const cfg_post_dominatorst::cfgt::nodet &
m_s=
110 if(
m_s.dominators.find(to)!=
m_s.dominators.end())
145 w_end.is_unknown() ||
161 // data dependencies using def-use pairs
164 // TODO use (future) reaching-definitions-dereferencing rw_set
166 dep_graph.reaching_definitions().get_value_sets();
187 // found a def-use pair
198 if(to->is_set_return_value())
231 // We do not propagate control dependencies on function calls, i.e., only the
232 // entry point of a function should have a control dependency on the call
241 // propagate control dependencies across function calls
244 // edge to function entry point
279 out <<
"Control dependencies: ";
280 for(depst::const_iterator
287 out << (*it)->location_number;
294 out <<
"Data dependencies: ";
295 for(depst::const_iterator
302 out << (*it)->location_number;
320 {
"locationNumber",
json_numbert(std::to_string(
cd->location_number))},
321 {
"sourceLocation",
json(
cd->source_location())},
329 {
"locationNumber",
json_numbert(std::to_string(
dd->location_number))},
330 {
"sourceLocation",
json(
dd->source_location())},
335 return std::move(graph);
355 auto p = std::make_unique<dep_graph_domaint>(node_id,
message_handler);
358 return std::unique_ptr<statet>(p.release());
372 rd(ns, message_handler)
386 // add_edge is redundant as the subsequent operations also insert
387 // entries into the edge maps (implicitly)
388 // add_edge(n_from, n_to);
This is the basic interface of the abstract interpreter with default implementations of the core func...
virtual void clear()
Reset the abstract state.
ai_history_baset::trace_ptrt trace_ptrt
goto_programt::const_targett locationt
ai_domain_factory_baset::locationt locationt
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
virtual statet & get_state(locationt l)
This ensures that all domains are constructed with the node ID that links them to the graph part of t...
std::unique_ptr< statet > make(locationt l) const override
dep_graph_domain_factoryt(dependence_grapht &_dg, message_handlert &message_handler)
message_handlert & message_handler
void control_dependencies(const irep_idt &function_id, goto_programt::const_targett from, goto_programt::const_targett to, dependence_grapht &dep_graph)
std::set< goto_programt::const_targett, goto_programt::target_less_than > depst
bool merge(const dep_graph_domaint &src, trace_ptrt from, trace_ptrt to)
bool is_bottom() const final override
void populate_dep_graph(dependence_grapht &, goto_programt::const_targett) const
jsont output_json(const ai_baset &ai, const namespacet &ns) const override
Outputs the current value of the domain.
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) final override
how function calls are treated: a) there is an edge from each call site to the function head b) there...
depst control_dep_candidates
void data_dependencies(goto_programt::const_targett from, const irep_idt &function_to, goto_programt::const_targett to, dependence_grapht &dep_graph, const namespacet &ns)
void output(std::ostream &out, const ai_baset &ai, const namespacet &ns) const final override
message_handlert & message_handler
void add_dep(dep_edget::kindt kind, goto_programt::const_targett from, goto_programt::const_targett to)
dependence_grapht(const namespacet &_ns, message_handlert &)
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
instructionst::const_iterator const_targett
nodet::node_indext node_indext
node_indext add_node(arguments &&... values)
jsont & push_back(const jsont &json)
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Data type to describe upper and lower bounds of the range of bits that a read or write access may aff...
std::map< locationt, rangest, goto_programt::target_less_than > ranges_at_loct
bool util_inplace_set_union(std::set< T, Compare, Alloc > &target, const std::set< T, Compare, Alloc > &source)
Compute union of two sets.
static bool may_be_def_use_pair(const range_spect &w_start, const range_spect &w_end, const range_spect &r_start, const range_spect &r_end)
Field-Sensitive Program Dependence Analysis, Litvak et al., FSE 2010.
static void goto_rw(const irep_idt &function, goto_programt::const_targett target, const exprt &lhs, const exprt &function_expr, const exprt::operandst &arguments, rw_range_sett &rw_set)
static void json(json_objectT &result, const irep_idt &property_id, const property_infot &property_info)
#define CHECK_RETURN(CONDITION)
#define PRECONDITION(CONDITION)