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 #include <alloca.h>
00059 #if defined(BUILD_OS_DARWIN)
00060 #include <darwin_elf.h>
00061 #else
00062 #include <elf.h>
00063 #endif
00064 #include <stdio.h>
00065
00066 #include "privatize_common.h"
00067
00068 #include "config.h"
00069 #include "dwarf_DST.h"
00070 #include "pu_info.h"
00071 #include "strtab.h"
00072 #include "wn_mp.h"
00073 #include "wn_util.h"
00074
00075 #include "symtab.h"
00076 #include "be_symtab.h"
00077
00078
00079 RENAMING_SCOPE::~RENAMING_SCOPE()
00080 {
00081 WN *old_priv_prag;
00082 BOOL present;
00083
00084 HASH_TABLE_ITER<WN *, BOOL> it(&old_prags);
00085
00086 while (it.Step(&old_priv_prag, &present))
00087 WN_DELETE_FromBlock(priv_list, old_priv_prag);
00088 }
00089
00090
00091
00092
00093
00094
00095
00096
00097 static BOOL ST_Is_Common_Block (ST *st)
00098 {
00099
00100
00101 PU& pu = Get_Current_PU();
00102 if (PU_ftn_lang(pu) &&
00103 (ST_sclass(st) == SCLASS_COMMON || ST_sclass(st) == SCLASS_DGLOBAL
00104 #ifdef KEY
00105
00106 || ST_sclass(st) == SCLASS_EXTERN
00107 #endif
00108 ) &&
00109 TY_kind(ST_type(st)) == KIND_STRUCT)
00110 return TRUE;
00111
00112 return FALSE;
00113 }
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124 #ifdef KEY
00125
00126
00127
00128 ST *ST_Source_COMMON_Block(ST *st, ST **split, BOOL want_st)
00129 #else
00130 ST *ST_Source_COMMON_Block(ST *st, ST **split)
00131 #endif // KEY
00132 {
00133 Is_True(st, ("ST_Source_COMMON_Block(): NULL st argument"));
00134
00135 if (split)
00136 *split = NULL;
00137
00138 ST *base = ST_base(st);
00139 #ifdef KEY
00140 if (want_st && base == st)
00141 return st;
00142 #endif // KEY
00143 if (base == st || !ST_Is_Common_Block(base))
00144 return NULL;
00145
00146 if (!ST_is_split_common(base))
00147 return base;
00148
00149 ST *base_full = ST_full(base);
00150 Is_True(base != base_full,
00151 ("invalid base for split-off COMMON for symbol %s", ST_name(st)));
00152 Is_True(ST_Is_Common_Block(base_full),
00153 ("base of split-off COMMON for symbol %s is not a COMMON "
00154 "block", ST_name(st)));
00155
00156
00157 if (split)
00158 *split = base;
00159
00160 return base_full;
00161 }
00162
00163 #ifdef KEY
00164
00165
00166
00167
00168
00169
00170
00171 ST *ST_Source_Block(ST *st, ST **split)
00172 {
00173 Is_True(st, ("ST_Source_Block(): NULL st argument"));
00174
00175 if (split)
00176 *split = NULL;
00177
00178 ST *base = ST_base(st);
00179 if (base == st) return st;
00180
00181 if (!ST_is_thread_private (base)) return st;
00182
00183 if (!ST_Is_Common_Block(base))
00184 return NULL;
00185
00186 if (!ST_is_split_common(base))
00187 return base;
00188
00189 ST *base_full = ST_full(base);
00190 Is_True(base != base_full,
00191 ("invalid base for split-off COMMON for symbol %s", ST_name(st)));
00192 Is_True(ST_Is_Common_Block(base_full),
00193 ("base of split-off COMMON for symbol %s is not a COMMON "
00194 "block", ST_name(st)));
00195
00196
00197 if (split)
00198 *split = base;
00199
00200 return base_full;
00201 }
00202 #endif
00203
00204
00205
00206
00207
00208
00209 static BOOL SCLASS_Is_Not_PU_Local(ST_SCLASS sclass)
00210 {
00211 switch (sclass) {
00212 case SCLASS_FSTATIC:
00213 case SCLASS_COMMON:
00214 case SCLASS_EXTERN:
00215 case SCLASS_UGLOBAL:
00216 case SCLASS_DGLOBAL:
00217 return TRUE;
00218
00219 case SCLASS_UNKNOWN:
00220 Fail_FmtAssertion("SCLASS_Is_Not_PU_Local() : got SCLASS_UNKNOWN");
00221
00222 default:
00223 break;
00224 }
00225
00226 return FALSE;
00227 }
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239 static ST *Create_Local_Symbol(ST *old_st)
00240 {
00241 ST_SCLASS sclass = ST_sclass(old_st);
00242 Is_True(SCLASS_Is_Not_PU_Local(sclass),
00243 ("Create_Local_Symbol() called for ST with sclass %d",
00244 (INT) sclass ) );
00245
00246 char *new_name, *old_name = ST_name(old_st);
00247 new_name = (char *) alloca(strlen(old_name) + 32);
00248 sprintf(new_name, "__localized_common_%s", old_name);
00249
00250
00251 TY_IDX old_ty_idx = ST_type(old_st), new_ty_idx = old_ty_idx;
00252
00253 TY &old_ty = Ty_Table[old_ty_idx];
00254
00255 BOOL is_dynamic_array = TY_kind(old_ty) == KIND_POINTER &&
00256 TY_kind(TY_pointed(old_ty)) == KIND_ARRAY &&
00257 TY_size(TY_pointed(old_ty)) == 0;
00258
00259
00260
00261 ST *new_st = New_ST(), &new_st_ref = *new_st, old_st_ref = *old_st;
00262 ST_Init(new_st, Save_Str(new_name), ST_class(old_st), SCLASS_AUTO,
00263 EXPORT_LOCAL, new_ty_idx);
00264
00265 if (ST_addr_saved(old_st_ref))
00266 Set_ST_addr_saved(new_st_ref);
00267 if (ST_addr_passed(old_st_ref))
00268 Set_ST_addr_passed(new_st_ref);
00269 if (is_dynamic_array) {
00270 Set_ST_pt_to_unique_mem(new_st_ref);
00271 Set_ST_pt_to_compiler_generated_mem(new_st_ref);
00272 }
00273
00274 if (Debug_Level > 0) {
00275
00276 DST_INFO_IDX dst_idx = Find_DST_From_ST(old_st, Current_PU_Info);
00277 if (!DST_IS_NULL(dst_idx))
00278 Create_New_DST(dst_idx, new_st, FALSE);
00279 }
00280
00281 return new_st;
00282 }
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298 void
00299 Rename_Privatized_COMMON(WN *wn, RENAMING_STACK *stack)
00300 {
00301 Is_True(wn, ("Rename_Privatized_COMMON(): NULL wn argument"));
00302
00303 ST *st = WN_has_sym(wn) ? WN_st(wn) : NULL;
00304 ST_SET *ignore = &stack->Top()->ignore;
00305
00306 if (st && !ignore->Find(st)) {
00307 ST *new_st;
00308 ST *split_block;
00309 ST *common_block = ST_Source_COMMON_Block(st, &split_block);
00310
00311 BOOL add_to_ignore;
00312
00313 #ifdef KEY
00314 if (ST_class(st) == CLASS_NAME) {
00315 #else
00316 if (ST_is_equivalenced(st) ||
00317 ST_class(st) == CLASS_NAME) {
00318 #endif
00319
00320 add_to_ignore = TRUE;
00321 } else if (ST_is_thread_private(st) ||
00322 (split_block && ST_is_thread_private(split_block)) ||
00323 (common_block && ST_is_thread_private(common_block))) {
00324
00325
00326 add_to_ignore = TRUE;
00327 } else {
00328
00329 add_to_ignore =
00330 ! (common_block || SCLASS_Is_Not_PU_Local(ST_sclass(st)));
00331 }
00332
00333 if (!add_to_ignore) {
00334 RENAMING_SCOPE *scope = NULL;
00335 WN *old_priv_prag;
00336
00337
00338 for (INT i = 0; i < stack->Elements(); i++) {
00339 WN *priv_list = stack->Top_nth(i)->priv_list;
00340
00341 for (old_priv_prag = priv_list ? WN_first(priv_list) : NULL;
00342 old_priv_prag; old_priv_prag = WN_next(old_priv_prag))
00343
00344 if (WN_opcode(old_priv_prag) == OPC_PRAGMA &&
00345 WN_pragma(old_priv_prag) == WN_PRAGMA_LOCAL &&
00346 (WN_st(old_priv_prag) == st ||
00347 WN_st(old_priv_prag) == common_block) ) {
00348 scope = stack->Top_nth(i);
00349 break;
00350 }
00351
00352 if (scope)
00353 break;
00354 }
00355
00356 if (scope) {
00357 new_st = scope->map.Find(st);
00358 if (!new_st) {
00359 new_st = Create_Local_Symbol(st);
00360 scope->map.Enter(st, new_st);
00361 WN *priv_pragma = WN_CreatePragma(WN_PRAGMA_LOCAL, new_st, 0, 0);
00362 WN_set_pragma_compiler_generated(priv_pragma);
00363 WN_INSERT_BlockLast(scope->priv_list, priv_pragma);
00364 scope->old_prags.Enter_If_Unique(old_priv_prag, TRUE);
00365 }
00366 } else
00367 add_to_ignore = TRUE;
00368 }
00369
00370 if (!add_to_ignore)
00371 WN_st_idx(wn) = ST_st_idx(new_st);
00372 else
00373 ignore->Enter(st, TRUE);
00374 }
00375
00376 WN *priv_pragma_block = NULL;
00377 OPCODE opc = WN_opcode(wn);
00378
00379
00380 if (opc == OPC_REGION) {
00381 WN *priv_prag = WN_first(WN_region_pragmas(wn));
00382
00383 while (priv_prag &&
00384 (WN_opcode(priv_prag) != OPC_PRAGMA ||
00385 WN_pragma(priv_prag) != WN_PRAGMA_LOCAL) )
00386 priv_prag = WN_next(priv_prag);
00387
00388 if (priv_prag) {
00389 priv_pragma_block = WN_region_pragmas(wn);
00390 MEM_POOL *pool = stack->Top()->pool;
00391 stack->Push(CXX_NEW(RENAMING_SCOPE(priv_pragma_block, pool), pool));
00392 }
00393 }
00394
00395
00396 if (!OPCODE_is_leaf(opc)) {
00397 if (opc == OPC_BLOCK)
00398 for (WN *kid = WN_first(wn); kid; kid = WN_next(kid))
00399 Rename_Privatized_COMMON(kid, stack);
00400 else {
00401 for (INT kidno = 0; kidno < WN_kid_count(wn); kidno++) {
00402 WN *kid = WN_kid(wn, kidno);
00403
00404 if (kid && kid != priv_pragma_block)
00405 Rename_Privatized_COMMON(kid, stack);
00406 }
00407 }
00408 }
00409
00410 if (priv_pragma_block) {
00411
00412
00413 CXX_DELETE(stack->Pop(), stack->Top()->pool);
00414 }
00415 }
00416 #ifdef KEY
00417
00418
00419
00420
00421
00422
00423 static ST *Create_Local_Threadprivate_Symbol(ST *old_st)
00424 {
00425 ST_SCLASS sclass = ST_sclass(old_st);
00426 Is_True(SCLASS_Is_Not_PU_Local(sclass),
00427 ("Create_Local_Symbol() called for ST with sclass %d",
00428 (INT) sclass ) );
00429
00430 char *new_name, *old_name = ST_name(old_st);
00431 new_name = (char *) alloca(strlen(old_name) + 32);
00432 sprintf(new_name, "__ppthd_common_%s", old_name);
00433
00434 TY_IDX old_ty_idx, new_ty_idx;
00435
00436 old_ty_idx = ST_type(old_st);
00437 new_ty_idx = Make_Pointer_Type(old_ty_idx);
00438
00439 ST *new_ppthd_st = New_ST(CURRENT_SYMTAB);
00440
00441 ST_Init(new_ppthd_st, Save_Str(new_name), ST_class(old_st), SCLASS_AUTO,
00442 EXPORT_LOCAL, new_ty_idx);
00443
00444
00445 if (Debug_Level > 0) {
00446
00447 DST_INFO_IDX dst_idx = Find_DST_From_ST(old_st, Current_PU_Info);
00448 if (!DST_IS_NULL(dst_idx))
00449 Create_New_DST(dst_idx, new_ppthd_st, FALSE);
00450 }
00451
00452 return new_ppthd_st;
00453 }
00454
00455
00456
00457
00458
00459
00460 static ST *Create_Global_Threadprivate_Symbol(ST *old_st)
00461 {
00462 char *new_name, *old_name = ST_name(old_st);
00463 new_name = (char *) alloca(strlen(old_name) + 32);
00464 sprintf(new_name, "__thdprv_common_%s", old_name);
00465
00466 ST *new_thdprv_st = New_ST(GLOBAL_SYMTAB);
00467
00468 ST_SCLASS sclass = (ST_sclass (old_st) == SCLASS_FSTATIC) ?
00469 SCLASS_FSTATIC : SCLASS_COMMON;
00470
00471 TY_IDX old_ty_idx, new_ty_idx;
00472
00473 old_ty_idx = ST_type(old_st);
00474 new_ty_idx = Make_Pointer_Type(Make_Pointer_Type(old_ty_idx));
00475 ST_Init(new_thdprv_st, Save_Str(new_name), ST_class(old_st), sclass,
00476 ST_export(old_st), new_ty_idx);
00477
00478 if (Debug_Level > 0) {
00479 DST_INFO_IDX dst_idx = Find_DST_From_ST(old_st, Current_PU_Info);
00480 if (!DST_IS_NULL(dst_idx))
00481 Create_New_DST(dst_idx, new_thdprv_st, FALSE);
00482 }
00483
00484 return new_thdprv_st;
00485 }
00486
00487
00488
00489
00490
00491
00492
00493
00494 void
00495 Rename_Threadprivate_COMMON(WN* pu, WN* parent, WN *wn, RENAMING_STACK *stack, RENAMING_SCOPE *scope, RENAMING_SCOPE *common_blk_scope)
00496 {
00497
00498 Is_True(wn, ("Rename_Threadprivate_COMMON(): NULL wn argument"));
00499
00500 ST *st = WN_has_sym(wn) ? WN_st(wn) : NULL;
00501
00502 if (st) {
00503 ST *split_block;
00504 ST *common_block = ST_Source_Block(st, &split_block);
00505 if (ST_is_thread_private(st) ||
00506 (split_block && ST_is_thread_private(split_block)) ||
00507 (common_block && ST_is_thread_private(common_block))) {
00508 ST *new_st;
00509 ST *new_st_for_common_blk;
00510
00511 new_st_for_common_blk = common_blk_scope->map.Find(common_block);
00512 if (!new_st_for_common_blk) {
00513 new_st_for_common_blk = Create_Global_Threadprivate_Symbol(common_block);
00514 common_blk_scope->map.Enter(common_block, new_st_for_common_blk);
00515 }
00516
00517 new_st = scope->map.Find(common_block);
00518 if (!new_st) {
00519 new_st = Create_Local_Threadprivate_Symbol(common_block);
00520 scope->map.Enter(common_block, new_st);
00521 WN *priv_pragma = WN_CreatePragma(WN_PRAGMA_THREADPRIVATE, common_block, ST_st_idx(new_st), ST_st_idx(new_st_for_common_blk));
00522 WN_set_pragma_compiler_generated(priv_pragma);
00523 WN_INSERT_BlockLast(WN_func_pragmas(pu), priv_pragma);
00524 }
00525
00526 WN *priv_list;
00527
00528 if (stack->Elements() > 1)
00529 priv_list = stack->Top_nth(0)->priv_list;
00530 else
00531 priv_list = WN_func_pragmas(pu);
00532
00533
00534
00535 for (INT i=0; i<2; i++)
00536 {
00537 BOOL match = FALSE;
00538 WN *old_priv_prag;
00539 for (old_priv_prag = priv_list ? WN_first(priv_list) : NULL;
00540 old_priv_prag; old_priv_prag = WN_next(old_priv_prag))
00541
00542 if (WN_opcode(old_priv_prag) == OPC_PRAGMA &&
00543 WN_pragma(old_priv_prag) == WN_PRAGMA_LOCAL &&
00544 WN_st(old_priv_prag) == new_st) {
00545 match = TRUE;
00546 break;
00547 }
00548
00549 if (match == FALSE && priv_list) {
00550 WN *priv_pragma = WN_CreatePragma(WN_PRAGMA_LOCAL, new_st, 0, 0);
00551 WN_set_pragma_compiler_generated(priv_pragma);
00552 WN_INSERT_BlockLast(priv_list, priv_pragma);
00553 match = TRUE;
00554 }
00555 if (priv_list == WN_func_pragmas (pu))
00556 break;
00557 else
00558 priv_list = WN_func_pragmas (pu);
00559 }
00560
00561 WN *new_wn = NULL;
00562
00563
00564 WN_OFFSET ofst = (st == common_block) ? 0 : ST_ofst (st);
00565 if (WN_operator(wn) == OPR_LDA) {
00566 new_wn = WN_CreateLdid(
00567 OPCODE_make_op(OPR_LDID,
00568 TY_mtype(ST_type(new_st)),
00569 TY_mtype(ST_type(new_st))),
00570 0, new_st, ST_type(new_st));
00571 ofst += WN_load_offset (wn);
00572 if (ofst)
00573 new_wn = WN_Add(Pointer_type, new_wn,
00574 WN_Intconst(Pointer_type, ofst));
00575 for (INT kidno = 0; kidno < WN_kid_count(parent); kidno++)
00576 if (WN_kid(parent, kidno) == wn)
00577 WN_kid(parent, kidno) = new_wn;
00578 }
00579 else if (WN_operator(wn) == OPR_LDID){
00580 ofst += WN_load_offset (wn);
00581 new_wn = WN_CreateIload(
00582 OPCODE_make_op(OPR_ILOAD,
00583 WN_rtype(wn),
00584 WN_desc(wn)),
00585 ofst,
00586 ST_type(st),
00587 Make_Pointer_Type(ST_type(st),FALSE),
00588 WN_CreateLdid(
00589 OPCODE_make_op(OPR_LDID,
00590 TY_mtype(ST_type(new_st)),
00591 TY_mtype(ST_type(new_st))),
00592 0, new_st, ST_type(new_st)));
00593 for (INT kidno = 0; kidno < WN_kid_count(parent); kidno++)
00594 if (WN_kid(parent, kidno) == wn)
00595 WN_kid(parent, kidno) = new_wn;
00596 }
00597 else if (WN_operator(wn) == OPR_LDBITS)
00598 Fail_FmtAssertion("SCLASS_Is_Not_PU_Local() : got SCLASS_UNKNOWN");
00599 else if (WN_operator(wn) == OPR_STID){
00600 ofst += WN_store_offset (wn);
00601 new_wn = WN_CreateIstore(
00602 OPCODE_make_op(OPR_ISTORE,WN_rtype(wn),WN_desc(wn)),
00603 ofst,
00604 Make_Pointer_Type(ST_type(st),FALSE),
00605 WN_COPY_Tree(WN_kid(wn,0)),
00606 WN_CreateLdid(
00607 OPCODE_make_op(OPR_LDID,
00608 TY_mtype(ST_type(new_st)),
00609 TY_mtype(ST_type(new_st))),
00610 0, new_st, ST_type(new_st)));
00611 if (WN_operator(parent) == OPR_BLOCK)
00612 {
00613 WN_INSERT_BlockBefore(parent, wn, new_wn);
00614 WN_DELETE_FromBlock(parent, wn);
00615 }
00616 else
00617 {
00618 for (INT kidno = 0; kidno < WN_kid_count(parent); kidno++)
00619 if (WN_kid(parent, kidno) == wn)
00620 WN_kid(parent, kidno) = new_wn;
00621 }
00622 wn = new_wn;
00623 }
00624 else if (WN_operator(wn) == OPR_STBITS)
00625 Fail_FmtAssertion("SCLASS_Is_Not_PU_Local() : got SCLASS_UNKNOWN");
00626 #ifdef KEY
00627
00628
00629 else if (WN_operator(wn) == OPR_PRAGMA &&
00630 WN_pragma(wn) == WN_PRAGMA_COPYPRIVATE)
00631 WN_st_idx (wn) = ST_st_idx (new_st);
00632 #endif
00633
00634 }
00635 }
00636
00637 WN *priv_pragma_block = NULL;
00638 OPCODE opc = WN_opcode(wn);
00639
00640 if (opc == OPC_REGION) {
00641 WN *priv_prag = WN_first(WN_region_pragmas(wn));
00642
00643 if (priv_prag && WN_pragma(priv_prag) != WN_PRAGMA_SINGLE_PROCESS_BEGIN && WN_pragma(priv_prag) != WN_PRAGMA_MASTER_BEGIN) {
00644 priv_pragma_block = WN_region_pragmas(wn);
00645 MEM_POOL *pool = stack->Top()->pool;
00646 stack->Push(CXX_NEW(RENAMING_SCOPE(priv_pragma_block, pool), pool));
00647 }
00648 }
00649
00650
00651
00652 if (!OPCODE_is_leaf(opc)) {
00653 if (opc == OPC_BLOCK)
00654 for (WN *kid = WN_first(wn); kid; ){
00655 WN *old_kid = WN_next(kid);
00656 Rename_Threadprivate_COMMON(pu, wn, kid, stack, scope, common_blk_scope);
00657 kid = old_kid;
00658 }
00659 else {
00660 for (INT kidno = 0; kidno < WN_kid_count(wn); kidno++) {
00661 WN *kid = WN_kid(wn, kidno);
00662 Rename_Threadprivate_COMMON(pu, wn, kid, stack, scope, common_blk_scope);
00663 }
00664 }
00665 }
00666 if (priv_pragma_block)
00667 CXX_DELETE(stack->Pop(), stack->Top()->pool);
00668 }
00669 #endif