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 "memorymodel.h"
00040 #include "memoryblock.h"
00041 #include "unification.h"
00042
00043
00044
00045
00046
00047
00048
00049 int memoryBlock::memoryblock_count = 0;
00050
00051
00052
00053
00054 memoryBlock::memoryBlock(declNode * decl, bool synthetic,
00055 memoryBlock * container,
00056 procNode * local_to)
00057 : _container(container),
00058 Defs(),
00059 Uses(),
00060 _parameter_assignments(),
00061 _current_use(0),
00062 _current_def(0),
00063 _components(),
00064 _decl(decl),
00065 _synthetic_decl(synthetic),
00066 _write_protected(false),
00067 _is_array(false),
00068 _is_array_element(false),
00069 _is_indexed(false),
00070 _is_allocation_object(false),
00071 _flow_sensitive(true),
00072 _unify(false),
00073 _unifytype(0),
00074 _single_assignment(true),
00075 _is_return_value(false),
00076 _local_to(local_to),
00077
00078 _allocation_site(0),
00079
00080 _allocation_object(0),
00081
00082
00083 _input_to(),
00084 _destructive_assignments(),
00085 _complicit_assignments(),
00086 property(0),
00087 property_blocks()
00088 {
00089
00090
00091
00092
00093 if (container) {
00094 if (container->is_indexed())
00095 set_indexed();
00096
00097 if (container->is_heap_object())
00098 set_heap_object(container->allocation_site());
00099
00100 if (container->is_return_value())
00101 set_return_value();
00102 }
00103
00104 memoryblock_count++;
00105 }
00106
00107 memoryBlock::~memoryBlock()
00108 {
00109 if (_synthetic_decl && ! is_heap_object())
00110 delete _decl;
00111
00112 clear();
00113
00114 memoryblock_count--;
00115
00116 if(unifyType()) unifyType()->block(NULL);
00117 }
00118
00119 void memoryBlock::clear()
00120 {
00121 if (is_array() && _current_def) {
00122
00123
00124 bool ok_delete = true;
00125 if(unifyType()) {
00126 const memorydef_list & defs = Defs.def_list();
00127 for(memorydef_list_cp d=defs.begin(); d!=defs.end(); d++)
00128 if(d->def == _current_def)
00129 { ok_delete = false; break; }
00130 }
00131
00132 if(ok_delete)
00133 delete _current_def;
00134 }
00135
00136 Defs.clear();
00137 Uses.clear();
00138
00139
00140
00141
00142
00143
00144
00145
00146 }
00147
00148 void memoryBlock::stats()
00149 {
00150 cout << " memoryBlock : " << memoryblock_count << " objects x "
00151 << sizeof(memoryBlock) << " bytes = " << memoryblock_count * sizeof(memoryBlock)
00152 << " bytes. " << endl;
00153
00154 FieldNames.stats();
00155 }
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167 memoryDef * memoryBlock::def_at(Location * where, bool & is_new)
00168 {
00169
00170
00171
00172
00173
00174 if (write_protected())
00175 assert(0);
00176
00177 if (memoryAccess::Verbose)
00178 cout << "memoryBlock::def_at " << name() << endl;
00179
00180 if ( ! is_array()) {
00181
00182
00183
00184 if (is_flow_sensitive()) {
00185
00186
00187
00188 _current_def = Defs.make_def_at(where, this, is_new);
00189 }
00190 else {
00191
00192
00193
00194 if ( ! _current_def)
00195 _current_def = Defs.make_def_at(where, this, is_new);
00196 else
00197 is_new = false;
00198 }
00199
00200
00201
00202
00203 Location * cur_where = _current_def->where();
00204
00205 if (_single_assignment) {
00206 if (cur_where->kind() != where->kind())
00207 _single_assignment = false;
00208 else {
00209 if (where->kind() == Location::Statement) {
00210 stmtLocation * one = (stmtLocation *) cur_where;
00211 stmtLocation * two = (stmtLocation *) where;
00212
00213 if (one->stmt() != two->stmt())
00214 _single_assignment = false;
00215 }
00216 if (where->kind() == Location::Procedure) {
00217 procLocation * one = (procLocation *) cur_where;
00218 procLocation * two = (procLocation *) where;
00219
00220 if (one->proc() != two->proc())
00221 _single_assignment = false;
00222 }
00223 if (where->kind() == Location::BasicBlock)
00224 _single_assignment = false;
00225 }
00226 }
00227 }
00228 else {
00229
00230
00231
00232 setup_array_def();
00233 is_new = false;
00234 }
00235
00236
00237
00238 if (_write_protected)
00239 cout << "WARNING: Def of write-protected object \"" << name() << "\"" << endl;
00240
00241
00242
00243
00244 return _current_def;
00245 }
00246
00247
00248
00249
00250
00251 memoryDef * memoryBlock::nearest_def_at(Location * where)
00252 {
00253 memoryDef * def = 0;
00254
00255 if ( ! is_array()) {
00256
00257
00258
00259 if (is_flow_sensitive()) {
00260
00261
00262
00263 def = Defs.find_strictly_dominating_def(where);
00264 }
00265 else {
00266
00267
00268
00269 bool is_new;
00270 if ( ! _current_def)
00271 _current_def = Defs.make_def_at(procLocation::main(), this, is_new);
00272
00273 def = _current_def;
00274 }
00275 }
00276 else
00277 def = setup_array_def();
00278
00279
00280
00281 return def;
00282 }
00283
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
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333 memoryUse * memoryBlock::use_at(Location * where)
00334 {
00335 if (memoryAccess::Verbose)
00336 cout << "memoryBlock::use_at " << name() << endl;
00337
00338
00339
00340
00341
00342 if (is_flow_sensitive()) {
00343
00344
00345
00346 _current_use = Uses.make_use_at(where, this);
00347 }
00348 else {
00349
00350
00351
00352 if ( ! _current_use)
00353 _current_use = Uses.make_use_at(procLocation::main()->last(), this);
00354 }
00355
00356
00357
00358
00359 if (is_array())
00360 memoryDef * def = setup_array_def();
00361
00362 return _current_use;
00363 }
00364
00365 memoryDef * memoryBlock::last_def_at(basicblockLocation * block)
00366 {
00367 memoryDef * def = 0;
00368
00369 if (! is_array()) {
00370
00371
00372
00373 if (is_flow_sensitive()) {
00374
00375
00376
00377 stmtLocation * last = block->last();
00378
00379 def = Defs.find_dominating_def(last);
00380 }
00381 else {
00382
00383
00384
00385 bool is_new;
00386 if ( ! _current_def)
00387 _current_def = Defs.make_def_at(procLocation::main(), this, is_new);
00388
00389 def = _current_def;
00390 }
00391 }
00392 else
00393 def = setup_array_def();
00394
00395 return def;
00396 }
00397
00398 memoryDef * memoryBlock::find_def_at(Location * where)
00399 {
00400 if ( ! is_array()) {
00401
00402
00403
00404 if (is_flow_sensitive()) {
00405
00406
00407
00408 return Defs.find_def(where);
00409 }
00410 else {
00411
00412
00413
00414 return _current_def;
00415 }
00416 }
00417 else
00418 return setup_array_def();
00419 }
00420
00426 memoryUse * memoryBlock::find_use_at(Location * where)
00427 {
00428
00429
00430 if (is_flow_sensitive()) {
00431
00432
00433
00434 return Uses.find_use(where);
00435 }
00436 else {
00437
00438
00439
00440 return _current_use;
00441 }
00442 }
00443
00444
00449 void memoryBlock::find_uses_at(Location * where, memoryuse_set & uses)
00450 {
00451 Uses.find_uses_at(where, uses);
00452 }
00453
00460 void memoryBlock::add_parameter_assignment(procNode * proc, stmtLocation * callsite,
00461 memoryBlock * block)
00462 {
00463 memoryblock_set temp;
00464 temp.insert(block);
00465
00466 _parameter_assignments[proc][callsite] = temp;
00467 }
00468
00475 void memoryBlock::add_parameter_assignment(procNode * proc, stmtLocation * callsite,
00476 memoryblock_set & blocks)
00477 {
00478 _parameter_assignments[proc][callsite] = blocks;
00479 }
00480
00481 void memoryBlock::apply_weak_update(Location * current,
00482 memoryDef * previous_def,
00483 memoryuse_set & uses)
00484 {
00485
00486
00487 memoryDef * block_def = current_def();
00488
00489
00490
00491 block_def->set_weak(true);
00492
00493
00494
00495 if (previous_def)
00496 block_def->add_pointers(previous_def->points_to());
00497
00498
00499
00500
00501
00502 memoryUse * weak_use = use_at(current);
00503
00504 uses.insert(weak_use);
00505
00506 weak_use->reaching_def(previous_def);
00507 weak_use->set_weak(true);
00508 }
00509
00510 static unsigned long int preds_size_histogram[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
00511 static unsigned long int preds_size_count = 0;
00512
00513
00514
00515
00516 void memoryBlock::setup_merge_uses_at(basicblockLocation * merge_location,
00517 memoryDef * reaching_def,
00518 basicblock_set & predecessors)
00519 {
00520
00521
00522
00533
00534
00535 basicblockNode * basicblock = merge_location->block();
00536
00537
00538
00539
00540 const pred_use_map & pred_uses = Uses.make_merge_uses_at(merge_location, this);
00541
00542 for (basicblock_set_p p = predecessors.begin();
00543 p != predecessors.end();
00544 ++p)
00545 {
00546 basicblockNode * predecessor = *p;
00547
00548
00549
00550
00551 pred_use_map_cp cp = pred_uses.find(predecessor);
00552 memoryUse * use = (*cp).second;
00553
00554
00555
00556
00557 memoryDef * old_def = use->reaching_def();
00558 if (( ! old_def) ||
00559 (old_def && Location::strictly_dominates(old_def->where(), reaching_def->where()))) {
00560
00561 use->reaching_def(reaching_def);
00562 use->search_for_def(false);
00563 }
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582 }
00583 }
00584
00585
00586
00587
00588
00589
00590
00591 void memoryBlock::merge_uses_at(basicblockLocation * where,
00592 memoryuse_list & uses,
00593 cfg_edge_set & active_edges,
00594 memoryDef * dominating_def,
00595 bool computePointers)
00596 {
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613 const pred_use_map & pred_uses = Uses.make_merge_uses_at(where, this);
00614
00615 basicblock_list & preds = where->block()->preds();
00616 const procLocation * proc_loc = where->proc_location();
00617
00618 int size = preds.size();
00619 if (size != pred_uses.size())
00620 cerr << "ERROR: Wrong number of uses in a merge node." << endl;
00621
00622 if (size < 2)
00623 cerr << "ERROR: Merge-point with only one predecessor." << endl;
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634 basicblockNode * basicblock = where->block();
00635
00636
00637
00638 if (computePointers) {
00639
00640
00641
00642
00643
00644
00645 int skipped = 0;
00646
00647 for (pred_use_map_cp cp = pred_uses.begin();
00648 cp != pred_uses.end();
00649 ++cp)
00650 {
00651 basicblockNode * predecessor = (*cp).first;
00652 memoryUse * use = (*cp).second;
00653
00654
00655
00656 if (pointerOptions::Conditional_analysis) {
00657
00658
00659
00660 cfg_edge_pair edge(predecessor, basicblock);
00661 if (active_edges.find(edge) == active_edges.end()) {
00662
00663
00664
00665
00666 use->set_inactive();
00667
00668 if (pointerOptions::Verbose)
00669 cout << "MERGE: skipping input of " << name() << " from inactive edge "
00670 << predecessor->dfn() << " -> " << basicblock->dfn() << endl;
00671 }
00672 else {
00673
00674
00675
00676 use->set_active();
00677
00678
00679
00680 if (use->search_for_def())
00681 use->reaching_def(dominating_def);
00682
00683
00684
00685 uses.push_back(use);
00686 }
00687 }
00688 else {
00689
00690
00691
00692
00693
00694
00695
00696 if (use->search_for_def())
00697 use->reaching_def(dominating_def);
00698
00699
00700
00701 uses.push_back(use);
00702 }
00703 }
00704 }
00705 else {
00706
00707
00708
00709
00710 for (pred_use_map_cp cp = pred_uses.begin();
00711 cp != pred_uses.end();
00712 ++cp)
00713 {
00714 memoryUse * use = (*cp).second;
00715 uses.push_back(use);
00716 }
00717 }
00718 }
00719
00720 void memoryBlock::reset_current_def_use(Location * unused)
00721 {
00722
00723
00724 if (is_flow_sensitive() &&
00725 ! is_array() && !unifyType() ) {
00726 _current_use = 0;
00727 _current_def = 0;
00728 }
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742 }
00743
00744 void memoryBlock::set_current_def_use(Location * where)
00745 {
00746 if ( ! is_array()) {
00747
00748
00749
00750 if (is_flow_sensitive()) {
00751
00752
00753
00754 _current_def = Defs.find_def(where);
00755 _current_use = Uses.find_use(where);
00756 }
00757 else {
00758
00759
00760
00761
00762
00763
00764 }
00765 }
00766 }
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776 void memoryBlock::dot(const string & field_name,
00777 declNode * field_decl,
00778 memoryModel & Memory,
00779 memoryblock_set & results)
00780 {
00781
00782
00783 memoryBlock * new_block = 0;
00784
00785
00786
00787 int field_num = FieldNames.get_field(field_name);
00788
00789
00790
00791 component_map_p p = _components.find(field_num);
00792
00793 if (p == _components.end()) {
00794
00795
00796 if(Memory.unification() && !is_unify() && decl() &&
00797 (decl()->decl_location()==declNode::PROC ||
00798 decl()->no_tdef_type() && decl()->no_tdef_type()->typ() == Func))
00799 return;
00800 if(name() == "load_actions_file" && field_name=="filename") {
00801 cout << Memory.unification() << " " << is_unify() << " " << this << endl;
00802 if(decl()) {
00803 cout << decl()->name() << " loc=" << decl()->decl_location();
00804 if(decl()->no_tdef_type()) cout << " " << decl()->no_tdef_type()->typ();
00805 cout << endl;
00806 }
00807 assert(false);
00808 }
00809
00810
00811
00812 new_block = Memory.generate_su_field(field_name, field_decl, this);
00813
00814
00815
00816 _components[field_num] = new_block;
00817
00818
00819
00820
00821 new_block->_local_to = _local_to;
00822
00823 results.insert(new_block);
00824 }
00825 else {
00826
00827
00828
00829 results.insert((*p).second);
00830 }
00831 }
00832
00833 void memoryBlock::set_array_element(memoryBlock * element)
00834 {
00835
00836
00837 _components[FieldNameDB::ArrayField] = element;
00838
00839
00840
00841 _is_array = true;
00842
00843
00844
00845
00846 element->_local_to = _local_to;
00847
00848
00849
00850 element->_container = this;
00851
00852
00853
00854 element->_is_array_element = true;
00855
00856
00857
00858 if(! unifyType())
00859 set_write_protected();
00860 }
00861
00862 memoryBlock * memoryBlock::get_array_element()
00863 {
00864
00865
00866 component_map_p p = _components.find(FieldNameDB::ArrayField);
00867 if (p != _components.end()) {
00868
00869
00870
00871 return (*p).second;
00872 }
00873 else
00874 return 0;
00875 }
00876
00877 memoryDef * memoryBlock::setup_array_def()
00878 {
00879
00880
00881 if ( ! _current_def) {
00882
00883
00884
00885 _current_def = new memoryDef(procLocation::main(), this);
00886
00887 memoryBlock * element = get_array_element();
00888 if ( element ) {
00889
00890 memoryblock_set temp;
00891
00892 temp.insert(element);
00893 _current_def->add_pointers(temp);
00894 }
00895 }
00896
00897
00898
00899
00900 return _current_def;
00901 }
00902
00903
00904
00905
00906
00907 void memoryBlock::reachable_blocks(Location * where,
00908 bool has_use_here,
00909 memoryblock_list & worklist,
00910 memoryblock_set & already_seen,
00911 memoryBlock * null)
00912 {
00913
00914
00915 memoryDef * def = 0;
00916
00917 if (has_use_here) {
00918
00919
00920
00921 memoryUse * use = find_use_at(where);
00922 if (use)
00923 def = use->reaching_def();
00924 }
00925 else {
00926
00927
00928
00929 def = nearest_def_at(where);
00930 }
00931
00932 if (def) {
00933
00934
00935
00936
00937 const memoryblock_set & pointers = def->points_to();
00938 for (memoryblock_set_cp p = pointers.begin();
00939 p != pointers.end();
00940 ++p)
00941 {
00942 memoryBlock * mb = *p;
00943 if ((mb != null) &&
00944 (already_seen.find(mb) == already_seen.end())) {
00945
00946
00947
00948 already_seen.insert(mb);
00949 worklist.push_back(mb);
00950 }
00951 }
00952 }
00953
00954
00955
00956 for (component_map_p p = _components.begin();
00957 p != _components.end();
00958 ++p)
00959 {
00960 memoryBlock * mb = (*p).second;
00961 if (already_seen.find(mb) == already_seen.end()) {
00962
00963
00964
00965 already_seen.insert(mb);
00966 worklist.push_back(mb);
00967 }
00968 }
00969 }
00970
00971
00972
00973
00974
00975 memoryBlock * memoryBlock::get_allocation_object(memoryModel & Memory)
00976 {
00977 memoryBlock * current = this;
00978
00979 if (pointerOptions::Verbose)
00980 cout << " + Get allocation object for " << name() << endl;
00981
00982
00983
00984 while (current->_container) {
00985 if(current == current->_container) break;
00986 current = current->_container;
00987 }
00988
00989 if (current->_allocation_object == 0) {
00990
00991
00992
00993 memoryBlock * alloc_object = Memory.generate_su_field(string("__alloc"),
00994 (declNode *)0, this);
00995
00996
00997
00998 alloc_object->_is_allocation_object = true;
00999
01000
01001
01002 if (current->is_unify()) {
01003 if(! alloc_object->is_unify()) {
01004 pointerOptions::Unify_objects++;
01005 alloc_object->set_unify(true);
01006 }
01007 alloc_object->set_flow_insensitive();
01008 } else if (current->is_flow_sensitive())
01009 alloc_object->set_flow_sensitive();
01010 else
01011 alloc_object->set_flow_sensitivity(pointerOptions::Flow_sensitive_allocation_objects);
01012
01013
01014
01015 current->_allocation_object = alloc_object;
01016
01017 if (pointerOptions::Verbose) {
01018 cout << " -> Not found: create " << alloc_object->name();
01019 if (alloc_object->is_flow_sensitive())
01020 cout << " (flow-sensitive)" << endl;
01021 else
01022 cout << " (not flow-sensitive)" << endl;
01023 }
01024 }
01025
01026 return current->_allocation_object;
01027 }
01028
01033 memoryBlock * memoryBlock::allocation_object()
01034 {
01035 memoryBlock * current = this;
01036
01037
01038
01039 while (current->_container) {
01040 if(current == current->_container) break;
01041 current = current->_container;
01042 }
01043
01044 return current->_allocation_object;
01045 }
01046
01047
01048 Multiplicity memoryBlock::at_allocation(Location * current,
01049 memoryDef * reaching_def,
01050 memoryblock_set & defs,
01051 memoryuse_set & uses,
01052 memoryblock_set & changes)
01053 {
01054 bool changed = false;
01055
01056
01057
01058 bool is_new;
01059 memoryDef * def = def_at(current, is_new);
01060
01061 #ifdef COLLECT_DEFS
01062 defs.insert(this);
01063 #endif
01064
01065
01066
01067
01068 if (is_new) {
01069 changes.insert(this);
01070 changed = true;
01071 }
01072
01073
01074
01075 Multiplicity reaching_multiplicity = Unallocated;
01076
01077 if (reaching_def)
01078 reaching_multiplicity = reaching_def->multiplicity();
01079
01080
01081
01082 memoryUse * use = use_at(current);
01083 use->reaching_def(reaching_def);
01084 uses.insert(use);
01085
01086
01087
01088 Multiplicity old_multiplicity = def->multiplicity();
01089
01090
01091
01092
01093 Multiplicity new_multiplicity;
01094
01095 switch (reaching_multiplicity) {
01096 case Unallocated:
01097 case Deallocated: new_multiplicity = Single;
01098 break;
01099 case Single: new_multiplicity = Unbounded;
01100 break;
01101 case Bounded: new_multiplicity = Bounded;
01102 break;
01103 case Unbounded: new_multiplicity = Unbounded;
01104 break;
01105 default: new_multiplicity = Error;
01106 break;
01107 }
01108
01109
01110
01111
01112 if ( ! is_flow_sensitive())
01113 new_multiplicity = Unbounded;
01114
01115
01116
01117
01118 if (old_multiplicity != new_multiplicity) {
01119
01120 def->set_multiplicity(new_multiplicity);
01121
01122 changes.insert(this);
01123 changed = true;
01124 }
01125
01126
01127
01128 if (pointerOptions::Verbose) {
01129 cout << " Allocate: " << _container->name() << " -- ";
01130
01131 print_multiplicity(reaching_multiplicity, cout);
01132 cout << " -> ";
01133 print_multiplicity(new_multiplicity, cout);
01134 cout << " -- ";
01135
01136 if (changed)
01137 cout << "changed";
01138 else
01139 cout << "unchanged";
01140
01141 cout << endl;
01142 }
01143
01144 return new_multiplicity;
01145 }
01146
01147 Multiplicity memoryBlock::at_deallocation(Location * current,
01148 memoryDef * reaching_def,
01149 memoryblock_set & defs,
01150 memoryuse_set & uses,
01151 memoryblock_set & changes)
01152 {
01153 bool changed;
01154
01155
01156
01157 bool is_new;
01158 memoryDef * def = def_at(current, is_new);
01159
01160 #ifdef COLLECT_DEFS
01161 defs.insert(this);
01162 #endif
01163
01164
01165
01166
01167 if (is_new) {
01168 changes.insert(this);
01169 changed = true;
01170 }
01171
01172
01173
01174 Multiplicity reaching_multiplicity = Unallocated;
01175
01176 if (reaching_def)
01177 reaching_multiplicity = reaching_def->multiplicity();
01178
01179
01180
01181 memoryUse * use = use_at(current);
01182 use->reaching_def(reaching_def);
01183 uses.insert(use);
01184
01185
01186
01187 Multiplicity old_multiplicity = def->multiplicity();
01188
01189
01190
01191
01192 Multiplicity new_multiplicity;
01193
01194 switch (reaching_multiplicity) {
01195 case Unallocated:
01196 case Deallocated: new_multiplicity = Unallocated;
01197 break;
01198 case Single: new_multiplicity = Deallocated;
01199 break;
01200 case Bounded: new_multiplicity = Bounded;
01201 break;
01202 case Unbounded: new_multiplicity = Unbounded;
01203 break;
01204 default: new_multiplicity = Error;
01205 break;
01206 }
01207
01208
01209
01210
01211 if ( ! is_flow_sensitive())
01212 new_multiplicity = Unbounded;
01213
01214
01215
01216
01217 if (old_multiplicity != new_multiplicity) {
01218
01219 def->set_multiplicity(new_multiplicity);
01220
01221 changes.insert(this);
01222 changed = true;
01223 }
01224
01225
01226
01227 if (pointerOptions::Verbose) {
01228 cout << " Deallocate: " << _container->name() << " -- ";
01229
01230 print_multiplicity(reaching_multiplicity, cout);
01231 cout << " -> ";
01232 print_multiplicity(new_multiplicity, cout);
01233 cout << " -- ";
01234
01235 if (changed)
01236 cout << "changed";
01237 else
01238 cout << "unchanged";
01239
01240 cout << endl;
01241 }
01242
01243 return new_multiplicity;
01244 }
01245
01246 void memoryBlock::print_multiplicity(Multiplicity m, ostream & out)
01247 {
01248 switch (m) {
01249 case Unallocated: out << "unallocated";
01250 break;
01251 case Deallocated: out << "deallocated";
01252 break;
01253 case Single: out << "single";
01254 break;
01255 case Bounded: out << "bounded";
01256 break;
01257 case Unbounded: out << "unbounded";
01258 break;
01259 case Error: out << "(error)";
01260 break;
01261 case Top: out << "(top)";
01262 break;
01263 default: out << "(unknown)";
01264 break;
01265 }
01266 }
01267
01268
01269
01270
01271
01277 void memoryBlock::add_destructive_assignment(Location * where, DestructiveKind cause)
01278 {
01279 _destructive_assignments[where] = cause;
01280
01281 if (pointerOptions::Verbose) {
01282 cout << " Monitor: add destructive assignment of " << name() << " at " << * where;
01283 switch (cause) {
01284 case Control_flow: cout << " -- control-flow merge " << endl;
01285 break;
01286 case Parameter_pass: cout << " -- parameter pass" << endl;
01287 break;
01288 case Weak_update: cout << " -- multiplicity weak update" << endl;
01289 break;
01290 case Additive: cout << " -- flow-insensitive assignment" << endl;
01291 break;
01292 default: cout << " -- ERROR unknown cause" << endl;
01293 break;
01294 }
01295 }
01296 }
01297
01303 void memoryBlock::add_complicit_assignment(Location * where, memoryblock_set & objects)
01304 {
01305 if ( ! objects.empty()) {
01306
01307 memoryblock_set & comps = _complicit_assignments[where];
01308
01309
01310
01311
01312 for (memoryblock_set_p p = objects.begin();
01313 p != objects.end();
01314 ++p)
01315 {
01316 memoryBlock * comp = *p;
01317
01318 if ( ! comp->write_protected())
01319 comps.insert(comp);
01320 }
01321
01322 if (pointerOptions::Verbose) {
01323 cout << " Monitor: add complicit assignment of " << name() << " at " << * where << endl;
01324 cout << " <= ";
01325 for (memoryblock_set_p p = objects.begin();
01326 p != objects.end();
01327 ++p)
01328 cout << (*p)->name() << " ";
01329 cout << endl;
01330 }
01331 }
01332 }
01333
01339 void memoryBlock::add_complicit_assignment(Location * where, memoryBlock * object)
01340 {
01341 _complicit_assignments[where].insert(object);
01342 }
01343
01352 void memoryBlock::add_to_flow_sensitive_list(flow_sensitive_set & flow_sensitive_objects)
01353 {
01354 stmtNode * the_stmt = 0;
01355 declNode * the_decl = 0;
01356 string field;
01357
01358 if (container())
01359 field = decl()->name();
01360
01361
01362
01363 if (is_heap_object())
01364 the_stmt = allocation_site()->stmt();
01365
01366
01367
01368 memoryBlock * cur = this;
01369 while (cur->container()) {
01370 if(cur == cur->container()) break;
01371 cur = cur->container();
01372 }
01373
01374
01375
01376 if ( ! cur->is_synthetic_decl())
01377 the_decl = cur->decl();
01378
01379
01380
01381 FSKey key(the_stmt, the_decl, field);
01382
01383
01384
01385 flow_sensitive_set_p found = find(flow_sensitive_objects.begin(),
01386 flow_sensitive_objects.end(),
01387 key);
01388
01389 if (found == flow_sensitive_objects.end()) {
01390 flow_sensitive_objects.push_back(key);
01391
01392
01393
01394
01395
01396
01397 }
01398
01399 if (pointerOptions::Verbose) {
01400
01401 if (found == flow_sensitive_objects.end())
01402 cout << "Adaptivity: Record block " << name() << " flow-sensitive -- key is "
01403 << "(" << the_stmt << "," << the_decl << "," << field << ")" << endl;
01404 }
01405 }
01406
01411 bool memoryBlock::is_in_flow_sensitive_list(flow_sensitive_set & flow_sensitive_objects)
01412 {
01413
01414
01415 stmtNode * the_stmt = 0;
01416 declNode * the_decl = 0;
01417 string field;
01418
01419
01420
01421 if (is_heap_object())
01422 the_stmt = allocation_site()->stmt();
01423
01424 if (container())
01425 field = decl()->name();
01426
01427
01428
01429 memoryBlock * cur = this;
01430 while (cur->container()) {
01431 if(cur == cur->container()) break;
01432 cur = cur->container();
01433 }
01434
01435
01436
01437 if ( ! cur->is_synthetic_decl())
01438 the_decl = cur->decl();
01439
01440
01441
01442 FSKey key(the_stmt, the_decl, field);
01443
01444
01445
01446 flow_sensitive_set_p found = find(flow_sensitive_objects.begin(),
01447 flow_sensitive_objects.end(),
01448 key);
01449
01450 if (pointerOptions::Verbose) {
01451
01452 if (found != flow_sensitive_objects.end()) {
01453 cout << "Adaptivity: Set block " << name();
01454
01455 if (found != flow_sensitive_objects.end())
01456 cout << " flow-sensitive ";
01457 else
01458 cout << " flow-insensitive ";
01459
01460 cout << "-- key is "
01461 << "(" << the_stmt << "," << the_decl << "," << field << ")" << endl;
01462 }
01463 }
01464
01465 return (found != flow_sensitive_objects.end());
01466 }
01467
01474 void memoryBlock::set_flow_sensitivity(flow_sensitive_set & flow_sensitive_objects)
01475 {
01476 if (pointerOptions::Flow_insensitive) {
01477
01478
01479
01480 if (is_in_flow_sensitive_list(flow_sensitive_objects)) {
01481
01482
01483
01484 set_flow_sensitive();
01485 }
01486 else {
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500 set_flow_insensitive();
01501 }
01502 }
01503 else {
01504
01505
01506
01507 set_flow_sensitive();
01508 }
01509 }
01510
01511
01513 void memoryBlock::add_to_non_unify_list(UnifyTypes & non_unify_types)
01514 {
01515 if (unifyType()) {
01516 non_unify_types.insert(unifyType());
01517
01518 if (pointerOptions::Verbose) {
01519 cout << "Adaptivity: Record block " << name() << " non-unify\n";
01520 }
01521 }
01522 }
01523
01528 void memoryBlock::set_unification(UnifyTypes & non_unify_types) {
01529 if (! pointerOptions::Unification) {
01530
01531
01532
01533 if (! unifyType() ||
01534 memoryModel::is_in_non_unify_list(non_unify_types, unifyType())) {
01535
01536
01537
01538 set_unify(false);
01539 _unifytype = NULL;
01540
01541 }
01542 else {
01543 if(! is_unify()) {
01544 pointerOptions::Unify_objects++;
01545 set_unify(true);
01546 }
01547 }
01548
01549 if (pointerOptions::Verbose) {
01550 cout << "Adaptivity: Set block " << name();
01551
01552 if (is_unify())
01553 cout << " as unified ";
01554 else
01555 cout << " as non-unified ";
01556 cout << endl;
01557 }
01558 }
01559 else {
01560
01561
01562
01563 if(! is_unify() && unifyType()) {
01564 set_unify(true);
01565 pointerOptions::Unify_objects++;
01566 }
01567 }
01568 }
01569
01570
01571
01572
01577 memoryBlock * memoryBlock::top_most_container()
01578 {
01579 memoryBlock * temp = this;
01580
01581 while (temp->_container) {
01582 if(pointerOptions::Unification && temp == temp->_container) break;
01583 temp = temp->_container;
01584 }
01585
01586 if(is_unify() && decl() && decl()->type()) {
01587
01588
01589 memoryblock_set tops = top_most_containers();
01590 if(tops.find(temp) == tops.end()) {
01591 cout << "this " << name();
01592 if(unifyType()) cout << " " << *unifyType();
01593 cout << "\ntemp " << name() << endl;
01594 cout << "tops: ";
01595 for(memoryblock_set_p t=tops.begin(); t!=tops.end(); t++)
01596 cout << (*t)->name() << " " << *(*t)->unifyType() << endl;
01597 }
01598 assert(tops.find(temp) != tops.end());
01599 }
01600 if(is_unify()) cout << name() << endl;
01601 assert(! is_unify());
01602 return temp;
01603 }
01604
01605 memoryblock_set memoryBlock::containers() const {
01606 memoryblock_set result;
01607 if(unifyType()) {
01608 set<Unify_ECR*> parents;
01609 switch(unifyType()->objTyp()) {
01610 case BOTTOM: break;
01611 case BLANK: parents = unifyType()->blank()->p.parents(); break;
01612 case SIMPLE: parents = unifyType()->simple()->p.parents(); break;
01613 case STRUCTURE: parents = unifyType()->structure()->p.parents(); break;
01614 case OBJECT: parents = unifyType()->object()->p.parents();
01615 }
01616 for(set<Unify_ECR*>::iterator p=parents.begin(); p!=parents.end(); p++)
01617 if((*p)->type()->block())
01618 result.insert((*p)->type()->block());
01619 }
01620 #define verify_container
01621 #ifdef verify_container
01622 if(container()) {
01623 if(result.find(container()) == result.end()) {
01624 cout << "this " << name() << endl;
01625 if(unifyType()) cout << *unifyType() << endl;
01626 cout << "container " << container()->name() << endl;
01627 if(container()->unifyType()) cout << *container()->unifyType() << endl;
01628 }
01629 assert(result.find(container()) != result.end());
01630 }
01631 #endif
01632 return result;
01633 }
01634
01635
01636 memoryblock_set memoryBlock::top_most_containers() {
01637 if(!unifyType()) {
01638 if(is_allocation_object() || property)
01639 return container()->top_most_containers();
01640 if(decl()->decl_location() == declNode::ENUM ||
01641 decl()->type() && decl()->type()->typ() == Func) {
01642 memoryblock_set r;
01643 r.insert(this);
01644 return r;
01645 }
01646 if(decl()->type() && decl()->no_tdef_type()->typ() == Ptr &&
01647 decl()->no_tdef_type()->no_tdef_type()->typ() == Func ||
01648 !decl()->type() ) {
01649 if(container()) return container()->top_most_containers();
01650 memoryblock_set r;
01651 r.insert(this);
01652 return r;
01653 }
01654 cout << this << " " << name() << endl;
01655 if(decl()) cout << decl()->name() << decl()->coord() << endl;
01656 if(local_to()) cout << "local_to " << local_to()->decl()->name() << endl;
01657 assert(false);
01658 }
01659 memoryblock_set visited;
01660 if(pointerOptions::Verbose)
01661 cout << "top_most_containers on " << name() << endl;
01662 return top_most_containers(visited);
01663 }
01664
01665
01666 memoryblock_set memoryBlock::top_most_containers(memoryblock_set &visited) {
01667 if(visited.find(this) != visited.end()) return memoryblock_set();
01668 visited.insert(this);
01669 if(pointerOptions::Verbose)
01670 cout << "top_most_containers (helper) on " << name() << endl;
01671 memoryblock_set parents = containers(),
01672 result;
01673 for(memoryblock_set_p p=parents.begin(); p!=parents.end(); p++) {
01674 memoryblock_set more = (*p)->top_most_containers(visited);
01675 result.insert(more.begin(), more.end());
01676 }
01677 if(parents.empty()) result.insert(this);
01678 else if(result.empty()) {
01679 if(parents.size() == 1 && *parents.begin() == this) result = parents;
01680
01681
01682
01683
01684
01685
01686
01687
01688
01689 }
01690 if(pointerOptions::Verbose)
01691 cout << "top_most_containers on " << name() <<" returns "<< result.size()<<endl;
01692 return result;
01693 }
01694
01695
01696
01697
01698
01703 void memoryBlock::def_uses(memoryDef * def,
01704 memoryuse_list & uses)
01705 {
01706 Uses.def_uses(def, uses);
01707 }
01708
01709
01710
01711
01712 void memoryBlock::update_def_use_chains()
01713 {
01714 Uses.update_def_use_chains();
01715 }
01716
01717
01718
01719
01720
01721 void memoryBlock::prune_defs_uses()
01722 {
01723 Defs.prune(Uses);
01724 }
01725
01726
01727
01728
01729
01730
01731
01732
01733
01734 bool memoryBlock::in_scope(basicblockLocation * where) const
01735 {
01736 if ( _local_to == 0)
01737 return true;
01738
01739 const procLocation * cur = where->proc_location();
01740 while (cur) {
01741 if (cur->proc() == _local_to)
01742 return true;
01743 cur = cur->parent_proc();
01744 }
01745
01746 return false;
01747 }
01748
01749
01750
01751
01752
01753
01754
01755 void memoryBlock::stats(ostream & out, bool header,
01756 long int & global_defs,
01757 long int & global_merge_defs,
01758 long int & global_weak_defs,
01759 long int & global_uses,
01760 long int & global_merge_uses)
01761 {
01762
01763 int total_defs;
01764 int merge_defs;
01765 int weak_defs;
01766 int total_uses;
01767 int merge_uses;
01768
01769 Defs.stats(total_defs, merge_defs, weak_defs);
01770 Uses.stats(total_uses, merge_uses);
01771
01772 global_defs += total_defs;
01773 global_merge_defs += merge_defs;
01774 global_weak_defs += weak_defs;
01775 global_uses += total_uses;
01776 global_merge_uses += merge_uses;
01777
01778 if (pointerOptions::Show_memoryblocks) {
01779
01780 out.width(35);
01781 if (header)
01782 out << "memoryBlock";
01783 else
01784 out << name();
01785
01786 out.width(6);
01787 if (header)
01788 out << "#defs";
01789 else
01790 out << total_defs;
01791
01792 out.width(7);
01793 if (header)
01794 out << "#merge";
01795 else
01796 out << merge_defs;
01797
01798 out.width(6);
01799 if (header)
01800 out << "#weak";
01801 else
01802 out << weak_defs;
01803
01804 out.width(6);
01805 if (header)
01806 out << "#uses";
01807 else
01808 out << total_uses;
01809
01810 out.width(7);
01811 if (header)
01812 out << "#merge";
01813 else
01814 out << merge_uses;
01815
01816 out.width(12);
01817 if (header)
01818 out << "local-to";
01819 else {
01820 if (_local_to)
01821 out << _local_to->decl()->name();
01822 else
01823 out << "(non-local)";
01824 }
01825
01826 out.width(6);
01827 if (header)
01828 out << "array";
01829 else {
01830 if (_is_array)
01831 out << "true";
01832 else
01833 out << "false";
01834 }
01835
01836 out.width(6);
01837 if (header)
01838 out << "index";
01839 else {
01840 if (_is_indexed)
01841 out << "true";
01842 else
01843 out << "false";
01844 }
01845
01846 out.width(6);
01847 if (header)
01848 out << "heap";
01849 else {
01850 if (is_heap_object())
01851 out << "true";
01852 else
01853 out << "false";
01854 }
01855
01856 out << endl;
01857 }
01858 }
01859
01860 void memoryBlock::print_def_use(ostream & o) const
01861 {
01862 o << "memoryBlock: " << name();
01863
01864 if ( ! _components.empty() ) {
01865 o << " {" << endl;
01866 for (component_map_cp p = _components.begin();
01867 p != _components.end();
01868 ++p)
01869 {
01870 o << " " << FieldNames.field_name((*p).first) << " ";
01871 o << (*p).second->name() << ";" << endl;
01872 }
01873 o << "}" << endl;
01874 }
01875 else {
01876 o << endl;
01877 o << " Defs: " << endl;
01878 Defs.print(o);
01879 o << " Uses: " << endl;
01880 Uses.print(o);
01881 }
01882 }
01883
01884 void memoryBlock::print(ostream & o, Location * path, Output_mode mode) const
01885 {
01886 o << "memoryBlock: " << name();
01887
01888 if (mode == NAME_ONLY) {
01889 o << endl;
01890 return;
01891 }
01892
01893 if ( ! _components.empty() ) {
01894 o << " {" << endl;
01895 for (component_map_cp p = _components.begin();
01896 p != _components.end();
01897 ++p)
01898 {
01899 o << " " << FieldNames.field_name((*p).first) << " ";
01900 (*p).second->print(o, path, mode);
01901 }
01902 o << "}";
01903 }
01904 else {
01905 memoryblock_list ps;
01906 o << endl;
01907
01908 if (mode == ALL_VALUES) {
01909
01910
01911
01912
01913
01914
01915
01916
01917
01918
01919
01920
01921
01922
01923
01924
01925
01926 }
01927 else {
01928
01929
01930
01931
01932
01933
01934
01935
01936
01937
01938
01939
01940
01941
01942
01943
01944 for (memoryblock_list_p p = ps.begin();
01945 p != ps.end();
01946 ++p)
01947 {
01948 memoryBlock * pb = *p;
01949
01950 o << " --> " << pb->name() << endl;
01951 }
01952 }
01953 }
01954 }
01955
01956 string memoryBlock::name() const
01957 {
01958
01959
01960 string name0;
01961
01962 if (container() && ! is_array_element()) {
01963 return container()->name() + "." + decl()->name();
01964 }
01965 else {
01966
01967 string & name1 = _decl->name();
01968
01969 if (decl()->type() &&
01970 decl()->type()->is_ellipsis())
01971 name1 = string("...");
01972
01973 if (_local_to)
01974 return _local_to->decl()->name() + "::" + name1;
01975 else {
01976
01977 if (_allocation_site) {
01978
01979 procLocation * alloc_proc = Location::procedure(_allocation_site);
01980
01981 if (alloc_proc->proc()->decl()->decl_location() == declNode::UNKNOWN)
01982 {
01983
01984
01985 procLocation * caller = Location::procedure(alloc_proc->stmt_location());
01986 if (caller)
01987 return caller->proc()->decl()->name() + "/" + name1;
01988 }
01989 }
01990
01991 return name1;
01992 }
01993 }
01994
01995
01996
01997
01998 }
01999
02000 string memoryBlock::generate_su_field_name(const string & field) const
02001 {
02002
02003
02004 string & name1 = _decl->name();
02005
02006 if (decl()->type() &&
02007 decl()->type()->is_ellipsis())
02008 name1 = string("...");
02009
02010 return name1 + "." + field;
02011
02012
02013
02014 }
02015
02016
02017
02018
02019
02020
02021
02022
02023 memoryBlock::FieldNameDB memoryBlock::FieldNames;
02024
02025 int memoryBlock::FieldNameDB::get_field(const string & name)
02026 {
02027 field_name_map_p p = _fields.find(name);
02028 if (p == _fields.end()) {
02029 ++_count;
02030 _fields[name] = _count;
02031 return _count;
02032 }
02033 else
02034 return (*p).second;
02035 }
02036
02037 string memoryBlock::FieldNameDB::field_name(int index)
02038 {
02039 field_name_map_p p = _fields.begin();
02040
02041 while (p != _fields.end()) {
02042 if ((*p).second == index)
02043 return (*p).first;
02044 ++p;
02045 }
02046 return string("");
02047 }
02048
02049 int memoryBlock::FieldNameDB::ArrayField = -1;