00001
00002
00003
00004
00005
00006 #include "../Collection/Iterator.h"
00007 #include "../Collection/KeyIterator.h"
00008 #include "../Collection/RefSet.h"
00009 #include "../Statement/Statement.h"
00010 #include "../Symbol/Symbol.h"
00011 #include "../Symbol/VariableSymbol.h"
00012 #include "../Directive/AssertMayMod.h"
00013 #include "../utilities/expression_util.h"
00014 #include "../CommonBlock.h"
00015 #include "../ProgramUnit.h"
00016 #include "../Range/range_dict_util.h"
00017
00018 #include "InterProcConstProp.h"
00019 #include "IPCPProcData.h"
00020 #include "JumpFunction.h"
00021 #include "constant.h"
00022
00023
00024
00025 template class TypedBaseMap<String, IPCPCallData>;
00026 template class ProtoDatabase<String, IPCPCallData>;
00027 template class Database<String, IPCPCallData>;
00028 template ostream & operator << (ostream &,
00029 const Database<String, IPCPCallData> &);
00030 template class KeyIterator<String, IPCPCallData>;
00031
00032 template class TypedCollection<IPCPConstants>;
00033 template class List<IPCPConstants>;
00034 template ostream & operator << (ostream &, const List<IPCPConstants> &);
00035 template class Assign<IPCPConstants>;
00036 template class Iterator<IPCPConstants>;
00037 template class Mutator<IPCPConstants>;
00038
00039
00040
00041
00042 IPCPCallData::IPCPCallData(IPCPProcData *called_pgm_data)
00043 {
00044 _called_pgm_data = called_pgm_data;
00045 _jump_function = 0;
00046 }
00047
00048 IPCPCallData::IPCPCallData(const IPCPCallData &other)
00049 {
00050 _called_pgm_data = other._called_pgm_data;
00051
00052 if (other._jump_function)
00053 _jump_function = new JumpFunction(*other._jump_function);
00054 else
00055 _jump_function = 0;
00056 }
00057
00058
00059
00060
00061 IPCPCallData::~IPCPCallData()
00062 {
00063 jump_function(0);
00064 }
00065
00066
00067
00068
00069 void
00070 IPCPCallData::jump_function(JumpFunction *jump_func)
00071 {
00072 if (_jump_function)
00073 delete _jump_function;
00074
00075 _jump_function = jump_func;
00076 }
00077
00078
00079
00080
00081 void
00082 IPCPCallData::add_constant_set(IPCPConstants *constants,
00083 const List<Expression> ¶m_values)
00084 {
00085 if (_called_pgm_data)
00086 _called_pgm_data->add_constant_set(constants, param_values);
00087 else
00088 delete constants;
00089 }
00090
00091
00092
00093
00094 void
00095 IPCPCallData::compute_rtoporder(int &max_visited_elems)
00096 {
00097 if (_called_pgm_data)
00098 _called_pgm_data->compute_rtoporder(max_visited_elems);
00099 }
00100
00101
00102
00103
00104 Listable *
00105 IPCPCallData::listable_clone() const
00106 {
00107 return new IPCPCallData(*this);
00108 }
00109
00110
00111
00112
00113 void
00114 IPCPCallData::print(ostream &o) const
00115 {
00116 o << "[";
00117 o << "_called_pgm_data=";
00118
00119 if (_called_pgm_data)
00120 _called_pgm_data->entry().print_debug(o, 0);
00121 else
00122 o << "NULL";
00123
00124 o << ", _jump_function=";
00125
00126 if (_jump_function)
00127 o << *_jump_function;
00128 else
00129 o << "NULL";
00130
00131 o << "]";
00132 }
00133
00134
00135
00136
00137 int
00138 IPCPCallData::structures_OK() const
00139 {
00140 return _called_pgm_data->structures_OK();
00141 }
00142
00143
00144
00145
00146
00147
00148 static const char *
00149 _proc_name(const Statement &call_stmt)
00150 {
00151 if (call_stmt.stmt_class() == CALL_STMT)
00152 return call_stmt.routine_guarded().symbol().name_ref();
00153 else if (call_stmt.stmt_class() == ASSIGNMENT_STMT
00154 && call_stmt.rhs().op() == FUNCTION_CALL_OP)
00155 return call_stmt.rhs().function().symbol().name_ref();
00156 else
00157 return 0;
00158 }
00159
00160
00161
00162
00163
00164 static const List<Expression> &
00165 _call_arg_list(const Statement &call_site)
00166 {
00167 const List<Expression> *args = NULL;
00168
00169 if (call_site.stmt_class() == CALL_STMT)
00170 args = &call_site.parameters_guarded().arg_list();
00171 else if (call_site.stmt_class() == ASSIGNMENT_STMT
00172 && call_site.rhs().op() == FUNCTION_CALL_OP)
00173 args = &call_site.rhs().parameters_guarded().arg_list();
00174 else
00175 p_abort("_call_arg_list(): Given statement is not a call statement or function call.");
00176
00177 return *args;
00178 }
00179
00180
00181
00182
00183
00184
00185 void
00186 IPCPProcData::_mark_external_func_calls(const Expression &expr)
00187 {
00188 if (expr.op() == ID_OP && expr.symbol().sym_class() == FUNCTION_CLASS) {
00189 IPCPProcData *called_proc_data
00190 = _ipcp_ref->_get_proc_data_ref(expr.symbol().name_ref());
00191
00192 if (called_proc_data)
00193 called_proc_data->called_externally();
00194 }
00195 else {
00196 Iterator<Expression> arg_iter = expr.arg_list();
00197
00198 for ( ; arg_iter.valid(); ++arg_iter)
00199 _mark_external_func_calls(arg_iter.current());
00200 }
00201 }
00202
00203
00204
00205
00206
00207 void
00208 IPCPProcData::_init_call_sites()
00209 {
00210 Iterator<Statement> stmt_iter = _pgm_ref->stmts().iterator();
00211
00212 for ( ; stmt_iter.valid(); ++stmt_iter) {
00213 Statement &stmt = stmt_iter.current();
00214 const char *proc_name = _proc_name(stmt);
00215
00216 if (proc_name) {
00217 IPCPProcData *called_proc_data = _ipcp_ref->_get_proc_data_ref(proc_name);
00218 _call_data.ins(stmt.tag(), new IPCPCallData(called_proc_data));
00219
00220 if (called_proc_data
00221 && _call_arg_list(stmt).entries() != called_proc_data->param_list().entries()) {
00222
00223 cout << "Error: The number of actual parameters of call to "
00224 << proc_name << " on line " << stmt.line() << endl;
00225 cout << " does not agree with the number of formal parameters for that routine.\n";
00226 p_abort("Aborting.");
00227 }
00228 }
00229 else if (contains_func_call(stmt)) {
00230 Iterator<Expression> expr_iter = stmt.iterate_expressions();
00231
00232 for ( ; expr_iter.valid(); ++expr_iter)
00233 _mark_external_func_calls(expr_iter.current());
00234 }
00235 }
00236 }
00237
00238
00239
00240
00241
00242 const Symbol &
00243 IPCPProcData::_convert_local_to_global(const Symbol &local_var,
00244 const char *global_namespace)
00245 {
00246 Symbol *global_var = _local_to_global_vars.find_ref(local_var);
00247
00248 if (! global_var) {
00249 String global_name = global_namespace;
00250 global_name += ":";
00251 global_name += local_var.name_ref();
00252
00253 global_var = _ipcp_ref->_global_vars.find_ref(global_name);
00254
00255 if (! global_var) {
00256 global_var = new VariableSymbol(global_name, local_var.type(),
00257 NOT_FORMAL, NOT_SAVED);
00258
00259
00260
00261 global_var->type(local_var.type());
00262
00263 global_var = &_ipcp_ref->_global_vars.ins(global_var);
00264 }
00265
00266 _local_to_global_vars.ins(local_var, *global_var);
00267 _global_to_local_vars.ins(*global_var, local_var);
00268 }
00269
00270 return *global_var;
00271 }
00272
00273
00274
00275
00276
00277 void
00278 IPCPProcData::_init_params()
00279 {
00280 p_assert(_entry->routine_guarded().op() == ID_OP,
00281 "Routine name for an entry statement is not a variable.");
00282 const char *entry_name = _entry->routine_guarded().symbol().name_ref();
00283 Iterator<Expression> param_iter = _entry->parameters_guarded().arg_list();
00284
00285 for ( ; param_iter.valid(); ++param_iter) {
00286 p_assert(param_iter.current().op() == ID_OP,
00287 "An entry statement has a parameter that is not a variable.");
00288 const Symbol &global_var
00289 = _convert_local_to_global(param_iter.current().symbol(),
00290 entry_name);
00291 _param_list.ins_last(CASTAWAY(Symbol &) global_var);
00292 }
00293
00294 if (_entry->routine_guarded().symbol().sym_class() == FUNCTION_CLASS) {
00295 const Symbol &global_var
00296 = _convert_local_to_global(_entry->routine_guarded().symbol(),
00297 entry_name);
00298 _return_var = &global_var;
00299 }
00300 else
00301 _return_var = 0;
00302 }
00303
00304
00305
00306
00307
00308 void
00309 IPCPProcData::_add_params_to_set(RefSet<Symbol> &vars) const
00310 {
00311 Iterator<Symbol> param_iter = _param_list;
00312
00313 for ( ; param_iter.valid(); ++param_iter)
00314 vars.ins(param_iter.current());
00315
00316 if (_return_var)
00317 vars.ins(* CASTAWAY(Symbol *) _return_var);
00318 }
00319
00320
00321
00322
00323
00324
00325 void
00326 IPCPProcData::_init_usable_global_vars()
00327 {
00328
00329
00330 KeyIterator<String, IPCPCallData> call_iter = _call_data;
00331
00332 for ( ; call_iter.valid(); ++call_iter) {
00333 const IPCPProcData *call_data = call_iter.current_data().data_ref();
00334
00335 if (call_data) {
00336 Iterator<Symbol> var_iter = call_data->usable_global_vars();
00337
00338 for ( ; var_iter.valid(); ++var_iter)
00339 if (! call_data->param_list().member(var_iter.current())
00340 && &var_iter.current() != call_data->return_var())
00341
00342 _usable_global_vars.ins(var_iter.current());
00343 }
00344 }
00345
00346
00347
00348 DictionaryIter<Symbol> common_iter = _pgm_ref->symtab().iterator();
00349
00350 for ( ; common_iter.valid(); ++common_iter) {
00351 const Symbol &var = common_iter.current();
00352
00353 if (var.sym_class() == VARIABLE_CLASS && var.common_ref()) {
00354 const Symbol &global_var = _convert_local_to_global(var, var.common_ref()->name_ref());
00355 _usable_global_vars.ins(CASTAWAY(Symbol &) global_var);
00356 }
00357 }
00358
00359
00360
00361 _add_params_to_set(_usable_global_vars);
00362 }
00363
00364
00365
00366
00367
00368 void
00369 IPCPProcData::_add_refs_to_globals(const RefSet<Expression> &refs)
00370 {
00371 Iterator<Expression> iter = refs;
00372
00373 for ( ; iter.valid(); ++iter) {
00374 const Symbol *var = iter.current().base_variable_ref();
00375
00376 if (var
00377 && var->sym_class() == VARIABLE_CLASS
00378 && var->common_ref()) {
00379
00380 const Symbol &global_var = _convert_local_to_global(*var, var->common_ref()->name_ref());
00381 _used_global_vars.ins(CASTAWAY(Symbol &) global_var);
00382 }
00383 }
00384 }
00385
00386
00387
00388
00389
00390
00391 void
00392 IPCPProcData::_init_used_global_vars()
00393 {
00394
00395
00396 KeyIterator<String, IPCPCallData> call_iter = _call_data;
00397
00398 for ( ; call_iter.valid(); ++call_iter) {
00399 const IPCPProcData *call_data = call_iter.current_data().data_ref();
00400
00401 if (call_data) {
00402 Iterator<Symbol> var_iter = call_data->used_global_vars();
00403
00404 for ( ; var_iter.valid(); ++var_iter)
00405 if (! call_data->param_list().member(var_iter.current())
00406 && &var_iter.current() != call_data->return_var())
00407
00408 _used_global_vars.ins(var_iter.current());
00409 }
00410 }
00411
00412
00413
00414 Iterator<Statement> stmt_iter = _pgm_ref->stmts().iterator();
00415
00416 for ( ; stmt_iter.valid(); ++stmt_iter) {
00417 const Statement &stmt = stmt_iter.current();
00418
00419 _add_refs_to_globals(stmt.in_refs());
00420 _add_refs_to_globals(stmt.out_refs());
00421 }
00422
00423
00424
00425 _add_params_to_set(_used_global_vars);
00426 }
00427
00428
00429
00430
00431
00432 static void
00433 _add_refs(RefSet<Symbol> &vars, const RefSet<Expression> &refs)
00434 {
00435 Iterator<Expression> iter = refs;
00436
00437 for ( ; iter.valid(); ++iter)
00438 if (iter.current().base_variable_ref())
00439 vars.ins(*iter.current().base_variable_ref());
00440 }
00441
00442
00443
00444
00445 RefSet<Symbol> *
00446 IPCPProcData::local_vars(const RefSet<Symbol> &vars) const
00447 {
00448 RefSet<Symbol> *local_ugvs = new RefSet<Symbol>;
00449 Iterator<Symbol> global_iter = vars;
00450
00451 for ( ; global_iter.valid(); ++global_iter) {
00452 const Symbol *local_var = _global_to_local_vars.find_ref(global_iter.current());
00453
00454 if (local_var)
00455 local_ugvs->ins(*local_var);
00456 else
00457 local_ugvs->ins(global_iter.current());
00458 }
00459
00460 return local_ugvs;
00461 }
00462
00463
00464
00465
00466
00467 static void
00468 _add_vars_to_set(RefSet<Symbol> &var_set, const Expression &expr)
00469 {
00470 if (expr.op() == ID_OP && expr.symbol().sym_class() == VARIABLE_CLASS)
00471 var_set.ins(expr.symbol());
00472 else {
00473 Iterator<Expression> iter = expr.arg_list();
00474
00475 for ( ; iter.valid(); ++iter)
00476 _add_vars_to_set(var_set, iter.current());
00477 }
00478 }
00479
00480
00481
00482
00483
00484 RefSet<Symbol> *
00485 IPCPProcData::_candidates() const
00486 {
00487
00488
00489
00490 RefSet<Symbol> *candidates = local_vars(usable_global_vars());
00491
00492
00493
00494 Iterator<Statement> stmt_iter = _pgm_ref->stmts().iterator();
00495
00496 for ( ; stmt_iter.valid(); ++stmt_iter) {
00497 const Statement &stmt = stmt_iter.current();
00498
00499 if (stmt.stmt_class() == CALL_STMT
00500 || contains_func_call(stmt)
00501 || (stmt.stmt_class() == ASSIGNMENT_STMT
00502 && stmt.lhs().op() == ID_OP
00503 && _ipcp_ref->_is_substitutable(stmt.lhs().symbol()))) {
00504
00505 if (stmt.stmt_class() == ASSIGNMENT_STMT)
00506 candidates->ins(stmt.lhs().symbol());
00507
00508 Iterator<Expression> ref_iter = stmt.in_refs();
00509
00510 for ( ; ref_iter.valid(); ++ref_iter) {
00511 Symbol *var = ref_iter.current().base_variable_ref();
00512
00513 if (var && _ipcp_ref->_is_substitutable(*var))
00514 candidates->ins(*var);
00515 }
00516 }
00517 }
00518
00519
00520
00521 Iterator<IPCPConstants> const_set_iter = _consts_sets;
00522
00523 for ( ; const_set_iter.valid(); ++const_set_iter) {
00524 KeyIterator<Symbol, Expression> const_iter
00525 = const_set_iter.current().constants();
00526
00527 for ( ; const_iter.valid(); ++const_iter)
00528 _add_vars_to_set(*candidates, const_iter.current_data());
00529 }
00530
00531 return candidates;
00532 }
00533
00534
00535
00536
00537
00538 IPCPProcData::IPCPProcData(ProgramUnit &pgm, InterProcConstProp &ipcp,
00539 const Statement &entry, int debug GIV(0))
00540 {
00541 if (debug > 0) {
00542 cout << "! Computing side effects for ";
00543 entry.print_debug(cout, 0);
00544 cout << endl;
00545 }
00546
00547 _pgm_ref = &pgm;
00548 _ipcp_ref = &ipcp;
00549 _entry = &entry;
00550 _return_jump_function = 0;
00551 _rtoporder = -1;
00552 _called_externally = False;
00553 _init_call_sites();
00554 _init_params();
00555 _init_used_global_vars();
00556 _init_usable_global_vars();
00557 }
00558
00559 IPCPProcData::IPCPProcData(ProgramUnit &cloned_proc,
00560 const Statement &clone_entry,
00561 IPCPProcData &orig_proc_data)
00562 {
00563 _pgm_ref = &cloned_proc;
00564 _ipcp_ref = orig_proc_data._ipcp_ref;
00565 _entry = &clone_entry;
00566 _rtoporder = -1;
00567 _called_externally = False;
00568 _call_data = orig_proc_data._call_data;
00569 _used_global_vars = orig_proc_data._used_global_vars;
00570 _usable_global_vars = orig_proc_data._usable_global_vars;
00571 _param_list = orig_proc_data._param_list;
00572 _return_var = orig_proc_data._return_var;
00573
00574 if (orig_proc_data._return_jump_function)
00575 _return_jump_function = new ReturnJumpFunction(*orig_proc_data._return_jump_function);
00576 else
00577 _return_jump_function = 0;
00578
00579
00580
00581 KeyIterator<Symbol,Symbol> ltog_iter = orig_proc_data._local_to_global_vars;
00582
00583 for ( ; ltog_iter.valid(); ++ltog_iter) {
00584 const Symbol &global_var = ltog_iter.current_data();
00585 const Symbol *local_var;
00586
00587 if (&global_var == _return_var)
00588 local_var = &_entry->routine_guarded().symbol();
00589 else
00590 local_var = &_pgm_ref->symtab()[ltog_iter.current_key().name_ref()];
00591
00592 _local_to_global_vars.ins(*local_var, global_var);
00593 _global_to_local_vars.ins(global_var, *local_var);
00594 }
00595 }
00596
00597
00598
00599
00600 IPCPProcData::~IPCPProcData()
00601 {
00602 if (_return_jump_function)
00603 delete _return_jump_function;
00604 }
00605
00606
00607
00608
00609
00610
00611 Boolean
00612 IPCPProcData::_contains_local_vars(const Expression &expr) const
00613 {
00614 if (expr.op() == ID_OP) {
00615 return (expr.symbol().sym_class() == VARIABLE_CLASS
00616 && ! _usable_global_vars.member(expr.symbol()));
00617 }
00618 else {
00619 Iterator<Expression> arg_iter = expr.arg_list();
00620
00621 for ( ; arg_iter.valid(); ++arg_iter)
00622 if (_contains_local_vars(arg_iter.current()))
00623 return True;
00624 }
00625
00626 return False;
00627 }
00628
00629 Boolean
00630 IPCPProcData::_contains_local_vars(const Expression &expr,
00631 const RefList<Symbol> &caller_formals) const
00632 {
00633 if (expr.op() == ID_OP) {
00634 return (expr.symbol().sym_class() == VARIABLE_CLASS
00635 && ! _usable_global_vars.member(expr.symbol())
00636 && ! caller_formals.member(expr.symbol()));
00637 }
00638 else {
00639 Iterator<Expression> arg_iter = expr.arg_list();
00640
00641 for ( ; arg_iter.valid(); ++arg_iter)
00642 if (_contains_local_vars(arg_iter.current(), caller_formals))
00643 return True;
00644 }
00645
00646 return False;
00647 }
00648
00649
00650
00651
00652
00653 void
00654 IPCPProcData::_filter_out_local_vars(Map<Symbol, Expression> &var_mods) const
00655 {
00656 RefSet<Symbol> *mod_vars = modified_vars(var_mods);
00657 Iterator<Symbol> mod_var_iter = *mod_vars;
00658
00659 for ( ; mod_var_iter.valid(); ++mod_var_iter) {
00660 Symbol &var = mod_var_iter.current();
00661
00662 if (! _usable_global_vars.member(var))
00663 var_mods.del(var);
00664 else if (_contains_local_vars(var_mods[var]))
00665 var_mods.ins(var, omega());
00666 }
00667
00668 delete mod_vars;
00669 }
00670
00671 void
00672 IPCPProcData::_filter_out_local_vars(Map<Symbol, Expression> &var_mods,
00673 const RefList<Symbol> &caller_formals) const
00674 {
00675 RefSet<Symbol> *mod_vars = modified_vars(var_mods);
00676 Iterator<Symbol> mod_var_iter = *mod_vars;
00677
00678 for ( ; mod_var_iter.valid(); ++mod_var_iter) {
00679 Symbol &var = mod_var_iter.current();
00680
00681 if (! _usable_global_vars.member(var))
00682 var_mods.del(var);
00683 else if (_contains_local_vars(var_mods[var], caller_formals))
00684 var_mods.ins(var, omega());
00685 }
00686
00687 delete mod_vars;
00688 }
00689
00690
00691
00692
00693
00694
00695
00696
00697 static void
00698 _filter_out_entering_consts(Map<Symbol,Expression> &new_consts,
00699 const Map<Symbol, Expression> &old_const_mods)
00700 {
00701 RefSet<Symbol> *mod_vars = modified_vars(new_consts);
00702 Iterator<Symbol> mod_var_iter = *mod_vars;
00703
00704 for ( ; mod_var_iter.valid(); ++mod_var_iter) {
00705 Symbol &var = mod_var_iter.current();
00706
00707 if (! old_const_mods.member(var))
00708 new_consts.del(var);
00709 }
00710
00711 delete mod_vars;
00712 }
00713
00714
00715
00716
00717 void
00718 IPCPProcData::create_return_jump_function(Map<Symbol, Expression> *old_const_mods,
00719 Map<Symbol, Expression> *new_consts)
00720 {
00721 _filter_out_entering_consts(*new_consts, *old_const_mods);
00722 _rename_locals_to_globals(*old_const_mods);
00723 _filter_out_local_vars(*old_const_mods);
00724 _rename_locals_to_globals(*new_consts);
00725 _filter_out_local_vars(*new_consts);
00726
00727 if (_return_jump_function)
00728 delete _return_jump_function;
00729
00730 _return_jump_function = new ReturnJumpFunction(_param_list,
00731 _usable_global_vars,
00732 old_const_mods, new_consts);
00733 }
00734
00735
00736
00737
00738 const IPCPCallData *
00739 IPCPProcData::call_data(const Statement &call_site) const
00740 {
00741 return _call_data.find_ref(call_site.tag());
00742 }
00743
00744
00745
00746
00747 void
00748 IPCPProcData::create_jump_function(const Statement &call_site,
00749 Map<Symbol, Expression> *old_const_mods,
00750 Map<Symbol, Expression> *new_consts,
00751 List<Expression> *actuals)
00752 {
00753 _filter_out_entering_consts(*new_consts, *old_const_mods);
00754 IPCPCallData *cdata = _call_data.find_ref(call_site.tag());
00755
00756 if (cdata && cdata->data_ref()) {
00757 _rename_locals_to_globals(*old_const_mods);
00758 _rename_locals_to_globals(*new_consts);
00759
00760
00761
00762 p_assert(cdata->data_ref()->param_list().entries() == actuals->entries(),
00763 "IPCPProcData::create_jump_function(): The number of given actuals does not equal the number of formals.");
00764
00765 Iterator<Symbol> formal_iter = cdata->data_ref()->param_list();
00766 Mutator<Expression> actual_iter = *actuals;
00767
00768 for ( ; formal_iter.valid(); ++formal_iter, ++actual_iter) {
00769 const Symbol &formal = formal_iter.current();
00770 Expression *actual_expr = actual_iter.grab();
00771
00772 if (formal.type() == actual_expr->type()
00773 && (_ipcp_ref->_is_substitutable(formal)
00774 || actual_expr->base_variable_ref())) {
00775
00776 _rename_locals_to_globals(*actual_expr);
00777 new_consts->ins(formal, actual_expr);
00778 }
00779 else {
00780 delete actual_expr;
00781 new_consts->ins(formal, omega());
00782 }
00783 }
00784
00785 cdata->data_ref()->_filter_out_local_vars(*old_const_mods, _param_list);
00786 cdata->data_ref()->_filter_out_local_vars(*new_consts, _param_list);
00787
00788 RefSet<Symbol> *new_const_mods = modified_vars(*new_consts);
00789 Iterator<Symbol> new_const_iter = *new_const_mods;
00790
00791 for ( ; new_const_iter.valid(); ++new_const_iter) {
00792 Symbol &var = new_const_iter.current();
00793
00794 if ((*new_consts)[var].op() == OMEGA_OP)
00795 if (old_const_mods->member(var))
00796 new_consts->del(var);
00797 else
00798 old_const_mods->ins(var, new_consts->grab(var));
00799 }
00800
00801 delete new_const_mods;
00802 cdata->jump_function(new JumpFunction(_param_list,
00803 cdata->data_ref()->usable_global_vars(),
00804 old_const_mods, new_consts));
00805 }
00806
00807 delete actuals;
00808 }
00809
00810
00811
00812
00813
00814
00815 void
00816 IPCPProcData::_rename_locals_to_globals(Expression &expr) const
00817 {
00818 if (expr.op() == ID_OP) {
00819 if (expr.symbol().sym_class() == VARIABLE_CLASS) {
00820 const Symbol *global_var = _local_to_global_vars.find_ref(expr.symbol());
00821
00822 if (global_var)
00823 expr.symbol(*global_var);
00824 }
00825 }
00826 else {
00827 Iterator<Expression> iter = expr.arg_list();
00828
00829 for ( ; iter.valid(); ++iter)
00830 _rename_locals_to_globals(iter.current());
00831 }
00832 }
00833
00834 void
00835 IPCPProcData::_rename_locals_to_globals(Map<Symbol,Expression> &var_mods) const
00836 {
00837 RefSet<Symbol> *mod_vars = modified_vars(var_mods);
00838 Iterator<Symbol> mod_var_iter = *mod_vars;
00839
00840 for ( ; mod_var_iter.valid(); ++mod_var_iter) {
00841 Symbol &local_var = mod_var_iter.current();
00842 const Symbol *global_var = _local_to_global_vars.find_ref(local_var);
00843
00844 if (! global_var)
00845 global_var = &local_var;
00846
00847 Expression *global_mod_expr = var_mods.grab(local_var);
00848 _rename_locals_to_globals(*global_mod_expr);
00849 var_mods.ins(*global_var, global_mod_expr);
00850 }
00851
00852 delete mod_vars;
00853 }
00854
00855 void
00856 IPCPProcData::_rename_locals_to_globals(List<Expression> &expr_list) const
00857 {
00858 Iterator<Expression> iter = expr_list;
00859
00860 for ( ; iter.valid(); ++iter)
00861 _rename_locals_to_globals(iter.current());
00862 }
00863
00864
00865
00866
00867
00868
00869 void
00870 IPCPProcData::_rename_globals_to_locals(Expression &expr) const
00871 {
00872 if (expr.op() == ID_OP) {
00873 if (expr.symbol().sym_class() == VARIABLE_CLASS) {
00874 const Symbol *local_var = _global_to_local_vars.find_ref(expr.symbol());
00875
00876 if (local_var)
00877 expr.symbol(*local_var);
00878 }
00879 }
00880 else {
00881 Iterator<Expression> iter = expr.arg_list();
00882
00883 for ( ; iter.valid(); ++iter)
00884 _rename_globals_to_locals(iter.current());
00885 }
00886 }
00887
00888 void
00889 IPCPProcData::_rename_globals_to_locals(Map<Symbol,Expression> &var_mods) const
00890 {
00891 RefSet<Symbol> *mod_vars = modified_vars(var_mods);
00892 Iterator<Symbol> mod_var_iter = *mod_vars;
00893
00894 for ( ; mod_var_iter.valid(); ++mod_var_iter) {
00895 Symbol &global_var = mod_var_iter.current();
00896 const Symbol *local_var = _global_to_local_vars.find_ref(global_var);
00897
00898 if (! local_var)
00899 local_var = &global_var;
00900
00901 Expression *local_mod_expr = var_mods.grab(global_var);
00902 _rename_globals_to_locals(*local_mod_expr);
00903 var_mods.ins(*local_var, local_mod_expr);
00904 }
00905
00906 delete mod_vars;
00907 }
00908
00909
00910
00911
00912 Map<Symbol,Expression> *
00913 IPCPProcData::local_old_const_mods(const Statement &call_site,
00914 const ReturnJumpFunction &jump_function) const
00915 {
00916 List<Expression> global_arg_list(_call_arg_list(call_site));
00917 _rename_locals_to_globals(global_arg_list);
00918 Map<Symbol, Expression> *var_mods = jump_function.const_mods(global_arg_list);
00919 _rename_globals_to_locals(*var_mods);
00920
00921 return var_mods;
00922 }
00923
00924
00925
00926
00927 Map<Symbol,Expression> *
00928 IPCPProcData::local_new_consts(const Statement &call_site,
00929 const ReturnJumpFunction &jump_function) const
00930 {
00931 List<Expression> global_arg_list(_call_arg_list(call_site));
00932 _rename_locals_to_globals(global_arg_list);
00933 Map<Symbol, Expression> *var_mods = jump_function.new_consts(global_arg_list);
00934 _rename_globals_to_locals(*var_mods);
00935
00936 return var_mods;
00937 }
00938
00939
00940
00941
00942 void
00943 IPCPProcData::add_constant_set(IPCPConstants *constants,
00944 const List<Expression> ¶m_values)
00945 {
00946 constants->filter_out_vars_not_in_set(_used_global_vars,
00947 _usable_global_vars);
00948
00949
00950
00951
00952 Iterator<IPCPConstants> consts_iter = _consts_sets;
00953
00954 for ( ; consts_iter.valid(); ++consts_iter)
00955 if (*constants == consts_iter.current()) {
00956 consts_iter.current().merge_invocation_sites(constants);
00957 return;
00958 }
00959
00960
00961
00962
00963 constants->proc_data_ref = this;
00964
00965 if (constants->constants().entries() == 0) {
00966
00967
00968
00969 _consts_sets.ins_first(constants);
00970 }
00971 else
00972 _consts_sets.ins_last(constants);
00973
00974
00975
00976 KeyIterator<String, IPCPCallData> call_iter = _call_data;
00977
00978 for ( ; call_iter.valid(); ++call_iter) {
00979 IPCPCallData &call_data = call_iter.current_data();
00980
00981 if (call_data.data_ref() && call_data.jump_function_valid()) {
00982 const Statement *call_site = _pgm_ref->stmts().find_ref(call_iter.current_key());
00983 p_assert(call_site, "Couldn't find the call statement for one of the object's call sites.");
00984 List<Expression> global_arg_list(param_values);
00985 _rename_locals_to_globals(global_arg_list);
00986 IPCPConstants *call_constants
00987 = call_data.jump_function().constants(*constants,
00988 global_arg_list);
00989 call_constants->add_invocation_site(
00990 new CallSite(constants, call_site->tag()));
00991
00992 call_data.add_constant_set(call_constants, _call_arg_list(*call_site));
00993 }
00994 }
00995 }
00996
00997
00998
00999
01000
01001
01002
01003 void
01004 IPCPProcData::_update_call_site(const char *call_site_tag,
01005 IPCPProcData &new_call_proc_data)
01006 {
01007 IPCPCallData *call_data = _call_data.find_ref(call_site_tag);
01008 p_assert(call_data,
01009 "IPCPConstants::_update_call_site(): Couldn't find the given call site.");
01010 call_data->data_ref(&new_call_proc_data);
01011 Statement *call_site = _pgm_ref->stmts().find_ref(call_site_tag);
01012 const Symbol &entry_var = new_call_proc_data.entry().routine_guarded().symbol();
01013 Symbol *call_site_symbol = _pgm_ref->symtab().find_ref(entry_var.name_ref());
01014
01015 if (! call_site_symbol) {
01016 call_site_symbol = entry_var.clone();
01017 call_site_symbol->external(IS_EXTERNAL);
01018 _pgm_ref->symtab().ins(call_site_symbol);
01019 }
01020
01021 if (call_site->stmt_class() == CALL_STMT)
01022 call_site->routine_guarded().symbol(*call_site_symbol);
01023 else if (call_site->stmt_class() == ASSIGNMENT_STMT
01024 && call_site->rhs().op() == FUNCTION_CALL_OP) {
01025
01026
01027
01028
01029 call_site_symbol->type(call_site->rhs().function().symbol().type());
01030 call_site->rhs().function().symbol(*call_site_symbol);
01031 }
01032 else
01033 p_abort("Internal error: Given call site does not make a subroutine call.");
01034 }
01035
01036
01037
01038
01039 void
01040 IPCPProcData::transfer_const_set(IPCPConstants &consts, IPCPProcData &other)
01041 {
01042 IPCPConstants *consts_obj = other._consts_sets.grab(consts);
01043
01044 _consts_sets.ins_last(consts_obj);
01045 consts.proc_data_ref = this;
01046
01047
01048
01049
01050 Iterator<CallSite> caller_iter = consts.invocation_sites();
01051
01052 for ( ; caller_iter.valid(); ++caller_iter) {
01053 CallSite &call_site = caller_iter.current();
01054 p_assert(call_site.caller_consts_ref(),
01055 "Internal error: main program unit was cloned.");
01056 call_site.caller_consts_ref()->proc_data_ref->_update_call_site(call_site.call_tag(),
01057 *this);
01058 }
01059 }
01060
01061
01062
01063
01064
01065
01066
01067 Map<Symbol,Expression> *
01068 IPCPProcData::_local_consts(const IPCPConstants &consts) const
01069 {
01070
01071
01072 RefSet<Symbol> locally_used_global_vars;
01073 RefSet<Symbol> locally_usable_global_vars;
01074
01075 KeyIterator<Symbol,Symbol> global_iter = _global_to_local_vars;
01076
01077 for ( ; global_iter.valid(); ++global_iter) {
01078 Symbol &global_var = global_iter.current_key();
01079 locally_usable_global_vars.ins(global_var);
01080
01081 if (_used_global_vars.member(global_var))
01082 locally_used_global_vars.ins(global_var);
01083 }
01084
01085 IPCPConstants my_consts(consts);
01086 my_consts.filter_out_vars_not_in_set(locally_used_global_vars,
01087 locally_usable_global_vars);
01088 Map<Symbol,Expression> *lconsts
01089 = new Map<Symbol,Expression>(my_consts.constants());
01090 _rename_globals_to_locals(*lconsts);
01091
01092 return lconsts;
01093 }
01094
01095
01096
01097
01098 void
01099 IPCPProcData::add_consts_to_pgm(const IPCPConstants &consts)
01100 {
01101 Map<Symbol,Expression> *const_map = _local_consts(consts);
01102 KeyIterator<Symbol, Expression> const_iter = *const_map;
01103
01104 for ( ; const_iter.valid(); ++const_iter)
01105 if (! const_iter.current_key().is_array()) {
01106
01107
01108
01109
01110
01111
01112 }
01113
01114 delete const_map;
01115 }
01116
01117 void
01118 IPCPProcData::add_consts_to_pgm()
01119 {
01120 p_assert(_consts_sets.entries() <= 1,
01121 "IPCPProcData::add_consts_to_pgm(): There are multiple number of sets of constants.");
01122
01123 if (_consts_sets.entries() == 1)
01124 add_consts_to_pgm(_consts_sets[0]);
01125 }
01126
01127
01128
01129
01130 void
01131 IPCPProcData::build_jump_functions(int debug GIV(0))
01132 {
01133 RefSet<Symbol> *use_candidates = _candidates();
01134 RefSet<Symbol> *def_candidates = new RefSet<Symbol>(*use_candidates);
01135
01136 Mutator<Symbol> cand_iter = *def_candidates;
01137
01138 for ( ; cand_iter.valid(); ++cand_iter)
01139 if (! _ipcp_ref->_is_substitutable(cand_iter.current()))
01140 cand_iter.del();
01141
01142 KeyIterator<String,IPCPCallData> call_iter = _call_data;
01143
01144 for ( ; call_iter.valid(); ++call_iter)
01145 call_iter.current_data().jump_function(0);
01146
01147 Map<Symbol,Expression> *entering_constants;
01148
01149 if (_consts_sets.entries() == 1)
01150 entering_constants = _local_consts(_consts_sets[0]);
01151 else
01152 entering_constants = new Map<Symbol, Expression>;
01153
01154 _ipcp_build_jump_functions(*_pgm_ref, *this, *def_candidates,
01155 *use_candidates, *entering_constants, debug);
01156 delete entering_constants;
01157 delete def_candidates;
01158 delete use_candidates;
01159 }
01160
01161
01162
01163
01164
01165 Expression *
01166 IPCPProcData::_expr_del_global_substituted(Expression *expr)
01167 {
01168 if (expr)
01169 if (expr->op() == ID_OP) {
01170 expr->substituted(_expr_del_global_substituted(expr->grab_substituted()));
01171
01172 if (_usable_global_vars.member(expr->symbol())) {
01173 Expression *new_expr = expr->grab_substituted();
01174 delete expr;
01175 return new_expr;
01176 }
01177 }
01178 else {
01179 Mutator<Expression> arg_iter = expr->arg_list();
01180
01181 for ( ; arg_iter.valid(); ++arg_iter) {
01182 Assign<Expression> eas(arg_iter.assign());
01183 Expression *new_arg = _expr_del_global_substituted(arg_iter.pull());
01184 if (new_arg)
01185 eas = new_arg;
01186 else {
01187 delete expr;
01188 delete new_arg;
01189 return 0;
01190 }
01191 }
01192 }
01193
01194 return expr;
01195 }
01196
01197
01198
01199
01200
01201 void
01202 IPCPProcData::_del_global_substituted()
01203 {
01204 Iterator<Statement> stmt_iter = _pgm_ref->stmts().iterator();
01205
01206 for ( ; stmt_iter.valid(); ++stmt_iter) {
01207 Mutator<Expression> expr_iter = stmt_iter.current().iterate_expressions();
01208
01209 for ( ; expr_iter.valid(); ++expr_iter) {
01210 Assign<Expression> eas(expr_iter.assign());
01211 Expression *new_expr = _expr_del_global_substituted(expr_iter.pull());
01212 p_assert(new_expr, "Internal error in IPCPProcData::_del_global_substituted()");
01213 eas = new_expr;
01214 }
01215 }
01216 }
01217
01218
01219
01220
01221
01222 void
01223 IPCPProcData::propagate_constants(PC_UNREACH_BOOL remove_unreachable,
01224 int debug GIV(0))
01225 {
01226 RefSet<Symbol> *use_candidates = _candidates();
01227 RefSet<Symbol> *def_candidates = new RefSet<Symbol>(*use_candidates);
01228
01229 Mutator<Symbol> cand_iter = *def_candidates;
01230
01231 for ( ; cand_iter.valid(); ++cand_iter)
01232 if (! _ipcp_ref->_is_substitutable(cand_iter.current()))
01233 cand_iter.del();
01234
01235 Map<Symbol,Expression> *entering_constants;
01236
01237 if (_consts_sets.entries() == 1)
01238 entering_constants = _local_consts(_consts_sets[0]);
01239 else
01240 entering_constants = new Map<Symbol, Expression>;
01241
01242 _ipcp_propagate_constants(*_pgm_ref, *this, *def_candidates,
01243 *use_candidates, remove_unreachable,
01244 *entering_constants, debug);
01245 delete entering_constants;
01246 delete def_candidates;
01247 delete use_candidates;
01248
01249 _del_global_substituted();
01250 }
01251
01252
01253
01254
01255 void
01256 IPCPProcData::add_maymods()
01257 {
01258 KeyIterator<String, IPCPCallData> call_iter = _call_data;
01259
01260 for ( ; call_iter.valid(); ++call_iter) {
01261 const IPCPProcData *call_data = call_iter.current_data().data_ref();
01262 const Statement *call_site = _pgm_ref->stmts().find_ref(call_iter.current_key());
01263
01264 if (call_data && call_site) {
01265
01266
01267 Mutator<Assertion> asrt_iter = call_site->assertions();
01268
01269 for ( ; asrt_iter.valid(); ++asrt_iter)
01270 if (asrt_iter.current().type() == AS_MAYMOD)
01271 asrt_iter.del();
01272
01273
01274
01275
01276 Map<Symbol, Expression> *var_modifications
01277 = local_old_const_mods(*call_site,
01278 call_data->return_jump_function());
01279
01280 RefList<Symbol> maymods;
01281 KeyIterator<Symbol, Expression> mod_iter = *var_modifications;
01282
01283 for ( ; mod_iter.valid(); ++mod_iter) {
01284 Symbol &var = mod_iter.current_key();
01285
01286 if (_pgm_ref->symtab().find_ref(var.name_ref()) == &var)
01287 maymods.ins_last(var);
01288 }
01289
01290 delete var_modifications;
01291 sort_sym_list(maymods);
01292
01293
01294
01295 AssertMayMod *assert = new AssertMayMod();
01296 Mutator<Symbol> mod_var_iter = maymods;
01297
01298 for ( ; mod_var_iter.valid(); ++mod_var_iter)
01299 assert->arg_list_guarded().ins_last(id(mod_var_iter.current()));
01300
01301 call_site->assertions().ins_last(assert);
01302 }
01303 }
01304 }
01305
01306
01307
01308
01309
01310 Boolean
01311 constant_value(const Expression &expr)
01312 {
01313 if(expr.arg_list().entries()==0)
01314 return (expr.op() == INTEGER_CONSTANT_OP
01315 || expr.op() == LOGICAL_CONSTANT_OP);
01316 else if(expr.op() == INTRINSIC_CALL_OP)
01317 return constant_value(expr.parameters_guarded());
01318 else {
01319 Iterator<Expression> iter = expr.arg_list();
01320
01321 for(; iter.valid(); ++iter)
01322 if(! constant_value(iter.current()))
01323 return false;
01324 }
01325
01326 return true;
01327 }
01328
01329
01330 void
01331 IPCPProcData::expand_all_substituted()
01332 {
01333
01334 expand_substituted(*_pgm_ref, 0, constant_value);
01335 }
01336
01337
01338
01339
01340 void
01341 IPCPProcData::make_consts_sets_old()
01342 {
01343 _old_consts_sets.clear();
01344
01345 while (_consts_sets.entries())
01346 _old_consts_sets.ins_first(_consts_sets.grab(0));
01347 }
01348
01349
01350
01351
01352 Boolean
01353 IPCPProcData::have_consts_sets_changed() const
01354 {
01355 if (_consts_sets.entries() != _old_consts_sets.entries())
01356 return True;
01357
01358 Iterator<IPCPConstants> new_consts_iter = _consts_sets;
01359
01360 for ( ; new_consts_iter.valid(); ++new_consts_iter) {
01361 const IPCPConstants &new_consts = new_consts_iter.current();
01362 Boolean is_consts_in_set = False;
01363 Iterator<IPCPConstants> old_consts_iter = _old_consts_sets;
01364
01365 for ( ; old_consts_iter.valid() && ! is_consts_in_set; ++old_consts_iter)
01366 if (new_consts == old_consts_iter.current())
01367 is_consts_in_set = True;
01368
01369 if (! is_consts_in_set)
01370 return True;
01371 }
01372
01373 return False;
01374 }
01375
01376
01377
01378
01379 Listable *
01380 IPCPProcData::listable_clone() const
01381 {
01382 return new IPCPProcData(*this);
01383 }
01384
01385
01386
01387
01388
01389 static void
01390 _print_var_map(ostream &o, const RefMap<Symbol,Symbol> &var_map)
01391 {
01392 o << "{";
01393 KeyIterator<Symbol,Symbol> iter = var_map;
01394
01395 if (iter.valid()) {
01396 o << iter.current_key().name_ref() << "="
01397 << iter.current_data().name_ref();
01398 ++iter;
01399
01400 for ( ; iter.valid(); ++iter)
01401 o << ", " << iter.current_key().name_ref() << "="
01402 << iter.current_data().name_ref();
01403 }
01404
01405 o << "}";
01406 }
01407
01408
01409
01410
01411 void
01412 IPCPProcData::init_rtoporder()
01413 {
01414 _rtoporder = -1;
01415 }
01416
01417
01418
01419
01420 void
01421 IPCPProcData::compute_rtoporder(int &max_visited_elems)
01422 {
01423 if (_rtoporder < 0) {
01424 KeyIterator<String, IPCPCallData> call_iter = _call_data;
01425
01426 for ( ; call_iter.valid(); ++call_iter)
01427 call_iter.current_data().compute_rtoporder(max_visited_elems);
01428
01429 _rtoporder = max_visited_elems;
01430 ++max_visited_elems;
01431 }
01432 }
01433
01434
01435
01436
01437
01438 static void
01439 _print_var_set(ostream &o, const RefSet<Symbol> &var_map)
01440 {
01441 o << "{";
01442 Iterator<Symbol> iter = var_map;
01443
01444 if (iter.valid()) {
01445 o << iter.current().name_ref();
01446 ++iter;
01447
01448 for ( ; iter.valid(); ++iter)
01449 o << ", " << iter.current().name_ref();
01450 }
01451
01452 o << "}";
01453 }
01454
01455
01456
01457
01458 void
01459 IPCPProcData::print(ostream &o, Boolean pretty_print) const
01460 {
01461 o << "[";
01462 o << "pgm=" << _pgm_ref->routine_name_ref();
01463 o << ", ipcp=" << _ipcp_ref;
01464 o << ", entry=";
01465 _entry->print_debug(o, 0);
01466 o << ", ";
01467 o << ", rtoporder=" << _rtoporder;
01468 o << ", ";
01469 if (pretty_print) o << "\n ";
01470 o << "used_global_vars={";
01471 _print_var_set(o, _used_global_vars);
01472 o << "}, ";
01473 if (pretty_print) o << "\n ";
01474 o << "usable_global_vars={";
01475 _print_var_set(o, _usable_global_vars);
01476 o << "}, ";
01477 if (pretty_print) o << "\n ";
01478 o << "local_to_global_vars=";
01479 _print_var_map(o, _local_to_global_vars);
01480 o << ", ";
01481 if (pretty_print) o << "\n ";
01482 o << "global_to_local_vars=";
01483 _print_var_map(o, _global_to_local_vars);
01484 o << ", ";
01485 if (pretty_print) o << "\n ";
01486 o << "param_list={";
01487 Iterator<Symbol> param_iter = _param_list;
01488
01489 if (param_iter.valid()) {
01490 o << param_iter.current().name_ref();
01491 ++param_iter;
01492
01493 for ( ; param_iter.valid(); ++param_iter)
01494 o << ", " << param_iter.current().name_ref();
01495 }
01496
01497 o << "}, ";
01498 if (pretty_print) o << "\n ";
01499 o << "return_var=";
01500
01501 if (_return_var)
01502 o << _return_var->name_ref();
01503 else
01504 o << "NULL";
01505
01506 o << ", ";
01507 if (pretty_print) o << "\n ";
01508 o << "return_jump_function=";
01509
01510 if (_return_jump_function)
01511 o << *_return_jump_function;
01512 else
01513 o << "NULL";
01514
01515 o << ", ";
01516 if (pretty_print) o << "\n ";
01517 o << "consts_sets=" << _consts_sets;
01518 o << ", ";
01519 if (pretty_print) o << "\n ";
01520 o << "_call_data={";
01521
01522 KeyIterator<String,IPCPCallData> call_iter = _call_data;
01523
01524 if (call_iter.valid()) {
01525 if (pretty_print) o << "\n ";
01526 o << call_iter.current_key() << ": " << call_iter.current_data();
01527 ++call_iter;
01528
01529 for ( ; call_iter.valid(); ++call_iter) {
01530 o << ", ";
01531 if (pretty_print) o << "\n ";
01532 o << call_iter.current_key() << ": " << call_iter.current_data();
01533 }
01534 }
01535
01536 o << "}";
01537 o << "]";
01538 if (pretty_print) o << "\n";
01539 }
01540
01541 void
01542 IPCPProcData::print(ostream &o) const
01543 {
01544 print(o, False);
01545 }
01546
01547
01548
01549
01550 int
01551 IPCPProcData::structures_OK() const
01552 {
01553 return (_call_data.structures_OK()
01554 && _used_global_vars.structures_OK()
01555 && _local_to_global_vars.structures_OK()
01556 && _global_to_local_vars.structures_OK()
01557 && _param_list.structures_OK()
01558 && (! _return_jump_function
01559 || _return_jump_function->structures_OK()));
01560 }