Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
fill_align.cxx
Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines