1/*******************************************************************\
3Module: analyses variable-sensitivity data_dependency_context
7\*******************************************************************/
35 std::dynamic_pointer_cast<const data_dependency_contextt>(before);
39 // The other context is not something we understand, so must assume
40 // that the abstract_object has been modified
44 // Check whether the data dependencies have changed as well
46 std::set_intersection(
60 std::set_intersection(
85 // If this is the first write to the context then it is also used as
86 // the initial set of data dependency dominators as well.
90 // Workout what new data dependencies need to be inserted
106 // If there are no new dependencies to add, just return
111 std::dynamic_pointer_cast<data_dependency_contextt>(
mutable_clone());
115 result->data_deps.insert(l);
120 // If this was the first insertion of any dependencies, then these
121 // data dependencies are also data dominators as well
124 result->data_dominators.insert(l);
135 std::dynamic_pointer_cast<data_dependency_contextt>(
mutable_clone());
136 result->set_last_written_locations(
locations);
148 // `locationst` is unsorted, so convert this to a sorted `dependenciest`
162 std::set_intersection(
165 dependencies.cbegin(),
170 // If this is the first write to the context then it is also used as
171 // the initial set of data dependency dominators as well.
197 const std::stack<exprt> &stack,
203 std::dynamic_pointer_cast<data_dependency_contextt>(
mutable_clone());
205 std::dynamic_pointer_cast<const data_dependency_contextt>(value);
228 std::dynamic_pointer_cast<const data_dependency_contextt>(other);
233 std::dynamic_pointer_cast<const data_dependency_contextt>(
246 std::dynamic_pointer_cast<const data_dependency_contextt>(other);
251 std::dynamic_pointer_cast<const data_dependency_contextt>(
265 std::dynamic_pointer_cast<const data_dependency_contextt>(
266 parent->insert_data_deps(other->data_deps));
268 const auto &result = std::dynamic_pointer_cast<data_dependency_contextt>(
271 // On a merge, data_dominators are the intersection of this object and the
272 // other object. In other words, the dominators at this merge point are
273 // those dominators that exist in all possible execution paths to this
275 result->data_dominators.clear();
276 std::set_intersection(
279 other->data_dominators.begin(),
280 other->data_dominators.end(),
281 std::inserter(result->data_dominators, result->data_dominators.end()),
284 // It is critically important that we only return a newly constructed result
285 // abstract object *iff* the data has actually changed, otherwise AI may
286 // never reach a fixpoint
312 std::dynamic_pointer_cast<const data_dependency_contextt>(other);
317 std::dynamic_pointer_cast<const data_dependency_contextt>(
330std::set<goto_programt::const_targett, goto_programt::target_less_than>
333 std::set<goto_programt::const_targett, goto_programt::target_less_than>
345std::set<goto_programt::const_targett, goto_programt::target_less_than>
348 std::set<goto_programt::const_targett, goto_programt::target_less_than>
362 out <<
"[Data dependencies: ";
367 out << (
comma ?
", " :
"") << d->location_number;
372 out <<
"[Data dominators: ";
377 out << (
comma ?
", " :
"") << d->location_number;
sharing_ptrt< class abstract_objectt > abstract_object_pointert
static combine_result merge(const abstract_object_pointert &op1, const abstract_object_pointert &op2, const locationt &merge_location, const widen_modet &widen_mode)
static combine_result meet(const abstract_object_pointert &op1, const abstract_object_pointert &op2)
Interface method for the meet operation.
This is the basic interface of the abstract interpreter with default implementations of the core func...
virtual void clear()
Reset the abstract state.
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
std::shared_ptr< context_abstract_objectt > context_abstract_object_ptrt
std::set< locationt, goto_programt::target_less_than > locationst
abstract_object_pointert get_child() const
std::set< goto_programt::const_targett, goto_programt::target_less_than > get_data_dominators() const
Return the set of data dominators associated with this node.
abstract_object_pointert merge(const abstract_object_pointert &other, const widen_modet &widen_mode) const override
Create a new abstract object that is the result of merging this abstract object with a given abstract...
internal_abstract_object_pointert mutable_clone() const override
dependenciest data_dominators
bool has_been_modified(const abstract_object_pointert &before) const override
Determine whether 'this' abstract_object has been modified in comparison to a previous 'before' state...
void output(std::ostream &out, const class ai_baset &ai, const namespacet &ns) const override
Output a representation of the value of this abstract object.
abstract_object_pointert insert_data_deps(const dependenciest &dependencies) const
Insert the given set of data dependencies into the data dependencies set for this data_dependency_con...
std::set< goto_programt::const_targett, goto_programt::target_less_than > get_data_dependencies() const
Return the set of data dependencies associated with this node.
abstract_object_pointert abstract_object_merge_internal(const abstract_object_pointert &other) const override
Helper function for abstract_objectt::abstract_object_merge to perform any additional actions after t...
std::shared_ptr< const data_dependency_contextt > data_dependency_context_ptrt
abstract_object_pointert write(abstract_environmentt &environment, const namespacet &ns, const std::stack< exprt > &stack, const exprt &specifier, const abstract_object_pointert &value, bool merging_write) const override
A helper function to evaluate writing to a component of an abstract object.
context_abstract_object_ptrt update_location_context_internal(const locationst &locations) const override
abstract_object_pointert combine(const data_dependency_context_ptrt &other, const data_dependency_context_ptrt &parent) const
void set_data_deps(const locationst &locations)
Set the given set of data dependencies for from the locations.
abstract_object_pointert meet(const abstract_object_pointert &other) const override
Base implementation of the meet operation: only used if no more precise abstraction can be used,...
std::set< goto_programt::const_targett, location_ordert > dependenciest
Base class for all expressions.
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
abstract_object_pointert merge(const abstract_object_pointert &other, const widen_modet &widen_mode) const override
Create a new abstract object that is the result of merging this abstract object with a given abstract...
abstract_object_pointert abstract_object_merge_internal(const abstract_object_pointert &other) const override
Helper function for abstract_objectt::abstract_object_merge to perform any additional actions after t...
void output(std::ostream &out, const class ai_baset &ai, const namespacet &ns) const override
Output a representation of the value of this abstract object.
abstract_object_pointert meet(const abstract_object_pointert &other) const override
Base implementation of the meet operation: only used if no more precise abstraction can be used,...
bool has_been_modified(const abstract_object_pointert &before) const override
Determine whether 'this' abstract_object has been modified in comparison to a previous 'before' state...
Maintain data dependencies as a context in the variable sensitivity domain.
void intersection(const typename graph_nodet< E >::edgest &a, const typename graph_nodet< E >::edgest &b, typename graph_nodet< E >::edgest &dest)
Compute intersection of two edge sets, in linear time.