void dep_graph_domaint::data_dependencies( goto_programt::const_targett from, goto_programt::const_targett to, dependence_grapht &dep_graph, const namespacet &ns) { // data dependencies using def-use pairs data_deps.clear(); // TODO use (future) reaching-definitions-dereferencing rw_set value_setst &value_sets= dep_graph.reaching_definitions().get_value_sets(); rw_range_set_value_sett rw_set(ns, value_sets); goto_rw(to, rw_set); forall_rw_range_set_r_objects(it, rw_set) { const range_domaint &r_ranges=rw_set.get_ranges(it); const rd_range_domaint::ranges_at_loct &w_ranges= dep_graph.reaching_definitions()[to].get(it->first); for(const auto &w_range : w_ranges) { bool found=false; for(const auto &wr : w_range.second) for(const auto &r_range : r_ranges) if(!found && may_be_def_use_pair(wr.first, wr.second, r_range.first, r_range.second)) { // found a def-use pair data_deps.insert(w_range.first); found=true; } } dep_graph.reaching_definitions()[to].clear_cache(it->first); } // add edges to the graph for(const auto &d_dep : data_deps) { // *it might be handled in a future call call to visit only, // depending on the sequence of successors; make sure it exists dep_graph.get_state(d_dep); dep_graph.add_dep(dep_edget::kindt::DATA, d_dep, to); } }
void rd_range_domaint::transform( locationt from, locationt to, ai_baset &ai, const namespacet &ns) { reaching_definitions_analysist *rd= dynamic_cast<reaching_definitions_analysist*>(&ai); assert(rd!=0); assert(bv_container); // kill values if(from->is_dead()) transform_dead(ns, from); // kill thread-local values else if(from->is_start_thread()) transform_start_thread(ns, *rd); // do argument-to-parameter assignments else if(from->is_function_call()) transform_function_call(ns, from, to, *rd); // cleanup parameters else if(from->is_end_function()) transform_end_function(ns, from, to, *rd); // lhs assignements else if(from->is_assign()) transform_assign(ns, from, from, *rd); // initial (non-deterministic) value else if(from->is_decl()) transform_assign(ns, from, from, *rd); #if 0 // handle return values if(to->is_function_call()) { const code_function_callt &code=to_code_function_call(to->code); if(code.lhs().is_not_nil()) { rw_range_set_value_sett rw_set(ns, rd->get_value_sets()); goto_rw(to, rw_set); const bool is_must_alias=rw_set.get_w_set().size()==1; forall_rw_range_set_w_objects(it, rw_set) { const irep_idt &identifier=it->first; // ignore symex::invalid_object const symbolt *symbol_ptr; if(ns.lookup(identifier, symbol_ptr)) continue; assert(symbol_ptr!=0); const range_domaint &ranges=rw_set.get_ranges(it); if(is_must_alias && (!rd->get_is_threaded()(from) || (!symbol_ptr->is_shared() && !rd->get_is_dirty()(identifier)))) for(const auto &range : ranges) kill(identifier, range.first, range.second); } } }