Open64 (mfef90, whirl2f, and IR tools)
TAG: version-openad; SVN changeset: 916
|
00001 /* 00002 00003 Copyright (C) 2000, 2001 Silicon Graphics, Inc. All Rights Reserved. 00004 00005 This program is free software; you can redistribute it and/or modify it 00006 under the terms of version 2 of the GNU General Public License as 00007 published by the Free Software Foundation. 00008 00009 This program is distributed in the hope that it would be useful, but 00010 WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00012 00013 Further, this software is distributed without any warranty that it is 00014 free of the rightful claim of any third person regarding infringement 00015 or the like. Any license provided herein, whether implied or 00016 otherwise, applies only to this software file. Patent licenses, if 00017 any, provided herein do not apply to combinations of this program with 00018 other software, or any other product whatsoever. 00019 00020 You should have received a copy of the GNU General Public License along 00021 with this program; if not, write the Free Software Foundation, Inc., 59 00022 Temple Place - Suite 330, Boston MA 02111-1307, USA. 00023 00024 Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pky, 00025 Mountain View, CA 94043, or: 00026 00027 http://www.sgi.com 00028 00029 For further information regarding this notice, see: 00030 00031 http://oss.sgi.com/projects/GenInfo/NoticeExplan 00032 00033 */ 00034 00035 00036 #include "defs.h" 00037 #include "stab.h" 00038 #include "wn.h" 00039 #include "ir_reader.h" 00040 #include "strtab.h" 00041 #include "stblock.h" 00042 #include "data_layout.h" 00043 #include "erbe.h" 00044 #include "cxx_hash.h" 00045 00046 /* 00047 * 00048 * Only one exported routine: 00049 * Process_Fill_Align_Pragmas (WN* func_wn) 00050 * 00051 */ 00052 00053 extern "C" { 00054 void Process_Fill_Align_Pragmas (WN* func_wn); 00055 } 00056 00057 /* From <targ>/fill_align_targ.cxx 00058 */ 00059 void Fill_Align_Initialize_Parameters (INT *L1_sz, INT *L2_sz, INT *pg_sz); 00060 00061 static void Process_Fill_Align_Pragmas_Recursive (WN* wn, WN* func_wn); 00062 static void Fill_Align_Symbol (WN* wn, WN* func_wn); 00063 00064 typedef HASH_TABLE<ST*, BOOL> ST_HASH_TABLE; 00065 static ST_HASH_TABLE *symbol_ht; 00066 static MEM_POOL symbol_ht_pool; 00067 static INT L1_cache_line_sz, L2_cache_line_sz, page_sz; 00068 00069 /* 00070 * 00071 * Given the PU-tree in func_wn and the current node, 00072 * recursively walk the tree looking for fill/align 00073 * pragmas, and process them. 00074 * 00075 */ 00076 void Process_Fill_Align_Pragmas (WN* wn) { 00077 00078 00079 /* Notice that this memory-pool is never deleted, and basically "leaks" 00080 * memory. But since it must survive all the way through all the PUs 00081 * in the back-end, it doesn't matter, since it will be freed when be 00082 * is basically over. 00083 */ 00084 static INT initialized = 0; 00085 if (!initialized) { 00086 initialized = 1; 00087 Fill_Align_Initialize_Parameters (&L1_cache_line_sz, 00088 &L2_cache_line_sz, 00089 &page_sz); 00090 MEM_POOL_Initialize (&symbol_ht_pool, "Fill Align Pool", FALSE); 00091 MEM_POOL_Push_Freeze (&symbol_ht_pool); 00092 symbol_ht = CXX_NEW (ST_HASH_TABLE (20, &symbol_ht_pool), &symbol_ht_pool); 00093 } 00094 00095 Process_Fill_Align_Pragmas_Recursive (wn, wn); 00096 } 00097 00098 static void Process_Fill_Align_Pragmas_Recursive (WN* wn, WN* func_wn) { 00099 OPCODE opc; 00100 OPERATOR oper; 00101 INT i; 00102 00103 if (!wn) return; 00104 00105 opc = WN_opcode(wn); 00106 oper = OPCODE_operator(opc); 00107 00108 00109 if (oper == OPR_PRAGMA) { 00110 if (WN_pragma(wn) == WN_PRAGMA_FILL || 00111 WN_pragma(wn) == WN_PRAGMA_ALIGN) { 00112 Fill_Align_Symbol (wn, func_wn); 00113 } 00114 return; 00115 } 00116 00117 if (WN_operator(wn) == OPR_BLOCK) { 00118 WN* kid = WN_first(wn); 00119 while (kid) { 00120 Process_Fill_Align_Pragmas_Recursive (kid, func_wn); 00121 kid = WN_next(kid); 00122 } 00123 return; 00124 } 00125 00126 for (i=0; i<WN_kid_count(wn); i++) { 00127 Process_Fill_Align_Pragmas_Recursive (WN_kid(wn, i), func_wn); 00128 } 00129 return; 00130 } 00131 00132 00133 /* 00134 * 00135 * Local routines. 00136 * 00137 */ 00138 00139 static BOOL Local_Variable (ST* st) { 00140 00141 if (ST_sclass(st) == SCLASS_AUTO || 00142 ST_sclass(st) == SCLASS_PSTATIC || 00143 (ST_base(st) && 00144 ST_sclass(ST_base(st)) == SCLASS_AUTO)) 00145 return TRUE; 00146 else return FALSE; 00147 00148 } 00149 00150 static BOOL Global_Variable (ST* st) { 00151 00152 if (Is_Global_Symbol(st) && ST_sclass(st) != SCLASS_COMMON) 00153 return TRUE; 00154 else return FALSE; 00155 } 00156 00157 static BOOL Common_Variable (ST* st) { 00158 00159 if (ST_sclass(st) == SCLASS_COMMON) { 00160 Is_True (Is_Global_Symbol(st) && ST_base_idx(st) != ST_st_idx(st), 00161 ("Symbol %s is SCLASS_COMMON but is weird\n", ST_name(st))); 00162 return TRUE; 00163 } 00164 else return FALSE; 00165 00166 } 00167 00168 /* 00169 * 00170 * Must be called for local or global variables. 00171 * Return TRUE if all sizes are completely specified and constant, 00172 * FALSE otherwise (i.e. if some size is not supplied, or is variable). 00173 * 00174 */ 00175 static BOOL Known_Size (ST* st) { 00176 00177 INT ndims; 00178 INT i; 00179 00180 TY& ty = Ty_Table[ST_type(st)]; 00181 00182 /* only arrays can be under-specified */ 00183 if (TY_kind(ty) != KIND_ARRAY) return TRUE; 00184 00185 /* extern int a[] should come out as non-const upper-bound, 00186 * with a NULL tree. 00187 * 00188 * VLAs will come out as non-const upper-bounds. 00189 */ 00190 ndims = TY_AR_ndims(ty); 00191 for (i=0; i<ndims; i++) { 00192 if (!TY_AR_const_lbnd(ty, i) || 00193 !TY_AR_const_ubnd(ty, i)) 00194 return FALSE; 00195 } 00196 return TRUE; 00197 00198 } 00199 00200 /* recursively search, looking inside regions, for an alloca */ 00201 static WN * 00202 Find_Alloca (WN *block, ST *sym) 00203 { 00204 Is_True (block && WN_opcode(block) == OPC_BLOCK, 00205 ("find_alloca: expected a OPC_BLOCK node")); 00206 WN *alloca_wn = WN_first(block); 00207 while (alloca_wn) { 00208 if ((WN_operator(alloca_wn) == OPR_STID) && 00209 (&St_Table[WN_st_idx(alloca_wn)] == sym)) { // found it 00210 return alloca_wn; 00211 } 00212 // Change this to a DevWarn, since the front-end cannot always 00213 // move the alloca before the preamble (in the presence of 00214 // initialization, for example). 00215 if (WN_operator(alloca_wn) == OPR_PRAGMA && 00216 WN_pragma(alloca_wn) == WN_PRAGMA_PREAMBLE_END) { 00217 DevWarn ("Reached end of preamble w/o finding alloca of %s\n", 00218 ST_name(sym)); 00219 } 00220 else if (WN_opcode(alloca_wn) == OPC_REGION) { 00221 WN *alloca_in_region; 00222 alloca_in_region = Find_Alloca (WN_region_body(alloca_wn), sym); 00223 if (alloca_in_region != NULL) { // found it 00224 return alloca_in_region; 00225 } 00226 } 00227 alloca_wn = WN_next(alloca_wn); 00228 } 00229 return alloca_wn; 00230 } 00231 00232 /* 00233 * 00234 * Given a fill/align pragma in wn, and the WN_func_body of a PU-tree in 00235 * body_wn, process the fill/align pragma by padding/aligning the symbol 00236 * appropriately. 00237 * 00238 * A fill_symbol (s, val) pragma requires that the symbol s be allocated 00239 * with enough padding around it such that there is no other data item 00240 * within "val" alignment at either end. For instance, if val is 32, then 00241 * the symbol "s" should not share a level-one cache line (32-bytes) with 00242 * any other data. 00243 * 00244 * A align_symbol (s, val) pragma requires that the symbol s be aligned 00245 * to start with the supplied alignment in "val". 00246 * 00247 * This routine processes all kinds of symbols, including 00248 * - local variables 00249 * - dynamically-size local arrays (VLAs) 00250 * - global variables (C/C++) 00251 * - common block variables (Fortran). 00252 * 00253 */ 00254 00255 static void Fill_Align_Symbol (WN* wn, WN* func_wn) { 00256 ST* st = &St_Table[WN_st_idx(wn)]; 00257 00258 INT orig_size; /* size of original variable */ 00259 INT new_size; /* new size after fill */ 00260 INT pad; /* amount of pad required to fill */ 00261 INT orig_align; /* original alignment of variable */ 00262 INT log_orig_align=0; /* log of original alignment */ 00263 INT64 new_ofst; /* offset into padded section after variable 00264 * has been filled. 00265 */ 00266 INT fa_value; /* power of 2 storage size that must contain 00267 * this variable. 00268 */ 00269 00270 BOOL is_fill; /* True if it is a fill, false otherwise 00271 * i.e. align 00272 */ 00273 00274 WN* body_wn = WN_func_body(func_wn); 00275 00276 BOOL ignore_global_symbols = FALSE; // when IPA is enabled, we 00277 // want to process global 00278 // symbols only in the 00279 // symtab.G file, and NOT in 00280 // each .I file. 00281 00282 if (FILE_INFO_ipa(File_info) && Read_Global_Data) { 00283 // IPA is enabled, and this is not symtab.G 00284 ignore_global_symbols = TRUE; 00285 } 00286 00287 is_fill = (WN_pragma(wn) == WN_PRAGMA_FILL); 00288 00289 fa_value = WN_pragma_arg2(wn); 00290 switch (fa_value) { 00291 case -1: 00292 /* L1 cache line */ 00293 fa_value = L1_cache_line_sz; 00294 break; 00295 case -2: 00296 /* L2 cache line */ 00297 fa_value = L2_cache_line_sz; 00298 break; 00299 case -3: 00300 /* page */ 00301 fa_value = page_sz; 00302 break; 00303 default: 00304 break; 00305 } 00306 00307 /* Error-checking cases */ 00308 00309 /* must be a variable */ 00310 if (!(ST_class(st) == CLASS_VAR && (Local_Variable(st) || 00311 Global_Variable(st) || 00312 Common_Variable(st)))) { 00313 ErrMsgSrcpos (EC_Bad_Pragma_Abort, WN_Get_Linenum(wn), 00314 WN_pragmas[WN_pragma(wn)].name, 00315 ST_name(st), 00316 "must be supplied a variable"); 00317 } 00318 00319 00320 /* global variables must be completely specified */ 00321 if (Global_Variable(st) && !Known_Size(st)) { 00322 ErrMsgSrcpos (EC_Bad_Pragma_Abort, WN_Get_Linenum(wn), 00323 WN_pragmas[WN_pragma(wn)].name, 00324 ST_name(st), 00325 "global variable must be completely specified"); 00326 } 00327 00328 00329 /* cannot align local fixed-size variables to greater than 16 bytes */ 00330 if (Local_Variable(st) && Known_Size(st) && !is_fill && fa_value > 16) { 00331 ErrMsgSrcpos (EC_Bad_Pragma_Abort, WN_Get_Linenum(wn), 00332 WN_pragmas[WN_pragma(wn)].name, 00333 ST_name(st), 00334 "cannot align automatic variables to greater than 16 bytes"); 00335 } 00336 00337 if (Global_Variable(st) && ignore_global_symbols) { 00338 return; 00339 } 00340 00341 00342 /* duplicates can arise due to inlining */ 00343 if (Is_Global_Symbol(st)) { 00344 if (symbol_ht->Find (st)) { 00345 /* printf ("Duplicate: %s\n", ST_name(st)); */ 00346 return; 00347 } 00348 else symbol_ht->Enter (st, TRUE); 00349 } 00350 00351 /* Only common variables can have an offset */ 00352 FmtAssert (Common_Variable(st) || ST_ofst(st) == 0, 00353 ("Fill/Align_Symbol (%s): ST has an unexpected offset %llu\n", 00354 ST_name(st), ST_ofst(st))); 00355 00356 00357 // IPA can sometimes mark symbols to be GP-rel, and we might expand 00358 // them beyond the gp-size, leading to problems later. So clear the 00359 // gp-rel bit. 00360 Clear_ST_gprel(st); 00361 00362 /* compute the original alignment */ 00363 00364 orig_align = TY_align(ST_type(st)); 00365 while (orig_align) { 00366 if (orig_align & 0x1) break; 00367 log_orig_align++; 00368 orig_align = orig_align >> 1; 00369 } 00370 orig_align = TY_align(ST_type(st)); 00371 00372 00373 /* compute the original and new sizes */ 00374 00375 orig_size = TY_size(ST_type(st)); 00376 if (is_fill) { 00377 00378 if (Local_Variable(st) && Known_Size(st) && is_fill) { 00379 /* pad on each side, since we cannot align on the stack. 00380 * the amount of front-pad is the larger of the desired fa_value 00381 * and the original alignment; the trailing pad is just fa_value. 00382 */ 00383 if (orig_align > fa_value) { 00384 pad = orig_align+fa_value; 00385 new_ofst = orig_align; 00386 } 00387 else { 00388 pad = 2*fa_value; 00389 new_ofst = fa_value; 00390 } 00391 new_size = orig_size + pad; 00392 } 00393 else { 00394 INT tmp; 00395 tmp = orig_size & (fa_value-1); 00396 if (tmp) new_size = orig_size+fa_value-tmp; 00397 else new_size = orig_size; 00398 pad = fa_value-tmp; /* amount of extra space */ 00399 new_ofst = pad/2; 00400 } 00401 } 00402 else { 00403 new_size = orig_size; 00404 pad = 0; 00405 new_ofst = 0; 00406 } 00407 00408 /* Now try to place the symbol someplace in the middle of the 00409 * new block. Must be subject to original alignment, though. 00410 */ 00411 new_ofst = ((new_ofst >> log_orig_align) << log_orig_align); 00412 00413 00414 00415 if (Global_Variable(st) || (Local_Variable(st) && Known_Size(st))) { 00416 00417 /* global, or non-vla local. similar processing. */ 00418 00419 /* 00420 * printf ("%s (%s): glob/fixed-local. oldsize %d, new_size %d, pad %lld ofst %d\n", 00421 * WN_pragmas[WN_pragma(wn)].name, ST_name(st), 00422 * orig_size, new_size, pad, new_ofst); 00423 */ 00424 00425 if (orig_size != new_size) { 00426 00427 /* create a base st, type class_block */ 00428 ST* base_st; 00429 INT new_align; 00430 00431 /* alignment of base block must be the larger of the original 00432 * alignment and the desired fa_value alignment. 00433 */ 00434 new_align = (orig_align > fa_value ? orig_align : fa_value); 00435 00436 base_st = New_ST_Block (Save_Str2("__fill_", ST_name(st)), 00437 Is_Global_Symbol(st), 00438 ST_sclass(st), new_align, new_size); 00439 Enter_ST(base_st); 00440 00441 Set_ST_base(st, base_st); 00442 Set_ST_ofst(st, ST_ofst(st) + new_ofst); 00443 } 00444 else { 00445 00446 /* size is unchanged; just align */ 00447 00448 if (TY_align(ST_type(st)) < fa_value) { 00449 TY_IDX new_ty = Copy_TY (ST_type(st)); 00450 Set_TY_align(new_ty, fa_value); 00451 Set_ST_type(st, new_ty); 00452 00453 FmtAssert (ST_ofst(st) == 0, 00454 ("Fill/Align_Symbol (%s): ST has an unexpected offset %llu\n", 00455 ST_name(st), ST_ofst(st))); 00456 } 00457 } 00458 if (Global_Variable(st)) { 00459 Allocate_Object (st); 00460 } 00461 } 00462 00463 else if (Local_Variable(st) && !Known_Size(st)) { 00464 00465 /* local VLA */ 00466 00467 WN* alloca_wn, *alloca_arg_wn, *alloca_store_wn; 00468 WN* arg_wn; 00469 ST* base_st = ST_base(st); /* vlas are based, with a base-st */ 00470 TYPE_ID rtype; 00471 WN *ldid_wn, *stid_wn; 00472 INT log_fa_value; 00473 INT tmp; 00474 00475 /* 00476 * printf ("%s (%s): VLA\n", WN_pragmas[WN_pragma(wn)].name, ST_name(st)); 00477 */ 00478 00479 /* find the alloca */ 00480 alloca_wn = Find_Alloca (body_wn, base_st); 00481 FmtAssert (alloca_wn, ("Reached end of PU w/o finding alloca of %s\n", 00482 ST_name(st))); 00483 00484 alloca_store_wn = alloca_wn; 00485 if (Alloca_Dealloca_On) { 00486 FmtAssert (WN_operator(WN_kid0(alloca_wn)) == OPR_ALLOCA, 00487 ("fill/align symbol (%s): Expected alloca", ST_name(st))); 00488 } else { 00489 alloca_wn = WN_prev(alloca_wn); 00490 FmtAssert (WN_operator(alloca_wn) == OPR_INTRINSIC_CALL, 00491 ("fill/align symbol (%s): Expected alloca", ST_name(st))); 00492 } 00493 00494 /* now allocate 1x to 2x of fa_value extra storage, to aid alignment 00495 * and padding (if fill). 00496 */ 00497 alloca_arg_wn = WN_kid0(WN_kid0(alloca_wn)); 00498 rtype = WN_rtype(alloca_arg_wn); 00499 00500 /* add 1x/2x fa_value to original size */ 00501 arg_wn = WN_CreateExp2 (OPCODE_make_op(OPR_ADD, rtype, MTYPE_V), 00502 alloca_arg_wn, 00503 WN_CreateIntconst(OPCODE_make_op(OPR_INTCONST, 00504 rtype, 00505 MTYPE_V), 00506 is_fill?(fa_value*2):fa_value)); 00507 WN_kid0(WN_kid0(alloca_wn)) = arg_wn; 00508 00509 /* now pad the start address up to fill-value alignment. 00510 * basically do: 00511 * p = ((p+fa_value-1) >> log_fa_value) << log_fa_value 00512 */ 00513 tmp = fa_value; 00514 log_fa_value = 0; 00515 while (tmp) { 00516 if (tmp & 0x1) break; 00517 log_fa_value++; 00518 tmp = tmp >> 1; 00519 } 00520 00521 /* now we're manipulating the return value of the alloca */ 00522 rtype = WN_desc(alloca_store_wn); 00523 00524 ldid_wn = WN_RLdid(Mtype_comparison(rtype), rtype, 0, base_st, ST_type(base_st)); 00525 ldid_wn = WN_CreateExp2 (OPCODE_make_op(OPR_ADD, rtype, MTYPE_V), 00526 ldid_wn, 00527 WN_CreateIntconst (OPCODE_make_op(OPR_INTCONST, 00528 rtype, 00529 MTYPE_V), 00530 fa_value-1)); 00531 ldid_wn = WN_CreateExp2 (OPCODE_make_op(OPR_ASHR, rtype, MTYPE_V), 00532 ldid_wn, 00533 WN_CreateIntconst (OPCODE_make_op(OPR_INTCONST, 00534 rtype, 00535 MTYPE_V), 00536 log_fa_value)); 00537 ldid_wn = WN_CreateExp2 (OPCODE_make_op(OPR_SHL, rtype, MTYPE_V), 00538 ldid_wn, 00539 WN_CreateIntconst (OPCODE_make_op(OPR_INTCONST, 00540 rtype, 00541 MTYPE_V), 00542 log_fa_value)); 00543 stid_wn = WN_CreateStid (OPCODE_make_op(OPR_STID, MTYPE_V, rtype), 00544 0, base_st, ST_type(base_st), ldid_wn); 00545 WN_next(stid_wn) = WN_next(alloca_store_wn); 00546 WN_prev(WN_next(alloca_store_wn)) = stid_wn; 00547 WN_next(alloca_store_wn) = stid_wn; 00548 WN_prev(stid_wn) = alloca_store_wn; 00549 } 00550 00551 else if (Common_Variable(st)) { 00552 00553 /* common variable */ 00554 00555 /* compute new size. 00556 * increase size of underlying common block 00557 * increase alignment of common block. 00558 * change offsets of this symbol, and all subsequent 00559 * offsets within that common. 00560 */ 00561 00562 00563 /* 00564 * printf ("%s (%s): Common\n",WN_pragmas[WN_pragma(wn)].name,ST_name(st)); 00565 */ 00566 00567 /* The common block needs expansion if the size has changed, 00568 * or even if the ofst is not a multiple of the fa_value. 00569 * The latter is necessary because we are going to up the 00570 * alignment of the common block, and need to ensure that the 00571 * ofst is a multiple of fa_value to ensure no false-sharing. 00572 */ 00573 00574 if (orig_size != new_size || (ST_ofst(st) % fa_value)) { 00575 00576 /* must expand the common block */ 00577 ST* cst; 00578 INT delta = new_size - orig_size; 00579 00580 /* it is possible that the current offset is not fa_value aligned. 00581 * in which case we may need a pre-pad to get there. 00582 * compute that here. 00583 */ 00584 delta += ST_ofst(st) % fa_value; 00585 new_size = orig_size + delta; 00586 new_ofst += ST_ofst(st) % fa_value; 00587 00588 /* the change in size MUST be a multiple of 8, 00589 * to preserve the alignment of subsequent STs. 00590 */ 00591 if (delta % 8) { 00592 delta = (((delta+7) >> 3) << 3); 00593 new_size = orig_size + delta; 00594 } 00595 00596 INT i; 00597 FOREACH_SYMBOL(CURRENT_SYMTAB, cst, i) { 00598 if (ST_base(cst) == ST_base(st) && st != cst && 00599 ST_ofst(cst) > ST_ofst(st)) { 00600 00601 /* this element is in the same common, but after our symbol */ 00602 Set_ST_ofst(cst, ST_ofst(cst) + delta); 00603 } 00604 } 00605 00606 TY_IDX common_ty; 00607 00608 /* now increase the size of the common block */ 00609 common_ty = ST_type(ST_base(st)); 00610 00611 Is_True (TY_kind(common_ty) == KIND_STRUCT, 00612 ("fill/align_symbol (%s): expected type struct for common", 00613 ST_name(st))); 00614 00615 /* now update the description of the underlying struct type */ 00616 TY &ty = Ty_Table[common_ty]; 00617 Set_TY_size(ty, TY_size(common_ty) + delta); 00618 FLD_ITER fld_iter = Make_fld_iter (TY_fld (ty)); 00619 do { 00620 FLD_HANDLE field (fld_iter); 00621 if (FLD_ofst(field) == ST_ofst(st)) { 00622 Set_FLD_ofst(field, FLD_ofst(field) + new_ofst); 00623 } 00624 else if (FLD_ofst(field) > ST_ofst(st)) { 00625 Set_FLD_ofst(field, FLD_ofst(field) + delta); 00626 } 00627 } while (! FLD_last_field (fld_iter++)); 00628 00629 /* finally change the offset of the original st */ 00630 Set_ST_ofst(st, ST_ofst(st) + new_ofst); 00631 00632 /* Now increase the alignment of the common block, if needed */ 00633 if (TY_align(common_ty) < fa_value) { 00634 TY_IDX new_ty = Copy_TY (common_ty); 00635 Set_TY_align(new_ty, fa_value); 00636 Set_ST_type(ST_base(st), new_ty); 00637 } 00638 } 00639 00640 else { 00641 00642 /* just need to adjust the alignment on the common block */ 00643 00644 TY_IDX common_ty = ST_type(ST_base(st)); 00645 00646 if (TY_align(common_ty) < fa_value) { 00647 TY_IDX new_ty = Copy_TY (common_ty); 00648 Set_TY_align(new_ty, fa_value); 00649 Set_ST_type(ST_base(st), new_ty); 00650 } 00651 } 00652 } 00653 else { 00654 /* error */ 00655 ErrMsgSrcpos (EC_Bad_Pragma_Abort, WN_Get_Linenum(wn), 00656 WN_pragmas[WN_pragma(wn)].name, 00657 ST_name(st), 00658 "variable must be local, global, or common"); 00659 } 00660 }