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
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092 #ifdef USE_PCH
00093 #include "be_com_pch.h"
00094 #endif
00095 #pragma hdrstop
00096 #include "goto_conv.h"
00097 #include "wn_util.h"
00098 #include "config_targ.h"
00099 #include "strtab.h"
00100 #include "stab.h"
00101 #include "wn_lower.h"
00102 #include "targ_sim.h"
00103 #include "fb_whirl.h"
00104
00105
00106
00107
00108 static inline BOOL opcode_is_scf (OPCODE opcode)
00109 {
00110 return ( (opcode == OPC_DO_WHILE) ||
00111 (opcode == OPC_WHILE_DO) );
00112 }
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122 void GTABLE::Build()
00123 {
00124 _parent_map = WN_MAP_Create(_pool);
00125 Is_True(_parent_map != -1, ("Ran out of mappings in GTABLE::Build"));
00126 if (_parent_map == -1) {
00127 return;
00128 }
00129
00130
00131 typedef HASH_TABLE<INT, LDESCRIPTOR *> THIS_HASH_TABLE;
00132 _label_table =
00133 CXX_NEW(THIS_HASH_TABLE(200, _pool), _pool);
00134
00135 Build_Rec(WN_func_body(_func_nd), _func_nd, FALSE);
00136 Backpatch();
00137 }
00138
00139 void GTABLE::Fixup_Parents(WN *wn, WN *parent)
00140 {
00141 const OPCODE opcode = WN_opcode(wn);
00142
00143 if (opcode == OPC_BLOCK) {
00144 Set_Parent(wn, parent);
00145 WN *kid = WN_first(wn);
00146 while (kid) {
00147 Fixup_Parents(kid, wn);
00148 kid = WN_next(kid);
00149 }
00150 return;
00151 }
00152 if (opcode == OPC_ALTENTRY) {
00153 Set_Parent(wn, parent);
00154 }
00155
00156
00157
00158 if ((opcode == OPC_DO_LOOP) || (opcode == OPC_DO_WHILE) ||
00159 (opcode == OPC_REGION) ||
00160 (opcode == OPC_WHILE_DO) || (opcode == OPC_IF)) {
00161 Set_Parent(wn, parent);
00162 for (INT kidno = 0; kidno < WN_kid_count(wn); kidno++) {
00163 Fixup_Parents(WN_kid(wn, kidno), wn);
00164 }
00165 return;
00166 }
00167 if (opcode == OPC_COMPGOTO) {
00168 Set_Parent(wn, parent);
00169 for (INT kidno = 0; kidno < WN_kid_count(wn); kidno++) {
00170 Fixup_Parents(WN_kid(wn, kidno), wn);
00171 }
00172 return;
00173 }
00174
00175 if ((opcode == OPC_GOTO) || (opcode == OPC_TRUEBR) ||
00176 (opcode == OPC_FALSEBR)) {
00177 Set_Parent(wn, parent);
00178 } else if (opcode == OPC_LABEL) {
00179 Set_Parent(wn, parent);
00180 }
00181
00182
00183
00184
00185 Set_Parent(wn, parent);
00186 if (WN_operator(wn) == OPR_COMMA) {
00187 Fixup_Parents(WN_kid(wn, 0), wn);
00188 }
00189 else
00190 for (INT kidno = 0; kidno < WN_kid_count(wn); kidno++) {
00191 Fixup_Parents(WN_kid(wn, kidno), wn);
00192 }
00193 }
00194
00195 void GTABLE::Build_Rec(WN *wn, WN *parent, BOOL inside_compgoto)
00196 {
00197 const OPCODE opcode = WN_opcode(wn);
00198
00199 if (opcode == OPC_BLOCK) {
00200 Set_Parent(wn, parent);
00201 WN *kid = WN_first(wn);
00202 while (kid) {
00203 Build_Rec(kid, wn, inside_compgoto);
00204 kid = WN_next(kid);
00205 }
00206 return;
00207 }
00208 if (opcode == OPC_ALTENTRY) {
00209 Set_Parent(wn, parent);
00210 }
00211
00212
00213 if ((opcode == OPC_DO_LOOP) || (opcode == OPC_DO_WHILE) ||
00214 (opcode == OPC_REGION) ||
00215 (opcode == OPC_WHILE_DO) || (opcode == OPC_IF)) {
00216 Set_Parent(wn, parent);
00217 for (INT kidno = 0; kidno < WN_kid_count(wn); kidno++) {
00218 Build_Rec(WN_kid(wn, kidno), wn, inside_compgoto);
00219 }
00220 return;
00221 }
00222 if (opcode == OPC_COMPGOTO) {
00223 Set_Parent(wn, parent);
00224 for (INT kidno = 0; kidno < WN_kid_count(wn); kidno++) {
00225 Build_Rec(WN_kid(wn, kidno), wn, TRUE);
00226 }
00227 return;
00228 }
00229
00230 if ((opcode == OPC_GOTO) || (opcode == OPC_TRUEBR) ||
00231 (opcode == OPC_FALSEBR)) {
00232 Set_Parent(wn, parent);
00233 _gd.Push(GDESCRIPTOR(wn, NULL, _offset, 0, inside_compgoto));
00234 _offset++;
00235 } else if (opcode == OPC_LABEL) {
00236 Set_Parent(wn, parent);
00237 LDESCRIPTOR *ld = CXX_NEW(LDESCRIPTOR(wn, _offset), _pool);
00238 if (LABEL_kind (Label_Table[WN_label_number(wn)]) == LKIND_ASSIGNED) {
00239 _bad_label.Push(*ld);
00240 }
00241 _label_table->Enter(WN_label_number(wn), ld);
00242 _offset++;
00243 } else if (opcode == OPC_ALTENTRY) {
00244 _contains_altentry = TRUE;
00245 _altentry.Push(wn);
00246 }
00247
00248
00249 Set_Parent(wn, parent);
00250 if (WN_operator(wn) == OPR_COMMA) {
00251 Build_Rec(WN_kid(wn, 0), wn, inside_compgoto);
00252 }
00253 else
00254 for (INT kidno = 0; kidno < WN_kid_count(wn); kidno++) {
00255 Build_Rec(WN_kid(wn, kidno), wn, inside_compgoto);
00256 }
00257 }
00258
00259
00260
00261
00262 void GTABLE::Backpatch()
00263 {
00264 for (INT i = 0; i<_gd.Elements(); i++) {
00265 GDESCRIPTOR *gd = &_gd.Bottom_nth(i);
00266 INT label_num = WN_label_number(gd->Goto_Wn);
00267 LDESCRIPTOR *ld = _label_table->Find(label_num);
00268 if (ld != NULL) {
00269 gd->Label_Wn = ld->Label_Wn;
00270 gd->Label_Offset = ld->Offset;
00271 }
00272 }
00273 }
00274
00275
00276
00277
00278 void GTABLE::Remove_Gotos()
00279 {
00280 INT goto_expanding_transformations = 0;
00281
00282 INT i;
00283 BOOL created_whiles=FALSE;
00284 for (i = _gd.Elements() - 1; i >= 0; i--) {
00285 GDESCRIPTOR *gd = &_gd.Bottom_nth(i);
00286
00287 if (gd->Label_Wn && ! WN_Label_Is_Break(gd->Label_Wn)
00288 && ! gd->Is_Compgoto) {
00289 if (Goto_Is_Noop(gd)) {
00290 WN_DELETE_FromBlock(Get_Parent(gd->Goto_Wn), gd->Goto_Wn);
00291 gd->Is_Dismantled = TRUE;
00292 } else {
00293 if (Is_Truebr(gd)) {
00294 Create_Truebr(gd);
00295 }
00296 if (Sibling(gd)) {
00297 if (gd->Goto_Offset < gd->Label_Offset) {
00298
00299 } else {
00300 BOOL converted_goto = Replace_Goto_With_While(gd);
00301 if (converted_goto)
00302 created_whiles = TRUE;
00303 }
00304 }
00305 }
00306 }
00307 }
00308
00309 if (created_whiles) {
00310 Promote_Do_While(Func_Nd());
00311 }
00312
00313
00314 for (i = _gd.Elements() - 1; i >= 0; i--) {
00315 GDESCRIPTOR *gd = &_gd.Bottom_nth(i);
00316 if (gd->Label_Wn && !gd->Is_Dismantled) {
00317 WN *label_wn = gd->Label_Wn;
00318 WN *goto_wn = gd->Goto_Wn;
00319 WN *ancestor = Find_Common_Ancestor(label_wn, goto_wn);
00320 WN *tmp = Get_Parent(label_wn);
00321 while (tmp != ancestor) {
00322 WN *next_tmp = Get_Parent(tmp);
00323 OPCODE opcode = WN_opcode(tmp);
00324 if (opcode_is_scf(opcode)) {
00325 Dismantle(tmp, next_tmp);
00326 }
00327 tmp = next_tmp;
00328 }
00329 }
00330 }
00331 for (i = _bad_label.Elements() - 1; i >= 0; i--) {
00332 WN *label_wn = _bad_label.Bottom_nth(i).Label_Wn;
00333 if (label_wn) {
00334 WN *tmp = Get_Parent(label_wn);
00335 while (tmp) {
00336 WN *next_tmp = Get_Parent(tmp);
00337 OPCODE opcode = WN_opcode(tmp);
00338 if (opcode_is_scf(opcode)) {
00339 Dismantle(tmp, next_tmp);
00340 }
00341 tmp = next_tmp;
00342 }
00343 }
00344 }
00345 for (i = _altentry.Elements() - 1; i >= 0; i--) {
00346 WN *tmp = _altentry.Bottom_nth(i);
00347 while (tmp) {
00348 WN *next_tmp = Get_Parent(tmp);
00349 OPCODE opcode = WN_opcode(tmp);
00350 if (opcode_is_scf(opcode)) {
00351 Dismantle(tmp, next_tmp);
00352 }
00353 tmp = next_tmp;
00354 }
00355 }
00356 }
00357
00358
00359 WN *GTABLE::Find_Common_Ancestor(WN *wn1, WN *wn2)
00360 {
00361 INT l1 = Find_Level(wn1);
00362 INT l2 = Find_Level(wn2);
00363
00364 if (l1 > l2) {
00365 for (INT i = 0; i < l1 - l2; i++) {
00366 wn1 = Get_Parent(wn1);
00367 }
00368 } else if (l2 > l1) {
00369 for (INT i = 0; i < l2 - l1; i++) {
00370 wn2 = Get_Parent(wn2);
00371 }
00372 }
00373 while (wn1 != wn2) {
00374 wn1 = Get_Parent(wn1);
00375 wn2 = Get_Parent(wn2);
00376 }
00377 return wn1;
00378 }
00379
00380 INT GTABLE::Find_Level(WN *wn)
00381 {
00382 INT result = 0;
00383 while ((wn = Get_Parent(wn)) != 0) {
00384 result++;
00385 }
00386 return result;
00387 }
00388
00389
00390
00391
00392
00393
00394
00395
00396 BOOL GTABLE::Goto_Is_Noop(const GDESCRIPTOR *gd) const
00397 {
00398 WN *goto_wn = gd->Goto_Wn;
00399
00400 if (WN_next(goto_wn) == gd->Label_Wn) {
00401 return TRUE;
00402 }
00403
00404 WN *tmp = goto_wn;
00405 WN *grand_parent = goto_wn;
00406 while (!WN_next(tmp)) {
00407 tmp = grand_parent;
00408 WN *parent = Get_Parent(tmp);
00409 if (WN_opcode(parent) != OPC_BLOCK) {
00410 return FALSE;
00411 }
00412 grand_parent = Get_Parent(parent);
00413 if (WN_opcode(grand_parent) != OPC_IF) {
00414 return FALSE;
00415 }
00416 }
00417 return (WN_next(tmp) == gd->Label_Wn);
00418 }
00419
00420
00421 BOOL GTABLE::Sibling(const GDESCRIPTOR *gd) const
00422 {
00423 return (Get_Parent(gd->Label_Wn) == Get_Parent(gd->Goto_Wn));
00424 }
00425
00426
00427
00428 BOOL GTABLE::Is_Truebr(const GDESCRIPTOR *gd) const
00429 {
00430 WN *wn = gd->Goto_Wn;
00431 if (WN_opcode(wn) != OPC_GOTO) {
00432 return FALSE;
00433 }
00434 WN *parent = Get_Parent(wn);
00435 if (WN_opcode(parent) != OPC_BLOCK) {
00436 return FALSE;
00437 }
00438 WN *grand_parent = Get_Parent(parent);
00439 if (WN_opcode(grand_parent) != OPC_IF) {
00440 return FALSE;
00441 }
00442
00443 WN *wn_else = WN_else(grand_parent);
00444 if (WN_first(wn_else)) {
00445 WN * stmt = WN_first(wn_else);
00446 if (stmt == WN_last(wn_else) &&
00447 wn != stmt &&
00448 WN_operator(stmt) == OPR_GOTO &&
00449 WN_next(grand_parent) &&
00450 WN_operator(WN_next(grand_parent)) == OPR_LABEL &&
00451 WN_label_number(stmt) == WN_label_number(WN_next(grand_parent)))
00452 ;
00453 else
00454 return FALSE;
00455 }
00456
00457 if (wn != WN_last(parent) || wn != WN_first(parent)) {
00458 return FALSE;
00459 }
00460 return TRUE;
00461 }
00462
00463 void GTABLE::Create_Truebr(GDESCRIPTOR *gd)
00464 {
00465 WN *block_wn = Get_Parent(gd->Goto_Wn);
00466 WN *if_wn = Get_Parent(block_wn);
00467 WN *if_parent = Get_Parent(if_wn);
00468 WN *if_test = WN_if_test(if_wn);
00469
00470 WN *truebr = WN_CreateTruebr(WN_label_number(gd->Goto_Wn),if_test);
00471 Set_Parent(if_test, truebr);
00472 WN_Set_Linenum(truebr, WN_Get_Linenum(gd->Goto_Wn));
00473 WN_INSERT_BlockBefore(if_parent,if_wn,truebr);
00474 gd->Goto_Wn = truebr;
00475 if (Cur_PU_Feedback) {
00476 Cur_PU_Feedback->FB_lower_branch( if_wn, truebr );
00477 }
00478 Set_Parent(truebr, if_parent);
00479 WN_if_test(if_wn) = NULL;
00480 if (WN_first(WN_else(if_wn)))
00481 {
00482 WN * stmt = WN_EXTRACT_FromBlock(WN_else(if_wn), WN_first(WN_else(if_wn)));
00483 WN_INSERT_BlockBefore(if_parent, if_wn, stmt);
00484 if (Get_Parent(stmt)) Set_Parent(stmt, if_parent);
00485 }
00486 WN_DELETE_FromBlock(if_parent,if_wn);
00487 }
00488
00489
00490
00491
00492
00493
00494
00495 void GTABLE::Replace_Goto_With_If(GDESCRIPTOR *gd)
00496 {
00497 WN *goto_wn = gd->Goto_Wn;
00498 WN *label_wn = gd->Label_Wn;
00499 WN *parent = Get_Parent(goto_wn);
00500
00501 if (WN_next(goto_wn) == label_wn) {
00502 WN_DELETE_FromBlock(parent, goto_wn);
00503 gd->Is_Dismantled = TRUE;
00504 return;
00505 }
00506
00507 const OPCODE goto_opcode = WN_opcode(goto_wn);
00508 WN *cond;
00509 if (goto_opcode == OPC_GOTO) {
00510
00511
00512 return;
00513
00514
00515 } else if (goto_opcode == OPC_TRUEBR) {
00516 cond = WN_CreateExp1(OPCODE_make_op(OPR_LNOT, Boolean_type, MTYPE_V),
00517 WN_kid0(goto_wn));
00518 } else {
00519 Is_True(goto_opcode == OPC_FALSEBR,
00520 ("Unknown goto in Replace_Goto_With_If"));
00521 cond = WN_kid0(goto_wn);
00522 }
00523
00524 WN *then_block = WN_CreateBlock();
00525 WN *else_block = WN_CreateBlock();
00526 WN_Set_Linenum(then_block, WN_Get_Linenum(goto_wn));
00527 WN_Set_Linenum(else_block, WN_Get_Linenum(goto_wn));
00528
00529
00530 WN *next_wn = NULL;
00531 for (WN *wn = WN_next(goto_wn); wn != label_wn; wn = next_wn) {
00532 next_wn = WN_next(wn);
00533 wn = WN_EXTRACT_FromBlock(parent, wn);
00534 WN_INSERT_BlockBefore(then_block, NULL, wn);
00535 if (Get_Parent(wn)) Set_Parent(wn, then_block);
00536 }
00537
00538 WN *if_wn = WN_CreateIf(cond, then_block, else_block);
00539 Set_Parent(then_block, if_wn);
00540 Set_Parent(else_block, if_wn);
00541 Set_Parent(if_wn, parent);
00542 WN_Set_Linenum(if_wn, WN_Get_Linenum(goto_wn));
00543
00544 WN_INSERT_BlockAfter(parent, goto_wn, if_wn);
00545 WN_EXTRACT_FromBlock(parent, goto_wn);
00546 gd->Is_Dismantled = TRUE;
00547
00548 if (Cur_PU_Feedback) {
00549 Cur_PU_Feedback->FB_convert_goto_to_if(goto_wn, if_wn);
00550 }
00551 WN_Delete(goto_wn);
00552 }
00553
00554
00555 static BOOL Equivalent(WN *wn1, WN *wn2)
00556 {
00557 if (!WN_Equiv(wn1, wn2)) return FALSE;
00558 for (INT i=0; i<WN_kid_count(wn1); i++) {
00559 if (!Equivalent(WN_kid(wn1,i), WN_kid(wn2,i))) return FALSE;
00560 }
00561 return TRUE;
00562 }
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572 void GTABLE::Promote_Do_While(WN *wn)
00573 {
00574 OPCODE opcode = WN_opcode(wn);
00575 if (opcode == OPC_BLOCK) {
00576 WN *kid = WN_first(wn);
00577 while (kid) {
00578 WN *next_kid = WN_next(kid);
00579 Promote_Do_While(kid);
00580 kid = next_kid;
00581 }
00582 } else {
00583 if (OPCODE_is_scf(opcode)) {
00584 if (opcode == OPC_IF) {
00585 if (WN_first(WN_else(wn)) == NULL) {
00586 if (WN_first(WN_then(wn)) && (WN_first(WN_then(wn)) == WN_last(WN_then(wn)))) {
00587 if (WN_opcode(WN_first(WN_then(wn))) == OPC_DO_WHILE) {
00588 WN *while_wn = WN_first(WN_then(wn));
00589 if (Equivalent(WN_if_test(wn), WN_while_test(while_wn))) {
00590 WN_set_opcode(while_wn, OPC_WHILE_DO);
00591 WN *parent = Get_Parent(wn);
00592 WN_INSERT_BlockBefore(parent, wn, while_wn);
00593 Set_Parent(while_wn, parent);
00594 WN_first(WN_then(wn)) = NULL;
00595 WN_DELETE_FromBlock(parent, wn);
00596 Promote_Do_While(while_wn);
00597 return;
00598 }
00599 }
00600 }
00601 }
00602 }
00603 }
00604 for (INT kidno=0; kidno<WN_kid_count(wn); kidno++) {
00605 Promote_Do_While(WN_kid(wn,kidno));
00606 }
00607 }
00608 }
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629 void GTABLE::Patch_Do_While (WN * while_wn, WN * parent)
00630 {
00631 BOOL patch = FALSE;
00632 Is_True (Get_Parent(while_wn) == parent, ("Invalid parent of while node"));
00633
00634
00635 WN * goto_wn = WN_prev(while_wn);
00636
00637 if (!goto_wn || WN_operator(goto_wn) != OPR_GOTO) return;
00638
00639
00640 WN * last_stmt = WN_last(WN_while_body(while_wn));
00641
00642
00643
00644
00645
00646 if (last_stmt &&
00647 WN_operator(last_stmt) == OPR_LABEL &&
00648 WN_label_number(goto_wn) == WN_label_number(last_stmt))
00649 patch = TRUE;
00650
00651
00652 WN * label_wn = NULL;
00653 GDESCRIPTOR * label_gd = NULL;
00654 for (INT i = _gd.Elements() - 1; i >= 0; i--) {
00655 GDESCRIPTOR *gd = &_gd.Bottom_nth(i);
00656 if (goto_wn == gd->Goto_Wn) {
00657 label_wn = gd->Label_Wn;
00658 label_gd = gd;
00659 break;
00660 }
00661 }
00662
00663 if (label_wn == NULL) return;
00664
00665
00666 WN * block = Get_Parent(label_wn);
00667
00668 if (!block || block != WN_while_body(while_wn)) return;
00669
00670 if (WN_next(label_wn))
00671 {
00672
00673 WN * comma_block = WN_CreateBlock();
00674 WN * wn = WN_next(label_wn);
00675 while (wn)
00676 {
00677
00678 WN * next_wn = WN_next(wn);
00679 wn = WN_EXTRACT_FromBlock(block, wn);
00680 WN_INSERT_BlockLast (comma_block, wn);
00681
00682 Fixup_Parents (wn, comma_block);
00683 wn = next_wn;
00684 }
00685
00686 WN * test = WN_while_test(while_wn);
00687 WN_while_test(while_wn) = WN_CreateComma(OPR_COMMA, WN_rtype(test),
00688 MTYPE_V, comma_block, test);
00689
00690 Fixup_Parents(comma_block, WN_while_test(while_wn));
00691 Fixup_Parents(WN_kid1(WN_while_test(while_wn)), WN_while_test(while_wn));
00692 patch = TRUE;
00693 }
00694
00695 if (patch)
00696 {
00697 label_gd->Label_Wn = NULL;
00698
00699
00700 WN_DELETE_FromBlock(parent, WN_prev(while_wn));
00701
00702 WN_set_opcode(while_wn, OPC_WHILE_DO);
00703 }
00704 }
00705
00706
00707
00708 static BOOL sanity_check_loop_body (WN * label_wn, WN * goto_wn)
00709 {
00710 BOOL found_target_label = FALSE;
00711 WN * prev = WN_prev(label_wn);
00712 if (!prev || WN_operator(prev) != OPR_GOTO)
00713 return TRUE;
00714
00715
00716
00717 if (!PU_ftn_lang(Get_Current_PU()))
00718 return TRUE;
00719
00720
00721
00722 INT label_num = WN_label_number(prev);
00723 WN * next_wn = NULL;
00724 for (WN *wn = label_wn; wn != goto_wn; wn = next_wn) {
00725 next_wn = WN_next(wn);
00726 if (WN_operator(wn) == OPR_LABEL && WN_label_number(wn) == label_num)
00727 found_target_label = TRUE;
00728
00729
00730 else if (found_target_label && PU_ftn_lang(Get_Current_PU()))
00731 return FALSE;
00732
00733
00734
00735 }
00736
00737 return TRUE;
00738 }
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763 BOOL GTABLE::Replace_Goto_With_While(GDESCRIPTOR *gd)
00764 {
00765 WN *goto_wn = gd->Goto_Wn;
00766 WN *label_wn = gd->Label_Wn;
00767 WN *parent = Get_Parent(goto_wn);
00768
00769 if (!sanity_check_loop_body(label_wn, goto_wn))
00770 return FALSE;
00771
00772 const OPCODE goto_opcode = WN_opcode(goto_wn);
00773 WN *cond;
00774 if (goto_opcode == OPC_GOTO) {
00775 cond = WN_CreateIntconst(OPCODE_make_op(OPR_INTCONST, Boolean_type,
00776 MTYPE_V), 1);
00777 } else if (goto_opcode == OPC_FALSEBR) {
00778 cond = WN_CreateExp1(OPCODE_make_op(OPR_LNOT, Boolean_type, MTYPE_V),
00779 WN_kid0(goto_wn));
00780 } else {
00781 Is_True(goto_opcode == OPC_TRUEBR,
00782 ("Unknown goto in Replace_Goto_With_While"));
00783 cond = WN_kid0(goto_wn);
00784 }
00785
00786 WN *block = WN_CreateBlock();
00787 WN_Set_Linenum(block, WN_Get_Linenum(goto_wn));
00788
00789
00790 WN *next_wn = NULL;
00791 for (WN *wn = label_wn; wn != goto_wn; wn = next_wn) {
00792 next_wn = WN_next(wn);
00793 wn = WN_EXTRACT_FromBlock(parent, wn);
00794 WN_INSERT_BlockBefore(block, NULL, wn);
00795 if (Get_Parent(wn)) Set_Parent(wn, block);
00796 }
00797
00798
00799 WN *while_wn = WN_CreateDoWhile(cond, block);
00800 Set_Parent(cond, while_wn);
00801 Set_Parent(block, while_wn);
00802 Set_Parent(while_wn, parent);
00803 WN_Set_Linenum(while_wn, WN_Get_Linenum(goto_wn));
00804
00805 WN_INSERT_BlockAfter(parent, goto_wn, while_wn);
00806 WN_EXTRACT_FromBlock(parent, goto_wn);
00807 gd->Is_Dismantled = TRUE;
00808
00809 if (Cur_PU_Feedback) {
00810 Cur_PU_Feedback->FB_convert_goto_to_loop(goto_wn, while_wn);
00811 }
00812
00813 Patch_Do_While (while_wn, parent);
00814
00815 WN_Delete(goto_wn);
00816
00817 return TRUE;
00818 }
00819
00820 void GTABLE::Print(FILE *fp)
00821 {
00822 fprintf(fp, "Printing a GTABLE\n");
00823 for (INT i = 0; i < _gd.Elements(); i++) {
00824 GDESCRIPTOR *gd = &_gd.Bottom_nth(i);
00825 fprintf(fp, "A goto with: \n");
00826 fprintf(fp, " offset = %d \n", gd->Goto_Offset);
00827 fprintf(fp, "to label = %d with \n", WN_label_number(gd->Goto_Wn));
00828 fprintf(fp, " offset = %d \n", gd->Label_Offset);
00829 fprintf(fp, "\n");
00830 }
00831 }
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841 static void convert_while_do (WN * block, WN * tree)
00842 {
00843 Is_True (WN_operator(tree) == OPR_WHILE_DO,
00844 ("convert_while_do() can only accept OPR_WHILE_DO!"));
00845 LABEL_IDX top_lbl;
00846 New_LABEL (CURRENT_SYMTAB, top_lbl);
00847
00848 LABEL_IDX br_lbl;
00849 New_LABEL (CURRENT_SYMTAB, br_lbl);
00850
00851
00852 WN_INSERT_BlockLast (block, WN_CreateGoto (br_lbl));
00853
00854 WN_INSERT_BlockLast (block, WN_CreateLabel ((ST_IDX) 0, top_lbl, 0, NULL));
00855
00856 WN_INSERT_BlockLast (block, WN_while_body(tree));
00857
00858 WN_INSERT_BlockLast (block, WN_CreateLabel((ST_IDX)0, br_lbl, 0, NULL));
00859
00860 WN_INSERT_BlockLast (block,
00861 WN_CreateTruebr (top_lbl, WN_while_test(tree)));
00862
00863 WN_Delete(tree);
00864 }
00865
00866
00867
00868
00869
00870
00871
00872 static void convert_do_while (WN * block, WN * tree)
00873 {
00874 Is_True (WN_operator(tree) == OPR_DO_WHILE,
00875 ("convert_do_while() can only accept OPR_DO_WHILE!"));
00876 LABEL_IDX top_lbl;
00877 New_LABEL (CURRENT_SYMTAB, top_lbl);
00878
00879 WN_INSERT_BlockLast (block, WN_CreateLabel ((ST_IDX) 0, top_lbl, 0, NULL));
00880
00881 WN_INSERT_BlockLast (block, WN_while_body(tree));
00882
00883 WN_INSERT_BlockLast (block,
00884 WN_CreateTruebr (top_lbl, WN_while_test(tree)));
00885
00886 WN_Delete(tree);
00887 }
00888
00889
00890 void GTABLE::Dismantle(WN *bad, WN *parent)
00891 {
00892 WN *prev = WN_prev(bad);
00893 WN *block = WN_CreateBlock();
00894 WN_EXTRACT_FromBlock(parent, bad);
00895
00896 switch (WN_operator(bad))
00897 {
00898 case OPR_WHILE_DO:
00899 convert_while_do (block, bad);
00900 break;
00901 case OPR_DO_WHILE:
00902 convert_do_while (block, bad);
00903 break;
00904 default:
00905 Is_True (FALSE, ("GTABLE::Dismantle does not dismantle %s",
00906 OPERATOR_name(WN_operator(bad))));
00907 }
00908
00909
00910 while (WN_last(block)) {
00911 WN *element = WN_EXTRACT_FromBlock(block, WN_last(block));
00912 WN_INSERT_BlockAfter(parent, prev, element);
00913 Fixup_Parents(element, parent);
00914 }
00915 WN_Delete(block);
00916 }
00917