00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include <list.h>
00014 #include <set.h>
00015 #include <algorithm>
00016
00017 #include "Directive/RecurrenceAssertion.h"
00018 #include "Directive/AssertLoopLabel.h"
00019
00020 #include "cdg/cdg_types.h"
00021 #include "cdg/cdg.h"
00022
00023 #include "Statement/Statement.h"
00024 #include "Statement/LabelStmt.h"
00025 #include "ProgramUnit.h"
00026 #include "Directive/AssertComment.h"
00027
00028 #include <exception>
00029
00030
00031
00032
00033 void cdg_clone(CDGNode* node, CDGNode* parent, bool value){
00034
00035
00036 p_assert(node, "Null CDG node to be cloned.");
00037
00038
00039
00040
00041 CDGNode* clone=new CDGNode(node->cfgnode());
00042
00043
00044 CDSet pred;
00045 CDElement newcde(parent, value);
00046 pred.ins(newcde);
00047 clone->ins(pred);
00048
00049
00050 for( Iterator<CDElement> cdit=node->outs(); cdit.valid(); ++cdit){
00051 cdg_clone(cdit.current().node(), clone, cdit.current().value());
00052 }
00053 }
00054
00055
00056
00057 typedef struct __cdg_ws_node{
00058 CDGNode* node;
00059 int outdeg;
00060 } _cdg_ws_node;
00061
00062
00063
00064
00065
00066
00067
00068 void cdg_dag2tree(ProgramUnit& pgm){
00069 clear_cdg_visited(pgm);
00070 int nnodes=pgm.stmts().entries();
00071 vector<_cdg_ws_node> all;
00072 int i=0;
00073 for (Iterator<Statement> stit=pgm.stmts().iterator();stit.valid();++stit){
00074 CDGNode* node=stit.current().cdgnode();
00075 _cdg_ws_node ws;
00076 ws.node=node;
00077 ws.outdeg=node->outs().entries();
00078 if (cdg_self_loop(node)){
00079 ws.outdeg--;
00080 }
00081 all.push_back(ws);
00082 node->visited(i);
00083 i++;
00084 }
00085
00086 list<int> todo;
00087
00088 for (i=0;i<nnodes;i++){
00089 if (all[i].outdeg==0){
00090 todo.push_back(i);
00091 }
00092 }
00093
00094 while (todo.size()!=0){
00095 int which=todo.front();
00096 todo.pop_front();
00097 CDGNode* node=all[which].node;
00098 RefList<CDElement> to_del;
00099 int at_first=1;
00100 for (Iterator<CDElement> cdit=node->ins();cdit.valid();++cdit){
00101 CDGNode* pred=cdit.current().node();
00102 if (pred==node) continue;
00103 if (at_first){
00104 at_first=0;
00105 continue;
00106 } else {
00107
00108
00109 to_del.ins_first(cdit.current());
00110
00111
00112 for(Iterator<CDElement> cdit2=pred->outs();cdit2.valid();++cdit2){
00113 if (cdit2.current().node()==node){
00114 pred->outs().del(cdit2.current());
00115 break;
00116 }
00117 }
00118
00119
00120 cdg_clone(node, pred, cdit.current().value());
00121
00122
00123
00124 int which_pred=pred->visited();
00125 if (all[which_pred].outdeg==0){
00126 todo.push_back(which_pred);
00127 }
00128 }
00129 }
00130
00131 for (Iterator<CDElement> cdit=to_del;cdit.valid();++cdit){
00132 node->ins().del(cdit.current());
00133 }
00134 }
00135 }
00136
00137
00138
00139
00140
00141
00142 void sort_pdt(vector<CDGNode*>& nodes){
00143 unsigned int size=nodes.size();
00144 unsigned int i,j;
00145
00146
00147 vector<int> zero(size,0);
00148 vector<vector<int> > table(size,zero);
00149
00150
00151 for (i=0;i<size;i++){
00152 for (j=0;j<size;j++){
00153 if (i==j) continue;
00154
00155
00156
00157 if (postdominates(nodes[i],nodes[j])){
00158
00159 table[i][j]=1;
00160 } else {
00161
00162 }
00163 }
00164 }
00165
00166 vector<CDGNode*> result(size);
00167
00168 vector<int> pos(size,0);
00169 for (i=0;i<size;i++){
00170 for (j=0;j<size;j++){
00171 pos[i]+=table[i][j];
00172 }
00173 result[pos[i]]=nodes[i];
00174 }
00175 nodes=result;
00176 }
00177
00178
00179
00180 void get_trues(CDGNode* node, vector<CDGNode*>& trues){
00181 if (node->outs().entries()==0){
00182 return;
00183 }
00184 for (CDElement* cdit=node->outs().last_ref(); cdit;
00185 cdit=(CDElement*)cdit->prev_ref()){
00186 if (cdit->node()==node) continue;
00187 Statement& stmt=*(cdit->node()->cfgnode());
00188 switch(stmt.stmt_class()){
00189 case ENDDO_STMT:
00190 case IMPLIED_GOTO_STMT:
00191 case ENTRY_STMT:
00192 case ENDIF_STMT:
00193 case ELSE_STMT:
00194 case RETURN_STMT:
00195 case LABEL_STMT:
00196 case GOTO_STMT:
00197 continue;
00198 default:
00199 break;
00200 }
00201 if (!cdit->value()) trues.push_back(cdit->node());
00202 }
00203 sort_pdt(trues);
00204 }
00205
00206 void write(vector<CDGNode*>& v, ostream& o);
00207
00208
00209 void get_falses(CDGNode* node, vector<CDGNode*>& falses ){
00210 if (node->outs().entries()==0){
00211 return;
00212 }
00213 for (CDElement* cdit=node->outs().last_ref(); cdit;
00214 cdit=(CDElement*)cdit->prev_ref()){
00215 if (cdit->node()==node) continue;
00216 Statement& stmt=*(cdit->node()->cfgnode());
00217
00218 switch(stmt.stmt_class()){
00219 case ENDDO_STMT:
00220 case IMPLIED_GOTO_STMT:
00221 case ENTRY_STMT:
00222 case ENDIF_STMT:
00223 case ELSE_STMT:
00224 case RETURN_STMT:
00225 case LABEL_STMT:
00226 case GOTO_STMT:
00227 continue;
00228 default:
00229 break;
00230 }
00231
00232 if (cdit->value()) falses.push_back(cdit->node());
00233 }
00234
00235
00236
00237 sort_pdt(falses);
00238 }
00239
00240
00241 static set<String> _loop_labels;
00242
00243 inline void copy_directives(Statement& from, Statement& to){
00244 static unsigned llc=0;
00245 to.pre_directives()=from.pre_directives();
00246 to.post_directives()=from.post_directives();
00247 to.assertions()=from.assertions();
00248
00249
00250 if (to.stmt_class()==DO_STMT){
00251 for(Iterator<Assertion> iter = to.assertions(); iter.valid(); ++iter) {
00252 if (iter.current().type() == AS_LOOPLABEL) {
00253 AssertLoopLabel &a = (AssertLoopLabel &) iter.current();
00254 p_assert(a.string_arg_list_valid(),
00255 "Loop Label assertion with no valid name");
00256 p_assert(a.string_arg_list_guarded().entries() == 1,
00257 "Only supporting Loop Label assertions with 1 field");
00258 String old_label=a.string_arg_list_guarded()[0];
00259 String new_label;
00260 if (_loop_labels.find(old_label)==_loop_labels.end()){
00261
00262 new_label=old_label;
00263 _loop_labels.insert(new_label);
00264 } else {
00265
00266 strstream oldname;
00267 oldname<<old_label<<"_"<<llc++<<'\0';
00268 const char* s=oldname.str();
00269 new_label=s;
00270 oldname.freeze(0);
00271 }
00272 a.string_arg_list_guarded()[0]=new_label;
00273 }
00274 }
00275 }
00276 }
00277
00278 void cdg_self_loop(CDGNode* root, bool& is_loop, bool& inside_predicate){
00279 is_loop=false;
00280 inside_predicate=false;
00281 for (Iterator<CDElement> cdit=root->outs(); cdit.valid(); ++cdit){
00282 CDGNode* next=cdit.current().node();
00283 if (next==root){
00284 is_loop=true;
00285 inside_predicate=cdit.current().value();
00286 return;
00287 }
00288 }
00289 return;
00290 }
00291
00292
00293
00294 inline void clean_line(const char* l, String& cl){
00295 const char* pc=l;
00296 char one[]="*";
00297 while (*pc){
00298 if (*pc!='\n'){
00299 one[0]=*pc;
00300 cl+=one;
00301 }
00302 ++pc;
00303 }
00304 }
00305
00306
00307
00308
00309
00310 Statement* cdg2cfg(CDGNode* node, Statement* ref, ProgramUnit& pgm){
00311
00312 vector<CDGNode*> trues;
00313 get_trues(node, trues);
00314 vector<CDGNode*> falses;
00315 get_falses(node, falses);
00316
00317
00318
00319 Statement* where=ref;
00320 Statement& stmt=*(node->cfgnode());
00321 if (node->outs().entries()==0){
00322
00323
00324 switch(stmt.stmt_class()){
00325 case ENDDO_STMT:
00326 case ENTRY_STMT:
00327 case IMPLIED_GOTO_STMT:
00328 case ENDIF_STMT:
00329 case ELSE_STMT:
00330 case RETURN_STMT:
00331 case LABEL_STMT:
00332 case GOTO_STMT:
00333
00334 return ref;
00335 case DO_STMT:
00336
00337
00338 cerr<<stmt;
00339 p_abort("Abnormal type of statement as CDG leaf.");
00340 return ref;
00341 case STOP_STMT:
00342
00343
00344 default:
00345 pgm.stmts().ins_after(stmt.clone(),ref);
00346 return ref->next_ref();
00347 }
00348 }
00349
00350 bool is_loop;
00351 bool inside_predicate;
00352 cdg_self_loop(node, is_loop, inside_predicate);
00353
00354 if (is_loop){
00355 Statement* where_else_is=0;
00356 if (inside_predicate){
00357
00358 for (unsigned int i=0;i<falses.size();i++){
00359 where=cdg2cfg(falses[i],where,pgm);
00360 }
00361 where_else_is=where;
00362
00363 for (unsigned int i=0;i<trues.size();i++){
00364 where=cdg2cfg(trues[i],where,pgm);
00365 }
00366 } else {
00367
00368 for (unsigned int i=0;i<trues.size();i++){
00369 where=cdg2cfg(trues[i],where,pgm);
00370 }
00371
00372 where_else_is=where;
00373 for (unsigned int i=0;i<falses.size();i++){
00374 where=cdg2cfg(falses[i],where,pgm);
00375 }
00376 }
00377
00378
00379
00380 switch(stmt.stmt_class()){
00381 case WRITE_STMT:
00382 case READ_STMT:
00383 pgm.stmts().ins_after(stmt.clone(),ref);
00384 return ref->next_ref();
00385 case IF_STMT:
00386 case ELSEIF_STMT:{
00387
00388
00389 Expression* predicate=stmt.expr().clone();
00390 if (inside_predicate==true){
00391 predicate=simplify(not(predicate));
00392 }
00393
00394 if (ref==where_else_is){
00395 Statement* dl=new LabelStmt(pgm.stmts().new_tag(),
00396 pgm.stmts().new_label());
00397 pgm.stmts().ins_after(dl, ref);
00398 where_else_is=dl;
00399 }
00400
00401 String comment="";
00402 for (Iterator<Assertion> ait=stmt.assertions(); ait.valid(); ++ait){
00403 if (ait.current().type()==AS_RECURRENCE){
00404 RecurrenceAssertion& ra=(RecurrenceAssertion&)ait.current();
00405 comment+=ra.ra_string_arg_list_guarded()[0];
00406 }
00407 }
00408 if (comment==""){
00409 strstream s;
00410 int w=1;
00411 stmt.write(s,w);
00412 s<<'\0';
00413 clean_line(s.str(), comment);
00414 s.freeze(0);
00415 }
00416 Statement& clone=pgm.stmts().ins_WHILE_after(predicate,
00417 ref, where_else_is);
00418 AssertComment* newassert=new AssertComment();
00419 newassert->string_arg_list_guarded().
00420 ins_last(new StringElem(comment));
00421 clone.assertions().ins_last(newassert);
00422 return ref->next_ref()->follow_ref();
00423 }
00424 case DO_STMT:
00425 if (ref==where){
00426 Statement* dummy=new LabelStmt(pgm.stmts().new_tag(),
00427 pgm.stmts().new_label());
00428 pgm.stmts().ins_after(dummy,ref);
00429 where=dummy;
00430 Statement& clone=pgm.stmts().ins_DO_after(stmt.index().clone(),
00431 stmt.init().clone(),
00432 stmt.limit().clone(),
00433 stmt.step().clone(),
00434 ref, where);
00435 copy_directives(stmt,clone);
00436 pgm.stmts().del(*dummy);
00437 return ref->next_ref()->next_ref();
00438 } else {
00439 Statement& clone=pgm.stmts().ins_DO_after(stmt.index().clone(),
00440 stmt.init().clone(),
00441 stmt.limit().clone(),
00442 stmt.step().clone(),
00443 ref, where);
00444 copy_directives(stmt,clone);
00445 return ref->next_ref()->follow_ref();
00446 }
00447 break;
00448 case WHILE_STMT:
00449 if (ref==where){
00450 Statement* dummy=new LabelStmt(pgm.stmts().new_tag(),
00451 pgm.stmts().new_label());
00452 pgm.stmts().ins_after(dummy,ref);
00453 where=dummy;
00454 Statement& clone=pgm.stmts().ins_WHILE_after(stmt.expr().clone(),
00455 ref, where);
00456 copy_directives(stmt,clone);
00457 pgm.stmts().del(*dummy);
00458 return where->next_ref()->follow_ref();
00459 } else {
00460 Statement& clone=pgm.stmts().ins_WHILE_after(stmt.expr().clone(),
00461 ref, where);
00462 copy_directives(stmt,clone);
00463 return ref->next_ref()->follow_ref();
00464 }
00465 break;
00466 default:
00467
00468
00469
00470 cerr<<"Unknown branch type encountered in the following statement:";
00471 stmt.print(cerr);
00472 p_abort("Fatal error in IPA_CDG: see above message");
00473 return ref;
00474 }
00475 } else {
00476
00477
00478
00479 for (unsigned int i=0;i<trues.size();i++){
00480 where=cdg2cfg(trues[i],where,pgm);
00481 }
00482
00483
00484 Statement* where_else_is=where;
00485 for (unsigned int i=0;i<falses.size();i++){
00486 where=cdg2cfg(falses[i],where,pgm);
00487 }
00488
00489
00490
00491 switch(stmt.stmt_class()){
00492 case IF_STMT:
00493 case ELSEIF_STMT:
00494 if (trues.size()==0){
00495 if (falses.size()==0){
00496
00497
00498
00499
00500 Statement* dummy=new LabelStmt(pgm.stmts().new_tag(),
00501 pgm.stmts().new_label());
00502 pgm.stmts().ins_after(dummy,ref);
00503 where=ref->next_ref();
00504 pgm.stmts().ins_IF_after(not(stmt.expr().clone()),ref,where);
00505
00506
00507 return ref->next_ref()->matching_endif_ref();
00508 } else {
00509
00510
00511 pgm.stmts().ins_IF_after(not(stmt.expr().clone()),ref,where);
00512 return ref->next_ref()->matching_endif_ref();
00513 }
00514 } else {
00515 if (falses.size()>0){
00516
00517 pgm.stmts().ins_IF_ELSE_after(stmt.expr().clone(),ref, where_else_is,where);
00518 return ref->next_ref()->matching_endif_ref();
00519 } else {
00520
00521 pgm.stmts().ins_IF_after(stmt.expr().clone(),ref,where);
00522 return ref->next_ref()->matching_endif_ref();
00523 }
00524 }
00525 break;
00526 case FLOW_ENTRY_STMT:
00527 return ref;
00528 case READ_STMT:
00529 case WRITE_STMT:
00530 case PRINT_STMT:
00531 case OPEN_STMT:
00532 case CLOSE_STMT:
00533 case REWIND_STMT:
00534 case BACKSPACE_STMT:
00535 case ENDFILE_STMT:
00536 case INQUIRE_STMT:
00537 cerr<<"\nThe restructurer cannot handle for now I/O exception"
00538 <<"\nhandling constructs. The following statement at line "
00539 <<stmt.line()<<",\nin file "<<pgm.original_file_ref()
00540 <<" contains such a construct: \n";
00541 {
00542 int w=1;
00543 stmt.write(cerr, w);
00544 }
00545 p_warning("Non-fatal error in CDG2CFG: see message above.");
00546 throw bad_exception();
00547
00548 default:
00549
00550
00551
00552 cerr<<"Unknown branch type encountered in the following statement:";
00553 stmt.print(cerr);
00554 p_abort("Fatal error in CDG2CFG: see above message");
00555 return ref;
00556 }
00557 }
00558 }
00559
00560
00561
00562 static void uncdg(Statement* stmt){
00563 CDGNode* cdgnode=stmt->cdgnode();
00564 if (cdgnode) {
00565 delete cdgnode;
00566 stmt->cdgnode(0);
00567 }
00568 }
00569
00570
00571
00572
00573
00574 static void custom_cleanup(ProgramUnit& pgm){
00575 uncdg(pgm.stmts().first_ref());
00576 uncdg(pgm.stmts().first_ref()->next_ref());
00577 uncdg(pgm.stmts().last_ref());
00578 _loop_labels.clear();
00579 }
00580
00581
00582
00583 void cdg2cfg(ProgramUnit& pgm){
00584
00585
00586 _loop_labels.clear();
00587
00588
00589 Statement* old_start=pgm.stmts().first_ref()->next_ref()->next_ref();
00590
00591
00592
00593 cdg2cfg(pgm.stmts().first_ref()->cdgnode(),
00594 pgm.stmts().first_ref()->next_ref(),pgm);
00595
00596
00597
00598
00599
00600 pgm.stmts().del(*old_start,*(pgm.stmts().last_ref()->prev_ref()));
00601
00602
00603 custom_cleanup(pgm);
00604 }