void local_SSAt::build_transfer(locationt loc) { if(loc->is_assign()) { const code_assignt &code_assign=to_code_assign(loc->code); exprt deref_lhs=dereference(code_assign.lhs(), loc); exprt deref_rhs=dereference(code_assign.rhs(), loc); assign_rec(deref_lhs, deref_rhs, true_exprt(), loc); } else if(loc->is_function_call()) { const code_function_callt &code_function_call= to_code_function_call(loc->code); const exprt &lhs=code_function_call.lhs(); if(lhs.is_not_nil()) { exprt deref_lhs=dereference(lhs, loc); // generate a symbol for rhs irep_idt identifier="ssa::return_value"+i2string(loc->location_number); symbol_exprt rhs(identifier, code_function_call.lhs().type()); assign_rec(deref_lhs, rhs, true_exprt(), loc); } } }
expr2tc abstract_domain_baset::get_return_lhs(locationt to) const { // get predecessor of "to" to--; if(to->is_end_function()) return expr2tc(); // must be the function call assert(to->is_function_call()); const code_function_call2t &code = to_code_function_call2t(to->code); return code.ret; }
exprt static_analysis_baset::get_return_lhs(locationt to) { // get predecessor of "to" to--; if(to->is_end_function()) return static_cast<const exprt &>(get_nil_irep()); // must be the function call assert(to->is_function_call()); const code_function_callt &code= to_code_function_call(to->code); return code.lhs(); }
exprt flow_insensitive_abstract_domain_baset::get_return_lhs(locationt to) const { // get predecessor of "to" to--; if(to->is_end_function()) return static_cast<const exprt &>(get_nil_irep()); // must be the function call assert(to->is_function_call()); const code_function_callt &code= to_code_function_call(to_code(to->code)); return code.lhs(); }
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); } } }
void ssa_domaint::transform( locationt from, locationt to, ai_baset &ai, const namespacet &ns) { if(from->is_assign() || from->is_decl() || from->is_function_call()) { const auto &assignments=static_cast<ssa_ait &>(ai).assignments; const std::set<ssa_objectt> &assigns=assignments.get(from); for(std::set<ssa_objectt>::const_iterator o_it=assigns.begin(); o_it!=assigns.end(); o_it++) { if(o_it->get_expr().get_bool("#is_rhs_assign") && is_pointed(o_it->get_root_object())) { // the second part excluded cases // when a result of malloc is at the right-handed side const auto object_ai_it= static_cast<ssa_ait &>(ai)[from].def_map.find(o_it->get_identifier()); if(object_ai_it!=static_cast<ssa_ait &>(ai)[from].def_map.end() && object_ai_it->second.def.is_assignment()) { const exprt pointer= get_pointer( o_it->get_root_object(), pointed_level(o_it->get_root_object())-1); const auto def_pointer= static_cast<ssa_ait &>(ai)[from] .def_map.find( ssa_objectt(pointer, ns).get_identifier())->second.def; if(!def_pointer.is_assignment() || def_pointer.loc->location_number< object_ai_it->second.def.loc->location_number) { continue; } } } irep_idt identifier=o_it->get_identifier(); def_entryt &def_entry=def_map[identifier]; def_entry.def.loc=from; def_entry.source=from; auto guard_it=assignments.alloc_guards_map.find({from, *o_it}); if(guard_it!=assignments.alloc_guards_map.end()) { def_entry.def.kind=deft::ALLOCATION; def_entry.def.guard=guard_it->second; } else def_entry.def.kind=deft::ASSIGNMENT; } } else if(from->is_dead()) { const code_deadt &code_dead=to_code_dead(from->code); const irep_idt &id=code_dead.get_identifier(); def_map.erase(id); } // update source in all defs for(def_mapt::iterator d_it=def_map.begin(); d_it!=def_map.end(); d_it++) d_it->second.source=from; }