00001
00002
00003
00004
00005 #include "../macros.h"
00006
00007 #include "PropConstMap.h"
00008
00009
00010
00011 template class Array<PropConstElem>;
00012
00013
00014
00015 void
00016 _collect_uses(const Expression &expr, IntSet &use_set,
00017 const Map<Symbol, IntElem> &candidates)
00018 {
00019 if (expr.op() == ID_OP) {
00020 const IntElem *elem = candidates.find_ref(expr.symbol());
00021
00022 if (elem)
00023 use_set.ins(elem->value());
00024 }
00025 else {
00026 Iterator<Expression> iter = expr.arg_list();
00027
00028 for ( ; iter.valid(); ++iter)
00029 _collect_uses(iter.current(), use_set, candidates);
00030 }
00031 }
00032
00033 PropConstValue::PropConstValue(const Expression &expr, const Statement &stmt,
00034 int stmt_toporder,
00035 const Map<Symbol,IntElem> &candidates)
00036 {
00037 _expr = expr.clone();
00038 _stmt = &stmt;
00039 _toporder = stmt_toporder;
00040
00041 _collect_uses(expr, _use_set, candidates);
00042 }
00043
00044 PropConstValue::PropConstValue(const PropConstValue &other)
00045 {
00046 _expr = other.expr().clone();
00047 _stmt = other._stmt;
00048 _toporder = other._toporder;
00049 _use_set = other._use_set;
00050 }
00051
00052 PropConstValue::~PropConstValue()
00053 {
00054 delete _expr;
00055 }
00056
00057 Listable *
00058 PropConstValue::listable_clone() const
00059 {
00060 return new PropConstValue(*this);
00061 }
00062
00063 void
00064 PropConstValue::print(ostream &o) const
00065 {
00066 o << "[expr=" << *_expr;
00067 o << ", stmt=" << _stmt->tag();
00068 o << ", toporder=" << _toporder;
00069 o << ", use_set=" << _use_set;
00070 o << "]";
00071 }
00072
00073 int
00074 PropConstValue::structures_OK() const
00075 {
00076 return (_expr->structures_OK()
00077 && _stmt->structures_OK()
00078 && _use_set.structures_OK());
00079 }
00080
00081
00082
00083 PropConstElem::PropConstElem()
00084 {
00085 _last_mod = 0;
00086 _const_val = 0;
00087 }
00088
00089 PropConstElem::PropConstElem(const PropConstElem &other)
00090 {
00091 *this = other;
00092 }
00093
00094 PropConstElem::~PropConstElem()
00095 {
00096
00097 }
00098
00099 const Expression &
00100 PropConstElem::expr() const
00101 {
00102 p_assert(_const_val, "Variable is not constant.");
00103 return _const_val->expr();
00104 }
00105
00106 const IntSet &
00107 PropConstElem::use_set() const
00108 {
00109 p_assert(_const_val, "Variable is not constant.");
00110 return _const_val->use_set();
00111 }
00112
00113 const PropConstValue &
00114 PropConstElem::const_val() const
00115 {
00116 p_assert(_const_val, "Variable is not constant.");
00117 return *_const_val;
00118 }
00119
00120 void
00121 PropConstElem::constant(const PropConstValue &const_val)
00122 {
00123 p_assert(state() == MAY_BE_CONST,
00124 "Can only change MAY_BE_CONST objects into CONST objects.");
00125 _last_mod = &const_val.stmt();
00126 _const_val = &const_val;
00127 }
00128
00129 void
00130 PropConstElem::non_const(const Statement &stmt)
00131 {
00132 _last_mod = &stmt;
00133 _const_val = 0;
00134 }
00135
00136 void
00137 PropConstElem::intersect(const PropConstElem &other,
00138 const Statement &curr_stmt)
00139 {
00140 CONST_STATE my_state = state();
00141 CONST_STATE other_state = other.state();
00142
00143 if (my_state == MAY_BE_CONST)
00144 *this = other;
00145 else if (other_state == MAY_BE_CONST)
00146 ;
00147 else if (my_state == NON_CONST || other_state == NON_CONST)
00148 non_const(*_last_mod);
00149 else if (my_state == CONST && other_state == CONST) {
00150
00151
00152 if (! _const_equal(other))
00153 non_const(curr_stmt);
00154 else if (_const_val->stmt_toporder() > other._const_val->stmt_toporder())
00155 _const_val = other._const_val;
00156 }
00157 else
00158 p_abort("Internal Error: PropConstElem has a bad state.");
00159
00160 if (_last_mod != other._last_mod)
00161 _last_mod = &curr_stmt;
00162 }
00163
00164 Boolean
00165 PropConstElem::_const_equal(const PropConstElem &other) const
00166 {
00167
00168
00169 return (! _const_val
00170 || ! other._const_val
00171 || _const_val == other._const_val
00172 || ((CASTAWAY(Expression &) expr())
00173 == (CASTAWAY(Expression &) other.expr())));
00174 }
00175
00176 int
00177 PropConstElem::operator == (const PropConstElem &other) const
00178 {
00179 return (state() == other.state()
00180 && _const_equal(other)
00181 && _last_mod == other._last_mod);
00182 }
00183
00184 PropConstElem &
00185 PropConstElem::operator = (const PropConstElem &other)
00186 {
00187 _last_mod = other._last_mod;
00188 _const_val = other._const_val;
00189 return *this;
00190 }
00191
00192 ostream &
00193 operator << (ostream &o, const PropConstElem &pcc)
00194 {
00195 pcc.print(o);
00196 return o;
00197 }
00198
00199 void
00200 PropConstElem::print(ostream &o) const
00201 {
00202 o << "<";
00203
00204 switch (state()) {
00205 case MAY_BE_CONST:
00206 o << "undef";
00207 break;
00208
00209 case CONST:
00210 o << _last_mod->tag() << ":" << expr();
00211 break;
00212
00213 case NON_CONST:
00214 o << _last_mod->tag() << ":?";
00215 break;
00216
00217 default:
00218 o << "error";
00219 break;
00220 }
00221
00222 o << ">";
00223 }
00224
00225 int
00226 PropConstElem::structures_OK() const
00227 {
00228 if (! _last_mod && _const_val) {
00229 cerr << "\n\nError: PropConstElem:structures_OK: Is in an invalid state.\n";
00230 return 0;
00231 }
00232
00233 return 1;
00234 }
00235
00236
00237
00238 PropConstIntMap::PropConstIntMap(int num_consts,
00239 const Array<Symbol *> &tag_to_candidate)
00240 : _const_map(num_consts), _const_elems(num_consts), _undefined_elems(num_consts)
00241 {
00242 _tag_to_candidate = &tag_to_candidate;
00243
00244 for (int i = 0; i < num_consts; ++i) {
00245 _undefined_elems.ins(i);
00246 _const_map[i] = -9999;
00247 }
00248 }
00249
00250 PropConstIntMap::PropConstIntMap(const PropConstIntMap &other)
00251 : _const_map(other._const_map), _const_elems(other._const_elems),
00252 _undefined_elems(other._undefined_elems)
00253 {
00254 _tag_to_candidate = other._tag_to_candidate;
00255 }
00256
00257 PropConstIntMap::~PropConstIntMap()
00258 {
00259 }
00260
00261 CONST_STATE
00262 PropConstIntMap::state(int sym_tag) const
00263 {
00264 if (_const_elems[sym_tag])
00265 return CONST;
00266 else if (_undefined_elems[sym_tag])
00267 return MAY_BE_CONST;
00268 else
00269 return NON_CONST;
00270 }
00271
00272 void
00273 PropConstIntMap::constant(int sym_tag, int const_val)
00274 {
00275 _const_elems.ins(sym_tag);
00276 _undefined_elems.del(sym_tag);
00277 _const_map[sym_tag] = const_val;
00278 }
00279
00280 void
00281 PropConstIntMap::non_const(int sym_tag)
00282 {
00283 _const_elems.del(sym_tag);
00284 _undefined_elems.del(sym_tag);
00285 _const_map[sym_tag] = -9999;
00286 }
00287
00288 int
00289 PropConstIntMap::int_const_val(int sym_tag) const
00290 {
00291 p_assert(_const_elems[sym_tag], "Variable is not a constant.");
00292
00293 return _const_map[sym_tag];
00294 }
00295
00296 void
00297 PropConstIntMap::all_non_const()
00298 {
00299 _const_elems.clear();
00300 _undefined_elems.clear();
00301
00302 for (int i = 0; i < _const_map.entries(); ++i)
00303 _const_map[i] = -9999;
00304 }
00305
00306 void
00307 PropConstIntMap::intersect(const PropConstIntMap &other)
00308 {
00309 for (int sym_tag = 0; sym_tag < _const_map.entries(); ++sym_tag) {
00310 if (other._undefined_elems[sym_tag])
00311 ;
00312 else if (_undefined_elems[sym_tag]) {
00313 if (other._const_elems[sym_tag])
00314 constant(sym_tag, other._const_map[sym_tag]);
00315 else
00316 non_const(sym_tag);
00317 }
00318 else if (! _const_elems[sym_tag])
00319 ;
00320 else if (! other._const_elems[sym_tag]
00321 || _const_map[sym_tag] != other._const_map[sym_tag])
00322 non_const(sym_tag);
00323 }
00324 }
00325
00326 PropConstIntMap &
00327 PropConstIntMap::operator = (const PropConstIntMap &other)
00328 {
00329 if (this != &other) {
00330 _const_map = other._const_map;
00331 _const_elems = other._const_elems;
00332 _undefined_elems = other._undefined_elems;
00333 _tag_to_candidate = other._tag_to_candidate;
00334 }
00335 return *this;
00336 }
00337
00338 int
00339 PropConstIntMap::operator == (const PropConstIntMap &other) const
00340 {
00341 if (_const_map.entries() != other._const_map.entries()
00342 || _const_elems != other._const_elems
00343 || _undefined_elems != other._undefined_elems)
00344
00345 return 0;
00346
00347 for (int sym_tag = _const_elems.first();
00348 sym_tag != -1;
00349 sym_tag = _const_elems.next(sym_tag))
00350 if (_const_map[sym_tag] != other._const_map[sym_tag])
00351 return 0;
00352
00353 return 1;
00354 }
00355
00356 ostream &
00357 operator << (ostream &o, const PropConstIntMap &pcm)
00358 {
00359 pcm.print(o);
00360 return o;
00361 }
00362
00363 void
00364 PropConstIntMap::print(ostream &o) const
00365 {
00366 o << "[_const_map=";
00367 _const_map.print(o);
00368 o << ", _const_elems=";
00369 _const_elems.print(o);
00370 o << ", _undefined_elems=";
00371 _undefined_elems.print(o);
00372 o << "]";
00373 }
00374
00375 void
00376 PropConstIntMap::pretty_print(ostream &o) const
00377 {
00378 const int max_elems = 6;
00379
00380 int elems_on_line = max_elems;
00381
00382 for (int sym_tag = 0; sym_tag < _const_map.entries(); sym_tag++) {
00383 if (++elems_on_line >= max_elems) {
00384 o << "\n ";
00385 elems_on_line = 0;
00386 }
00387
00388 o << (*_tag_to_candidate)[sym_tag]->name_ref() << ":";
00389
00390 switch (state(sym_tag)) {
00391 case MAY_BE_CONST:
00392 o << "undef";
00393 break;
00394
00395 case CONST:
00396 o << _const_map[sym_tag];
00397 break;
00398
00399 case NON_CONST:
00400 o << "?";
00401 break;
00402
00403 default:
00404 o << "error";
00405 break;
00406 }
00407
00408 o << ", ";
00409 }
00410 }
00411
00412 int
00413 PropConstIntMap::structures_OK() const
00414 {
00415 if (! _const_map.structures_OK()
00416 || ! _const_elems.structures_OK()
00417 || ! _undefined_elems.structures_OK())
00418 return 0;
00419
00420 IntSet inter_elems = _const_elems & _undefined_elems;
00421
00422 if (inter_elems.entries()) {
00423 cerr << "PropConstIntMap::structures_OK() found a variable marked as\n";
00424 cerr << "constant and undefined.";
00425
00426 return 0;
00427 }
00428
00429 return 1;
00430 }
00431
00432
00433
00434 PropConstMap::PropConstMap(int num_consts,
00435 const Array<Symbol *> &tag_to_candidate)
00436 : _const_map(num_consts), _int_const_map(num_consts, tag_to_candidate)
00437 {
00438 _tag_to_candidate = &tag_to_candidate;
00439 }
00440
00441 PropConstMap::PropConstMap(const PropConstMap &other)
00442 : _const_map(other._const_map), _int_const_map(other._int_const_map)
00443 {
00444 _tag_to_candidate = other._tag_to_candidate;
00445 }
00446
00447 PropConstMap::~PropConstMap()
00448 {
00449
00450 }
00451
00452 void
00453 PropConstMap::all_non_const(const Statement &stmt)
00454 {
00455 _int_const_map.all_non_const();
00456
00457 for (int sym_tag = 0; sym_tag < _const_map.entries(); ++sym_tag)
00458 _const_map[sym_tag].non_const(stmt);
00459 }
00460
00461 void
00462 PropConstMap::intersect(const PropConstMap &other, const Statement &stmt)
00463 {
00464 _int_const_map.intersect(other._int_const_map);
00465
00466 for (int sym_tag = 0; sym_tag < _const_map.entries(); ++sym_tag)
00467 _const_map[sym_tag].intersect(other._const_map[sym_tag], stmt);
00468 }
00469
00470 PropConstMap &
00471 PropConstMap::operator = (const PropConstMap &other)
00472 {
00473 if (this != &other) {
00474 _int_const_map = other._int_const_map;
00475 _const_map = other._const_map;
00476 _tag_to_candidate = other._tag_to_candidate;
00477 }
00478 return *this;
00479 }
00480
00481 int
00482 PropConstMap::operator == (const PropConstMap &other) const
00483 {
00484 if (_int_const_map != other._int_const_map)
00485 return 0;
00486
00487 if (_const_map.entries() != other._const_map.entries())
00488 return 0;
00489
00490 for (int sym_tag = 0; sym_tag < _const_map.entries(); ++sym_tag)
00491 if (_const_map[sym_tag] != other._const_map[sym_tag])
00492 return 0;
00493
00494 return 1;
00495 }
00496
00497 ostream &
00498 operator << (ostream &o, const PropConstMap &pcm)
00499 {
00500 pcm.print(o);
00501 return o;
00502 }
00503
00504 void
00505 PropConstMap::print(ostream &o) const
00506 {
00507 o << "[int_const_map=";
00508 _int_const_map.print(o);
00509 o << ", const_map=";
00510 _const_map.print(o);
00511 o << "]";
00512 }
00513
00514 void
00515 PropConstMap::pretty_print(ostream &o) const
00516 {
00517 _int_const_map.pretty_print(o);
00518
00519 const int max_elems = 4;
00520
00521 int elems_on_line = max_elems;
00522
00523 for (int sym_tag = 0; sym_tag < _const_map.entries(); sym_tag++) {
00524 if (++elems_on_line >= max_elems) {
00525 o << "\n ";
00526 elems_on_line = 0;
00527 }
00528
00529 o << (*_tag_to_candidate)[sym_tag]->name_ref() << ":"
00530 << _const_map[sym_tag] << ", ";
00531 }
00532 }
00533
00534 int
00535 PropConstMap::structures_OK() const
00536 {
00537 if (! _int_const_map.structures_OK() || ! _const_map.structures_OK())
00538 return 0;
00539
00540 for (int sym_tag = 0; sym_tag < _const_map.entries(); sym_tag++)
00541 if (! _const_map[sym_tag].structures_OK())
00542 return 0;
00543
00544 return 1;
00545 }
00546