build parameters first, then the function body. this way the generation order is in sync with execution order, and the dataflow analyzer doesn't need to visit the function twice */
| 183 | with execution order, and the dataflow analyzer doesn't need to visit the function twice |
| 184 | */ |
| 185 | FunctionInvocationUser* |
| 186 | FunctionInvocationUser::build_invocation_and_function(CGContext &cg_context, const Type* type, const CVQualifiers* qfer) |
| 187 | { |
| 188 | assert(type); // return type must be provided |
| 189 | FactMgr* caller_fm = get_fact_mgr(&cg_context); |
| 190 | Effect running_eff_context(cg_context.get_effect_context()); |
| 191 | Function* func = Function::make_random_signature(cg_context, type, qfer); |
| 192 | |
| 193 | if (func->name == "func_51") |
| 194 | BREAK_NOP; // for debugging |
| 195 | vector<const Expression*> param_values; |
| 196 | size_t i; |
| 197 | for (i = 0; i < func->param.size(); i++) { |
| 198 | Effect param_eff_accum; |
| 199 | CGContext param_cg_context(cg_context, running_eff_context, ¶m_eff_accum); |
| 200 | Variable* v = func->param[i]; |
| 201 | // to avoid too much function invocations as parameters |
| 202 | Expression *p = Expression::make_random_param(param_cg_context, v->type, &v->qfer); |
| 203 | // typecast, if needed. |
| 204 | p->check_and_set_cast(v->type); |
| 205 | param_values.push_back(p); |
| 206 | // Update the "running effect context": the context that we must use |
| 207 | // when we generate subsequent parameters within this invocation. |
| 208 | running_eff_context.add_effect(param_eff_accum); |
| 209 | // Update the total effect of this invocation, too. |
| 210 | cg_context.merge_param_context(param_cg_context); |
| 211 | } |
| 212 | |
| 213 | FunctionInvocationUser* fiu = new FunctionInvocationUser(func, false, NULL); |
| 214 | fiu->param_value = param_values; |
| 215 | // hand-over from caller to callee |
| 216 | FactMgr* fm = get_fact_mgr_for_func(func); |
| 217 | fm->global_facts = caller_fm->global_facts; |
| 218 | fm->caller_to_callee_handover(fiu, fm->global_facts); |
| 219 | |
| 220 | // create function body |
| 221 | Effect effect_accum; |
| 222 | func->generate_body_with_known_params(cg_context, effect_accum); |
| 223 | |
| 224 | // post creation processing |
| 225 | FactVec ret_facts = fm->map_facts_out[func->body]; |
| 226 | func->body->add_back_return_facts(fm, ret_facts); |
| 227 | fiu->save_return_fact(ret_facts); |
| 228 | |
| 229 | // remove facts related to passing parameters |
| 230 | //FactMgr::update_facts_for_oos_vars(func->param, fm->global_facts); |
| 231 | fm->setup_in_out_maps(true); |
| 232 | // hand-over from callee to caller: points-to facts |
| 233 | renew_facts(caller_fm->global_facts, ret_facts); |
| 234 | |
| 235 | // hand-over from callee to caller: effects |
| 236 | func->accum_eff_context.add_external_effect(cg_context.get_effect_context()); |
| 237 | Effect& func_effect = func->feffect; |
| 238 | func_effect.add_external_effect(effect_accum, cg_context.call_chain); |
| 239 | cg_context.add_visible_effect(effect_accum, cg_context.get_current_block()); |
| 240 | |
| 241 | // hand-over from callee to caller: new global variables |
| 242 | Function* caller_func = cg_context.get_current_func(); |
nothing calls this directly
no test coverage detected