bool replace_symbolt::replace(exprt &dest) { if(dest.id()=="symbol") { expr_mapt::const_iterator it= expr_map.find(dest.identifier()); if(it!=expr_map.end()) { dest=it->second; return false; } } bool result=true; Forall_operands(it, dest) result=replace(*it) && result; result=replace(dest.type()) && result; return result; }
void goto_inlinet::expand_function_call( goto_programt &dest, goto_programt::targett &target, const exprt &lhs, const exprt &function, const exprt::operandst &arguments, const exprt &constrain, bool full) { // look it up if(function.id()!="symbol") { err_location(function); throw "function_call expects symbol as function operand, " "but got `"+function.id_string()+"'"; } const irep_idt &identifier=function.identifier(); // see if we are already expanding it if(recursion_set.find(identifier)!=recursion_set.end()) { if(!full) { target++; return; // simply ignore, we don't do full inlining, it's ok } // it's really recursive. Uh. Buh. Give up. err_location(function); warning("recursion is ignored"); target->make_skip(); target++; return; } goto_functionst::function_mapt::iterator m_it= goto_functions.function_map.find(identifier); if(m_it==goto_functions.function_map.end()) { err_location(function); str << "failed to find function `" << identifier << "'"; throw 0; } goto_functiont &f=m_it->second; // see if we need to inline this if(!full) { if(!f.body_available || (!f.is_inlined() && f.body.instructions.size() > smallfunc_limit)) { target++; return; } } if(f.body_available) { inlined_funcs.insert(identifier.as_string()); for (std::set<std::string>::const_iterator it2 = f.inlined_funcs.begin(); it2 != f.inlined_funcs.end(); it2++) { inlined_funcs.insert(*it2); } recursion_sett::iterator recursion_it= recursion_set.insert(identifier).first; goto_programt tmp2; tmp2.copy_from(f.body); assert(tmp2.instructions.back().is_end_function()); tmp2.instructions.back().type=LOCATION; replace_return(tmp2, lhs, constrain); goto_programt tmp; parameter_assignments(tmp2.instructions.front().location, f.type, arguments, tmp); tmp.destructive_append(tmp2); // set local variables Forall_goto_program_instructions(it, tmp) it->local_variables.insert(target->local_variables.begin(), target->local_variables.end()); if(f.type.hide()) { const locationt &new_location=function.find_location(); Forall_goto_program_instructions(it, tmp) { if(new_location.is_not_nil()) { // can't just copy, e.g., due to comments field it->location.id(""); // not NIL it->location.set_file(new_location.get_file()); it->location.set_line(new_location.get_line()); it->location.set_column(new_location.get_column()); it->location.set_function(new_location.get_function()); } } } // do this recursively goto_inline_rec(tmp, full); // set up location instruction for function call target->type=LOCATION; target->code = expr2tc(); goto_programt::targett next_target(target); next_target++; dest.instructions.splice(next_target, tmp.instructions); target=next_target; recursion_set.erase(recursion_it); }