00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include "c_breeze.h"
00039 #include "path.h"
00040
00041
00042
00043
00044
00045 const Path * Path::Always = new Path();
00046
00047 Path::Path(PathDB * db, const Path * parent,
00048 procNode * proc)
00049 : Location(proc, 0, 0),
00050 _parent(0),
00051 _depth(0),
00052
00053 _dominates_exit(false),
00054 _db(0)
00055 {
00056 if (parent) {
00057 _parent = db->intern(parent);
00058 _depth = 1 + _parent->depth();
00059
00060 }
00061 }
00062
00063 Path::Path(PathDB * db, const Path * parent,
00064 procNode * proc, basicblockNode * block)
00065 : Location(proc, block, 0),
00066 _parent(0),
00067 _depth(0),
00068
00069 _dominates_exit(false),
00070 _db(0)
00071 {
00072 if (parent) {
00073 _parent = db->intern(parent);
00074 _depth = 1 + _parent->depth();
00075
00076 }
00077 }
00078
00079 Path::Path(PathDB * db, const Path * parent,
00080 const Location & loc)
00081 : Location(loc),
00082 _parent(0),
00083 _depth(0),
00084
00085 _dominates_exit(false),
00086 _db(0)
00087 {
00088 if (parent) {
00089 _parent = db->intern(parent);
00090 _depth = 1 + _parent->depth();
00091
00092 }
00093 }
00094
00095
00096
00097 Path::Path(const Path & other)
00098 : Location(other),
00099 _parent(other._parent),
00100 _depth(other._depth),
00101
00102 _dominates_exit(false),
00103 _db(0)
00104 {
00105
00106
00107 }
00108
00109
00110
00111 Path::Path()
00112 : Location(0, 0, 0),
00113 _parent(0),
00114 _depth(0),
00115
00116 _dominates_exit(false),
00117 _db(0)
00118 {}
00119
00120
00121
00122 Path::~Path()
00123 {
00124 if (_db)
00125 cerr << "ERROR: Attempted to delete a recorded path:" << *this << endl;
00126
00127
00128
00129
00130
00131
00132 }
00133
00134
00135
00136 bool Path::is_recursive() const
00137 {
00138 if (is_always())
00139 return false;
00140
00141 procNode * cur = proc();
00142 const Path * par = parent();
00143
00144 while (par) {
00145 if (par->proc() == cur)
00146 return true;
00147 par = par->parent();
00148 }
00149
00150 return false;
00151 }
00152
00153 bool Path::is_proc_present(procNode * cur_proc) const
00154 {
00155 if (is_always())
00156 return false;
00157
00158 const Path * par = this;
00159
00160 while (par) {
00161 if (par->proc() == cur_proc)
00162 return true;
00163 par = par->parent();
00164 }
00165
00166 return false;
00167 }
00168
00169
00170
00171
00172
00173
00174 PathDB::PathDB()
00175 : _paths()
00176 {}
00177
00178
00179
00180
00181 class Equal_path
00182 {
00183 public:
00184 const Path * _path_to_look_for;
00185
00186 Equal_path(const Path * path_to_look_for)
00187 : _path_to_look_for(path_to_look_for)
00188 {}
00189
00190 bool operator()(const pair<const Path * const, const Path *> & entry) {
00191 const Path * cur = entry.second;
00192 if (cur == _path_to_look_for)
00193 return true;
00194
00195 return Location::equals(*cur, *_path_to_look_for);
00196 }
00197 };
00198
00199
00200
00201
00202 const Path * PathDB::lookup(const Path * con)
00203 {
00204 if (con) {
00205
00206 if (con->is_always())
00207 return con;
00208
00209
00210
00211 const Path * parent = con->parent();
00212
00213
00214
00215 pair<path_map_cp, path_map_cp> range = _paths.equal_range(parent);
00216
00217
00218
00219 path_map_cp p = find_if(range.first, range.second, Equal_path(con));
00220
00221 if ((p != _paths.end()) &&
00222 (p != range.second))
00223 return (*p).second;
00224 }
00225
00226 return 0;
00227 }
00228
00229
00230
00231
00232 const Path * PathDB::intern(const Path * con)
00233 {
00234 if (con) {
00235
00236 const Path * orig = lookup(con);
00237
00238 if (orig)
00239 return orig;
00240 else {
00241
00242
00243
00244 bool dom_exit;
00245 if ( ! con->is_always())
00246 dom_exit = Location::strictly_dominates(*con,
00247 Location::exit(*con));
00248 else
00249 dom_exit = true;
00250
00251 Path * new_intern = new Path(*con);
00252 new_intern->_dominates_exit = dom_exit;
00253 new_intern->_db = this;
00254
00255
00256
00257 path_map_pair entry(con->parent(), new_intern);
00258 _paths.insert(entry);
00259
00260 return new_intern;
00261 }
00262 }
00263 else
00264 cout << "ERROR: Interning a null path" << endl;
00265
00266 return 0;
00267 }
00268
00269 bool PathDB::equals(const Path * one, const Path * two)
00270 {
00271 if (one == two)
00272 return true;
00273
00274 if ( ! (one && two))
00275 return false;
00276
00277 if (Location::equals(*one, *two))
00278 return (one->parent() == two->parent());
00279
00280 return false;
00281 }
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315 bool PathDB::dominates(const Path * dom, const Path * cur)
00316 {
00317 if (equals(dom, cur))
00318 return true;
00319
00320 return strictly_dominates(dom, cur);
00321 }
00322
00323 bool PathDB::strictly_dominates(const Path * dom, const Path * cur)
00324 {
00325
00326
00327
00328
00329 if (equals(dom, cur))
00330 return false;
00331
00332
00333
00334 if (dom->is_always())
00335 return true;
00336
00337 int depth_dom = dom->depth();
00338 int depth_cur = cur->depth();
00339 int min_depth = (depth_dom < depth_cur) ? depth_dom : depth_cur;
00340 int tmp;
00341
00342 const Path * dom_p = dom;
00343 const Path * cur_p = cur;
00344
00345
00346
00347 bool dom_exit = true;
00348
00349 while (dom_p && (dom_p->depth() > min_depth)) {
00350 dom_exit = dom_exit && dom_p->dominates_exit();
00351 dom_p = dom_p->parent();
00352 }
00353
00354
00355
00356 while (cur_p && (cur_p->depth() > min_depth))
00357 cur_p = cur_p->parent();
00358
00359
00360
00361
00362
00363
00364 if (equals(dom_p, cur_p))
00365 return (depth_dom > depth_cur);
00366
00367
00368
00369 while (dom_p && cur_p &&
00370 (! equals(dom_p->parent(), cur_p->parent()))) {
00371 dom_exit = dom_exit && dom_p->dominates_exit();
00372 dom_p = dom_p->parent();
00373 cur_p = cur_p->parent();
00374 }
00375
00376
00377
00378 if (dom_p && cur_p) {
00379 bool res = (Location::strictly_dominates( *dom_p, *cur_p ) && dom_exit);
00380 return res;
00381 }
00382
00383
00384
00385 cerr << "ERROR: Cannot determine path dominance." << endl;
00386 return false;
00387 }
00388
00389
00390
00391 void PathDB::stats()
00392 {
00393 cout << "CLASS: PathDB" << endl;
00394 cout << " Total number of path nodes: " << _paths.size() << endl;
00395 cout << " Total memory used (bytes): " <<
00396 _paths.size() * (sizeof(path_map::value_type) + sizeof(Path)) << endl;
00397 }
00398
00399 void PathDB::print(ostream & o) const
00400 {
00401 for (path_map_cp p = _paths.begin();
00402 p != _paths.end();
00403 ++p)
00404 {
00405 const Path * cur = (*p).second;
00406 cur->print_shallow(o);
00407 o << " in ";
00408 cur->parent()->print_shallow(o);
00409 o << endl;
00410 }
00411 }
00412