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 "print_walker.h"
00040 #include "pointers.h"
00041
00042 long int Pointers::call_counter;
00043
00044
00045
00046
00047
00050 bool pointerOptions::Context_insensitive = false;
00051
00054 bool pointerOptions::Recursion_Context_sensitive = true;
00055
00058 bool pointerOptions::Use_multiplicity = true;
00059
00062 bool pointerOptions::Verbose = false;
00063
00070 bool pointerOptions::Show_memoryblocks = false;
00071
00077 bool pointerOptions::Show_procedures = false;
00078
00081 bool pointerOptions::Pointer_statistics = false;
00082
00088 bool pointerOptions::Ignore_fields = false;
00089
00096 bool pointerOptions::One_struct_per_type = false;
00097
00100 bool pointerOptions::Show_stack = false;
00101
00110 bool pointerOptions::Flow_insensitive = false;
00111
00112
00117 bool pointerOptions::Unification = false;
00118
00119
00122 bool pointerOptions::Unification_use_annotation = true;
00123
00126 bool pointerOptions::Show_Unification = false;
00127
00133 bool pointerOptions::Conditional_analysis = false;
00134
00142 bool pointerOptions::Bidirectional_assignment = false;
00143
00161 bool pointerOptions::Aggressive_multiplicity = false;
00162
00169 bool pointerOptions::One_string_constant = true;
00170
00177 bool pointerOptions::Context_insensitive_memory = false;
00178
00184 bool pointerOptions::Use_escape_analysis = false;
00185
00190 bool pointerOptions::Verbose_unification = false;
00191
00196 bool pointerOptions::Verbose_constants = false;
00197
00202 bool pointerOptions::Verbose_liveness = false;
00203
00207 bool pointerOptions::Show_unknown_procedures = false;
00208
00214 bool pointerOptions::Show_memory_leaks = false;
00215
00221 bool pointerOptions::Monitor_precision = false;
00222
00228 str_set pointerOptions::Context_sensitive_procedures;
00229
00235 flow_sensitive_set pointerOptions::Flow_sensitive_objects;
00236
00242 flow_sensitive_set pointerOptions::Flow_sensitive_allocation_objects;
00243
00244
00250 UnifyTypes pointerOptions::Non_unify_types;
00251
00253 int pointerOptions::Unify_objects = 0;
00254
00261 basicblock_set pointerOptions::Path_sensitive_branches;
00262
00267 str_set pointerOptions::Verbose_procedures;
00268
00269
00270
00271
00272
00273
00274
00275 Pointers::Pointers(procNode * root, Linker & l, unitNode * unit)
00276 : Memory(),
00277 HeapMap(),
00278 Root(root),
00279 root_location(0),
00280 linker(l),
00281 Procedures(),
00282 _constants(),
00283 Problem(0),
00284 computePointers(true),
00285 _direction(Forward),
00286 _procedureCount(0),
00287 _skipCount(0),
00288 _show_progress(true),
00289 _use_multiplicity(true),
00290 _unknown_procedures(),
00291 _def_accuracy(),
00292 _star_accuracy(),
00293 _unification_based(0)
00294 {
00295 _constants.set_null_object(Memory.null());
00296 }
00297
00298 Pointers::~Pointers()
00299 {
00300 delete root_location;
00301
00302 for (heap_map_p p = HeapMap.begin();
00303 p != HeapMap.end();
00304 ++p)
00305 {
00306 delete (*p).second;
00307 }
00308 }
00309
00310
00311 void Pointers::run_unification() {
00312 if(pointerOptions::Unification) {
00313 if(pointerOptions::Show_Unification || pointerOptions::Verbose)
00314 cout << "Start unification-based analysis\n";
00315 _unification_based = UnificationBasedPtr::analyze_all(linker);
00316 Memory.unification(_unification_based);
00317 if(pointerOptions::Show_Unification || pointerOptions::Verbose)
00318 cout << "Unification-based analysis done\n";
00319 if(pointerOptions::Show_Unification)
00320 _unification_based->print_ecr();
00321 }
00322 }
00323
00324
00325
00326
00327
00328 void Pointers::analyze()
00329 {
00330
00331
00332 if (root_location) {
00333
00334
00335
00336
00337
00338 Memory.clear();
00339
00340
00341
00342 HeapMap.clear();
00343
00344
00345
00346 computePointers = true;
00347
00348
00349
00350 _direction = Forward;
00351
00352
00353
00354 delete root_location;
00355
00356
00357
00358 Problem = 0;
00359
00360
00361 }
00362
00363
00364
00365
00366
00367
00368
00369 Procedures.build(Root, linker);
00370
00371
00372
00373 root_location = new procLocation(0, Root);
00374
00375
00376
00377 memoryblock_set external_defs;
00378 memoryuse_set external_uses;
00379 memoryblock_set external_changes;
00380
00381 _procedureCount = 0;
00382 _skipCount = 0;
00383 int iterations = 0;
00384 call_counter = 0;
00385
00386 if (_show_progress)
00387 cout << " ==== Analyze Pointers ====" << endl;
00388
00389 procedureInfo * root_info = Procedures.lookup(root_location->proc());
00390
00391 Procedures.setup_analysis();
00392
00393 bool done = false;
00394
00395 pointerValue main_return;
00396
00397
00398
00399 initialize();
00400
00401
00402
00403 do {
00404
00405 Procedures.call_to((stmtLocation *)0, root_info);
00406
00407 root_info->start_self_timer();
00408 root_info->start_total_timer();
00409
00410 analyze_procedure(root_location,
00411 external_defs,
00412 external_uses,
00413 external_changes);
00414
00415 Procedures.return_from();
00416
00417 root_info->stop_self_timer();
00418 root_info->stop_total_timer();
00419
00420 iterations++;
00421
00422 bool needs_reanalysis = Procedures.is_reanalysis_required(root_info);
00423
00424 done = ( ! needs_reanalysis) || (iterations > 10);
00425
00426
00427
00428 if (_show_progress && ! done)
00429 cout << " ---- Reanalyze ----" << endl;
00430
00431 } while ( ! done );
00432
00433
00434
00435 Memory.update_def_use_chains();
00436
00437 computePointers = false;
00438
00439
00440
00441 if (pointerOptions::Show_unknown_procedures) {
00442 cout << "-----------------------------------------------------------" << endl;
00443 cout << "Unknown procedures:" << endl;
00444 for (string_set_p p = _unknown_procedures.begin();
00445 p != _unknown_procedures.end();
00446 ++p)
00447 cout << " " << (*p) << endl;
00448 pointerOptions::Show_unknown_procedures = false;
00449 }
00450 }
00451
00452 void Pointers::analyze(analysisProblem * problem)
00453 {
00454
00455
00456 if (computePointers == true) {
00457
00458
00459
00460
00461
00462
00463
00464 Procedures.build(Root, linker);
00465
00466
00467
00468 root_location = new procLocation(0, Root);
00469 }
00470
00471 Problem = problem;
00472
00473 _direction = problem->direction();
00474
00475 memoryblock_set external_defs;
00476 memoryuse_set external_uses;
00477 memoryblock_set external_changes;
00478
00479 _procedureCount = 0;
00480 _skipCount = 0;
00481 int iterations = 0;
00482 call_counter = 0;
00483
00484 if (_show_progress)
00485 cout << " ==== Analyze " << Problem->name() << " ====" << endl;
00486
00487 procedureInfo * root_info = Procedures.lookup(root_location->proc());
00488
00489 Procedures.setup_analysis();
00490
00491 bool done = false;
00492
00493 pointerValue main_return;
00494
00495
00496
00497 initialize();
00498
00499
00500
00501 do {
00502
00503 root_info->start_self_timer();
00504 root_info->start_total_timer();
00505
00506 Procedures.call_to((stmtLocation *)0, root_info);
00507
00508 if (Problem) {
00509 if (_direction == Forward)
00510 Problem->at_procedure_entry(root_location, root_info, main_return);
00511 else
00512 Problem->at_procedure_exit(root_location, root_info, main_return);
00513 }
00514
00515 analyze_procedure(root_location,
00516 external_defs,
00517 external_uses,
00518 external_changes);
00519
00520 if (Problem) {
00521 if (_direction == Forward)
00522 Problem->at_procedure_exit(root_location, root_info, main_return);
00523 else
00524 Problem->at_procedure_entry(root_location, root_info, main_return);
00525 }
00526
00527 Procedures.return_from();
00528
00529 root_info->stop_self_timer();
00530 root_info->stop_total_timer();
00531
00532 iterations++;
00533
00534 bool needs_reanalysis = Procedures.is_reanalysis_required(root_info);
00535
00536 done = ( ! needs_reanalysis) || (iterations > 10);
00537
00538 if (_show_progress)
00539 Procedures.print_leftovers();
00540
00541 if (_show_progress && ! done)
00542 cout << " ---- Reanalyze ----" << endl;
00543
00544 } while ( ! done );
00545
00546 Problem = 0;
00547
00548
00549
00550 computePointers = false;
00551
00552
00553
00554 if (pointerOptions::Show_unknown_procedures) {
00555 cout << "-----------------------------------------------------------" << endl;
00556 cout << "Unknown procedures:" << endl;
00557 for (string_set_p p = _unknown_procedures.begin();
00558 p != _unknown_procedures.end();
00559 ++p)
00560 cout << " " << (*p) << endl;
00561 pointerOptions::Show_unknown_procedures = false;
00562 }
00563
00564 if (pointerOptions::Show_procedures)
00565 Procedures.stats(cout);
00566 }
00567
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605 void Pointers::analyze_procedure(procLocation * current,
00606 memoryblock_set & defs,
00607 memoryuse_set & uses,
00608 memoryblock_set & changes)
00609 {
00610 procNode * procedure = current->proc();
00611 basicblockNode * procedure_exit = procedure->exit();
00612
00613
00614
00615 procedureInfo * info = Procedures.lookup(procedure);
00616
00617 info->add_all_blocks();
00618 info->incr_analysis_count();
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628 bool hack = pointerOptions::Verbose;
00629 pointerOptions::Verbose = info->is_verbose();
00630 while ( ! info->is_empty() ) {
00631
00632
00633
00634 basicblockNode * bb = info->get_next_block(_direction);
00635 basicblockLocation * current_block = current->lookup_block(bb);
00636
00637
00638
00639 current_block->visit();
00640
00641
00642
00643 if (pointerOptions::Verbose)
00644 cout << "==== " << *current_block << " ====" << endl << endl;
00645
00646
00647
00648
00649 bool never_returns = false;
00650
00651
00652
00653 pointerValue result;
00654
00655 if (Problem) {
00656 if (_direction == Forward)
00657 Problem->at_basicblock_entry(current_block, info, result);
00658 else
00659 Problem->at_basicblock_exit(current_block, info, result);
00660 }
00661
00662
00663
00664
00665
00666 memoryblock_set merge_changes;
00667 memoryblock_set stmt_changes;
00668
00669
00670
00671 const constant * branch_value = _constants.bottom();
00672
00673
00674
00675
00676 if (_direction == Forward)
00677 process_merge_point(info, current_block, result, defs, uses, merge_changes);
00678
00679
00680
00681 stmt_list & stmts = bb->stmts();
00682 stmt_location_vec & stmt_locs = current_block->statements();
00683
00684
00685
00686
00687 stmtLocation * current_stmt = 0;
00688 stmtLocation * previous_stmt = 0;
00689
00690 stmt_list_p stmt_p;
00691 int stmt_num;
00692 int number_of_statements = stmts.size();
00693
00694
00695
00696 if (_direction == Forward) {
00697 stmt_p = stmts.begin();
00698 stmt_num = 0;
00699 }
00700 else {
00701 stmt_p = stmts.end();
00702 stmt_p--;
00703 stmt_num = number_of_statements - 1;
00704 }
00705
00706 for (int counter = 0; counter < number_of_statements; counter++)
00707 {
00708
00709
00710 stmtNode * statement = *stmt_p;
00711 current_stmt = & (stmt_locs[stmt_num]);
00712
00713
00714
00715 if (pointerOptions::Verbose) {
00716 cout << "---- " << *current_stmt << " -- (" << statement->coord() << ") ----" << endl;
00717
00718 output_context oc(cout);
00719 statement->output(oc, 0);
00720 cout << endl << endl;
00721 }
00722
00723
00724
00725
00726 current_stmt->visit();
00727
00728
00729
00730
00731 if ( ! never_returns) {
00732
00733
00734
00735 result.initialize_pointers();
00736 _constants.at_stmt_entry(current_stmt, result);
00737
00738 if (Problem) {
00739 if (_direction == Forward)
00740 Problem->at_stmt_entry(current_stmt, result);
00741 else
00742 Problem->at_stmt_exit(current_stmt, result);
00743 }
00744
00745
00746
00747
00748
00749
00750
00751
00752 if (statement->typ() == Expr)
00753 assert(! ((exprstmtNode*) statement)->expr() );
00754
00755
00756 if(statement->typ() == ThreeAddr) {
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789 result.is_a_use = false;
00790
00791 threeAddrNode * t = (threeAddrNode *) statement;
00792 eval(info, current_stmt, t,
00793 defs, uses, stmt_changes, result, never_returns);
00794
00795
00796
00797 if (Problem)
00798 Problem->at_threeAddr(current_stmt, t, result);
00799 }
00800
00801
00802
00803 if (statement->typ() == If)
00804 assert(false);
00805
00806
00807 if(statement->typ() == Condition) {
00808
00809
00810 pointerValue left, right;
00811 left.is_a_use = true;
00812 right.is_a_use = true;
00813 result.is_a_use = true;
00814
00815 conditiongotoNode * C = (conditiongotoNode *) statement;
00816 if (C->left()) {
00817 eval(info, current_stmt, C->left(), statement,
00818 defs, uses, stmt_changes, left, never_returns);
00819
00820 if (C->right()) {
00821 eval(info, current_stmt, C->right(), statement,
00822 defs, uses, stmt_changes, right, never_returns);
00823 _constants.at_binary(current_stmt, C, left, right, result);
00824 } else
00825 _constants.at_unary(current_stmt, C, left, result);
00826 }
00827
00828
00829
00830 if (Problem)
00831 Problem->at_conditiongoto(current_stmt, C, result);
00832
00833
00834
00835 if (result.constant_value)
00836 branch_value = result.constant_value;
00837 }
00838
00839
00840
00841 if (Problem) {
00842 if (_direction == Forward)
00843 Problem->at_stmt_exit(current_stmt, result);
00844 else
00845 Problem->at_stmt_entry(current_stmt, result);
00846 }
00847 }
00848
00849
00850
00851 if (_direction == Forward) {
00852 stmt_p++;
00853 stmt_num++;
00854 }
00855 else {
00856 stmt_p--;
00857 stmt_num--;
00858 }
00859 }
00860
00861
00862
00863
00864 if (pointerOptions::Verbose) {
00865 cout << " --- (end basic block) ---" << endl << endl;
00866 }
00867
00868
00869
00870
00871 if (bb->children().empty() &&
00872 (bb != procedure->exit()))
00873 {
00874 stmtLocation * last = current_block->last();
00875 last->finish();
00876 }
00877
00878
00879
00880
00881 if ( ! merge_changes.empty() ||
00882 ! stmt_changes.empty())
00883 {
00884
00885 if (pointerOptions::Verbose) {
00886 print_memoryblock_def_set(" Phi Changes : ", merge_changes, cout);
00887 print_memoryblock_def_set(" Stmt Changes : ", stmt_changes, cout);
00888 }
00889
00890 if ( ! never_returns ) {
00891
00892
00893
00894
00895
00896 process_local_changes(info, current_block, merge_changes, changes);
00897 process_local_changes(info, current_block, stmt_changes, changes);
00898
00899
00900
00901
00902 info->add_reachable_blocks(bb, Forward);
00903 }
00904 }
00905
00906
00907
00908
00909
00910 if (_direction == Backward)
00911 process_merge_point(info, current_block, result, defs, uses, merge_changes);
00912
00913
00914
00915 if (Problem) {
00916 if (_direction == Forward)
00917 Problem->at_basicblock_exit(current_block, info, result);
00918 else
00919 Problem->at_basicblock_entry(current_block, info, result);
00920 }
00921
00922
00923
00924 if (pointerOptions::Conditional_analysis) {
00925
00926 bool has_truth_value = false;
00927 bool which_branch = false;
00928
00929 has_truth_value = _constants.has_truth_value(branch_value, which_branch);
00930 if (has_truth_value) {
00931
00932
00933
00934 if (pointerOptions::Verbose)
00935 cout << "Found constant branch at " << * current_block
00936 << " -- value = " << _constants.to_string(branch_value) << endl;
00937 }
00938
00939
00940
00941
00942
00943
00944 if ( ! never_returns)
00945 info->update_conditional_worklist(bb, has_truth_value, which_branch);
00946 }
00947
00948
00949
00950
00951
00952 if (never_returns &&
00953 Dominators::dominates(bb, procedure_exit)) {
00954
00955 info->set_never_returns();
00956
00957 if (pointerOptions::Verbose)
00958 cout << info->qualified_name() << " never returns." << endl;
00959 }
00960
00961 }
00962 pointerOptions::Verbose = hack;
00963 }
00964
00965
00966
00967
00968
00969 void Pointers::procedure_call(procedureInfo * caller,
00970 stmtLocation * callsite,
00971 operandNode * call,
00972 operand_list & args,
00973 pointerValue & call_target,
00974 memoryBlock * target_mb,
00975 pointervalue_list & arguments,
00976 memoryblock_set & external_defs,
00977 memoryuse_set & external_uses,
00978 memoryblock_set & external_changes,
00979 pointerValue & return_val,
00980 bool & never_returns)
00981 {
00982 procedureInfo * info = 0;
00983 bool resolved = false;
00984 bool recursive_call = false;
00985 procNode * callee = 0;
00986
00987
00988
00989
00990
00991 if (is_allocation(call_target)) {
00992
00993
00994
00995 memoryBlock * alloc_block;
00996
00997 string name = caller->proc()->decl()->name() + "/malloc";
00998
00999 alloc_block = at_allocation(name, caller,
01000 callsite, callsite->stmt(), (declNode *)0,
01001 external_defs, external_uses, external_changes,
01002 return_val);
01003
01004 if (pointerOptions::Verbose)
01005 cout << "Allocate heap object: " << alloc_block->name() << endl;
01006
01007
01008
01009 if (Problem)
01010 Problem->at_allocation(callsite, arguments, alloc_block, external_changes);
01011
01012 return;
01013 }
01014
01015 if (is_deallocation(call_target)) {
01016
01017
01018
01019 pointerValue & dealloc_ptrs = arguments.front();
01020 pointerValue to_deallocate;
01021
01022 star_operator(caller, callsite, dealloc_ptrs,
01023 external_defs, external_uses, external_changes, to_deallocate);
01024
01025 if (pointerOptions::Verbose)
01026 print_memoryblock_set("Deallocate heap objects: ", to_deallocate.blocks, cout);
01027
01028
01029
01030 at_deallocation(caller, callsite, to_deallocate,
01031 external_defs, external_uses, external_changes);
01032
01033
01034
01035 if (Problem)
01036 Problem->at_deallocation(callsite, to_deallocate, external_changes);
01037
01038 return;
01039 }
01040
01041 if (is_reallocation(call_target)) {
01042
01043
01044
01045 pointerValue & realloc_ptrs = arguments.front();
01046
01047
01048
01049 star_operator(caller, callsite, realloc_ptrs,
01050 external_defs, external_uses, external_changes, return_val);
01051 return_val.is_address = true;
01052
01053 if (pointerOptions::Verbose)
01054 print_memoryblock_set("Reallocate heap objects: ", return_val.blocks, cout);
01055
01056 return;
01057 }
01058
01059 if (is_va_arg(call_target)) {
01060
01061
01062
01063
01064 pointerValue & varargs_list = arguments.front();
01065
01066
01067
01068 star_operator(caller, callsite, varargs_list,
01069 external_defs, external_uses, external_changes, return_val);
01070 return_val.is_address = true;
01071
01072 if (pointerOptions::Verbose)
01073 print_memoryblock_set("Get varargs objects: ", return_val.blocks, cout);
01074
01075 return;
01076 }
01077
01078 if (is_va_start(call_target) ||
01079 is_va_end(call_target))
01080 return;
01081
01082 if (is_exit(call_target)) {
01083
01084
01085
01086
01087 never_returns = true;
01088 return;
01089 }
01090
01091
01092
01093
01094
01095 callee = linker.lookup_procedure(target_mb->decl());
01096 if (callee == 0) {
01097
01098 if (pointerOptions::Verbose)
01099 cout << "WARNING: No source for " << target_mb->name() <<
01100 " at " << * callsite << endl;
01101
01102 _unknown_procedures.insert(target_mb->name());
01103 }
01104 else {
01105
01106
01107
01108
01109
01110 resolved = true;
01111 }
01112
01113
01114
01115 if ( ! resolved ) {
01116
01117
01118
01119
01120 return;
01121
01122 memoryblock_set reachable_blocks;
01123 conservative_procedure_call(caller, callsite, arguments, reachable_blocks,
01124 external_defs, external_uses, external_changes,
01125 return_val);
01126
01127
01128
01129 _constants.at_conservative_procedure_call(callsite, call, args, call_target,
01130 arguments, reachable_blocks,
01131 return_val, external_changes);
01132
01133
01134
01135 if (Problem)
01136 Problem->at_conservative_procedure_call(callsite, call, args, call_target,
01137 arguments, reachable_blocks,
01138 return_val, external_changes);
01139
01140 return;
01141 }
01142
01143
01144
01145
01146
01147 if (Problem)
01148 Problem->at_call(callsite, call, call_target, callee, arguments, return_val);
01149
01150
01151
01152 info = Procedures.lookup(callee);
01153
01154
01155
01156 int num_instances = 0;
01157 recursive_call = Procedures.is_recursive_call(info, num_instances);
01158
01159
01160
01161 bool multiple_call_targets = false;
01162
01163 if (call_target.blocks.size() > 1)
01164 multiple_call_targets = true;
01165
01166
01167
01168 info->setup_call_at(caller, callsite, recursive_call, multiple_call_targets);
01169
01170
01171
01172 caller->stop_self_timer();
01173
01174 if (! recursive_call) {
01175 info->start_self_timer();
01176 info->start_total_timer();
01177 }
01178
01179
01180
01181 analyze_procedure_at(info, callsite, arguments,
01182 external_defs,
01183 external_uses,
01184 external_changes,
01185 return_val);
01186
01187
01188
01189 caller->start_self_timer();
01190
01191 if (! recursive_call) {
01192 info->stop_self_timer();
01193 info->stop_total_timer();
01194 }
01195
01196
01197
01198
01199 memoryblock_set pending_changes;
01200 caller->get_pending_changes(callsite, pending_changes);
01201
01202 if ( ! pending_changes.empty()) {
01203
01204 if (pointerOptions::Verbose)
01205 print_memoryblock_set(" => Pickup pending changes: ", pending_changes, cout);
01206
01207 external_changes.insert(pending_changes.begin(), pending_changes.end());
01208 }
01209
01210
01211
01212
01213 never_returns = info->never_returns();
01214 }
01215
01216 void Pointers::analyze_procedure_at(procedureInfo * info,
01217 stmtLocation * callsite,
01218 pointervalue_list & arguments,
01219 memoryblock_set & external_defs,
01220 memoryuse_set & external_uses,
01221 memoryblock_set & external_changes,
01222 pointerValue & return_val)
01223 {
01224 long int call_id;
01225
01226
01227
01228
01229 int num_instances = 0;
01230 bool recursive_call = Procedures.is_recursive_call(info, num_instances);
01231
01232
01233
01234 Procedures.call_to(callsite, info);
01235
01236
01237
01238 procLocation * callee_path = info->procedure_location(callsite);
01239
01240
01241
01242 if (pointerOptions::Verbose || pointerOptions::Show_stack) {
01243
01244 call_id = call_counter;
01245 call_counter++;
01246
01247 cout << "------------------------------------------------------------" << endl;
01248
01249 if (info->is_context_insensitive())
01250 cout << " CI Call ";
01251 else
01252 cout << " CS Call ";
01253
01254 cout << info->name() << " (id=" << call_id << ")";
01255
01256 if (callsite) {
01257
01258
01259
01260
01261
01262
01263
01264 cout << *callsite;
01265 }
01266
01267 cout << endl;
01268
01269 cout << " Call-Path: ";
01270 Procedures.print_call_stack(cout);
01271 cout << endl;
01272 cout << "------------------------------------------------------------" << endl;
01273 cout << endl;
01274 }
01275
01276
01277
01278 bool reanalysis_required = Procedures.is_reanalysis_required(info);
01279
01280
01281
01282 memoryblock_set defs;
01283 memoryuse_set uses;
01284 memoryblock_set changes;
01285 memoryblock_set changed_inputs;
01286 memoryblock_set parameters;
01287
01288
01289
01290 if (_direction == Forward) {
01291
01292
01293
01294
01295
01296 pass_parameters(info, callsite, arguments, parameters, changed_inputs);
01297
01298
01299
01300 pass_external_inputs(info, callsite, external_uses, changed_inputs);
01301
01302
01303
01304
01305
01306 bool skip_analysis = false;
01307
01308 if ((num_instances >= 1) || (info->is_context_insensitive() &&
01309 (! reanalysis_required) &&
01310 (changed_inputs.empty())))
01311 {
01312 skip_analysis = true;
01313
01314 if (pointerOptions::Verbose) {
01315 cout << "SKIP " << info->name() << " at ";
01316 Procedures.print_call_stack(cout);
01317 cout << endl;
01318 }
01319 }
01320
01321
01322
01323 int start_progress = _procedureCount;
01324 int start_def_count = memoryAccess::def_count;
01325
01326 progress_meter(info, skip_analysis);
01327
01328 if ( ! skip_analysis) {
01329
01330 if (Problem)
01331 Problem->at_procedure_entry(callee_path, info, return_val);
01332
01333
01334
01335
01336 analyze_procedure(callee_path, defs, uses, changes);
01337
01338
01339
01340
01341 record_external_inputs_and_outputs(info, callee_path, arguments,
01342 parameters, defs, external_defs,
01343 uses, external_uses,
01344 changes, external_changes);
01345
01346 if (Problem)
01347 Problem->at_procedure_exit(callee_path, info, return_val);
01348 }
01349
01350
01351
01352
01353 callsite->visit();
01354
01355 int end_progress = _procedureCount;
01356 int end_def_count = memoryAccess::def_count;
01357
01358
01359
01360 pass_return_value(info, callsite, return_val, external_changes);
01361
01362
01363
01364
01365
01366
01367
01368
01369 if ( ! skip_analysis && ! info->never_returns()) {
01370 pass_external_outputs(info, callsite);
01371 }
01372 }
01373 else {
01374
01375
01376
01377
01378
01379
01380 if (! info->never_returns())
01381 pass_external_outputs(info, callsite);
01382
01383 pass_return_value(info, callsite, return_val, changed_inputs);
01384
01385
01386
01387
01388
01389
01390
01391 bool skip_analysis = false;
01392
01393 if (info->is_context_insensitive() &&
01394 ( ! reanalysis_required) &&
01395 (changed_inputs.empty()))
01396 {
01397 skip_analysis = true;
01398
01399 if (pointerOptions::Verbose) {
01400 cout << "SKIP " << info->name() << " at ";
01401 Procedures.print_call_stack(cout);
01402 cout << endl;
01403 }
01404 }
01405
01406 if ( ! skip_analysis) {
01407
01408 if (Problem)
01409 Problem->at_procedure_exit(callee_path, info, return_val);
01410
01411
01412
01413
01414 analyze_procedure(callee_path, defs, uses, changes);
01415
01416
01417
01418
01419 record_external_inputs_and_outputs(info, callee_path, arguments,
01420 parameters, defs, external_defs,
01421 uses, external_uses,
01422 changes, external_changes);
01423
01424 if (Problem)
01425 Problem->at_procedure_entry(callee_path, info, return_val);
01426 }
01427
01428 progress_meter(info, skip_analysis);
01429
01430
01431
01432 pass_external_inputs(info, callsite, external_uses, external_changes);
01433
01434 pass_parameters(info, callsite, arguments, parameters, external_changes);
01435 }
01436
01437
01438
01439 Procedures.return_from();
01440
01441
01442
01443 if (pointerOptions::Verbose || pointerOptions::Show_stack) {
01444 cout << "------------------------------------------------------------" << endl;
01445 cout << " Return from " << info->name() << " (id=" << call_id << ")" << endl;
01446 cout << " Return-Path: ";
01447 Procedures.print_call_stack(cout);
01448 cout << endl;
01449
01450 print_memoryblock_set(" Returning: ", return_val.blocks, cout);
01451
01452 cout << "------------------------------------------------------------" << endl;
01453 cout << endl;
01454 }
01455 }
01456
01457 void Pointers::pass_parameters(procedureInfo * info,
01458 stmtLocation * callsite,
01459 pointervalue_list & arguments,
01460 memoryblock_set & parameters,
01461 memoryblock_set & changed_inputs)
01462 {
01463 procNode * callee = info->proc();
01464 procLocation * callee_path = info->procedure_location(callsite);
01465 procedureInfo * caller = Procedures.current_caller();
01466
01467
01468
01469 funcNode * f = (funcNode *) callee->decl()->no_tdef_type();
01470 if (f->typ() != Func) {
01471 if (pointerOptions::Verbose)
01472 cout << "INTERNAL ERROR: Attempting to call a non-procedure." << endl;
01473 return;
01474 }
01475
01476 if ( ! f->is_void_args()) {
01477
01478 decl_list & params = f->args();
01479
01480
01481
01482
01483
01484 memoryblock_set defs;
01485 memoryuse_set uses;
01486 memoryblock_set changes;
01487
01488 pointervalue_list_p args_p = arguments.begin();
01489
01490 for (decl_list_p params_p = params.begin();
01491 params_p != params.end();
01492 ++params_p)
01493 {
01494 declNode * formal = * params_p;
01495 typeNode * formal_type = formal->no_tdef_type();
01496
01497
01498
01499 if (formal_type->is_ellipsis() ||
01500 is_va_list(formal)) {
01501
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511 memoryBlock * ellipsis = Memory.lookup_variable(callee_path, formal, callee);
01512
01513 parameters.insert(ellipsis);
01514
01515 pointerValue lhs(ellipsis);
01516
01517 if (pointerOptions::Verbose)
01518 cout << "Pass varargs object: " << ellipsis->name() << endl;
01519
01520
01521
01522 while (args_p != arguments.end()) {
01523 pointerValue & actual = * args_p;
01524
01525
01526
01527 assignment_operator(info, callee_path, callsite, lhs, actual,
01528 defs, uses, changed_inputs);
01529
01530
01531
01532 _constants.at_parameter_pass(callee_path, lhs, actual, changed_inputs);
01533
01534
01535
01536 if (Problem)
01537 Problem->at_parameter_pass(callee_path, callsite, lhs, actual, changed_inputs);
01538
01539 args_p++;
01540 }
01541
01542
01543
01544 setup_va_list_variables(info, callee_path, callsite, callee, ellipsis);
01545
01546
01547
01548 break;
01549 }
01550 else {
01551
01552
01553
01554
01555
01556 if (args_p == arguments.end()) {
01557 if (pointerOptions::Verbose)
01558 cout << "ERROR: Too few arguments to " << callee->decl()->name() <<
01559 " at " << callee->coord() << endl;
01560 break;
01561 }
01562
01563 pointerValue & actual = * args_p;
01564
01565
01566
01567 memoryBlock * left = Memory.lookup_variable(callee_path, formal, callee);
01568 parameters.insert(left);
01569 pointerValue lhs(left);
01570
01571 if (pointerOptions::Verbose)
01572 cout << endl << "Pass parameter: " << left->name() << endl;
01573
01574
01575
01576
01577
01578
01579 assignment_operator(info, callee_path, callsite, lhs, actual,
01580 defs, uses, changed_inputs);
01581
01582
01583
01584 if (_direction == Backward)
01585 generate_uses(info, callsite, uses, actual);
01586
01587
01588
01589 _constants.at_parameter_pass(callee_path, lhs, actual, changed_inputs);
01590
01591
01592
01593 if (Problem)
01594 Problem->at_parameter_pass(callee_path, callsite, lhs, actual, changed_inputs);
01595
01596
01597
01598 if ((formal_type->typ() == Struct) ||
01599 (formal_type->typ() == Union))
01600 {
01601
01602
01603
01604
01605
01606
01607 }
01608 }
01609
01610 ++args_p;
01611 }
01612 }
01613 }
01614
01615 void Pointers::pass_return_value(procedureInfo * info,
01616 stmtLocation * current_callsite,
01617 pointerValue & return_val,
01618 memoryblock_set & changes)
01619 {
01620 procLocation * callee_path = info->procedure_location(current_callsite);
01621
01622
01623
01624 declNode * return_var = info->return_variable();
01625 returnNode * return_stmt = info->return_stmt();
01626
01627 if (return_stmt &&
01628 return_stmt->expr()) {
01629
01630
01631
01632
01633 stmtLocation * last = callee_path->last();
01634
01635 if (last->stmt() != return_stmt) {
01636 cout << "FATAL ERROR returning from " << info->name()
01637 << " at " << * current_callsite << ":" << endl;
01638 cout << " Last statement of the procedure is not the return statement." << endl;
01639 abort();
01640 }
01641
01642 memoryblock_set ignore_defs;
01643 memoryuse_set ignore_uses;
01644 memoryblock_set ignore_changes;
01645 bool ignore_never_returns;
01646
01647 return_val.is_a_use = true;
01648
01649 eval(info, last, return_stmt->expr(), NULL,
01650 ignore_defs, ignore_uses, ignore_changes,
01651 return_val, ignore_never_returns);
01652
01653
01654
01655
01656
01657
01658
01659
01660
01661
01662
01663
01664
01665
01666
01667
01668
01669
01670
01671
01672
01673
01674
01675
01676
01677
01678
01679
01680
01681
01682
01683
01684
01685
01686
01687
01688
01689
01690 }
01691 }
01692
01693
01694 void Pointers::process_merge_point(procedureInfo * info,
01695 basicblockLocation * current_block,
01696 pointerValue & result,
01697 memoryblock_set & defs,
01698 memoryuse_set & uses,
01699 memoryblock_set & changes)
01700 {
01701
01702
01703 const memoryblock_set * to_be_merged = info->lookup_merge_point(current_block);
01704 if (to_be_merged) {
01705
01706
01707
01708
01709 for (memoryblock_set_cp p = to_be_merged->begin();
01710 p != to_be_merged->end();
01711 ++p)
01712 {
01713 memoryuse_list phi_uses;
01714 memoryBlock * block_to_merge = *p;
01715
01716
01717
01718 if (block_to_merge->is_flow_sensitive()) {
01719
01720
01721
01722
01723 memoryDef * dominating_def = 0;
01724 if (computePointers)
01725 dominating_def = nearest_def_at(info, block_to_merge, current_block);
01726
01727
01728
01729
01730 block_to_merge->merge_uses_at(current_block, phi_uses, info->active_edges(),
01731 dominating_def, computePointers);
01732
01733
01734 merge_operator(info, current_block, block_to_merge, phi_uses, defs, uses, changes);
01735
01736
01737
01738 _constants.at_merge(current_block, block_to_merge, phi_uses, result, changes);
01739
01740
01741
01742 if (Problem)
01743 Problem->at_merge(current_block, block_to_merge, phi_uses, result, changes);
01744 }
01745 }
01746 }
01747 }
01748
01754 void Pointers::process_local_changes(procedureInfo * info,
01755 basicblockLocation * current_block,
01756 memoryblock_set & local_changes,
01757 memoryblock_set & changes)
01758 {
01759 if (pointerOptions::Verbose)
01760 cout << " Process local changes at " << * current_block << endl;
01761
01762
01763
01764
01765 for (memoryblock_set_p q = local_changes.begin();
01766 q != local_changes.end();
01767 ++q)
01768 {
01769 memoryBlock * block = (*q);
01770
01771 if (pointerOptions::Verbose)
01772 cout << " Change: " << block->name();
01773
01774
01775
01776 changes.insert(block);
01777
01778 if (pointerOptions::Verbose) {
01779 memoryDef * cur_def = block->current_def();
01780 memoryDef * def;
01781
01782 if ( cur_def )
01783 def = cur_def;
01784 else
01785 def = block->last_def_at(current_block);
01786
01787 if (def)
01788 cout << " -- def at " << * (def->where()) << endl;
01789 else
01790 cout << " -- (non-local def)" << endl;
01791 }
01792
01793
01794
01795
01796 if ( ! block->is_flow_sensitive()) {
01797 procedureinfo_set input_to = block->input_to();
01798
01799 for (procedureinfo_set_p w = input_to.begin(); w != input_to.end();
01800 ++w) {
01801 procedureInfo * info_needs_input = *w;
01802
01803 bool mark = true;
01804 if(block->property && Problem) {
01805 memoryDef *def = block->current_def() ?
01806 def = block->current_def() :
01807 block->last_def_at(current_block);
01808 memoryblock_set ext_inputs = info_needs_input->external_inputs();
01809
01810
01811
01812 if(def && ext_inputs.find(block) != ext_inputs.end() &&
01813 Problem->compare_property_value(def->where(), block,
01814 info_needs_input))
01815 mark = false;
01816 }
01817
01818 if(mark)
01819 Procedures.mark_for_reanalysis(info_needs_input, (stmtLocation *)0, true);
01820
01821 }
01822 }
01823
01824
01825
01826
01827 if (computePointers)
01828 info->setup_merge_point(block, current_block);
01829
01830
01831
01832
01833
01834
01835
01836
01837 }
01838
01839 if (pointerOptions::Verbose && ( ! local_changes.empty()))
01840 cout << endl;
01841 }
01842
01854 void Pointers::pass_external_inputs(procedureInfo * info,
01855 stmtLocation * current_callsite,
01856 memoryuse_set & external_uses,
01857 memoryblock_set & changed_inputs)
01858 {
01859
01860
01861 if ( ! info->is_context_insensitive())
01862 return;
01863
01864 pointerValue result;
01865
01866
01867
01868 procedureInfo * caller = Procedures.current_caller();
01869
01870
01871
01872 const memoryblock_set & external_inputs = info->external_inputs();
01873
01874
01875
01876 for (memoryblock_set_cp p = external_inputs.begin();
01877 p != external_inputs.end();
01878 ++p)
01879 {
01880 memoryBlock * block_to_pass = *p;
01881
01882 pass_one_external_input(info, caller, current_callsite, block_to_pass, changed_inputs);
01883 }
01884 }
01885
01893 void Pointers::pass_one_external_input(procedureInfo * callee,
01894 procedureInfo * caller,
01895 stmtLocation * current_callsite,
01896 memoryBlock * block_to_pass,
01897 memoryblock_set & changed_inputs)
01898 {
01899
01900
01901 Location * input_location = callee->procedure_location(current_callsite);
01902
01903
01904
01905 if (block_to_pass->write_protected()) {
01906
01907
01908
01909
01910 if (pointerOptions::Verbose)
01911 cout << endl << "Pass write-protected input " << block_to_pass->name() << endl;
01912 }
01913 else
01914 if ( ! block_to_pass->is_flow_sensitive()) {
01915
01916
01917
01918 if (pointerOptions::Verbose)
01919 cout << endl << "Skip flow-insensitive input " << block_to_pass->name() << endl;
01920 }
01921 else {
01922
01923
01924
01925 if (Procedures.is_visible_to_caller(callee, block_to_pass)) {
01926
01927
01928
01929
01930
01931
01932
01933
01934
01935
01936 if (pointerOptions::Verbose)
01937 cout << endl << "Pass external input " << block_to_pass->name() << endl;
01938
01939
01940
01941
01942
01943
01944 Location * attach_to = current_callsite;
01945
01946
01947
01948
01949 memoryUse * use = block_to_pass->use_at(attach_to);
01950
01951
01952
01953 memoryDef * def = 0;
01954
01955 if (computePointers) {
01956 def = nearest_def_at(caller, block_to_pass, current_callsite);
01957 use->reaching_def(def);
01958 }
01959
01960 if (pointerOptions::Verbose) {
01961 def = use->reaching_def();
01962 cout << " At callsite " << * current_callsite
01963 << " use at " << * attach_to << " reaching def is ";
01964 if (def)
01965 cout << * (def->where()) << endl;
01966 else
01967 cout << "(no reaching def)" << endl;
01968 }
01969
01970
01971
01972
01973
01974
01975 self_assignment(attach_to, input_location, block_to_pass, changed_inputs);
01976
01977
01978
01979 _constants.at_self_assignment(attach_to, input_location, block_to_pass, changed_inputs);
01980
01981
01982
01983 if (Problem)
01984 Problem->at_self_assignment(attach_to, input_location, block_to_pass, changed_inputs, true);
01985 }
01986 }
01987
01988
01989 if(Problem && block_to_pass->property)
01990 Problem->record_input_to_value(callee, block_to_pass, current_callsite);
01991 }
01992
02002 void Pointers::pass_external_outputs(procedureInfo * callee,
02003 stmtLocation * current_callsite)
02004 {
02005
02006
02007 if ( ! callee->is_context_insensitive())
02008 return;
02009
02010
02011
02012 if (callee->never_returns())
02013 return;
02014
02015
02016
02017 const memoryblock_set & external_outputs = callee->external_outputs();
02018
02019
02020
02021
02022
02023
02024
02025
02026
02027
02028
02029
02030
02031
02032
02033
02034
02035
02036
02037
02038
02039
02040
02041
02042
02043
02044
02045
02046
02047
02048
02049
02050
02051
02052
02053
02054
02055
02056 for (memoryblock_set_cp p = external_outputs.begin();
02057 p != external_outputs.end();
02058 ++p)
02059 {
02060 memoryBlock * block_to_pass = *p;
02061
02062 if (pointerOptions::Verbose)
02063 cout << endl << "Pass external output " << block_to_pass->name() << endl;
02064
02065 bool is_return_value = false;
02066
02067 pass_one_external_output(callee, current_callsite,
02068 block_to_pass, is_return_value);
02069 }
02070 }
02071
02072 void Pointers::pass_one_external_output(procedureInfo * callee,
02073 stmtLocation * current_callsite,
02074 memoryBlock * block_to_pass,
02075 bool is_return_value)
02076 {
02077
02078
02079
02080 stmtLocation * last_stmt_of_proc = callee->get_context()->last();
02081
02082 memoryUse * use = block_to_pass->use_at(last_stmt_of_proc);
02083
02084
02085
02086
02087 memoryDef * internal_reaching_def = 0;
02088
02089 if (computePointers) {
02090 internal_reaching_def = block_to_pass->nearest_def_at(last_stmt_of_proc);
02091 use->reaching_def(internal_reaching_def);
02092 }
02093
02094 internal_reaching_def = use->reaching_def();
02095
02096 if (pointerOptions::Verbose) {
02097
02098 cout << " Interal use at " << * (use->where())
02099 << " with reaching def at ";
02100
02101 memoryDef * def = use->reaching_def();
02102 if (def)
02103 cout << * (def->where()) << endl;
02104 else
02105 cout << "(no reaching def)" << endl;
02106 }
02107
02108
02109
02110 if (! block_to_pass->is_flow_sensitive()) {
02111 if (pointerOptions::Verbose)
02112 cout << endl << " Skip flow-insensitive external output " << block_to_pass->name() << endl;
02113 return;
02114 }
02115
02116
02117
02118 const procedureInfo::callsite_map & callsites = callee->callsites();
02119
02120
02121
02122 for (procedureInfo::callsite_map_cp csp = callsites.begin();
02123 csp != callsites.end();
02124 ++csp)
02125 {
02126
02127
02128 stmtLocation * target_callsite = (*csp).first;
02129 procedureInfo * caller = (*csp).second;
02130
02131
02132
02133
02134
02135 if (is_return_value ||
02136 Procedures.is_visible_to(caller, block_to_pass)) {
02137
02138 if (pointerOptions::Verbose)
02139 cout << "+ Back to callsite " << * target_callsite << endl;
02140
02141
02142
02143 memoryblock_set pending_changes;
02144
02145 self_assignment(last_stmt_of_proc, target_callsite,
02146 block_to_pass, pending_changes);
02147
02148
02149
02150 _constants.at_self_assignment(last_stmt_of_proc, target_callsite,
02151 block_to_pass, pending_changes);
02152
02153
02154
02155 if (Problem)
02156 Problem->at_self_assignment(last_stmt_of_proc, target_callsite,
02157 block_to_pass, pending_changes, false);
02158
02159
02160
02161
02162
02163 if ( ! is_return_value && ! pending_changes.empty()) {
02164
02165
02166
02167 caller->set_pending_changes(target_callsite, pending_changes);
02168 if (pointerOptions::Verbose)
02169 print_memoryblock_set(" => Pending changes: ", pending_changes, cout);
02170
02171
02172
02173
02174 if (target_callsite != current_callsite) {
02175 Procedures.mark_for_reanalysis(caller, target_callsite, true);
02176 }
02177 }
02178 }
02179 else {
02180
02181
02182
02183 if (pointerOptions::Verbose)
02184 cout << "+ Not visible at callsite " << * target_callsite << endl;
02185 }
02186 }
02187
02188
02189
02190
02191
02192 if ( ! is_return_value)
02193 block_to_pass->reset_current_def_use((Location *)0);
02194 }
02195
02203 void Pointers::record_external_inputs_and_outputs(procedureInfo * callee,
02204 procLocation * current,
02205 pointervalue_list & arguments,
02206 memoryblock_set & parameters,
02207 memoryblock_set & defs,
02208 memoryblock_set & external_defs,
02209 memoryuse_set & uses,
02210 memoryuse_set & external_uses,
02211 memoryblock_set & changes,
02212 memoryblock_set & external_changes)
02213 {
02214
02215
02216
02217
02218
02219
02220
02221
02222
02223 procNode * procedure = callee->proc();
02224 procedureInfo * caller = Procedures.current_caller();
02225 stmtLocation * current_callsite = Procedures.current_callsite();
02226 stmtLocation * last_stmt_of_proc = current->last();
02227
02228
02229
02230 const memoryblock_set & external_inputs = callee->external_inputs();
02231
02232
02233
02234 memoryblock_set roots(parameters);
02235
02236
02237
02238 memoryblock_set proposed_external_changes;
02239
02240
02241
02242 memoryblock_set new_inputs;
02243
02244
02245
02246 memoryblock_set new_outputs;
02247
02248
02249
02250
02251 if (pointerOptions::Verbose) {
02252 cout << "Record external inputs to " << procedure->decl()->name() << " at ";
02253 Procedures.print_call_stack(cout);
02254 cout << endl;
02255 }
02256
02257
02258 memoryblock_set external_uses_blocks;
02259 bool gathered_external_uses_blocks = false;
02260
02261 if ( ! uses.empty() )
02262 for (memoryuse_set_p p = uses.begin();
02263 p != uses.end();
02264 ++p)
02265 {
02266 memoryUse * use = *p;
02267 memoryBlock * block = use->owner();
02268 memoryDef * def = use->reaching_def();
02269
02270
02271
02272 if (external_inputs.find(block) != external_inputs.end())
02273 roots.insert(block);
02274
02275
02276
02277
02278 if ( ! block->write_protected() &&
02279 (block->local_to() != procedure)) {
02280
02281
02282
02283
02284 if ( ! block->is_flow_sensitive())
02285 block->input_to().insert(callee);
02286
02287
02288
02289
02290
02291
02292 bool is_external_input = false;
02293
02294 if (def) {
02295
02296
02297
02298
02299
02300
02301
02302 if ( ! Location::is_prefix(current, def->where()))
02303 is_external_input = true;
02304 }
02305 else {
02306
02307
02308
02309 if (block->is_heap_object())
02310 is_external_input = false;
02311 else
02312 is_external_input = true;
02313 }
02314
02315 if (is_external_input) {
02316
02317
02318
02319 if (computePointers)
02320 new_inputs.insert(block);
02321
02322
02323
02324
02325
02326
02327 if (caller &&
02328 Procedures.is_visible_to(caller, block)) {
02329
02330 external_uses.insert(use);
02331
02332 if(_unification_based && gathered_external_uses_blocks)
02333 external_uses_blocks.insert(use->owner());
02334
02335 if(!(_unification_based && block->is_unify()))
02336 roots.insert(block->top_most_container());
02337 else {
02338
02339
02340
02341 memoryblock_set tops = block->top_most_containers();
02342 for(memoryblock_set_p t=tops.begin(); t!=tops.end(); t++) {
02343 memoryBlock *one_top = *t;
02344 if(roots.find(one_top) != roots.end()) continue;
02345 if(one_top == block) { roots.insert(block); continue; }
02346 bool is_global =
02347 one_top->decl()->decl_location()==declNode::TOP ||
02348
02349 !one_top->decl()->type() && !one_top->local_to();
02350 bool is_arg = false;
02351 if(! is_global)
02352 for(pointervalue_list_p a=arguments.begin();
02353 a!=arguments.end(); a++)
02354 if(a->blocks.find(one_top) != a->blocks.end())
02355 { is_arg=true; break; }
02356
02357 if(is_global || is_arg) {
02358 if(! gathered_external_uses_blocks) {
02359 for(memoryuse_set_p u=external_uses.begin();
02360 u!=external_uses.end(); u++)
02361 external_uses_blocks.insert((*u)->owner());
02362 gathered_external_uses_blocks = true;
02363 }
02364 if(external_uses_blocks.find(one_top) !=
02365 external_uses_blocks.end()) {
02366 roots.insert(one_top);
02367 }
02368 }
02369 }
02370 }
02371 }
02372 }
02373 }
02374 }
02375
02376 if (pointerOptions::Verbose)
02377 cout << endl;
02378
02379
02380
02381
02382
02383 if (pointerOptions::Verbose) {
02384 cout << "Record external outputs to " << procedure->decl()->name() << " at ";
02385 Procedures.print_call_stack(cout);
02386 cout << endl;
02387 }
02388
02389
02390
02391 Location * input_location = 0;
02392 if (current_callsite)
02393 input_location = callee->procedure_location(current_callsite);
02394
02395 if ( ! changes.empty() ) {
02396 for (memoryblock_set_p p = changes.begin();
02397 p != changes.end();
02398 ++p)
02399 {
02400 memoryBlock * block = *p;
02401
02402
02403
02404
02405
02406
02407 if ((block->local_to() != procedure)) {
02408
02409
02410
02411
02412
02413
02414 bool trivial_def = false;
02415
02416 if (input_location &&
02417 block->current_def()) {
02418
02419 if (block->current_def()->where() == input_location)
02420 trivial_def = true;
02421 }
02422
02423
02424
02425
02426 bool not_allocated = false;
02427
02428
02429 if (block->is_heap_object()) {
02430
02431
02432
02433
02434
02435
02436
02437
02438
02439
02440
02441
02442
02443
02444
02445
02446
02447
02448
02449
02450
02451
02452
02453
02454
02455
02456
02457
02458
02459
02460
02461
02462
02463
02464
02465
02466
02467
02468
02469
02470
02471
02472
02473
02474
02475 }
02476 else {
02477
02478
02479
02480
02481 if(!(_unification_based && block->is_unify()))
02482 roots.insert(block->top_most_container());
02483 else {
02484
02485
02486
02487 memoryblock_set tops = block->top_most_containers();
02488 for(memoryblock_set_p t=tops.begin(); t!=tops.end(); t++) {
02489 memoryBlock *one_top = *t;
02490 if(roots.find(one_top) != roots.end()) continue;
02491 if(one_top == block) { roots.insert(block); continue; }
02492 bool is_global =
02493 one_top->decl()->decl_location()==declNode::TOP ||
02494 !one_top->decl()->type() && !one_top->local_to();
02495 bool is_arg = false;
02496 if(! is_global)
02497 for(pointervalue_list_p a=arguments.begin();
02498 a!=arguments.end(); a++)
02499 if(a->blocks.find(one_top) != a->blocks.end())
02500 { is_arg=true; break; }
02501
02502 if(is_global || is_arg) {
02503 if(! gathered_external_uses_blocks) {
02504 for(memoryuse_set_p u=external_uses.begin();
02505 u!=external_uses.end(); u++)
02506 external_uses_blocks.insert((*u)->owner());
02507 gathered_external_uses_blocks = true;
02508 }
02509 if(external_uses_blocks.find(one_top) !=
02510 external_uses_blocks.end())
02511 roots.insert(one_top);
02512 }
02513 }
02514 }
02515 }
02516
02517
02518
02519
02520 if (computePointers) {
02521 if (! trivial_def && ! not_allocated) {
02522 new_outputs.insert(block);
02523
02524
02525
02526 }
02527 else
02528 if (pointerOptions::Verbose) {
02529 if (trivial_def)
02530 cout << " Skip external output " << block->name() << " -- trivial def" << endl;
02531 if (not_allocated)
02532 cout << " Skip external output " << block->name() << " -- no longer allocated" << endl;
02533 }
02534 }
02535
02536 if (! trivial_def && ! not_allocated) {
02537
02538
02539
02540 if (caller &&
02541 Procedures.is_visible_to(caller, block)) {
02542
02543
02544 proposed_external_changes.insert(block);
02545 }
02546
02547
02548
02549
02550
02551 }
02552
02553
02554
02555 block->reset_current_def_use((Location *)0);
02556 }
02557 }
02558 }
02559
02560 if (pointerOptions::Verbose)
02561 cout << endl;
02562
02563
02564
02565
02566
02567
02568
02569
02570
02571
02572
02573
02574
02575
02576
02577
02578
02579
02580
02581
02582
02583
02584
02585
02586
02587
02588
02589
02590
02591
02592
02593
02594 if (pointerOptions::Verbose) {
02595 cout << "Escape analysis at " << callee->name() << endl;
02596 }
02597
02598
02599
02600 declNode * return_var = callee->return_variable();
02601
02602 if (return_var) {
02603
02604
02605
02606 memoryBlock * return_block = Memory.lookup_variable(current, return_var, callee->proc());
02607 roots.insert(return_block);
02608 }
02609
02610
02611
02612 memoryblock_list worklist;
02613
02614 for (memoryblock_set_p p = roots.begin();
02615 p != roots.end();
02616 ++p)
02617 {
02618 worklist.push_back(*p);
02619 }
02620
02621 if (pointerOptions::Verbose) {
02622 print_memoryblock_set(" + Roots: ", roots, cout);
02623 }
02624
02625
02626
02627
02628 memoryblock_set unreachable;
02629
02630
02631
02632 if (pointerOptions::Use_escape_analysis) {
02633
02634
02635
02636
02637 memoryblock_set reachable(roots);
02638 reachable_blocks(last_stmt_of_proc, worklist, reachable);
02639
02640 if (pointerOptions::Verbose) {
02641 print_memoryblock_set(" + Reachable: ", reachable, cout);
02642 }
02643
02644
02645
02646
02647
02648
02649 for (memoryblock_set_p p = proposed_external_changes.begin();
02650 p != proposed_external_changes.end();
02651 ++p)
02652 {
02653 memoryBlock * one_change = (*p);
02654
02655 if(!(_unification_based && one_change->is_unify())) {
02656 memoryBlock * top_most = one_change->top_most_container();
02657 if (reachable.find(top_most) == reachable.end()) {
02658
02659
02660
02661 unreachable.insert(one_change);
02662 }
02663 else {
02664
02665
02666
02667
02668
02669 external_changes.insert(one_change);
02670 }
02671
02672 } else {
02673 memoryblock_set tops = one_change->top_most_containers();
02674 bool reach = false;
02675 for(memoryblock_set_p t=tops.begin(); !reach && t!=tops.end(); t++)
02676 if(reachable.find(*t) != reachable.end()) reach = true;
02677 if(! reach)
02678 unreachable.insert(one_change);
02679 else
02680 external_changes.insert(one_change);
02681 }
02682 }
02683 }
02684 else {
02685
02686
02687
02688 external_changes.insert(proposed_external_changes.begin(),
02689 proposed_external_changes.end());
02690 }
02691
02692
02693
02694 for (memoryblock_set_p p = new_inputs.begin();
02695 p != new_inputs.end();
02696 ++p)
02697 {
02698 memoryBlock * one_input = (*p);
02699
02700 if (unreachable.find(one_input) == unreachable.end())
02701 callee->add_external_input(one_input);
02702 }
02703
02704
02705
02706 for (memoryblock_set_p p = new_outputs.begin();
02707 p != new_outputs.end();
02708 ++p)
02709 {
02710 memoryBlock * one_output = (*p);
02711
02712 if (unreachable.find(one_output) == unreachable.end())
02713 callee->add_external_output(one_output);
02714 }
02715
02716
02717 if (pointerOptions::Show_memory_leaks) {
02718
02719
02720
02721 memoryblock_set leaks;
02722
02723 for (memoryblock_set_p p = unreachable.begin();
02724 p != unreachable.end();
02725 ++p)
02726 {
02727 memoryBlock * one_unreachable = (*p);
02728
02729 memoryuse_set ignore;
02730 Multiplicity multiplicity = current_multiplicity(callee, last_stmt_of_proc, one_unreachable, ignore);
02731
02732 if (multiplicity == Single) {
02733 leaks.insert(one_unreachable->top_most_container());
02734 }
02735 }
02736
02737 if (leaks.size() != 0) {
02738 cout << "WARNING: Potential memory leak at " << callee->name() << " (" << procedure->coord() << ")" << endl;
02739
02740 for (memoryblock_set_p p = leaks.begin();
02741 p != leaks.end();
02742 ++p)
02743 {
02744 memoryBlock * one_leak = *p;
02745 stmtLocation * alloc_site = one_leak->allocation_site();
02746
02747 if (alloc_site->stmt()->coord().is_unknown())
02748 alloc_site = alloc_site->block_location()->proc_location()->stmt_location();
02749
02750 cout << " + " << one_leak->name() << " allocated at " << alloc_site->stmt()->coord() << endl;
02751 }
02752 }
02753 }
02754
02755
02756 if (pointerOptions::Verbose) {
02757
02758 if (unreachable.size() > 0) {
02759
02760 cout << callee->name() << ": unreachable "
02761 << unreachable.size() << "/" << proposed_external_changes.size() << endl;
02762
02763 print_memoryblock_set(" Unreachable blocks: ", unreachable, cout);
02764
02765
02766
02767
02768
02769
02770
02771
02772
02773
02774
02775 }
02776 }
02777 }
02778
02779
02780
02781
02782
02783
02784 void Pointers::eval(procedureInfo * info,
02785 stmtLocation * current,
02786 exprNode * E,
02787 stmtNode *cur_stmt,
02788 memoryblock_set & defs,
02789 memoryuse_set & uses,
02790 memoryblock_set & changes,
02791 pointerValue & result,
02792 bool & never_returns)
02793 {
02794 switch (E->typ()) {
02795
02796 case Id:
02797 {
02798
02799
02800
02801 idNode * id = (idNode *) E;
02802 procLocation * procloc = Location::procedure(current);
02803 procNode * proc = procloc->proc();
02804 memoryBlock * mb = Memory.lookup_variable(procloc, id->decl(), proc);
02805 result.blocks.insert(mb);
02806
02807 if (mb->decl() == info->return_variable())
02808 mb->set_return_value();
02809
02810
02811
02812
02813 typeNode * the_type = NULL;
02814 if(id->decl()) the_type = id->decl()->no_tdef_type();
02815 if (the_type && the_type->typ() == Func)
02816 result.is_address = true;
02817
02818
02819
02820 if (result.is_a_use)
02821 generate_uses(info, current, uses, result);
02822
02823
02824
02825 _constants.at_id(current, id, result);
02826
02827
02828
02829 if (Problem)
02830 Problem->at_id(current, id, result);
02831 }
02832 break;
02833
02834 case Const:
02835 {
02836
02837
02838
02839 constNode * con = (constNode *) E;
02840
02841
02842
02843
02844
02845
02846
02847
02848
02849
02850
02851 if (con->value().is_str()) {
02852 memoryBlock * mb = Memory.lookup_string_constant(con);
02853 result.blocks.insert(mb);
02854 result.is_address = true;
02855 }
02856
02857
02858
02859 if (result.is_a_use)
02860 generate_uses(info, current, uses, result);
02861
02862
02863
02864 _constants.at_const(current, con, result);
02865
02866
02867
02868 if (Problem)
02869 Problem->at_const(current, con, result);
02870 }
02871 break;
02872
02873 case Operand:
02874 {
02875 operandNode * o = (operandNode *) E;
02876
02877
02878
02879
02880 bool o_is_lhs = (cur_stmt && cur_stmt->typ()==ThreeAddr &&
02881 ((threeAddrNode*)cur_stmt)->lhs()==o);
02882 if(o_is_lhs)
02883 result.is_a_use = o->index() || !o->fields().empty() || o->star();
02884 else
02885 result.is_a_use = ! o->addr() || o->index() || !o->fields().empty() ||
02886 o->star();
02887 eval(info, current, o->var(), cur_stmt,
02888 defs, uses, changes, result, never_returns);
02889
02890
02891 if(o->var()->typ() == Id &&
02892 ((idNode*)o->var())->decl()->no_tdef_type()->typ() == Func) {
02893 assert(result.is_address);
02894
02895 assert(! o->star() && o->fields().empty() && !o->index());
02896 if (o->cast() &&
02897 (!o->cast()->follow_tdefs()->type() ||
02898 o->cast()->follow_tdefs()->type()->typ() != Func))
02899 result.is_address = false;
02900 }
02901
02902
02903
02904
02905 if(o->star()) {
02906
02907
02908 pointerValue subexpr;
02909 subexpr.copy_pointers_from(result);
02910 result.initialize_pointers();
02911 if(o_is_lhs)
02912 result.is_a_use = !o->fields().empty() || o->index();
02913 star_operator(info, current, subexpr, defs, uses, changes, result);
02914 result.is_address = false;
02915
02916
02917
02918 if (result.is_a_use)
02919 generate_uses(info, current, uses, result);
02920
02921
02922
02923 _constants.at_dereference(current, o, result);
02924
02925
02926
02927 if (Problem)
02928 Problem->at_dereference(current, o, subexpr, result);
02929 }
02930
02931
02932 for(id_list_p f=o->fields().begin(); f!=o->fields().end(); f++) {
02933 pointerValue left;
02934 left.copy_pointers_from(result);
02935 result.initialize_pointers();
02936 if(o_is_lhs)
02937 result.is_a_use = (*f!=o->fields().back()) || o->index();
02938
02939 declNode * field_decl = (*f)->decl();
02940
02941
02942
02943 dot_operator(current, (*f)->name(), field_decl, left, uses, result);
02944
02945
02946
02947 if (result.is_a_use)
02948 generate_uses(info, current, uses, result);
02949
02950
02951
02952 if (Problem)
02953 Problem->at_field_access(current, o, left, result);
02954 }
02955 if (! o->fields().empty())
02956
02957 _constants.at_field_access(current, o, result);
02958
02959
02960 if(o->index()) {
02961 pointerValue left;
02962 left.copy_pointers_from(result);
02963 pointerValue right;
02964 result.initialize_pointers();
02965 if(o_is_lhs)
02966 result.is_a_use = false;
02967
02968
02969
02970 right.is_a_use = true;
02971
02972 eval(info, current, o->index(), cur_stmt,
02973 defs, uses, changes, right, never_returns);
02974
02975
02976
02977 star_operator(info, current, left, defs, uses, changes, result);
02978
02979
02980
02981 mark_as_indexed(result.blocks);
02982
02983
02984
02985 if (result.is_a_use)
02986 generate_uses(info, current, uses, result);
02987
02988
02989
02990 _constants.at_index(current, o, result);
02991
02992
02993
02994 if (Problem)
02995 Problem->at_index(current, o, left, right, result);
02996 }
02997
02998
02999 if(o->addr()) {
03000
03001
03002
03003 pointerValue subexpr;
03004 subexpr.copy_pointers_from(result);
03005 result.is_address = true;
03006
03007
03008
03009 _constants.at_address(current, o, result);
03010
03011
03012
03013 if (Problem)
03014 Problem->at_address(current, o, subexpr, result);
03015 }
03016
03017
03018 if(o->cast()) {
03019
03020
03021
03022
03023
03024
03025
03026 pointerValue operand;
03027 operand.copy_pointers_from(result);
03028 operand.constant_value = result.constant_value;
03029 _constants.at_cast(current, o, operand, result);
03030 if (Problem)
03031 Problem->at_cast(current, o, operand, result);
03032 }
03033 }
03034
03035 break;
03036
03037 default:
03038 {
03039
03040 assert(false);
03041 }
03042 }
03043 }
03044
03045
03046 void Pointers::eval(procedureInfo * info,
03047 stmtLocation * current,
03048 threeAddrNode *threeaddr,
03049 memoryblock_set & defs,
03050 memoryuse_set & uses,
03051 memoryblock_set & changes,
03052 pointerValue & result,
03053 bool & never_returns)
03054 {
03055 operandNode *rhs1 = threeaddr->rhs1(),
03056 *rhs2 = threeaddr->rhs2(),
03057 *lhs = threeaddr->lhs();
03058 Operator *op = threeaddr->op();
03059
03060 pointerValue rhs1_value, rhs2_value, rhs_value;
03061 bool is_call;
03062 pointerValue call_targets;
03063
03064 if(rhs1) {
03065 if(op && op->id() == Operator::FUNC_CALL) {
03066
03067 is_call = true;
03068 call_operator(info, current, rhs1, threeaddr->arg_list(), defs, uses,
03069 changes, rhs1_value, call_targets, never_returns);
03070 } else {
03071 is_call = false;
03072 rhs1_value.is_a_use = true;
03073 eval(info, current, rhs1, threeaddr, defs, uses, changes, rhs1_value,
03074 never_returns);
03075 }
03076 }
03077
03078 if(rhs2) {
03079 rhs2_value.is_a_use = true;
03080 eval(info, current, rhs2, threeaddr, defs, uses, changes, rhs2_value,
03081 never_returns);
03082 }
03083
03084 if(threeaddr->sizeof_type() || op && op->id()== Operator::SIZEOF) {
03085
03086
03087
03088
03089
03090 _constants.at_sizeof(current, threeaddr, rhs1_value, rhs_value);
03091
03092
03093
03094 if (Problem)
03095 Problem->at_sizeof(current, threeaddr, rhs1_value, rhs_value);
03096 }
03097
03098 if(rhs1 && !rhs2) {
03099 rhs_value.copy_pointers_from(rhs1_value);
03100 rhs_value.constant_value = rhs1_value.constant_value;
03101
03102 if(op && op->id() != Operator::FUNC_CALL) {
03103
03104
03105
03106
03107 if (rhs_value.is_a_use)
03108 generate_uses(info, current, uses, rhs_value);
03109
03110
03111
03112 _constants.at_unary(current, threeaddr, rhs1_value, rhs_value);
03113
03114
03115
03116 if (Problem)
03117 Problem->at_unary(current, threeaddr, rhs1_value, rhs_value);
03118 }
03119 }
03120
03121 if(rhs1 && rhs2) {
03122
03123
03124
03125
03126 assert(op);
03127 if ((op->id() == '+') || (op->id() == '-')) {
03128
03129
03130
03131 pointerValue left_after_star;
03132 star_operator(info, current, rhs1_value, defs, uses, changes,
03133 left_after_star);
03134
03135
03136
03137 pointerValue right_after_star;
03138 star_operator(info, current, rhs2_value, defs, uses, changes,
03139 right_after_star);
03140
03141
03142
03143
03144
03145
03146 bool pointers_on_left = (! left_after_star.blocks.empty());
03147 bool pointers_on_right = (! right_after_star.blocks.empty());
03148
03149 if (pointers_on_left &&
03150 pointers_on_right)
03151 {
03152
03153 }
03154 else
03155 {
03156 rhs_value.add_blocks_from(rhs1_value);
03157 rhs_value.add_blocks_from(rhs2_value);
03158 }
03159
03160 if (pointerOptions::Verbose &&
03161 (! rhs_value.blocks.empty())) {
03162 print_memoryblock_set("binaryOp: combination is: ", rhs_value.blocks, cout);
03163 print_memoryblock_set(" Left after star: ", left_after_star.blocks, cout);
03164 print_memoryblock_set(" Right after star: ", right_after_star.blocks, cout);
03165 }
03166
03167
03168
03169 if (rhs_value.is_a_use)
03170 generate_uses(info, current, uses, rhs_value);
03171 }
03172
03173
03174
03175 _constants.at_binary(current, threeaddr, rhs1_value, rhs2_value, rhs_value);
03176
03177
03178
03179 if (Problem)
03180 Problem->at_binary(current, threeaddr, rhs1_value, rhs2_value, rhs_value);
03181 }
03182
03183 if (lhs) {
03184
03185
03186
03187 pointerValue lhs_value;
03188 lhs_value.is_a_use = false;
03189 eval(info, current, lhs, threeaddr, defs, uses, changes, lhs_value,
03190 never_returns);
03191
03192
03193
03194 result.copy_pointers_from(lhs_value);
03195
03196
03197
03198 assignment_operator(info, current, (stmtLocation *)0, lhs_value, rhs_value, defs, uses, changes);
03199
03200
03201
03202 if (result.is_a_use)
03203 generate_uses(info, current, uses, result);
03204
03205
03206
03207 _constants.at_assignment(current, lhs_value, rhs_value, result, changes);
03208
03209
03210
03211 if (Problem)
03212 Problem->at_assignment(current, lhs_value, rhs_value, result, changes);
03213
03214
03215
03216 if(!rhs2 && rhs1) {
03217 typeNode * btype=NULL;
03218 if(!is_call)
03219 btype = rhs1->type()->follow_tdefs();
03220 else if(rhs1->cast())
03221 btype = rhs1->cast()->follow_tdefs();
03222 else if(! call_targets.blocks.empty()) {
03223
03224
03225 for(memoryblock_set_p c=call_targets.blocks.begin();
03226 !btype && c!=call_targets.blocks.end(); c++) {
03227 declNode *one_callee = (*c)->decl();
03228 if(one_callee && one_callee->type() &&
03229 one_callee->type()->follow_tdefs()->typ()==Func)
03230 btype = ((funcNode*) one_callee->type()->follow_tdefs())
03231 ->returns()->follow_tdefs();
03232 }
03233 if(!btype)
03234 btype = lhs->type()->follow_tdefs();
03235 }
03236
03237 if (btype &&
03238 ((btype->typ() == Struct) ||
03239 (btype->typ() == Union)))
03240 {
03241 sueNode * suetype = (sueNode *) btype;
03242 struct_union_assignment(info, current, threeaddr, suetype,
03243 lhs_value, rhs_value, defs, uses, changes);
03244 }
03245 }
03246 }
03247 }
03248
03249
03250
03251
03252
03253
03254
03255
03256
03257 #define print_pt2_set pointerOptions::Verbose // unify_debug
03258 #define p2MAX 2
03259
03260 void Pointers::star_operator(procedureInfo * info,
03261 Location * current,
03262 pointerValue & operand,
03263 memoryblock_set & defs,
03264 memoryuse_set & uses,
03265 memoryblock_set & changes,
03266 pointerValue & result)
03267 {
03268
03269
03270
03271
03272
03273 if (pointerOptions::Monitor_precision) {
03274 result.dereferenced.insert(operand.dereferenced.begin(),
03275 operand.dereferenced.end());
03276 }
03277
03278
03279
03280 if (operand.is_address) {
03281 result.copy_pointers_from(operand);
03282 result.is_address = false;
03283
03284 #ifdef check_pt2_size
03285 if(pointerOptions::Unification) {
03286 bool is_ellipsis = false;
03287 int points_to_size = 0;
03288 if(result.blocks.size() > 1) {
03289 if(print_pt2_set) cout << "star & operand: ";
03290 for(memoryblock_set_p p=operand.blocks.begin();p!=operand.blocks.end();++p)
03291 {
03292
03293
03294
03295
03296 if(print_pt2_set) cout << (*p)->name() << ",";
03297 string s = (*p)->name();
03298 if(s.find("...")<s.length() || is_va_list((*p)->decl())) is_ellipsis=true;
03299 bool is_block = s.find("malloc_#") < s.length(),
03300 is_string = s.find("__string_") < s.length();
03301 if(! (*p)->property && !is_string &&
03302 (is_block ||!(*p)->decl()->type() ||(*p)->decl()->type()->typ()!=Func))
03303 points_to_size++;
03304 }
03305 if(print_pt2_set) cout << endl;
03306 }
03307 if(points_to_size > 1 && !is_ellipsis) {
03308 if(UnificationBasedPtr::unify_points_to_max < points_to_size)
03309 UnificationBasedPtr::unify_points_to_max=points_to_size;
03310 if(print_pt2_set)
03311 cout << "Unification points-to=" << points_to_size << " (star&) max="
03312 << UnificationBasedPtr::unify_points_to_max << "\n";
03313 assert(UnificationBasedPtr::unify_points_to_max <p2MAX);
03314 }
03315 }
03316 #endif
03317
03318 return;
03319 }
03320
03321
03322
03323 for (memoryblock_set_p p = operand.blocks.begin();
03324 p != operand.blocks.end();
03325 ++p)
03326 {
03327 memoryBlock * mb = *p;
03328
03329 if (mb == Memory.null()) {
03330 if (pointerOptions::Verbose)
03331 cout << "ERROR: Attempt to access location zero." << endl;
03332 }
03333 else {
03334
03335
03336
03337
03338 memoryUse * use = mb->current_use();
03339 if ( ! use)
03340 use = mb->use_at(current);
03341
03342 if ( ! mb->is_return_value())
03343 uses.insert(use);
03344
03345
03346
03347
03348 memoryDef * def = use->reaching_def();
03349
03350 if (def) {
03351
03352 const memoryblock_set & points_to = def->points_to();
03353
03354 if (points_to.empty())
03355 if (pointerOptions::Verbose)
03356 cout << "ERROR: Attempt to dereference a pointer with no value:" <<
03357 mb->name() << endl;
03358
03359 #ifdef check_pt2_size
03360 if(pointerOptions::Unification) {
03361 bool is_ellipsis = false;
03362 int points_to_size = 0;
03363 if(points_to.size() > 1
03364
03365 ) {
03366 if(print_pt2_set) cout << "star operand: " << (*p)->name();
03367 string s = (*p)->name();
03368 if(print_pt2_set && (*p)->unifyType())
03369 cout << " {" << * (*p)->unifyType()->ecr() << "}";
03370 if(s.find("...") < s.length() || is_va_list((*p)->decl())) is_ellipsis=true;
03371 if(print_pt2_set) cout << " result: ";
03372 for (memoryblock_set_cp q=points_to.begin(); q!=points_to.end(); ++q)
03373 {
03374
03375
03376
03377 if(print_pt2_set) {
03378 cout << *q << " " << (*q)->name();
03379 if((*q)->unifyType()) cout << " {" << * (*q)->unifyType()->ecr() << "}";
03380 cout << ", ";
03381 }
03382 s = (*q)->name();
03383 bool is_block = s.find("malloc_#") < s.length(),
03384 is_string = s.find("__string_") < s.length();
03385 if(!(*q)->property && !is_string &&
03386 (is_block || !(*q)->decl()->type() ||
03387 (*q)->decl()->type()->typ()!=Func))
03388 points_to_size++;
03389 }
03390 if(print_pt2_set) cout << endl;
03391 }
03392 if(points_to_size > 1 && !is_ellipsis) {
03393 if(UnificationBasedPtr::unify_points_to_max < points_to_size)
03394 UnificationBasedPtr::unify_points_to_max=points_to_size;
03395 if(print_pt2_set)
03396 cout << "Unification points-to=" << points_to_size << " (star) max="
03397 << UnificationBasedPtr::unify_points_to_max << "\n";
03398 assert(UnificationBasedPtr::unify_points_to_max <p2MAX);
03399 }
03400 }
03401 #endif
03402
03403 bool may_point_to_null = false;
03404
03405 for (memoryblock_set_cp q = points_to.begin();
03406 q != points_to.end();
03407 ++q)
03408 {
03409 memoryBlock * target = *q;
03410
03411 if (target == Memory.null())
03412 may_point_to_null = true;
03413 else {
03414
03415
03416
03417
03418 result.blocks.insert(*q);
03419 }
03420 }
03421
03422 if (pointerOptions::Monitor_precision) {
03423
03424
03425
03426
03427 if (points_to.size() > 1)
03428 result.dereferenced.insert(mb);
03429 }
03430
03431
03432
03433
03434 if (0) {
03435
03436
03437
03438 pointerValue non_null_pointers;
03439
03440 for (memoryblock_set_cp q = points_to.begin();
03441 q != points_to.end();
03442 ++q)
03443 {
03444 memoryBlock * target = *q;
03445
03446 if (target != Memory.null())
03447 non_null_pointers.blocks.insert(target);
03448 }
03449
03450
03451
03452 pointerValue temp(mb);
03453
03454 assignment_operator(info, current, (stmtLocation *)0, temp, non_null_pointers, defs, uses, changes);
03455 }
03456
03457
03458 }
03459 }
03460
03461 if(pointerOptions::Unification && _unification_based) {
03462 UnifyType *mb_type = mb->is_unify() ? mb->unifyType() : NULL;
03463 if(mb_type &&
03464 (!mb->decl()->type() ||
03465 mb->decl()->no_tdef_type()->typ()!=Ptr ||
03466 mb->decl()->no_tdef_type()->no_tdef_type()->typ()!=Func) &&
03467 (mb_type->objTyp()==SIMPLE || mb_type->objTyp()==OBJECT)) {
03468 Unify_ECR *defer = _unification_based->ecrDeref(mb_type);
03469 if(defer && defer->type()->block())
03470 result.blocks.insert( defer->type()->block() );
03471 }
03472 }
03473 }
03474
03475
03476
03477 if (current->kind() == Location::Statement) {
03478
03479 stmtLocation * stmt_loc = (stmtLocation *) current;
03480
03481 }
03482 }
03483
03484
03485
03486
03487
03488 void Pointers::dot_operator(Location * current,
03489 const string & field_name,
03490 declNode * field_decl,
03491 pointerValue & operand,
03492 memoryuse_set & uses,
03493 pointerValue & result)
03494 {
03495 if (operand.is_address) {
03496 if (pointerOptions::Verbose)
03497 cout << "ERROR: Cannot apply \".\" to address." << endl;
03498 return;
03499 }
03500
03501 for (memoryblock_set_p p = operand.blocks.begin();
03502 p != operand.blocks.end();
03503 ++p)
03504 {
03505 memoryBlock * mb = *p;
03506
03507 if(pointerOptions::Unification && _unification_based &&
03508
03509
03510
03511 !mb->is_unify() && mb->decl()->type() &&
03512 mb->decl()->type()->typ()==Func) {
03513
03514
03515
03516
03517
03518
03519
03520 continue;
03521 }
03522
03523
03524 if (mb == Memory.null()) {
03525 if (pointerOptions::Verbose)
03526 cout << "ERROR: Attempt to access memory at address zero." << endl;
03527 }
03528 else {
03529
03530
03531
03532 memoryUse * use = mb->current_use();
03533 if ( ! use)
03534 use = mb->use_at(current);
03535
03536 if ( ! mb->is_return_value())
03537 uses.insert(use);
03538
03539 if (pointerOptions::Ignore_fields) {
03540
03541
03542
03543 result.blocks.insert(mb);
03544
03545
03546
03547 mb->set_indexed();
03548 }
03549 else {
03550
03551
03552
03553 memoryBlock * block = *p;
03554
03555 if (block->write_protected()) {
03556 if (pointerOptions::Verbose)
03557 cout << "ERROR at " << * current << ": attempt to access field " << field_name
03558 << " of write-protected block " << block->name() << endl;
03559 }
03560 else
03561 block->dot(field_name, field_decl, Memory, result.blocks);
03562 }
03563 }
03564
03565 if(pointerOptions::Unification && _unification_based) {
03566 UnifyType *mb_type = mb->is_unify() ? mb->unifyType() : NULL;
03567 if(mb_type &&
03568 (!field_decl->type() ||
03569 field_decl->no_tdef_type()->typ()!=Ptr ||
03570 field_decl->no_tdef_type()->no_tdef_type()->typ()!=Func) &&
03571 (mb_type->objTyp()==STRUCTURE || mb_type->objTyp()==OBJECT)) {
03572 bool from_annotation;
03573 Unify_ECR *field = _unification_based->ecrField(mb_type, field_decl,
03574 from_annotation);
03575 if(field && field->type()->block())
03576 result.blocks.insert( field->type()->block() );
03577 }
03578 }
03579 }
03580
03581
03582
03583 result.dereferenced.insert(operand.dereferenced.begin(),
03584 operand.dereferenced.end());
03585 #ifdef check_pt2_size
03586 if(pointerOptions::Unification) {
03587 int result_size = 0;
03588 if(result.blocks.size() > 1) {
03589 if(print_pt2_set) cout << "dot operand: ";
03590 for (memoryblock_set_p p=operand.blocks.begin();p!=operand.blocks.end();++p)
03591 {
03592 if(print_pt2_set) cout << (*p)->name() << ", ";
03593 }
03594 if(print_pt2_set) cout << "\nresult: ";
03595 for (memoryblock_set_p p=result.blocks.begin(); p!=result.blocks.end(); ++p)
03596 {
03597
03598
03599 if(print_pt2_set) cout << *p << " " << (*p)->name() << ", ";
03600 string s = (*p)->name();
03601 bool is_block = s.find("malloc_#") < s.length();
03602 if(! (*p)->property &&
03603 (is_block || (*p)->decl()->type()&& (*p)->decl()->type()->typ()!=Func))
03604 result_size++;
03605 }
03606 if(print_pt2_set) cout << endl;
03607 }
03608 if(result_size > 1) {
03609 if(UnificationBasedPtr::unify_points_to_max < result_size)
03610 UnificationBasedPtr::unify_points_to_max=result_size;
03611 if(print_pt2_set)
03612 cout << "Unification points-to=" << result_size << " (dot) max="
03613 << UnificationBasedPtr::unify_points_to_max << "\n";
03614 assert(UnificationBasedPtr::unify_points_to_max <p2MAX);
03615 }
03616 }
03617 #endif
03618 }
03619
03626 void Pointers::struct_union_assignment(procedureInfo * info,
03627 stmtLocation * current,
03628 threeAddrNode *threeaddr,
03629 sueNode * suetype,
03630 pointerValue & left_hand_side,
03631 pointerValue & right_hand_side,
03632 memoryblock_set & defs,
03633 memoryuse_set & uses,
03634 memoryblock_set & changes)
03635 {
03636
03637
03638 suespecNode * spec = suetype->spec();
03639
03640 if (spec) {
03641
03642 if (pointerOptions::Verbose)
03643 cout << "Struct/Union assignment: type is " << spec->name() << endl;
03644
03645 decl_list & fields = spec->fields();
03646
03647 for (decl_list_p p = fields.begin();
03648 p != fields.end();
03649 ++p)
03650 {
03651 declNode * field = *p;
03652
03653
03654
03655 pointerValue left_field;
03656
03657 dot_operator(current, field->name(), field,
03658 left_hand_side, uses, left_field);
03659
03660
03661
03662 pointerValue right_field;
03663
03664 dot_operator(current, field->name(), field,
03665 right_hand_side, uses, right_field);
03666
03667 generate_uses(info, current, uses, right_field);
03668
03669
03670
03671 assignment_operator(info, current, (stmtLocation *)0, left_field, right_field,
03672 defs, uses, changes);
03673
03674 pointerValue ignore_result;
03675
03676
03677
03678 _constants.at_assignment(current, left_field, right_field,
03679 ignore_result, changes);
03680
03681
03682
03683 if (Problem)
03684 Problem->at_assignment(current, left_field, right_field,
03685 ignore_result, changes);
03686
03687
03688
03689
03690 typeNode * field_type = field->no_tdef_type();
03691
03692 if ((field_type->typ() == Struct) ||
03693 (field_type->typ() == Union))
03694 {
03695 sueNode * field_suetype = (sueNode *) field_type;
03696
03697 struct_union_assignment(info, current, threeaddr, field_suetype,
03698 left_field, right_field, defs, uses, changes);
03699 }
03700 }
03701 }
03702 }
03703
03712 void Pointers::assignment_operator(procedureInfo * info,
03713 Location * current,
03714 stmtLocation * parameter_callsite,
03715 pointerValue & left_hand_side,
03716 pointerValue & right_hand_side,
03717 memoryblock_set & defs,
03718 memoryuse_set & uses,
03719 memoryblock_set & changes)
03720 {
03721 bool unique_lhs = false;
03722 bool changed = false;
03723
03724
03725
03726 if (left_hand_side.blocks.empty())
03727 return;
03728
03729
03730
03731 const constant * right_c = right_hand_side.constant_value;
03732
03733
03734
03735 memoryblock_set rhs_points_to;
03736
03737
03738
03739 int min_size = 999999;
03740 bool any_must_pointers = false;
03741 memoryblock_set complicit_pointers;
03742
03743
03744
03745 if (right_hand_side.is_address) {
03746
03747
03748
03749
03750 memoryblock_set & rhs_blocks = right_hand_side.blocks;
03751
03752 rhs_points_to.insert(rhs_blocks.begin(),
03753 rhs_blocks.end());
03754
03755
03756
03757
03758 min_size = 1;
03759 }
03760 else {
03761
03762
03763
03764
03765 for (memoryblock_set_p q = right_hand_side.blocks.begin();
03766 q != right_hand_side.blocks.end();
03767 ++q)
03768 {
03769 memoryBlock * right = *q;
03770
03771
03772
03773
03774 memoryUse * right_use = right->current_use();
03775 if ( ! right_use)
03776 right_use = right->use_at(current);
03777
03778
03779
03780
03781 memoryDef * reaching_def = right_use->reaching_def();
03782 if (reaching_def) {
03783 const memoryblock_set & reaching_points_to = reaching_def->points_to();
03784
03785 rhs_points_to.insert(reaching_points_to.begin(),
03786 reaching_points_to.end());
03787
03788
03789
03790 if (pointerOptions::Monitor_precision) {
03791
03792 int size = reaching_points_to.size();
03793 if (size < min_size)
03794
03795 min_size = size;
03796
03797 if (size > 1)
03798 complicit_pointers.insert(right);
03799 }
03800
03801 }
03802 else
03803 if (pointerOptions::Verbose) {
03804 cout << "WARNING: Variable " << right->name() <<
03805 " may not have a value at " << *current << endl;
03806 right->print_def_use(cout);
03807 }
03808
03809 if(pointerOptions::Unification && _unification_based) {
03810 UnifyType *right_type = right->is_unify() ?
03811 right->unifyType() : NULL;
03812 if(right_type &&
03813 (!right->decl()->type() ||
03814 right->decl()->no_tdef_type()->typ()!=Ptr ||
03815 right->decl()->no_tdef_type()->no_tdef_type()->typ()!=Func) &&
03816 (right_type->objTyp()==SIMPLE || right_type->objTyp()==OBJECT)) {
03817 Unify_ECR *defer = _unification_based->ecrDeref(right_type);
03818 if(defer && defer->type()->block()) {
03819 rhs_points_to.insert( defer->type()->block() );
03820 }
03821 }
03822 }
03823
03824 }
03825 }
03826
03827
03828
03829
03830
03831 if (left_hand_side.blocks.size() == 1 &&
03832 ! left_hand_side.blocks.front()->is_indexed())
03833 unique_lhs = true;
03834
03835
03836
03837 if (current->kind() == Location::Statement) {
03838
03839 stmtLocation * stmt_loc = (stmtLocation *) current;
03840
03841 }
03842
03843
03844
03845 int rhs_points_to_size = rhs_points_to.size();
03846
03847
03848
03849
03850
03851
03852
03853
03854
03855 if (pointerOptions::Monitor_precision) {
03856
03857 if ((rhs_points_to_size > 1) && (rhs_points_to_size > min_size))
03858 complicit_pointers.insert(right_hand_side.dereferenced.begin(),
03859 right_hand_side.dereferenced.end());
03860 }
03861
03862
03863
03864 if (pointerOptions::Bidirectional_assignment) {
03865
03866
03867
03868
03869
03870
03871 if ( ! right_hand_side.is_address) {
03872 left_hand_side.blocks.insert(right_hand_side.blocks.begin(),
03873 right_hand_side.blocks.end());
03874 }
03875
03876
03877
03878
03879 for (memoryblock_set_p p = left_hand_side.blocks.begin();
03880 p != left_hand_side.blocks.end();
03881 ++p)
03882 {
03883 memoryBlock * left = *p;
03884
03885 memoryDef * def = left->find_def_at(current);
03886 if (def) {
03887 const memoryblock_set & points_to = def->points_to();
03888
03889 rhs_points_to.insert(points_to.begin(),
03890 points_to.end());
03891 }
03892 }
03893 }
03894
03895
03896
03897 for (memoryblock_set_p p = left_hand_side.blocks.begin();
03898 p != left_hand_side.blocks.end();
03899 ++p)
03900 {
03901 memoryBlock * left = *p;
03902
03903
03904
03905 if ( ! left->write_protected()) {
03906
03907
03908
03909 bool is_new;
03910 memoryDef * left_def = left->def_at(current, is_new);
03911
03912 #ifdef COLLECT_DEFS
03913 defs.insert(left);
03914 #endif
03915
03916
03917
03918 if (computePointers) {
03919
03920
03921
03922
03923 if (is_new) {
03924 changes.insert(left);
03925 changed = true;
03926 }
03927
03928
03929
03930
03931
03932 memoryblock_set previous = left_def->points_to();
03933
03934
03935
03936 bool single_multiplicity = false;
03937 bool strong_update = true;
03938 memoryDef * reaching_def = 0;
03939 bool reaching_def_is_must_pointer = false;
03940
03941 Multiplicity multiplicity = current_multiplicity(info, current, left, uses);
03942
03943 if (left->is_flow_sensitive()) {
03944
03945
03946
03947
03948
03949 single_multiplicity = ((multiplicity == Unallocated) ||
03950 (multiplicity == Deallocated) ||
03951 (multiplicity == Single));
03952
03953 strong_update = unique_lhs && single_multiplicity;
03954
03955
03956
03957
03958
03959
03960
03961 if ( ! strong_update) {
03962
03963
03964
03965
03966 reaching_def = nearest_def_at(info, left, current);
03967
03968
03969
03970
03971
03972 if ( ! left_def->is_weak()) {
03973 changes.insert(left);
03974 changed = true;
03975 }
03976
03977 left->apply_weak_update(current, reaching_def, uses);
03978
03979
03980
03981
03982
03983
03984
03985 }
03986 }
03987
03988
03989
03990
03991
03992
03993
03994
03995
03996
03997
03998
03999
04000
04001
04002
04003
04004
04005
04006 left_def->add_pointers(rhs_points_to);
04007
04008 if(pointerOptions::Unification && _unification_based) {
04009 UnifyType *left_type = left->is_unify() ?
04010 left->unifyType() : NULL;
04011 if(left_type &&
04012 (!left->decl()->type() ||
04013 left->decl()->no_tdef_type()->typ()!=Ptr ||
04014 left->decl()->no_tdef_type()->no_tdef_type()->typ()!=Func) &&
04015 (left_type->objTyp()==SIMPLE || left_type->objTyp()==OBJECT)) {
04016 Unify_ECR *defer = _unification_based->ecrDeref(left_type);
04017 if(defer && defer->type()->block()) {
04018 memoryblock_set left_point_to;
04019 left_point_to.insert( defer->type()->block() );
04020 left_def->add_pointers( left_point_to );
04021 }
04022 }
04023 }
04024
04025 const memoryblock_set & lhs_points_to = left_def->points_to();
04026
04027
04028
04029
04030
04031
04032
04033
04034
04035
04036
04037
04038
04039
04040
04041
04042 if (pointerOptions::Monitor_precision) {
04043
04044
04045
04046
04047 if ((parameter_callsite) &&
04048 (current->kind() == Location::Procedure))
04049 {
04050 procLocation * procloc = (procLocation *) current;
04051
04052 left->add_parameter_assignment(procloc->proc(),
04053 parameter_callsite,
04054 right_hand_side.blocks);
04055 }
04056
04057 if (lhs_points_to.size() > 1) {
04058
04059
04060
04061 left->add_complicit_assignment(current, complicit_pointers);
04062
04063
04064
04065
04066 if (rhs_points_to_size < lhs_points_to.size()) {
04067
04068
04069
04070 if (strong_update) {
04071
04072
04073
04074
04075
04076
04077 if (current->kind() == Location::Statement) {
04078
04079
04080
04081
04082 left->add_destructive_assignment(current, memoryBlock::Additive);
04083 }
04084
04085 if (current->kind() == Location::Procedure) {
04086
04087
04088
04089
04090
04091 left->add_destructive_assignment(current, memoryBlock::Parameter_pass);
04092 }
04093 }
04094 else {
04095
04096
04097
04098 if (reaching_def &&
04099 (reaching_def->points_to().size() < lhs_points_to.size())) {
04100
04101
04102
04103
04104 if ( ! single_multiplicity) {
04105
04106
04107
04108
04109
04110
04111
04112
04113
04114
04115 memoryBlock * alloc_object = left->allocation_object();
04116 if (alloc_object)
04117 left->add_complicit_assignment(current, alloc_object);
04118 else
04119 left->add_destructive_assignment(current, memoryBlock::Weak_update);
04120 }
04121
04122 if ( ! unique_lhs) {
04123
04124
04125
04126
04127 left->add_complicit_assignment(current, left_hand_side.dereferenced);
04128 }
04129 }
04130 }
04131 }
04132 }
04133 }
04134
04135
04136
04137 if (lhs_points_to != previous) {
04138 changes.insert(left);
04139 #ifdef check_pt2_size
04140 if(pointerOptions::Unification) {
04141 bool is_ellipsis = false;
04142 int points_to_size = 0;
04143 if(lhs_points_to.size() > 1) {
04144 if(print_pt2_set) cout << "lhs_points_to: ";
04145 for(memoryblock_set_cp p=lhs_points_to.begin(); p!=lhs_points_to.end(); ++p)
04146 {
04147
04148
04149
04150
04151 if(print_pt2_set) cout << (*p)->name() << ",";
04152 string s = (*p)->name();
04153 if(s.find("...")<s.length() || is_va_list((*p)->decl())) is_ellipsis=true;
04154 bool is_block = s.find("malloc_#") < s.length(),
04155 is_string = s.find("__string_") < s.length();
04156 if(! (*p)->property && !is_string &&
04157 (is_block ||!(*p)->decl()->type() ||(*p)->decl()->type()->typ()!=Func))
04158 points_to_size++;
04159 }
04160 if(print_pt2_set) cout << endl;
04161 }
04162 if(points_to_size > 1 && !is_ellipsis) {
04163 if(UnificationBasedPtr::unify_points_to_max < points_to_size)
04164 UnificationBasedPtr::unify_points_to_max=points_to_size;
04165 if(print_pt2_set)
04166 cout << "Unification points-to=" << points_to_size
04167 << " (lhs_points_to) max="
04168 << UnificationBasedPtr::unify_points_to_max << "\n";
04169 assert(UnificationBasedPtr::unify_points_to_max <p2MAX);
04170 }
04171 }
04172 #endif
04173 changed = true;
04174
04175
04176
04177
04178
04179
04180
04181
04182
04183
04184
04185
04186
04187
04188
04189
04190
04191
04192
04193 }
04194
04195 if (pointerOptions::Verbose) {
04196
04197 if (left->is_flow_sensitive()) {
04198 if (strong_update)
04199 cout << " Strong assign -- ";
04200 else
04201 cout << " Weak assign -- ";
04202 }
04203 else
04204 cout << " Flow-insensitive assign -- ";
04205
04206 memoryBlock::print_multiplicity(multiplicity, cout);
04207 cout << " -- ";
04208
04209 if (changed)
04210 cout << "changed: ";
04211 else
04212 cout << "unchanged: ";
04213
04214 cout << left->name() << endl;
04215 left_def->print(cout);
04216
04217 if ( ! lhs_points_to.empty())
04218 print_memoryblock_set(" points-to NOW: ", lhs_points_to, cout);
04219
04220 if (reaching_def) {
04221 cout << " Reaching def at " << * (reaching_def->where());
04222 print_memoryblock_set(" before assignment: ", reaching_def->points_to(), cout);
04223 }
04224
04225 if (changed && ( ! previous.empty()))
04226 print_memoryblock_set(" points-to WAS: ", previous, cout);
04227
04228 cout << endl;
04229 }
04230 }
04231 else {
04232
04233
04234
04235
04236
04237
04238 if (left_def->is_weak()) {
04239 memoryUse * use = left->use_at(current);
04240
04241 }
04242
04243 if (is_new) {
04244
04245 if (pointerOptions::Verbose) {
04246 cout << "WARNING: in assignment: No new defs of " << left->name()
04247 << " should be created at " << *current << " in ";
04248 Procedures.print_call_stack(cout);
04249 cout << endl;
04250 }
04251
04252 changes.insert(left);
04253 }
04254 }
04255 }
04256 }
04257 }
04258
04259 void Pointers::merge_operator(procedureInfo * info,
04260 Location * merge_point,
04261 memoryBlock * block_to_merge,
04262 memoryuse_list & phi_uses,
04263 memoryblock_set & defs,
04264 memoryuse_set & uses,
04265 memoryblock_set & changes)
04266 {
04267 bool changed = false;
04268
04269
04270
04271 if (block_to_merge->write_protected())
04272 return;
04273
04274
04275
04276 bool is_new;
04277 memoryDef * def = block_to_merge->def_at(merge_point, is_new);
04278
04279 #ifdef COLLECT_DEFS
04280 defs.insert(block_to_merge);
04281 #endif
04282
04283
04284
04285 if (computePointers) {
04286
04287
04288
04289
04290 if (is_new) {
04291 changes.insert(block_to_merge);
04292 changed = true;
04293 }
04294
04295 if (block_to_merge->is_allocation_object()) {
04296
04297
04298
04299
04300
04301
04302 Multiplicity old_multiplicity = def->multiplicity();
04303
04304
04305
04306 Multiplicity multiplicity = Unallocated;
04307
04308
04309
04310 Multiplicity min = Error;
04311
04312 for (memoryuse_list_p use_p = phi_uses.begin();
04313 use_p != phi_uses.end();
04314 ++use_p)
04315 {
04316 memoryUse * use = *use_p;
04317
04318 uses.insert(use);
04319
04320
04321
04322 memoryDef * reaching_def = use->reaching_def();
04323 if (reaching_def) {
04324
04325
04326
04327
04328
04329 Multiplicity reaching_multiplicity = reaching_def->multiplicity();
04330
04331 if (reaching_multiplicity > multiplicity)
04332 multiplicity = reaching_multiplicity;
04333
04334
04335
04336
04337 if (reaching_multiplicity < min)
04338 min = reaching_multiplicity;
04339 }
04340 }
04341
04342
04343
04344
04345
04346
04347 if (pointerOptions::Aggressive_multiplicity) {
04348
04349 if ((multiplicity == Single) &&
04350 (min == Deallocated))
04351 multiplicity = Unallocated;
04352 }
04353
04354
04355
04356 if (old_multiplicity > multiplicity)
04357 multiplicity = old_multiplicity;
04358
04359
04360
04361 def->set_multiplicity(multiplicity);
04362
04363
04364
04365 if (multiplicity != old_multiplicity) {
04366 changes.insert(block_to_merge);
04367 changed = true;
04368 }
04369
04370 if (pointerOptions::Verbose) {
04371 cout << "Merge -- ";
04372
04373 if (changed)
04374 cout << "changed: ";
04375 else
04376 cout << "unchanged: ";
04377
04378 cout << block_to_merge->name() << " : ";
04379
04380 memoryBlock::print_multiplicity(old_multiplicity, cout);
04381 cout << " -> ";
04382 memoryBlock::print_multiplicity(multiplicity, cout);
04383 cout << endl;
04384
04385 def->print(cout);
04386 cout << endl;
04387 }
04388 }
04389 else {
04390
04391
04392
04393
04394
04395
04396 memoryblock_set previous = def->points_to();
04397
04398
04399
04400 bool any_must_pointers = false;
04401
04402
04403
04404 memoryblock_set merged_points_to;
04405
04406 for (memoryuse_list_p use_p = phi_uses.begin();
04407 use_p != phi_uses.end();
04408 ++use_p)
04409 {
04410 memoryUse * use = *use_p;
04411
04412 if (! use) {
04413
04414 cout << "ERROR: block " << block_to_merge->name() << " at " << *merge_point << endl;
04415 cout << " Num uses = " << phi_uses.size() << endl;
04416 block_to_merge->print_def_use(cout);
04417 }
04418
04419 uses.insert(use);
04420
04421
04422
04423
04424
04425
04426 memoryDef * reaching_def = use->reaching_def();
04427 if (reaching_def) {
04428 const memoryblock_set & reaching_points_to = reaching_def->points_to();
04429
04430 if (reaching_points_to.size() <= 1)
04431 any_must_pointers = true;
04432
04433 merged_points_to.insert(reaching_points_to.begin(),
04434 reaching_points_to.end());
04435 }
04436 }
04437
04438
04439
04440 def->add_pointers(merged_points_to);
04441
04442
04443
04444 if (pointerOptions::Monitor_precision) {
04445
04446 if ((def->points_to().size() > 1) &&
04447 any_must_pointers) {
04448
04449
04450
04451 block_to_merge->add_destructive_assignment(merge_point, memoryBlock::Control_flow);
04452 }
04453 }
04454
04455
04456
04457 if (def->points_to() != previous) {
04458 changes.insert(block_to_merge);
04459 changed = true;
04460 }
04461
04462 if (pointerOptions::Verbose) {
04463 cout << "Merge -- ";
04464
04465 if (changed)
04466 cout << "changed: ";
04467 else
04468 cout << "unchanged: ";
04469
04470 cout << block_to_merge->name() << endl;
04471 def->print(cout);
04472
04473 if ( ! def->points_to().empty())
04474 print_memoryblock_set(" points-to: ", def->points_to(), cout);
04475 cout << endl;
04476 }
04477 }
04478 }
04479 else {
04480
04481
04482
04483 if (is_new) {
04484
04485 if (pointerOptions::Verbose) {
04486 cout << "WARNING: in merge: No new defs of " << block_to_merge->name() <<
04487 " should be created at " << * merge_point << endl;
04488 Procedures.print_call_stack(cout);
04489
04490 cout << endl;
04491
04492 block_to_merge->print_def_use(cout);
04493
04494 cout << endl;
04495 }
04496
04497 changes.insert(block_to_merge);
04498 }
04499 }
04500 }
04501
04508 void Pointers::self_assignment(Location * source,
04509 Location * target,
04510 memoryBlock * block,
04511 memoryblock_set & changes)
04512 {
04513 bool changed = false;
04514
04515
04516
04517 if (block->write_protected())
04518 return;
04519
04520
04521
04522 bool is_new;
04523 memoryDef * def = block->def_at(target, is_new);
04524
04525
04526
04527
04528 memoryUse * use = block->use_at(source);
04529
04530
04531
04532 def->set_self_assign_use(use);
04533
04534
04535
04536 memoryDef * reaching_def = use->reaching_def();
04537
04538
04539
04540 if (computePointers) {
04541
04542
04543
04544
04545 if (is_new) {
04546 changes.insert(block);
04547 changed = true;
04548 }
04549
04550
04551
04552 if ( ! block->is_flow_sensitive())
04553 return;
04554
04555
04556
04557 if ((target->kind() == Location::Procedure) &&
04558 (source->kind() == Location::Statement))
04559 {
04560 procLocation * procloc = (procLocation *) target;
04561 stmtLocation * callsite = (stmtLocation *) source;
04562
04563
04564
04565 if ( ! block->property)
04566 block->add_parameter_assignment(procloc->proc(),
04567 callsite,
04568 block);
04569 }
04570
04571 if (block->is_allocation_object()) {
04572
04573
04574
04575
04576
04577
04578 Multiplicity old_multiplicity = def->multiplicity();
04579
04580
04581
04582
04583 Multiplicity reaching_multiplicity = Unallocated;
04584 if (reaching_def)
04585 reaching_multiplicity = reaching_def->multiplicity();
04586
04587
04588
04589 Multiplicity multiplicity;
04590
04591 if (old_multiplicity > reaching_multiplicity)
04592 multiplicity = old_multiplicity;
04593 else
04594 multiplicity = reaching_multiplicity;
04595
04596
04597
04598 def->set_multiplicity(multiplicity);
04599
04600
04601
04602
04603 if (pointerOptions::Monitor_precision) {
04604
04605
04606
04607
04608
04609
04610 if (((old_multiplicity == Single) && (reaching_multiplicity == Unbounded)) ||
04611 ((old_multiplicity == Unbounded) && (reaching_multiplicity == Single))) {
04612
04613
04614
04615
04616
04617
04618
04619
04620
04621 block->add_destructive_assignment(target, memoryBlock::Parameter_pass);
04622 }
04623 }
04624
04625
04626
04627 if (multiplicity != old_multiplicity) {
04628 changes.insert(block);
04629 changed = true;
04630 }
04631
04632 if (pointerOptions::Verbose) {
04633 cout << " Self-assign -- ";
04634
04635 if (changed)
04636 cout << "changed: ";
04637 else
04638 cout << "unchanged: ";
04639
04640 cout << block->name() << " : ";
04641
04642 memoryBlock::print_multiplicity(old_multiplicity, cout);
04643 cout << " -> ";
04644 memoryBlock::print_multiplicity(multiplicity, cout);
04645 cout << endl;
04646
04647 def->print(cout);
04648 }
04649 }
04650 else {
04651
04652
04653
04654
04655
04656
04657 memoryblock_set previous = def->points_to();
04658
04659
04660
04661 if (reaching_def) {
04662
04663
04664
04665 def->add_pointers(reaching_def->points_to());
04666 }
04667
04668
04669
04670 if (pointerOptions::Monitor_precision) {
04671
04672 memoryBlock * current = block;
04673
04674
04675
04676 while (current->container()) {
04677 if(_unification_based && current == current->container())
04678 break;
04679 current = current->container();
04680 }
04681
04682 if (current->decl()->decl_location() == declNode::TOP) {
04683 if (reaching_def &&
04684 (previous.size() > 0) &&
04685 (reaching_def->points_to().size() > 0) &&
04686 (def->points_to().size() > reaching_def->points_to().size())) {
04687
04688
04689
04690
04691 block->add_destructive_assignment(target, memoryBlock::Parameter_pass);
04692 }
04693 }
04694 }
04695
04696
04697
04698 if (def->points_to() != previous) {
04699 changes.insert(block);
04700 changed = true;
04701 }
04702
04703 if (pointerOptions::Verbose) {
04704 cout << " Self-assign -- ";
04705
04706 if (changed)
04707 cout << "changed: ";
04708 else
04709 cout << "unchanged: ";
04710
04711 cout << block->name() << endl;
04712 cout << " From " << * source << " to " << * target << endl;
04713 def->print(cout);
04714
04715 if ( ! def->points_to().empty())
04716 print_memoryblock_set(" points-to: ", def->points_to(), cout);
04717 cout << endl;
04718 }
04719 }
04720 }
04721 else {
04722
04723
04724
04725 if (is_new) {
04726
04727 if (pointerOptions::Verbose) {
04728 cout << "ERROR in Self-assign: No new defs of " << block->name() <<
04729 " should be created at " << * target << endl;
04730 Procedures.print_call_stack(cout);
04731 cout << endl;
04732 }
04733
04734
04735 changes.insert(block);
04736 }
04737 }
04738 }
04739
04740
04741 void Pointers::call_operator(procedureInfo * caller,
04742 stmtLocation * current,
04743 operandNode * call,
04744 operand_list & args,
04745 memoryblock_set & defs,
04746 memoryuse_set & uses,
04747 memoryblock_set & changes,
04748 pointerValue & result,
04749 pointerValue & call_targets,
04750 bool & never_returns)
04751 {
04752
04753
04754
04755 pointervalue_list actuals;
04756
04757 for (operand_list_p p = args.begin();
04758 p != args.end();
04759 ++p)
04760 {
04761 operandNode * actual = * p;
04762 actuals.push_back(pointerValue());
04763 pointerValue & actual_results = actuals.back();
04764
04765
04766
04767 actual_results.is_a_use = true;
04768 eval(caller, current, actual, NULL,
04769 defs, uses, changes, actual_results, never_returns);
04770 }
04771
04772 if (pointerOptions::Verbose) {
04773 cout << " Arguments:" << endl;
04774 int count = 0;
04775 for (pointervalue_list_p p = actuals.begin();
04776 p != actuals.end();
04777 ++p)
04778 {
04779 cout << " Arg " << count << " : ";
04780 if ((*p).is_address)
04781 cout << "pointer-to: ";
04782 print_memoryblock_set("", (*p).blocks, cout);
04783 count++;
04784 }
04785 cout << endl;
04786 }
04787
04788
04789
04790 determine_call_targets(caller, current, call, defs, uses, changes, call_targets);
04791
04792
04793
04794
04795 if (call_targets.blocks.size() == 0) {
04796
04797 if (pointerOptions::Verbose)
04798 cout << "WARNING: No call target at " << call->coord() << " -- " << * current << endl;
04799 }
04800 else {
04801
04802
04803
04804
04805
04806
04807
04808
04809
04810
04811
04812
04813
04814
04815
04816
04817
04818
04819
04820
04821
04822
04823
04824 for (memoryblock_set_p p = call_targets.blocks.begin();
04825 p != call_targets.blocks.end();
04826 ++p)
04827 {
04828 memoryBlock * current_target = *p;
04829 bool local_never_returns = false;
04830
04831 procedure_call(caller, current,
04832 call, args, call_targets, current_target, actuals,
04833 defs, uses, changes, result, local_never_returns);
04834
04835 if (local_never_returns)
04836 never_returns = true;
04837 }
04838 }
04839 }
04840
04841 void Pointers::determine_call_targets(procedureInfo * caller,
04842 stmtLocation * current,
04843 operandNode * call,
04844 memoryblock_set & defs,
04845 memoryuse_set & uses,
04846 memoryblock_set & changes,
04847 pointerValue & call_targets)
04848 {
04849
04850
04851
04852 pointerValue temp;
04853 bool exit_not_allowed_here;
04854
04855 if(! ((idNode*)call->var())->decl())
04856 temp.is_address = true;
04857 eval(caller, current, call, NULL,
04858 defs, uses, changes, temp, exit_not_allowed_here);
04859
04860
04861
04862
04863
04864
04865
04866
04867
04868
04869
04870
04871 bool func_ptr = false;
04872
04873 assert (((idNode*)call->var())->typ() == Id);
04874 if(call->star() || call->index() || !call->fields().empty())
04875 func_ptr = true;
04876 else {
04877 idNode * call_name = (idNode *) call->var();
04878 if (call_name->decl()->no_tdef_type()->typ() != Func)
04879 func_ptr = true;
04880 }
04881
04882
04883
04884
04885
04886
04887
04888
04889
04890
04891
04892
04893
04894
04895 if (func_ptr) {
04896 temp.is_address = false;
04897
04898
04899 if(call->no_tdef_type()->typ() != Func)
04900 star_operator(caller, current, temp, defs, uses, changes, call_targets);
04901 else
04902 call_targets.copy_pointers_from(temp);
04903
04904 if(_unification_based && pointerOptions::Unification) {
04905
04906
04907 assert(current && current->stmt()->typ() == ThreeAddr);
04908 int actuals = ((threeAddrNode*) current->stmt())->arg_list().size();
04909 memoryblock_set call_targets_blocks = call_targets.blocks;
04910 call_targets.blocks.clear();
04911 for (memoryblock_set_p c = call_targets_blocks.begin();
04912 c != call_targets_blocks.end(); c++) {
04913 string c_name = (*c)->name();
04914 if(c_name == "null" || c_name.find("__string_") < c_name.length())
04915 continue;
04916 UnifyType *one = (*c)->is_unify() ? (*c)->unifyType() : NULL;
04917
04918
04919 if(! one)
04920 call_targets.blocks.insert(*c);
04921
04922
04923
04924
04925
04926
04927
04928
04929
04930
04931
04932
04933
04934
04935
04936
04937
04938
04939
04940
04941
04942
04943
04944
04945
04946
04947
04948
04949 }
04950 }
04951
04952 } else {
04953 if(! _unification_based)
04954 call_targets = temp;
04955 else {
04956
04957
04958 if(! temp.blocks.empty()) {
04959 assert(temp.blocks.size() == 1);
04960 UnifyType *one = temp.blocks.front()->is_unify() ?
04961 temp.blocks.front()->unifyType() : NULL ;
04962 if(one) {
04963 for(set<procNode*>::iterator p=one->procs().begin();
04964 p!=one->procs().end(); p++)
04965
04966 if((*p)->decl()->name() == ((idNode*)call->var())->name()) {
04967 UnifyType *proc_type = _unification_based->proctype(*p);
04968 assert(proc_type);
04969 if(!proc_type->block()) {
04970
04971 procLocation * cur_proc_loc = Location::procedure(current);
04972 procNode * cur_proc = cur_proc_loc->proc();
04973 _unification_based->createProcBlock(*p, Memory, cur_proc_loc);
04974 }
04975 call_targets.blocks.insert( proc_type->block() );
04976 }
04977 if(one->procs().empty()) call_targets = temp;
04978 assert(call_targets.blocks.size() <= 1);
04979 } else
04980 call_targets = temp;
04981 }
04982 }
04983 }
04984
04985 if (pointerOptions::Verbose) {
04986 cout << "Call targets:" << endl;
04987 for (memoryblock_set_p p = call_targets.blocks.begin();
04988 p != call_targets.blocks.end();
04989 ++p) {
04990 cout << " + " << (*p)->name() << endl;
04991 }
04992 }
04993 }
04994
04995 void Pointers::generate_uses(procedureInfo * info,
04996 Location * where,
04997 memoryuse_set & uses,
04998 pointerValue & pointer)
04999 {
05000 if ( ! pointer.is_address ) {
05001
05002 for (memoryblock_set_p p = pointer.blocks.begin();
05003 p != pointer.blocks.end();
05004 ++p)
05005 {
05006 memoryBlock * block = (*p);
05007
05008
05009
05010
05011 memoryUse * use = block->use_at(where);
05012
05013 if ( ! block->is_return_value())
05014 uses.insert(use);
05015
05016
05017
05018
05019 if (computePointers) {
05020
05021
05022
05023 memoryDef * def = nearest_def_at(info, block, where);
05024 use->reaching_def(def);
05025 }
05026 }
05027 }
05028 }
05029
05038 memoryDef * Pointers::nearest_def_at(procedureInfo * info,
05039 memoryBlock * block,
05040 Location * where)
05041 {
05042 if (pointerOptions::Verbose) {
05043 cout << " + Look for reaching def of " << block->name() << " at " << * where << endl;
05044 if (info)
05045 cout << " (procedure is " << info->name() << ")" << endl;
05046 else
05047 cout << " (no procedure)" << endl;
05048 }
05049
05050 memoryDef * def = block->nearest_def_at(where);
05051 procedureInfo * current_info = 0;
05052 stmtLocation * current_callsite = 0;
05053
05054
05055
05056 const procedurecall_stack & callstack = Procedures.callstack();
05057
05058 procedurecall_stack_crp stack_p = callstack.rbegin();
05059
05060 while ( ! def &&
05061 (stack_p != callstack.rend()))
05062 {
05063 current_callsite = (*stack_p).first;
05064 current_info = (*stack_p).second;
05065
05066
05067
05068
05069 if (block->local_to() == current_info->proc())
05070 return 0;
05071
05072 if (current_callsite &&
05073 current_info->is_context_insensitive()) {
05074
05075 if (pointerOptions::Verbose)
05076 cout << " --> Look for def dominating " << * current_callsite << endl;
05077
05078
05079
05080
05081
05082
05083
05084
05085 def = block->nearest_def_at(current_callsite);
05086 }
05087
05088
05089
05090 stack_p++;
05091 }
05092
05093 if (pointerOptions::Verbose)
05094 if (! def) {
05095 cout << "Pointers::nearest_def_at(" << block->name() << ", " << * where << ") -- Failed" << endl;
05096 block->print_def_use(cout);
05097 }
05098
05099 return def;
05100
05101 #if 0
05102
05103
05104
05105
05106
05107 memoryDef * def = block->nearest_def_at(where);
05108
05109 if (def)
05110 return def;
05111
05112
05113
05114 if ( ! info)
05115 return 0;
05116
05117
05118
05119 procedureInfo * current_callee = 0;
05120 stmtLocation * current_callsite = 0;
05121
05122
05123
05124
05125
05126 const procedurecall_stack & callstack = Procedures.callstack();
05127
05128 procedurecall_stack_crp stack_p = callstack.rbegin();
05129
05130 while (stack_p != callstack.rend()) {
05131 current_callee = (*stack_p).second;
05132
05133 if (current_callee == info)
05134 break;
05135
05136 stack_p++;
05137 }
05138
05139
05140
05141 bool found = false;
05142
05143 while (stack_p != callstack.rend()) {
05144
05145 current_callsite = (*stack_p).first;
05146 current_callee = (*stack_p).second;
05147
05148
05149
05150
05151
05152 if (block->local_to() == current_callee->proc())
05153 return 0;
05154
05155
05156
05157
05158 if (current_callsite &&
05159 info->is_context_insensitive()) {
05160 found = true;
05161 break;
05162 }
05163
05164
05165
05166 stack_p++;
05167 }
05168
05169 if (found) {
05170
05171 if (pointerOptions::Verbose)
05172 cout << " -> No local def: try passing as external input to " << current_callee->name()
05173 << " at " << * current_callsite << endl;
05174
05175
05176
05177
05178 if (computePointers)
05179 bool found_new_inputs = current_callee->add_external_input(block);
05180
05181
05182
05183 stack_p++;
05184 procedureInfo * caller = (*stack_p).second;
05185
05186
05187
05188
05189
05190 memoryblock_set ignore_changes;
05191 pass_one_external_input(current_callee, caller, current_callsite, block, ignore_changes);
05192
05193
05194
05195
05196 def = block->current_def();
05197 }
05198
05199 return def;
05200 }
05201
05202 #endif
05203 }
05204
05205
05206
05207
05208
05209
05210 void Pointers::conservative_procedure_call(procedureInfo * info,
05211 stmtLocation * current,
05212 pointervalue_list & arguments,
05213 memoryblock_set & reachable,
05214 memoryblock_set & external_defs,
05215 memoryuse_set & external_uses,
05216 memoryblock_set & external_changes,
05217 pointerValue & return_val)
05218 {
05219
05220
05221
05222 memoryblock_list worklist;
05223
05224
05225
05226 for (pointervalue_list_p p = arguments.begin();
05227 p != arguments.end();
05228 ++p)
05229 {
05230 pointerValue & pointer = (*p);
05231
05232 for (memoryblock_set_p q = pointer.blocks.begin();
05233 q != pointer.blocks.end();
05234 ++q)
05235 {
05236 memoryBlock * arg = (*q);
05237
05238
05239
05240 if (arg != Memory.null()) {
05241
05242
05243
05244 worklist.push_back(arg);
05245
05246
05247
05248
05249 if (pointer.is_address)
05250 reachable.insert(arg);
05251 }
05252 }
05253 }
05254
05255
05256
05257 reachable_blocks(current, worklist, reachable);
05258
05259
05260
05261
05262
05263
05264
05265 pointerValue left;
05266 pointerValue right;
05267
05268
05269
05270
05271 right.blocks = reachable;
05272
05273
05274
05275 generate_uses(info, current, external_uses, right);
05276
05277
05278
05279
05280
05281
05282
05283
05284
05285 for (memoryblock_set_p p = reachable.begin();
05286 p != reachable.end();
05287 ++p)
05288 {
05289 memoryBlock * block = *p;
05290
05291
05292
05293 if ( ! block->write_protected()) {
05294
05295 bool is_new;
05296 memoryDef * def = block->def_at(current, is_new);
05297
05298 #ifdef COLLECT_DEFS
05299 external_defs.insert(block);
05300 #endif
05301
05302 if (is_new) {
05303 external_changes.insert(block);
05304 }
05305
05306
05307
05308
05309 memoryDef * reaching_def = block->current_use()->reaching_def();
05310 if (reaching_def &&
05311 ! reaching_def->points_to().empty()) {
05312 def->add_pointers(reaching_def->points_to());
05313 }
05314 }
05315 }
05316
05317 if (pointerOptions::Verbose)
05318 print_memoryblock_def_set(" Potentially reachable:", reachable, cout);
05319 }
05320
05326 void Pointers::reachable_blocks(Location * where,
05327 memoryblock_list & worklist,
05328 memoryblock_set & already_seen)
05329 {
05330 while ( ! worklist.empty()) {
05331
05332
05333
05334 memoryBlock * mb = worklist.front();
05335 worklist.pop_front();
05336
05337
05338
05339 mb->reachable_blocks(where, false, worklist, already_seen, Memory.null());
05340 }
05341 }
05342
05343
05344
05345
05346
05347 memoryBlock * Pointers::at_allocation(const string & name,
05348 procedureInfo * info,
05349 stmtLocation * current,
05350 stmtNode * allocation_stmt,
05351 declNode * decl,
05352 memoryblock_set & defs,
05353 memoryuse_set & uses,
05354 memoryblock_set & changes,
05355 pointerValue & result)
05356 {
05357 bool changed;
05358 declNode * the_decl = decl;
05359 bool from_heap_map = false;
05360 string fullname = name;
05361
05362 if (decl == 0) {
05363
05364
05365
05366 from_heap_map = true;
05367
05368 stmtNode * stmt = current->stmt();
05369 heap_map_p p = HeapMap.find(stmt);
05370 if (p == HeapMap.end()) {
05371
05372
05373
05374
05375
05376 char buf[50];
05377
05378 sprintf(buf, "_#%d", Memory.counter());
05379
05380 fullname = name + buf;
05381
05382
05383
05384 the_decl = new declNode(fullname.c_str(),
05385 declNode::NONE,
05386 (typeNode *)0,
05387 (exprNode *)0,
05388 (exprNode *)0);
05389
05390
05391
05392 HeapMap[stmt] = the_decl;
05393 }
05394 else {
05395
05396
05397
05398 the_decl = (*p).second;
05399 }
05400 }
05401
05402
05403
05404
05405
05406
05407
05408
05409 memoryBlock * block = Memory.lookup_heap_object(fullname, current, allocation_stmt,
05410 the_decl, from_heap_map);
05411
05412 if (pointerOptions::Verbose)
05413 cout << " - At allocation: " << fullname << endl;
05414
05415
05416
05417
05418 if (computePointers) {
05419
05420
05421
05422
05423 memoryBlock * alloc_object = block->get_allocation_object(Memory);
05424 if (alloc_object->is_flow_sensitive()) {
05425
05426
05427
05428 memoryDef * previous_alloc_def = nearest_def_at(info, alloc_object, current);
05429
05430
05431
05432 Multiplicity new_multiplicity;
05433
05434 new_multiplicity = alloc_object->at_allocation(current,
05435 previous_alloc_def,
05436 defs, uses, changes);
05437 }
05438 }
05439
05440
05441
05442 result.blocks.insert(block);
05443 result.is_address = true;
05444
05445 return block;
05446 }
05447
05448 void Pointers::at_deallocation(procedureInfo * info,
05449 Location * current,
05450 pointerValue & to_deallocate,
05451 memoryblock_set & defs,
05452 memoryuse_set & uses,
05453 memoryblock_set & changes)
05454 {
05455
05456
05457 for (memoryblock_set_p p = to_deallocate.blocks.begin();
05458 p != to_deallocate.blocks.end();
05459 ++p)
05460 {
05461 memoryBlock * block = *p;
05462 bool changed = false;
05463
05464 if (block->write_protected()) {
05465
05466 if (pointerOptions::Verbose)
05467 cout << " Skip deallocation of write-protected object: " << block->name() << endl;
05468 }
05469 else {
05470
05471
05472
05473
05474
05475
05476 if (computePointers) {
05477
05478
05479
05480
05481 memoryBlock * alloc_object = block->get_allocation_object(Memory);
05482 if (alloc_object->is_flow_sensitive()) {
05483
05484
05485
05486 memoryDef * previous_alloc_def = nearest_def_at(info, alloc_object, current);
05487
05488
05489
05490 Multiplicity new_multiplicity;
05491
05492 new_multiplicity = alloc_object->at_deallocation(current,
05493 previous_alloc_def,
05494 defs, uses, changes);
05495 }
05496 }
05497 }
05498 }
05499 }
05500
05501 Multiplicity Pointers::current_multiplicity(procedureInfo * info,
05502 Location * current,
05503 memoryBlock * block_in,
05504 memoryuse_set & uses)
05505 {
05506 Multiplicity multiplicity = Unallocated;
05507
05508
05509
05510 memoryBlock * block = block_in;
05511 while (block->container()) {
05512 if(_unification_based && block == block->container()) break;
05513 block = block->container();
05514 }
05515
05516
05517
05518 if (block->is_indexed())
05519 multiplicity = Bounded;
05520 else
05521 if (block->is_heap_object()) {
05522
05523
05524
05525
05526 if (
05527 _use_multiplicity)
05528 {
05529
05530
05531 memoryBlock * alloc_object = block->get_allocation_object(Memory);
05532 if (alloc_object->is_flow_sensitive()) {
05533
05534
05535
05536 memoryDef * alloc_def = nearest_def_at(info, alloc_object, current);
05537
05538
05539
05540 memoryUse * use = alloc_object->use_at(current);
05541 use->reaching_def(alloc_def);
05542 uses.insert(use);
05543
05544
05545
05546 if (alloc_def)
05547 multiplicity = alloc_def->multiplicity();
05548 }
05549 else {
05550
05551
05552
05553 multiplicity = Unbounded;
05554 }
05555 }
05556 else {
05557
05558
05559
05560
05561 multiplicity = Unbounded;
05562 }
05563 }
05564 else {
05565
05566
05567
05568 multiplicity = Single;
05569 }
05570
05571 return multiplicity;
05572 }
05573
05574
05575 bool Pointers::is_allocation(pointerValue & call_targets)
05576 {
05577 if (call_targets.blocks.size() == 1) {
05578 memoryBlock * call = * call_targets.blocks.begin();
05579 declNode * decl = call->decl();
05580 if ((decl->name() == string("malloc")) ||
05581 (decl->name() == string("calloc")))
05582 return true;
05583 }
05584
05585 return false;
05586 }
05587
05588 bool Pointers::is_deallocation(pointerValue & call_targets)
05589 {
05590 if (call_targets.blocks.size() == 1) {
05591 memoryBlock * call = * call_targets.blocks.begin();
05592 declNode * decl = call->decl();
05593 if ((decl->name() == string("free")) ||
05594 (decl->name() == string("cfree")))
05595 return true;
05596 }
05597
05598 return false;
05599 }
05600
05601 bool Pointers::is_reallocation(pointerValue & call_targets)
05602 {
05603 if (call_targets.blocks.size() == 1) {
05604 memoryBlock * call = * call_targets.blocks.begin();
05605 declNode * decl = call->decl();
05606 if (decl->name() == string("realloc"))
05607 return true;
05608 }
05609
05610 return false;
05611 }
05612
05621 void Pointers::mark_as_indexed(memoryblock_set & blocks)
05622 {
05623 for (memoryblock_set_p p = blocks.begin();
05624 p != blocks.end();
05625 ++p)
05626 {
05627 memoryBlock * block = *p;
05628 block->set_indexed();
05629 }
05630 }
05631
05632
05633
05634
05635
05636
05637
05638 void Pointers::stats(ostream & out)
05639 {
05640 out << "Pointer analysis:" << endl;
05641 out << " Number of procedure-level passes: " << _procedureCount << endl;
05642
05643 Memory.stats(out);
05644
05645 cout << "Number of pointerValue objects: " << pointerValue::count << endl;
05646
05647 out << "Unknown procedures:" << endl;
05648 for (string_set_p p = _unknown_procedures.begin();
05649 p != _unknown_procedures.end();
05650 ++p)
05651 out << " " << (*p) << endl;
05652
05653 Procedures.stats(out);
05654 }
05655
05656 void Pointers::uses_and_defs()
05657 {
05658 Memory.print(cout);
05659 }
05660
05661 void Pointers::print_memoryblock_set(const string & label,
05662 const memoryblock_set & the_set,
05663 ostream & o)
05664 {
05665 cout << label;
05666 for (memoryblock_set_cp mbp = the_set.begin();
05667 mbp != the_set.end();
05668 ++mbp)
05669 {
05670 if (mbp != the_set.begin())
05671 cout << " , ";
05672 cout << (*mbp)->name();
05673 }
05674 cout << endl;
05675 }
05676
05677 void Pointers::print_memorydef_set(const string & label,
05678 const memorydef_set & the_set,
05679 ostream & o)
05680 {
05681 cout << label << endl;
05682 for (memorydef_set_cp p = the_set.begin();
05683 p != the_set.end();
05684 ++p)
05685 {
05686 memoryBlock * owner = (*p)->owner();
05687 cout << " " << owner->name() << " (def at " << * (*p)->where() << ")" << endl;
05688 }
05689 cout << endl;
05690 }
05691
05692 void Pointers::print_memoryblock_def_set(const string & label,
05693 const memoryblock_set & the_set,
05694 ostream & o)
05695 {
05696 cout << label << endl;
05697 for (memoryblock_set_cp p = the_set.begin();
05698 p != the_set.end();
05699 ++p)
05700 {
05701 memoryBlock * owner = (*p);
05702 memoryDef * def = owner->current_def();
05703
05704 if (def)
05705 cout << " " << owner->name() << " (def at " << * def->where() << ")" << endl;
05706 else
05707 cout << " " << owner->name() << " (Non-local def)" << endl;
05708 }
05709 cout << endl;
05710 }
05711
05712
05713
05714
05715
05716
05717
05718 procedureInfo * Pointers::lookup_procedure(procNode * proc)
05719 {
05720 return Procedures.lookup(proc);
05721 }
05722
05723
05724 bool Pointers::is_pointer_expression(operandNode * operand)
05725 {
05726 if(operand->star() || operand->addr() || !operand->fields().empty())
05727 return true;
05728 return false;
05729 }
05730
05731
05732
05733
05734
05735 bool Pointers::is_exit(pointerValue & call_targets)
05736 {
05737 if (call_targets.blocks.size() == 1) {
05738 memoryBlock * call = * call_targets.blocks.begin();
05739 declNode * decl = call->decl();
05740 if ((decl->name() == string("exit")) ||
05741 (decl->name() == string("_exit")) ||
05742 (decl->name() == string("abort")))
05743 return true;
05744 }
05745
05746 return false;
05747 }
05748
05749
05750
05751
05752
05753
05754 void Pointers::setup_va_list_variables(procedureInfo * info,
05755 procLocation * callee_path,
05756 stmtLocation * parameter_callsite,
05757 procNode * callee,
05758 memoryBlock * ellipsis)
05759 {
05760 memoryblock_set defs;
05761 memoryuse_set uses;
05762 memoryblock_set changes;
05763 pointerValue rhs(ellipsis);
05764 rhs.is_address = true;
05765
05766 decl_list & local_vars = callee->body()->decls();
05767 for (decl_list_p lvp = local_vars.begin();
05768 lvp != local_vars.end();
05769 ++lvp)
05770 {
05771 declNode * cur_lv = *lvp;
05772
05773
05774
05775 if (is_va_list(cur_lv)) {
05776
05777
05778
05779 memoryBlock * left = Memory.lookup_variable(callee_path, cur_lv, callee);
05780 pointerValue lhs(left);
05781
05782 assignment_operator(info, callee_path, parameter_callsite, lhs, rhs, defs, uses, changes);
05783
05784
05785
05786
05787
05788 left->set_indexed();
05789
05790
05791
05792 _constants.at_parameter_pass(callee_path, lhs, rhs, changes);
05793
05794
05795
05796 if (Problem)
05797 Problem->at_parameter_pass(callee_path, parameter_callsite, lhs, rhs, changes);
05798 }
05799 }
05800 }
05801
05802
05803
05804 bool Pointers::is_va_arg(pointerValue & call_targets)
05805 {
05806 if (call_targets.blocks.size() == 1) {
05807 memoryBlock * call = * call_targets.blocks.begin();
05808 declNode * decl = call->decl();
05809 if (decl->name() == "__builtin_va_arg")
05810 return true;
05811 }
05812
05813 return false;
05814 }
05815
05816 bool Pointers::is_va_start(pointerValue & call_targets)
05817 {
05818 if (call_targets.blocks.size() == 1) {
05819 memoryBlock * call = * call_targets.blocks.begin();
05820 declNode * decl = call->decl();
05821 if (decl->name() == "__builtin_next_arg")
05822 return true;
05823 }
05824
05825 return false;
05826 }
05827
05828 bool Pointers::is_va_end(pointerValue & call_targets)
05829 {
05830 return false;
05831 }
05832
05833 bool Pointers::is_va_list(declNode * decl)
05834 {
05835
05836
05837 if (decl->type() && (decl->type()->typ() == Tdef)) {
05838 tdefNode * tdef = (tdefNode *) decl->type();
05839 if (tdef->name() == "va_list")
05840 return true;
05841 if (tdef->name() == "__builtin_va_alist_t")
05842 return true;
05843 if (tdef->name() == "__gnuc_va_list")
05844 return true;
05845 }
05846
05847 return false;
05848 }
05849
05850 bool Pointers::is_va_list(exprNode * expr)
05851 {
05852 if (expr->typ() == Id) {
05853 idNode * id = (idNode *) expr;
05854 if (id->decl())
05855 return is_va_list(id->decl());
05856 }
05857
05858 return false;
05859 }
05860
05861 void Pointers::progress_meter(procedureInfo * info, bool skipped)
05862 {
05863 if (skipped)
05864 _skipCount++;
05865
05866 _procedureCount++;
05867
05868 bool show_now = false;
05869
05870 if (_procedureCount < 50000)
05871 show_now = ((_procedureCount % 5000) == 0);
05872 else
05873 show_now = ((_procedureCount % 10000) == 0);
05874
05875 if (_show_progress && show_now) {
05876 if (info->is_context_insensitive())
05877 cout << "Progress (I): ";
05878 else
05879 cout << "Progress (S): ";
05880
05881 cout << _procedureCount << "/" << _skipCount << " at ";
05882 Procedures.progress_meter(cout);
05883 cout << endl;
05884 }
05885 }
05886
05887 void Pointers::show_accuracy()
05888 {
05889 double defs = compute_accuracy(_def_accuracy);
05890
05891 cout << "STAT-accuracy-pointers-defs " << defs << endl;
05892
05893 double star = compute_accuracy(_star_accuracy);
05894
05895 cout << "STAT-accuracy-pointers-star " << star << endl;
05896
05897
05898
05899 _def_accuracy.clear();
05900 _star_accuracy.clear();
05901 }
05902
05903 double Pointers::compute_accuracy(accuracy_map & accuracy_data)
05904 {
05905
05906
05907 typedef map< stmtNode *, count_accuracy_pair > stmt_accuracy_map;
05908 typedef stmt_accuracy_map::iterator stmt_accuracy_map_p;
05909
05910 stmt_accuracy_map by_statement;
05911
05912 for (accuracy_map_p p = accuracy_data.begin();
05913 p != accuracy_data.end();
05914 ++p)
05915 {
05916 stmtLocation * where = (*p).first;
05917 count_accuracy_pair & cap = (*p).second;
05918
05919
05920
05921 procLocation * cur = Location::procedure(where);
05922
05923
05924
05925 procedureInfo * info = lookup_procedure(cur->proc());
05926
05927
05928
05929 int count = info->count_calling_contexts();
05930
05931
05932
05933
05934 count_accuracy_pair new_cap;
05935
05936 new_cap.first = cap.first * count;
05937 new_cap.second = cap.second * ((double)count);
05938
05939
05940
05941 stmtNode * stmt = where->stmt();
05942
05943
05944
05945 stmt_accuracy_map_p w = by_statement.find(stmt);
05946 if (w == by_statement.end())
05947 by_statement[stmt] = new_cap;
05948 else {
05949 count_accuracy_pair & existing_cap = (*w).second;
05950
05951 existing_cap.first += new_cap.first;
05952 existing_cap.second += new_cap.second;
05953 }
05954 }
05955
05956
05957
05958
05959 double total = 0.0;
05960 int count = 0;
05961
05962 for (stmt_accuracy_map_p p = by_statement.begin();
05963 p != by_statement.end();
05964 ++p)
05965 {
05966 stmtNode * stmt = (*p).first;
05967 count_accuracy_pair & cap = (*p).second;
05968
05969 double local_accuracy = (cap.second) / ((double) cap.first);
05970
05971
05972
05973 count++;
05974 total += local_accuracy;
05975 }
05976
05977 return (total / ((double)count));
05978 }