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 #ifdef USE_PCH
00091 #include "be_com_pch.h"
00092 #endif
00093 #pragma hdrstop
00094 #define USE_STANDARD_TYPES
00095 #include <algorithm>
00096 #include <stdlib.h>
00097 #include <vector>
00098 #include <stack>
00099
00100 #include "defs.h"
00101 #include "stab.h"
00102 #include "wn.h"
00103 #include "wn_map.h"
00104 #include "wn_util.h"
00105 #include "mempool.h"
00106 #include "tracing.h"
00107 #include "targ_sim.h"
00108 #include "wn_pragmas.h"
00109 #include "ir_reader.h"
00110 #include "cxx_template.h"
00111 #include "cxx_hash.h"
00112 #include "config_asm.h"
00113 #include "glob.h"
00114 #include "pu_info.h"
00115
00116
00117
00118 #define Verifier_DEBUG 0
00119
00120
00121
00122
00123 struct pragma_stack_type
00124 {
00125 WN *parent_wn;
00126 WN_PRAGMA_ID pragma_id;
00127 };
00128
00129
00130
00131
00132
00133
00134
00135
00136 #define NUM_PRAGMAS_SUPPORTED 26
00137
00138 struct pragma_mapped_ids
00139 {
00140 WN_PRAGMA_ID pragma_id;
00141 BOOL push;
00142 WN_PRAGMA_ID pragma_starting_id;
00143 };
00144
00145
00146
00147
00148
00149
00150
00151 pragma_mapped_ids pragmas_supported[NUM_PRAGMAS_SUPPORTED] =
00152 {
00153 { WN_PRAGMA_INLINE_BODY_START, TRUE, WN_PRAGMA_UNDEFINED },
00154 { WN_PRAGMA_INLINE_BODY_END, FALSE, WN_PRAGMA_INLINE_BODY_START },
00155 { WN_PRAGMA_ENTER_GATE, TRUE, WN_PRAGMA_UNDEFINED },
00156 { WN_PRAGMA_EXIT_GATE, FALSE, WN_PRAGMA_ENTER_GATE },
00157 { WN_PRAGMA_CRITICAL_SECTION_BEGIN, TRUE, WN_PRAGMA_UNDEFINED },
00158 { WN_PRAGMA_CRITICAL_SECTION_END, FALSE, WN_PRAGMA_CRITICAL_SECTION_BEGIN },
00159 { WN_PRAGMA_PARALLEL_BEGIN, TRUE, WN_PRAGMA_UNDEFINED },
00160 { WN_PRAGMA_PARALLEL_END, FALSE, WN_PRAGMA_PARALLEL_BEGIN },
00161 { WN_PRAGMA_PDO_BEGIN, TRUE, WN_PRAGMA_UNDEFINED },
00162 { WN_PRAGMA_PDO_END, FALSE, WN_PRAGMA_PDO_BEGIN },
00163 { WN_PRAGMA_PSECTION_BEGIN, TRUE, WN_PRAGMA_UNDEFINED },
00164 { WN_PRAGMA_PSECTION_END, FALSE, WN_PRAGMA_PSECTION_BEGIN },
00165 { WN_PRAGMA_SINGLE_PROCESS_BEGIN, TRUE, WN_PRAGMA_UNDEFINED },
00166 { WN_PRAGMA_SINGLE_PROCESS_END, FALSE, WN_PRAGMA_SINGLE_PROCESS_BEGIN },
00167 { WN_PRAGMA_FLIST_SKIP_BEGIN, TRUE, WN_PRAGMA_UNDEFINED },
00168 { WN_PRAGMA_FLIST_SKIP_END, FALSE, WN_PRAGMA_FLIST_SKIP_BEGIN },
00169 { WN_PRAGMA_CLIST_SKIP_BEGIN, TRUE, WN_PRAGMA_UNDEFINED },
00170 { WN_PRAGMA_CLIST_SKIP_END, FALSE, WN_PRAGMA_CLIST_SKIP_BEGIN },
00171 { WN_PRAGMA_INDEPENDENT_BEGIN, TRUE, WN_PRAGMA_UNDEFINED },
00172 { WN_PRAGMA_INDEPENDENT_END, FALSE, WN_PRAGMA_INDEPENDENT_BEGIN },
00173 { WN_PRAGMA_CRI_CASE, TRUE, WN_PRAGMA_UNDEFINED },
00174 { WN_PRAGMA_CRI_ENDCASE, FALSE, WN_PRAGMA_CRI_CASE },
00175 { WN_PRAGMA_CRI_GUARD, TRUE, WN_PRAGMA_UNDEFINED },
00176 { WN_PRAGMA_CRI_ENDGUARD, FALSE, WN_PRAGMA_CRI_GUARD },
00177 { WN_PRAGMA_CRI_PARALLEL, TRUE, WN_PRAGMA_UNDEFINED },
00178 { WN_PRAGMA_CRI_ENDPARALLEL, FALSE, WN_PRAGMA_CRI_PARALLEL}
00179 };
00180
00181 class WN_Verifier{
00182 private:
00183
00184
00185
00186
00187
00188 MEM_POOL _mem_pool;
00189 WN_MAP _map;
00190 BOOL _is_tree_OK;
00191 WN *_func;
00192 std::stack< pragma_stack_type > _pragma_stack;
00193
00194
00195
00196
00197
00198
00199 BOOL Is_return_register_of_call(WN *call_wn, PREG_NUM preg);
00200 WN *One_level_removed_node(WN *parent_wn,OPERATOR opr);
00201 BOOL Is_dedicated_return_register(WN_OFFSET preg);
00202
00203 protected:
00204
00205
00206
00207
00208
00209 BOOL Is_WHIRL_tree(WN *wn, WN *parent);
00210 BOOL CALL_parent_LDID(WN *wn, WN *parent_wn);
00211 BOOL Proper_Block_Structure(WN *wn,OPCODE op);
00212 BOOL Param_parent_is_Call(WN *wn,WN *parent_wn);
00213 BOOL Call_children_are_PARM(WN *wn);
00214 BOOL Is_legal_wn_opcode(OPCODE opc);
00215 BOOL LDA_ty_not_NULL(WN *wn);
00216 BOOL STID_check_st_class(WN *wn);
00217 BOOL TY_is_not_NULL(WN *wn, OPCODE op);
00218 BOOL ST_is_not_NULL(WN *wn, OPCODE op);
00219 BOOL Load_addr_TY_is_not_NULL(WN *wn, OPCODE op);
00220 BOOL Are_enclosed_pragmas(WN *wn, WN *parent_wn);
00221 BOOL Field_id_valid (WN* wn);
00222
00223
00224 public:
00225 WN_Verifier(WN *wn);
00226 ~WN_Verifier();
00227 BOOL WN_traverse_tree(WN *wn, WN *parent_wn);
00228 };
00229
00230
00231
00232
00233
00234
00235
00236 WN_Verifier::WN_Verifier(WN *wn)
00237 {
00238
00239
00240 MEM_POOL_Initialize(&_mem_pool, "Verifier_Pool", FALSE);
00241 MEM_POOL_Push(&_mem_pool);
00242 _map = WN_MAP_Create(&_mem_pool);
00243
00244
00245
00246 _is_tree_OK=TRUE;
00247
00248 if (WN_operator(wn) == OPR_FUNC_ENTRY)
00249 _func = wn;
00250 else
00251 _func = NULL;
00252 }
00253
00254
00255 WN_Verifier::~WN_Verifier(void)
00256 {
00257
00258
00259 WN_MAP_Delete(_map);
00260 MEM_POOL_Pop(&_mem_pool);
00261 MEM_POOL_Delete(&_mem_pool);
00262 }
00263
00264
00265
00266
00267
00268
00269
00270
00271 BOOL
00272 WN_Verifier::WN_traverse_tree(WN *wn, WN *parent_wn)
00273 {
00274 OPCODE op;
00275
00276 if (wn)
00277 {
00278 op = WN_opcode(wn);
00279
00280
00281 _is_tree_OK &= Is_WHIRL_tree(wn, parent_wn);
00282
00283
00284
00285 switch(OPCODE_operator(op))
00286 {
00287 case OPR_FUNC_ENTRY:
00288 case OPR_XGOTO:
00289 case OPR_ALTENTRY:
00290
00291 _is_tree_OK &= ST_is_not_NULL(wn,op);
00292 break;
00293 case OPR_LDID:
00294
00295
00296
00297 _is_tree_OK &= CALL_parent_LDID(wn, parent_wn);
00298 _is_tree_OK &= TY_is_not_NULL(wn,op);
00299 _is_tree_OK &= ST_is_not_NULL(wn,op);
00300 _is_tree_OK &= Field_id_valid(wn);
00301 break;
00302 case OPR_LDA:
00303
00304
00305
00306 _is_tree_OK &= LDA_ty_not_NULL(wn);
00307 _is_tree_OK &= ST_is_not_NULL(wn,op);
00308 break;
00309 case OPR_IDNAME:
00310 case OPR_CONST:
00311
00312 _is_tree_OK &= ST_is_not_NULL(wn,op);
00313 break;
00314 case OPR_STID:
00315
00316
00317 _is_tree_OK &= STID_check_st_class(wn);
00318 _is_tree_OK &= TY_is_not_NULL(wn,op);
00319 _is_tree_OK &= ST_is_not_NULL(wn,op);
00320 _is_tree_OK &= Field_id_valid(wn);
00321 break;
00322 case OPR_MLOAD:
00323 case OPR_ISTORE:
00324 case OPR_MSTORE:
00325
00326 _is_tree_OK &= TY_is_not_NULL(wn,op);
00327 _is_tree_OK &= Field_id_valid(wn);
00328 break;
00329 case OPR_ISTOREX:
00330 case OPR_TAS:
00331
00332 _is_tree_OK &= TY_is_not_NULL(wn,op);
00333 break;
00334 case OPR_ILOAD:
00335
00336 _is_tree_OK &= TY_is_not_NULL(wn,op);
00337 _is_tree_OK &= Load_addr_TY_is_not_NULL(wn,op);
00338 _is_tree_OK &= Field_id_valid(wn);
00339 break;
00340 case OPR_PARM:
00341
00342 _is_tree_OK &= Param_parent_is_Call(wn,parent_wn);
00343 break;
00344 case OPR_CALL:
00345 case OPR_PICCALL:
00346
00347
00348 _is_tree_OK &= Call_children_are_PARM(wn);
00349 _is_tree_OK &= ST_is_not_NULL(wn,op);
00350 break;
00351 case OPR_ICALL:
00352
00353
00354 _is_tree_OK &= Call_children_are_PARM(wn);
00355 _is_tree_OK &= TY_is_not_NULL(wn,op);
00356 break;
00357 case OPR_INTRINSIC_CALL:
00358 case OPR_IO:
00359 case OPR_INTRINSIC_OP:
00360 #ifdef KEY
00361 case OPR_PURE_CALL_OP:
00362 #endif
00363
00364
00365 _is_tree_OK &= Call_children_are_PARM(wn);
00366 break;
00367 case OPR_PRAGMA:
00368
00369 _is_tree_OK &= Are_enclosed_pragmas(wn,parent_wn);
00370 break;
00371 default:
00372
00373 _is_tree_OK &= Is_legal_wn_opcode(op);
00374 }
00375
00376 if ( op == OPC_BLOCK)
00377 {
00378
00379 Proper_Block_Structure(wn,op);
00380 for(WN *node = WN_first(wn); node; node = WN_next(node))
00381 _is_tree_OK &= WN_traverse_tree(node,wn);
00382 } else {
00383 for(INT32 i = 0; i < WN_kid_count(wn); i++)
00384 _is_tree_OK &= WN_traverse_tree(WN_kid(wn,i),wn);
00385 }
00386 }
00387 if (!parent_wn) {
00388 if (WN_Tree_Has_Duplicate_Labels(wn, &_mem_pool))
00389 Fail_FmtAssertion("WN_Verifier() found duplicate labels in "
00390 "WHIRL tree");
00391 }
00392 return _is_tree_OK;
00393 }
00394
00395
00396 BOOL WN_Verifier::TY_is_not_NULL(WN *wn, OPCODE op)
00397 {
00398 FmtAssert(WN_ty(wn) != (TY_IDX)NULL,
00399 ("WN_verifier Error (TY_is_not_NULL): whirl node %s has "
00400 "a TY == NULL", OPCODE_name(op)));
00401 return TRUE;
00402 }
00403
00404
00405 BOOL WN_Verifier::Load_addr_TY_is_not_NULL(WN *wn, OPCODE op)
00406 {
00407 FmtAssert(WN_load_addr_ty(wn) != (TY_IDX)NULL,
00408 ("WN_verifier Error (Load_addr_TY_is_not_NULL): whirl "
00409 "node %s has a TY == NULL", OPCODE_name(op)));
00410 return TRUE;
00411 }
00412
00413
00414
00415
00416 BOOL WN_Verifier::ST_is_not_NULL(WN *wn, OPCODE op)
00417 {
00418 FmtAssert(WN_st_idx(wn)!=(ST_IDX)NULL,
00419 ("WN_verifier Error (ST_is_not_NULL): whirl node %s "
00420 "has a ST == NULL", OPCODE_name(op)));
00421
00422 if (ST_is_not_used (WN_st(wn)) && !OPERATOR_is_store (WN_operator (wn)))
00423 DevWarn ("WN_verifier Error: whirl node %s references symbol"
00424 " %s that is marked NOT_USED", OPCODE_name(op),
00425 ST_name (WN_st(wn)));
00426 return TRUE;
00427 }
00428
00429
00430
00431
00432
00433
00434
00435
00436 BOOL
00437 WN_Verifier::Is_WHIRL_tree(WN *wn, WN *parent_wn)
00438 {
00439 if (Is_legal_wn_opcode(WN_opcode(wn)) == FALSE)
00440 return FALSE;
00441 if ( WN_MAP_Get(_map, wn) != NULL ) {
00442 FmtAssert(FALSE, ("WN_verifier ERROR: This is not a WHIRL tree\n\t"
00443 "(0x%x --> 0x%x, 0x%x --> 0x%x).\n",
00444 WN_MAP_Get(_map, wn), wn, parent_wn, wn));
00445 return FALSE;
00446 } else
00447 WN_MAP_Set(_map, wn, (void *)parent_wn);
00448 return TRUE;
00449 }
00450
00451
00452
00453 BOOL WN_Verifier::Is_dedicated_return_register(WN_OFFSET preg)
00454 {
00455 #if defined(TARG_NVISA) || defined(TARG_SL)
00456 return Is_Return_Preg(preg);
00457 #else
00458 return ((preg == 2) || (preg == 3) || (preg == 32) || (preg==34));
00459 #endif
00460 }
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471 WN *
00472 WN_Verifier::One_level_removed_node(WN *parent_wn,OPERATOR opr)
00473 {
00474 WN *temp_wn = NULL;
00475
00476 if (opr == OPR_LDID && parent_wn != NULL &&
00477 WN_operator(parent_wn) == OPR_STID)
00478 temp_wn = WN_prev(parent_wn);
00479 return temp_wn;
00480 }
00481
00482
00483
00484
00485
00486
00487
00488
00489 BOOL
00490 WN_Verifier::Is_return_register_of_call(WN *call_wn, PREG_NUM preg)
00491 {
00492 PREG_NUM retreg1, retreg2;
00493 TYPE_ID ty1,ty2;
00494
00495 if (Verifier_DEBUG)
00496 DevWarn("Verifier TODO: how do I know to use "
00497 "Use_Similated/Complex_Not...");
00498
00499
00500 const PU& pu = Pu_Table[ST_pu (WN_st (call_wn))];
00501
00502 #if defined(TARG_NVISA)
00503 FmtAssert(WHIRL_Return_Info_On, ("return_info required"));
00504 #else
00505 if (WHIRL_Return_Info_On)
00506 #endif
00507 {
00508
00509 RETURN_INFO return_info = Get_Return_Info (TY_ret_type (Ty_Table[PU_prototype (pu)]),
00510 Complex_Not_Simulated
00511 #ifdef TARG_X8664
00512 , PU_ff2c_abi(pu)
00513 #endif
00514 );
00515
00516 if (RETURN_INFO_count(return_info) <= MAX_NUMBER_OF_REGISTERS_FOR_RETURN) {
00517 INT i;
00518 for (i = 0; i < RETURN_INFO_count(return_info); ++i) {
00519 if (preg == RETURN_INFO_preg(return_info,i))
00520 return TRUE;
00521 }
00522 return FALSE;
00523 }
00524 else
00525 Fail_FmtAssertion (
00526 "WN_Verifier::Is_return_register_of_call: more than expected return registers");
00527 }
00528
00529 #if !defined(TARG_NVISA)
00530 else
00531 Get_Return_Mtypes (TY_ret_type (Ty_Table[PU_prototype (pu)]),
00532 Complex_Not_Simulated, &ty1,&ty2);
00533
00534
00535
00536 if (!WHIRL_Return_Info_On)
00537 Get_Return_Pregs(ty1,ty2,&retreg1,&retreg2);
00538 return ((preg == retreg1) || (preg == retreg2));
00539 #endif
00540 }
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553 BOOL WN_Verifier::CALL_parent_LDID(WN *wn, WN *parent_wn)
00554 {
00555 OPCODE opc=WN_opcode(wn);
00556 OPERATOR opr = OPCODE_operator(opc);
00557 WN *temp_wn;
00558 BOOL slink_used;
00559
00560 #if !defined(TARG_IA64) && !defined(TARG_X8664)
00561
00562
00563
00564
00565
00566
00567 if (opr == OPR_LDID && ST_class(WN_st(wn)) == CLASS_PREG &&
00568 Is_dedicated_return_register(WN_offset(wn)))
00569 {
00570 temp_wn = One_level_removed_node(parent_wn,opr);
00571 if (_func != NULL) {
00572 const PU& pu = Pu_Table[ST_pu (WN_st (_func))];
00573 slink_used = PU_is_nested_func(pu);
00574 } else
00575 slink_used = TRUE;
00576
00577 if ((temp_wn !=NULL) && (WN_operator(temp_wn) == OPR_STID))
00578 temp_wn = WN_prev(temp_wn);
00579
00580
00581
00582
00583 if (temp_wn==NULL) {
00584 if (!slink_used) {
00585 DevWarn("WN_verifier Error (Call_parent_LDID): no CALL "
00586 "instruction one/two level(s) removed from LDID %d",
00587 WN_offset(wn));
00588 return FALSE;
00589 } else {
00590 return TRUE;
00591 }
00592 }
00593
00594 OPCODE t_opc = WN_opcode(temp_wn);
00595 OPERATOR t_opr = OPCODE_operator(t_opc);
00596
00597
00598
00599 if ( t_opr == OPR_CALL || t_opr == OPR_ICALL ||
00600 t_opr == OPR_INTRINSIC_CALL ||
00601 t_opr == OPR_PICCALL || t_opr == OPR_IO ||
00602 t_opr == OPR_INTRINSIC_OP)
00603 {
00604
00605 if ( t_opr == OPR_CALL &&
00606 !Is_return_register_of_call(temp_wn,WN_offset(wn)))
00607 {
00608 DevWarn("WN_verifier Error (Call_parent_LDID): different register "
00609 "follows CALL than needed, LDID %d", WN_offset(wn));
00610 return FALSE;
00611 }
00612 else if (Verifier_DEBUG)
00613 DevWarn("Verifier (Call_parent_LDID): Call is Ok");
00614 }
00615
00616
00617
00618
00619 else if (!slink_used)
00620 {
00621 DevWarn("WN_verifier Error (Call_parent_LDID): LDID %d was not "
00622 "following any CALL node", WN_offset(wn));
00623 return FALSE;
00624 }
00625
00626 }
00627 #endif
00628 return TRUE;
00629 }
00630
00631
00632
00633 BOOL WN_Verifier::Proper_Block_Structure(WN *wn,OPCODE op)
00634 {
00635 BOOL block_ok = TRUE;
00636
00637 if (op == OPC_BLOCK)
00638 {
00639
00640 WN *first = WN_first(wn);
00641 WN *last = WN_last(wn);
00642 if ( first == NULL ) {
00643 FmtAssert( last == NULL,
00644 ("WN_verifier Error (Proper_Block_Structure): first is NULL but last is not."));
00645 block_ok = FALSE;
00646 }
00647 if ( first != NULL && WN_prev(first) != NULL){
00648 FmtAssert(FALSE, ("WN_verifier Error (Proper_Block_Structure): This block does "
00649 "not have a null pointer in the first wn node"));
00650 block_ok = FALSE;
00651 }
00652
00653
00654 if ( last != NULL && WN_next(last) != NULL ) {
00655 FmtAssert(FALSE, ("WN_verifier Error (Proper_Block_Structure): This block does "
00656 "not have a null pointer in the last wn node"));
00657 block_ok = FALSE;
00658 }
00659
00660
00661 WN *tmp = first;
00662 while (tmp && WN_next(tmp) != NULL)
00663 tmp = WN_next(tmp);
00664 if (tmp != last) {
00665 FmtAssert (FALSE, ("WN_verifier Error (Proper_Block_Structure): last is not really last\n"));
00666 block_ok = FALSE;
00667 }
00668
00669
00670 tmp = last;
00671 while (tmp && WN_prev(tmp) != NULL)
00672 tmp = WN_prev(tmp);
00673 if (tmp != first) {
00674 FmtAssert (FALSE, ("WN_verifier Error (Proper_Block_Structure): first is not really firstt\n"));
00675 block_ok = FALSE;
00676 }
00677 }
00678 return block_ok;
00679 }
00680
00681
00682
00683
00684 BOOL WN_Verifier::Param_parent_is_Call(WN *wn,WN *parent_wn)
00685 {
00686 OPCODE opc=WN_opcode(wn);
00687 OPERATOR opr = OPCODE_operator(opc);
00688
00689 if (opr == OPR_PARM)
00690 {
00691 opc = WN_opcode(parent_wn);
00692 opr = OPCODE_operator(opc);
00693 if (opr == OPR_CALL || opr == OPR_ICALL ||
00694 opr == OPR_INTRINSIC_CALL ||
00695 opr == OPR_PICCALL || opr == OPR_IO ||
00696 #ifdef KEY
00697 opr == OPR_PURE_CALL_OP ||
00698 #endif
00699 opr == OPR_INTRINSIC_OP)
00700 {
00701
00702 return TRUE;
00703 } else {
00704
00705 DevWarn("WN_verifier Error (Param_parent_is_Call): The parent of the "
00706 "PARM node is not a CALL node but a %s node",OPCODE_name(opc));
00707 return FALSE;
00708 }
00709 }
00710 return TRUE;
00711 }
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721 BOOL WN_Verifier::Call_children_are_PARM(WN *wn)
00722 {
00723 OPCODE opc=WN_opcode(wn);
00724 OPCODE parent_opc=opc;
00725 OPERATOR opr = OPCODE_operator(opc);
00726 OPERATOR parent_opr=opr;
00727
00728 if (opr == OPR_CALL ||
00729 opr == OPR_INTRINSIC_CALL ||
00730 opr == OPR_INTRINSIC_OP ||
00731 #ifdef KEY
00732 opr == OPR_PURE_CALL_OP ||
00733 #endif
00734 opr == OPR_IO)
00735 {
00736 for(INT32 i=0; i < WN_kid_count(wn); i++)
00737 {
00738 opc = WN_opcode(WN_kid(wn,i));
00739 opr = OPCODE_operator(opc);
00740
00741
00742
00743
00744
00745
00746
00747
00748 if ((opr != OPR_PARM ) &&
00749 ((parent_opr == OPR_IO) && (opr != OPR_IO_ITEM)) )
00750 {
00751
00752 DevWarn("WN_verifier Error (Call_children_are_PARM): The child of %s "
00753 "node is not a PARM node but a %s node",
00754 OPCODE_name(parent_opc), OPCODE_name(opc));
00755 return FALSE;
00756 }
00757 }
00758 }
00759 else if ( opr == OPR_PICCALL || opr == OPR_ICALL)
00760 {
00761 for(INT32 i=0; i < WN_kid_count(wn); i++)
00762 { opc = WN_opcode(WN_kid(wn,i));
00763 opr = OPCODE_operator(opc);
00764
00765
00766
00767 if ((opr != OPR_PARM) && (i < (WN_kid_count(wn)-1) ))
00768 {
00769
00770 DevWarn("WN_verifier Error (Call_children_are_PARM): The child of "
00771 "CALL node is not a PARM node but a %s node",
00772 OPCODE_name(opc));
00773 return FALSE;
00774 }
00775
00776 else if ((opr == OPR_PARM) && (i == (WN_kid_count(wn)-1)))
00777 {
00778 DevWarn("WN_verifier Error (Call_children_are_PARM): The last "
00779 "child of (P)ICALL node is a PARM node");
00780 return FALSE;
00781 }
00782 }
00783 }
00784
00785 return TRUE;
00786 }
00787
00788
00789
00790
00791
00792
00793
00794
00795 BOOL WN_Verifier::Is_legal_wn_opcode(OPCODE opc)
00796 {
00797
00798 if (opc < OPCODE_FIRST || opc > OPCODE_LAST)
00799 {
00800 DevWarn("WN_verifier Error (Is_legal_wn_opcode): The opcode %s "
00801 "is illegal",OPCODE_name(opc));
00802 }
00803 return ((opc >= OPCODE_FIRST) && (opc <= OPCODE_LAST));
00804 }
00805
00806
00807
00808 BOOL WN_Verifier::LDA_ty_not_NULL(WN *wn)
00809 {
00810 OPCODE opc = WN_opcode(wn);
00811 OPERATOR opr = OPCODE_operator(opc);
00812
00813 if (opr == OPR_LDA) {
00814 const TY& ty = Ty_Table[WN_ty (wn)];
00815 if (WN_ty (wn) == 0 ||
00816 !(TY_kind(ty) == KIND_POINTER || TY_kind(ty) == KIND_SCALAR)) {
00817 DevWarn("WN_verifier Error (LDA_ty_not_NULL): TY of the %s is "
00818 "either NULL or is not a pointer or scalar",
00819 OPCODE_name(opc));
00820 if (DevWarn_Enabled()) {
00821 #ifdef KEY // print type name only for shorter output
00822 if (TY_name_idx(ty) == 0)
00823 fprintf(stderr, "(anon)\n");
00824 else fprintf(stderr, "%s\n", TY_name(ty));
00825 #else
00826 ty.Print (stderr);
00827 #endif
00828 }
00829 return FALSE;
00830 }
00831 }
00832 return TRUE;
00833 }
00834
00835
00836
00837
00838
00839 BOOL WN_Verifier::STID_check_st_class(WN *wn)
00840 {
00841 OPCODE opc = WN_opcode(wn);
00842 OPERATOR opr = OPCODE_operator(opc);
00843
00844 if (opr == OPR_STID) {
00845 ST * st = WN_st(wn);
00846
00847 if ( ( ST_class(st)!=CLASS_VAR ) &&
00848 ( ST_class(st)!=CLASS_PREG ) &&
00849 ( ST_class(st)!=CLASS_BLOCK) )
00850 {
00851 DevWarn("WN_verifier Error (STID_check_st_class): ST of the STID is "
00852 "not CLASS: VAR, PREG or Block but %d", ST_class(st));
00853 return FALSE;
00854 }
00855 #ifndef TARG_X8664
00856 if ( (ST_class(st) == CLASS_PREG) &&
00857 (Is_dedicated_return_register(WN_offset(wn))) )
00858 {
00859 WN *temp_wn = WN_next(wn);
00860
00861
00862
00863 if ((temp_wn != NULL) &&
00864 (WN_operator(temp_wn) == OPR_STID) &&
00865 (ST_class(WN_st(temp_wn)) == CLASS_PREG ) &&
00866 (Is_dedicated_return_register(WN_offset(temp_wn))) )
00867 {
00868
00869
00870
00871
00872 temp_wn=WN_next(temp_wn);
00873 }
00874
00875
00876
00877
00878
00879 if ((WN_offset(wn) != Static_Link_Preg_Offset) &&
00880 ((temp_wn == NULL) || (WN_operator(temp_wn) != OPR_RETURN)) )
00881 {
00882 DevWarn("WN_verifier Error (STID_check_st_class): STID %d was "
00883 "followed by %s and not by OPC_RETURN",
00884 WN_offset(wn),
00885 temp_wn ? OPCODE_name(WN_opcode(temp_wn)) : "NULL");
00886 }
00887 else if ((WN_offset(wn) == Static_Link_Preg_Offset) &&
00888 ((temp_wn == NULL) || (WN_operator(temp_wn) != OPR_RETURN)
00889 && (WN_operator(temp_wn) != OPR_PICCALL)
00890 && (WN_operator(temp_wn) != OPR_CALL)) )
00891 {
00892 DevWarn("WN_verifier Error (STID_check_st_class): STID %d was "
00893 "followed by %s and not by OPC_RETURN or OPR_CALL or OPR_PICCALL",
00894 WN_offset(wn),OPCODE_name(WN_opcode(temp_wn)));
00895 }
00896 }
00897 #endif
00898
00899
00900 switch(ST_sclass(st))
00901 {
00902 case SCLASS_UNKNOWN:
00903 case SCLASS_AUTO:
00904 case SCLASS_FORMAL:
00905 case SCLASS_PSTATIC:
00906 case SCLASS_FSTATIC:
00907 case SCLASS_COMMON:
00908 case SCLASS_EXTERN:
00909 case SCLASS_UGLOBAL:
00910 case SCLASS_DGLOBAL:
00911 case SCLASS_REG:
00912 case SCLASS_FORMAL_REF:
00913
00914
00915 break;
00916
00917 case SCLASS_TEXT:
00918 DevWarn("WN_verifier Error (STID_check_st_class): ST SCLASS "
00919 "is SCALSS_TEXT");
00920 Print_ST(stderr, st, FALSE);
00921 return FALSE;
00922
00923
00924 default:
00925 DevWarn("WN_verifier Error (STID_check_st_class): ST SCLASS "
00926 "is unknown");
00927 Print_ST(stderr, st, FALSE);
00928 return FALSE;
00929 }
00930 }
00931 return TRUE;
00932 }
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953 BOOL WN_Verifier::Are_enclosed_pragmas(WN *wn,WN *parent_wn)
00954 {
00955 pragma_stack_type temp;
00956 WN_PRAGMA_ID temp_id= (WN_PRAGMA_ID) WN_pragma(wn);
00957 int i = 0;
00958
00959
00960 while(i<NUM_PRAGMAS_SUPPORTED)
00961 {
00962
00963 if (pragmas_supported[i].pragma_id=temp_id)
00964 {
00965
00966
00967 if (pragmas_supported[i].push)
00968 {
00969 temp.pragma_id = temp_id;
00970 temp.parent_wn = parent_wn;
00971 _pragma_stack.push(temp);
00972 return TRUE;
00973 }
00974
00975
00976 else if (_pragma_stack.size()>0)
00977 {
00978 temp= _pragma_stack.top();
00979
00980
00981
00982
00983
00984 if (temp.pragma_id == pragmas_supported[i].pragma_starting_id &&
00985 temp.parent_wn == parent_wn)
00986 {
00987 if (Verifier_DEBUG)
00988 DevWarn("Stack worked!!");
00989 _pragma_stack.pop();
00990 return TRUE;
00991 }
00992 else if (temp.pragma_id != pragmas_supported[i].pragma_starting_id)
00993 {
00994 DevWarn("WN_verifier Error (Are_enclosed_pragmas): on stack "
00995 "expecting %d but got %d",
00996 pragmas_supported[i].pragma_starting_id, temp.pragma_id);
00997 return FALSE;
00998 }
00999 else
01000 {
01001 DevWarn("WN_verifier Error (Are_enclosed_pragmas): the pragma "
01002 "is closed by different level of the parent");
01003 return FALSE;
01004 }
01005
01006 }
01007 else
01008 {
01009 return FALSE;
01010 }
01011 }
01012 i++;
01013 }
01014 return TRUE;
01015 }
01016
01017
01018 BOOL
01019 WN_Verifier::Field_id_valid (WN* wn)
01020 {
01021 const TY* ty = &Ty_Table[WN_ty (wn)];
01022
01023 switch (WN_operator(wn)) {
01024 case OPR_MLOAD:
01025 case OPR_MSTORE:
01026 Is_True (TY_kind (*ty) == KIND_POINTER,
01027 ("MLOAD/MSTORE expects a pointer type"));
01028 if (TY_kind(TY_pointed(*ty)) == KIND_STRUCT &&
01029 WN_field_id(wn) == 0) {
01030 WN* kid = WN_operator(wn) == OPR_MLOAD ? WN_kid1(wn) : WN_kid2(wn);
01031 if (WN_operator(kid) == OPR_INTCONST) {
01032 INT64 ty_size = TY_size(TY_pointed(*ty));
01033
01034 Is_True (ty_size == 0 || WN_const_val (kid) % ty_size == 0,
01035 ("MLOAD/MSTORE size is inconsistent with TY"));
01036 }
01037 }
01038 break;
01039 case OPR_ILOAD:
01040 ty = &Ty_Table[WN_load_addr_ty(wn)];
01041
01042 case OPR_ISTORE:
01043 ty = &Ty_Table[TY_pointed (*ty)];
01044 if (strncmp(TY_name(*ty), ".dope.", 6) == 0)
01045 break;
01046
01047 case OPR_STID:
01048 case OPR_LDID:
01049 if (TY_kind(*ty) != KIND_STRUCT) {
01050 Is_True (WN_field_id(wn) == 0,
01051 ("non-zero field id for memory op on scalar"));
01052 } else if (WN_field_id(wn) == 0) {
01053 Is_True (WN_desc(wn) == MTYPE_M ||
01054 MTYPE_byte_size(WN_desc(wn)) == TY_size(*ty),
01055 ("field_id and descriptor type are inconsistent"));
01056 }
01057 break;
01058 default:
01059 break;
01060 }
01061
01062 return TRUE;
01063 }
01064
01065
01066
01067
01068
01069
01070
01071 BOOL WN_Tree_Has_Duplicate_Labels(WN *pu_wn, MEM_POOL *tmp_pool)
01072 {
01073 MEM_POOL_Popper popper(tmp_pool);
01074 WN_ITER *it = WN_WALK_TreeIter(pu_wn);
01075 HASH_TABLE<LABEL_IDX, WN *> labels_found(257, tmp_pool);
01076
01077 while (it) {
01078 WN *wn = it->wn;
01079
01080 if (WN_operator(wn) == OPR_LABEL) {
01081 LABEL_IDX lab = WN_label_number(wn);
01082 Is_True(LABEL_IDX_index(lab) > 0, ("WN_verifier: found label with number 0"));
01083 Is_True(LABEL_IDX_index(lab)<=LABEL_Table_Size(LABEL_IDX_level(lab)),
01084 ("WN_verifier: label %d greater than last label %d",
01085 (INT) lab, LABEL_Table_Size(LABEL_IDX_level(lab))));
01086 WN *dup_lab_wn = labels_found.Find(lab);
01087
01088 if (dup_lab_wn){
01089 WN_WALK_Abort(it);
01090 return TRUE;
01091 }
01092
01093 labels_found.Enter(lab, wn);
01094 }
01095
01096 it = WN_WALK_TreeNext(it);
01097 }
01098
01099 return FALSE;
01100 }
01101
01102
01103
01104 enum WN_Label_Fields {
01105 WN_HAS_NO_LABELS,
01106 WN_HAS_LABEL,
01107 WN_HAS_LAST_LABEL
01108 };
01109
01110
01111 static WN_Label_Fields WN_Has_Label(WN *wn)
01112 {
01113 Is_True(wn, ("NULL wn"));
01114
01115 switch (WN_operator(wn)) {
01116 case OPR_CASEGOTO:
01117 case OPR_FALSEBR:
01118 case OPR_GOTO:
01119 case OPR_LABEL:
01120 case OPR_REGION_EXIT:
01121 case OPR_TRUEBR:
01122 return WN_HAS_LABEL;
01123 case OPR_COMPGOTO:
01124 case OPR_SWITCH:
01125 return WN_HAS_LAST_LABEL;
01126 default:
01127 break;
01128 }
01129
01130 return WN_HAS_NO_LABELS;
01131 }
01132
01133 typedef HASH_TABLE<LABEL_IDX, LABEL_IDX> LABEL_RENAMING_MAP;
01134
01135 static BOOL
01136 References_Some_Label(WN *pu_wn, LABEL_RENAMING_MAP *lab_map, WN *orig_wn);
01137
01138 static void
01139 Rename_INITV_Labels(INITO_IDX inito_idx, LABEL_RENAMING_MAP *lab_map,
01140 MEM_POOL *tmp_pool);
01141
01142 BOOL
01143 WN_Rename_Duplicate_Labels(WN *orig_wn, WN *copied_wn, WN *pu_wn,
01144 MEM_POOL *tmp_pool)
01145 {
01146 MEM_POOL_Popper popper(tmp_pool);
01147 LABEL_RENAMING_MAP lab_map(1021, tmp_pool);
01148
01149
01150 WN_ITER *orig_it = WN_WALK_TreeIter(orig_wn);
01151
01152 while (orig_it) {
01153 WN *wn = orig_it->wn;
01154
01155 if (WN_operator(wn) == OPR_LABEL) {
01156
01157 LABEL_IDX lab_idx = WN_label_number(wn), new_lab_idx;
01158 Is_True(!lab_map.Find(lab_idx),
01159 ("duplicate label %d in orig_wn", (INT) lab_idx));
01160
01161 LABEL &new_lab = New_LABEL(LABEL_IDX_level(lab_idx), new_lab_idx);
01162 char* Cur_PU_Name = ST_name(PU_Info_proc_sym(Current_PU_Info));
01163 INT strsize = strlen(User_Label_Number_Format) + 64 + strlen(Cur_PU_Name);
01164 char * labelname = (char*) calloc(strsize, 1);
01165 sprintf(labelname, User_Label_Number_Format, (INT)LABEL_IDX_level(new_lab_idx),
01166 (INT) new_lab_idx, Cur_PU_Name);
01167 LABEL_Init(new_lab, Save_Str(labelname),
01168 LABEL_kind((*Scope_tab[LABEL_IDX_level(new_lab_idx)].label_tab)[LABEL_IDX_index(lab_idx)]));
01169
01170 lab_map.Enter(lab_idx, new_lab_idx);
01171 }
01172
01173 orig_it = WN_WALK_TreeNext(orig_it);
01174 }
01175
01176
01177 WN_ITER *copied_it = WN_WALK_TreeIter(copied_wn);
01178
01179 while (copied_it) {
01180 WN *wn = copied_it->wn;
01181 WN_Label_Fields wn_lab = WN_Has_Label(wn);
01182
01183 if (wn_lab == WN_HAS_LABEL || wn_lab == WN_HAS_LAST_LABEL) {
01184 LABEL_IDX lab_idx = (wn_lab == WN_HAS_LABEL) ? WN_label_number(wn) :
01185 WN_last_label(wn);
01186
01187 LABEL_IDX new_lab_idx = lab_map.Find(lab_idx);
01188 if (new_lab_idx) {
01189 if (wn_lab == WN_HAS_LABEL)
01190 WN_label_number(wn) = new_lab_idx;
01191 else
01192 WN_last_label(wn) = new_lab_idx;
01193 }
01194
01195 } else if (wn_lab != WN_HAS_NO_LABELS)
01196 Fail_FmtAssertion("impossible return value from WN_Has_Label");
01197
01198 if (WN_operator(wn) == OPR_REGION && WN_ereg_supp(wn))
01199 Rename_INITV_Labels(WN_ereg_supp(wn), &lab_map, tmp_pool);
01200
01201 copied_it = WN_WALK_TreeNext(copied_it);
01202 }
01203
01204 if (!pu_wn)
01205 return TRUE;
01206
01207
01208 return !References_Some_Label(pu_wn, &lab_map, orig_wn);
01209 }
01210
01211
01212
01213 static BOOL
01214 References_Some_Label(WN *pu_wn, LABEL_RENAMING_MAP *lab_map, WN *orig_wn)
01215 {
01216 Is_True(pu_wn, ("NULL pu_wn"));
01217
01218 if (pu_wn == orig_wn)
01219 return FALSE;
01220
01221 WN_Label_Fields wn_lab = WN_Has_Label(pu_wn);
01222
01223 if (wn_lab == WN_HAS_LABEL || wn_lab == WN_HAS_LAST_LABEL) {
01224 LABEL_IDX lab_idx = (wn_lab == WN_HAS_LABEL) ? WN_label_number(pu_wn) :
01225 WN_last_label(pu_wn);
01226 if (lab_map->Find(lab_idx))
01227 return TRUE;
01228
01229 } else if (wn_lab != WN_HAS_NO_LABELS)
01230 Fail_FmtAssertion("impossible return value from WN_Has_Label");
01231
01232 OPERATOR opr = WN_operator(pu_wn);
01233
01234 if (!OPERATOR_is_leaf(opr)) {
01235 if (opr == OPR_BLOCK) {
01236 for (WN *kid = WN_first(pu_wn); kid; kid = WN_next(kid))
01237 if (References_Some_Label(kid, lab_map, orig_wn))
01238 return TRUE;
01239
01240 } else {
01241 for (INT kidno = 0; kidno < WN_kid_count(pu_wn); kidno++)
01242 if (References_Some_Label(WN_kid(pu_wn, kidno), lab_map, orig_wn))
01243 return TRUE;
01244 }
01245 }
01246
01247 return FALSE;
01248 }
01249
01250
01251
01252
01253
01254 static void
01255 Rename_INITV_Labels(INITO_IDX inito_idx, LABEL_RENAMING_MAP *lab_map,
01256 MEM_POOL *tmp_pool)
01257 {
01258 {
01259 BOOL renamed_labels_found = FALSE;
01260 STACK<INITV_IDX> initv_stack(tmp_pool);
01261 INITV_IDX val_idx = INITO_val(inito_idx);
01262
01263 while (val_idx) {
01264 INITVKIND k = INITV_kind(val_idx);
01265 switch (k) {
01266 case INITVKIND_SYMOFF:
01267 case INITVKIND_ZERO:
01268 case INITVKIND_ONE:
01269 case INITVKIND_VAL:
01270 case INITVKIND_PAD:
01271 val_idx = INITV_next(val_idx);
01272 break;
01273
01274 case INITVKIND_BLOCK:
01275 initv_stack.Push(val_idx);
01276 val_idx = INITV_blk(val_idx);
01277 break;
01278
01279 case INITVKIND_SYMDIFF:
01280 case INITVKIND_SYMDIFF16:
01281 case INITVKIND_LABEL:
01282 {
01283 LABEL_IDX lab = (k == INITVKIND_LABEL) ? INITV_lab(val_idx) :
01284 INITV_lab1(val_idx);
01285 if (lab_map->Find(lab))
01286 renamed_labels_found = TRUE;
01287 #ifdef KEY
01288
01289 else
01290 val_idx = INITV_next(val_idx);
01291 #endif // KEY
01292 }
01293 break;
01294
01295 default:
01296 Fail_FmtAssertion("unknown INITV kind %d", (INT) k);
01297 }
01298 if (renamed_labels_found)
01299 break;
01300
01301 while (!val_idx && initv_stack.Elements() > 0) {
01302 val_idx = INITV_next(initv_stack.Pop());
01303 }
01304 }
01305
01306 if (!renamed_labels_found)
01307 return;
01308 }
01309
01310
01311 STACK<INITV_IDX> old_stack(tmp_pool), new_stack(tmp_pool);
01312 INITV_IDX old_initv = INITO_val(inito_idx),
01313 new_initv,
01314 parent = INITV_IDX_ZERO,
01315 prev = INITV_IDX_ZERO;
01316 BOOL first_new_initv = TRUE;
01317
01318 while (old_initv) {
01319 new_initv = Copy_INITV(INITV_IDX_ZERO, INITO_IDX_ZERO, old_initv);
01320
01321 if (first_new_initv) {
01322 Set_INITO_val(inito_idx, new_initv);
01323 first_new_initv = FALSE;
01324 } else if (parent) {
01325 Set_INITV_blk(parent, new_initv);
01326 parent = INITV_IDX_ZERO;
01327 } else if (prev) {
01328 Set_INITV_next(prev, new_initv);
01329 }
01330
01331 INITVKIND k = INITV_kind(old_initv);
01332 switch (k) {
01333 case INITVKIND_SYMOFF:
01334 case INITVKIND_ZERO:
01335 case INITVKIND_ONE:
01336 case INITVKIND_VAL:
01337 case INITVKIND_PAD:
01338 old_initv = INITV_next(old_initv);
01339 prev = new_initv;
01340 break;
01341
01342 case INITVKIND_BLOCK:
01343 old_stack.Push(old_initv);
01344 new_stack.Push(new_initv);
01345 old_initv = INITV_blk(old_initv);
01346 parent = new_initv;
01347 prev = INITV_IDX_ZERO;
01348 break;
01349
01350 case INITVKIND_SYMDIFF:
01351 case INITVKIND_SYMDIFF16:
01352 case INITVKIND_LABEL:
01353 {
01354 LABEL_IDX lab = (k == INITVKIND_LABEL) ? INITV_lab(new_initv) :
01355 INITV_lab1(new_initv),
01356 new_lab = lab_map->Find(lab);
01357
01358 if (new_lab)
01359 if (k == INITVKIND_LABEL)
01360 Set_INITV_lab(new_initv, new_lab);
01361 else
01362 Set_INITV_lab1(new_initv, new_lab);
01363 }
01364 old_initv = INITV_next(old_initv);
01365 prev = new_initv;
01366 break;
01367
01368 default:
01369 Fail_FmtAssertion("unknown INITV kind %d", (INT) k);
01370 }
01371
01372 while (!old_initv && old_stack.Elements() > 0) {
01373 old_initv = INITV_next(old_stack.Pop());
01374 prev = new_stack.Pop();
01375 }
01376
01377 }
01378
01379 }
01380
01381
01382 BOOL
01383 WN_verifier(WN *wn)
01384 {
01385 Temporary_Error_Phase ("WN_verifier");
01386 #ifdef Is_True_On
01387 char *p = getenv ("WN_VERIFIER");
01388 if (p != 0 && strcasecmp (p, "off") == 0)
01389 return TRUE;
01390 if (Verifier_DEBUG)
01391 DevWarn("I am running newest verifier");
01392 WN_Verifier wnv(wn);
01393 return wnv.WN_traverse_tree(wn, NULL);
01394 #else
01395 return TRUE;
01396 #endif
01397 }