* Internal helper function. */
| 255 | * Internal helper function. |
| 256 | */ |
| 257 | bool |
| 258 | FunctionInvocationUser::build_invocation(Function *target, CGContext &cg_context) |
| 259 | { |
| 260 | unsigned int i; |
| 261 | func = target; // XXX: unnecessary; done by constructor |
| 262 | Effect running_eff_context(cg_context.get_effect_context()); |
| 263 | FactMgr* fm = get_fact_mgr(&cg_context); |
| 264 | // XXX DEBUGGING |
| 265 | if (func->name == "func_36" && cg_context.get_current_func()->name=="func_22") { |
| 266 | i = 0; // Set breakpoint here. |
| 267 | } |
| 268 | |
| 269 | for (i = 0; i < func->param.size(); i++) { |
| 270 | Effect param_eff_accum; |
| 271 | CGContext param_cg_context(cg_context, running_eff_context, ¶m_eff_accum); |
| 272 | Variable* v = func->param[i]; |
| 273 | // to avoid too much function invocations as parameters |
| 274 | Expression *p = Expression::make_random_param(param_cg_context, v->type, &v->qfer); |
| 275 | ERROR_GUARD(false); |
| 276 | // typecast, if needed. |
| 277 | p->check_and_set_cast(v->type); |
| 278 | param_value.push_back(p); |
| 279 | // Update the "running effect context": the context that we must use |
| 280 | // when we generate subsequent parameters within this invocation. |
| 281 | running_eff_context.add_effect(param_eff_accum); |
| 282 | // Update the total effect of this invocation, too. |
| 283 | cg_context.merge_param_context(param_cg_context); |
| 284 | } |
| 285 | |
| 286 | // no need to validate func_1 as it has no parameters and it's called only once |
| 287 | // in addition, the hack (calling func_1 in a func_1 context) we used would |
| 288 | // ruin DFA |
| 289 | failed = false; |
| 290 | if (target != GetFirstFunction() && (target->fact_changed || target->union_field_read || target->is_pointer_referenced())) { |
| 291 | // revisit with a new context |
| 292 | Effect effect_accum; |
| 293 | // retrive the context effect in prev. visits, and include them for this visit |
| 294 | Effect effect_context = cg_context.get_effect_context(); |
| 295 | effect_context.add_effect(func->accum_eff_context); |
| 296 | CGContext new_context(cg_context, func, effect_context, &effect_accum); |
| 297 | failed = !revisit(fm->global_facts, new_context); |
| 298 | // incorporate facts from revisit |
| 299 | if (!failed) { |
| 300 | assert(cg_context.get_current_block()); |
| 301 | cg_context.add_visible_effect(*new_context.get_effect_accum(), cg_context.get_current_block()); |
| 302 | Effect& func_effect = func->feffect; |
| 303 | func_effect.add_external_effect(*new_context.get_effect_accum(), cg_context.call_chain); |
| 304 | } |
| 305 | } |
| 306 | else { |
| 307 | // if the function neither change pointer facts, nor dereference pointer (which means |
| 308 | // the read/write set are static, no need to re-analyze |
| 309 | cg_context.add_external_effect(func->get_feffect()); |
| 310 | } |
| 311 | return !failed; |
| 312 | } |
| 313 | |
| 314 | /* |
no test coverage detected