Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
stblock.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 /* ====================================================================
00037  * ====================================================================
00038  *
00039  *
00040  * Revision history:
00041  *  11-Nov-94 - Original Version
00042  *
00043  * Description:
00044  *
00045  * General support for ST blocks and bases.
00046  *
00047  * ====================================================================
00048  * ====================================================================
00049  */
00050 
00051 #ifdef USE_PCH
00052 #include "be_com_pch.h"
00053 #endif /* USE_PCH */
00054 #pragma hdrstop
00055 #include <elf.h>
00056 #include <cmplrs/rcodes.h>
00057 #include <sys/resource.h>
00058 #include "defs.h"
00059 #include "erglob.h"
00060 #include "erbe.h"
00061 #include "config.h"
00062 #include "tracing.h"
00063 #include "strtab.h"
00064 #include "stab.h"
00065 #include "const.h"
00066 #include "glob.h"
00067 #include "mtypes.h"
00068 #include "targ_const.h"
00069 #include "targ_sim.h"
00070 #include "ttype.h"
00071 #include "irbdata.h"
00072 #include "util.h"
00073 #include "stblock.h"
00074 #include "data_layout.h"
00075 
00076 #define SYMTAB_level(s) s
00077 
00078 #define Has_No_Base_Block(st) (ST_base(st) == st)
00079 
00080 #define ROUNDUP(val,align)      ( (-(INT64)align) & (INT64)(val+align-1) )
00081 #define ROUNDDOWN(val,align)    ( (-(INT64)align) & (INT64)(val)         )
00082 
00083 
00084 /* ====================================================================
00085  *
00086  * Adjusted_Alignment
00087  *
00088  * Adjust the alignment during data layout for all objects by either
00089  *      ST_use_reg_align()  or  Aggregate_Alignment
00090  *
00091  * ====================================================================
00092  */
00093 extern INT16
00094 Adjusted_Alignment(ST *sym)
00095 {
00096   if (ST_class(sym) == CLASS_BLOCK)
00097       return STB_align(sym);
00098 
00099   INT32  align;
00100   TY_IDX ty_idx = ST_type(sym);
00101   TY& ty = Ty_Table[ST_type (sym)];
00102 
00103   switch(ST_class(sym))
00104   {
00105   case CLASS_VAR:
00106     align=      TY_align(ty_idx);
00107 
00108     if (Is_Structure_Type(ty) && TY_is_packed(ty))
00109     {
00110       return align;
00111     }
00112 
00113     switch(ST_sclass(sym))
00114     {
00115     case SCLASS_AUTO:
00116     case SCLASS_PSTATIC:
00117     case SCLASS_FSTATIC:
00118     case SCLASS_DGLOBAL:
00119     case SCLASS_UGLOBAL:
00120     case SCLASS_COMMON:
00121 
00122      /*
00123       *  variables of this class can have at least Aggregate_Alignment
00124       */
00125       if (Is_Composite_Type(ty))
00126       {
00127         /* datapool's only have one element, so use existing alignment */
00128         if (ST_is_datapool(sym)) {
00129                 break;
00130         }
00131         else {
00132                 align = MAX(align, Aggregate_Alignment);
00133         }
00134       }
00135       break;
00136 
00137     case SCLASS_FORMAL:
00138      /*
00139       *  the offsets for these are predetermined.
00140       *  You cannot change it, or you will affect upformals
00141       */
00142       break;
00143     }
00144 #ifdef TARG_IA32
00145     // Stack-based objects should not have alignment greater than the
00146     // stack alignment. This is a temporary kludge for that, to keep
00147     // ia32 development going. The real fix may require FE changes.
00148     if (ST_sclass(sym) == SCLASS_AUTO || ST_sclass(sym) == SCLASS_FORMAL) {
00149       INT16 stack_align = Stack_Alignment();
00150       if (align > stack_align) {
00151         align = stack_align;
00152       }
00153     }
00154 #endif
00155     return align ;
00156  
00157   case CLASS_CONST:
00158     if (TCON_ty(STC_val(sym)) == MTYPE_STR && TY_kind(ty) == KIND_POINTER)
00159     {
00160      /*
00161       *  can be either char string or wchar string; use element alignment. 
00162       *  please note we cannot use ST_use_reg_align() on a const
00163       */
00164       align =   TY_align(TY_pointed(ty));
00165     }
00166     else
00167     {
00168       align =   TY_align(ty_idx);
00169     }
00170 
00171     if (TY_kind(ty) != KIND_SCALAR) {
00172         /*
00173          * allow users to specify const alignment of 
00174          * composite and string types.
00175          * (could also use Is_Composite_Type or is-string-type).
00176          */
00177         align = MAX(align, Aggregate_Alignment);
00178     }
00179 
00180    /*
00181     *  let string fall into their natural alignment class
00182     *    ex     size (1 -> 1), (2 ->2), (3,4 -> 4) , etc
00183     */
00184     if ( /* Optimize_Space==FALSE */ TRUE )
00185     {
00186       INT64 size = ST_size(sym);
00187 
00188       if (size)
00189       { 
00190         if(size < MTYPE_align_best(Spill_Int_Mtype))
00191         {
00192           INT32 pow2= nearest_power_of_two(size);
00193 
00194           align = MAX(align, pow2);
00195         }
00196         else
00197         {
00198           align = MAX(align, MTYPE_align_best(Spill_Int_Mtype));
00199         }
00200       }
00201     }
00202     return align;
00203   }
00204 
00205   return TY_align(ty_idx);
00206 }
00207 
00208 
00209 
00210 
00211 
00212 /* ====================================================================
00213  *
00214  * New_ST_Block
00215  *
00216  * Allocate a ST entry of CLASS_BLOCK, set up appropriate flags.
00217  *
00218  * ====================================================================
00219  */
00220 extern ST*
00221 New_ST_Block (STR_IDX name, BOOL is_global, ST_SCLASS sclass, UINT16 align, INT64 size)
00222 {
00223   ST *new_blk = New_ST(is_global ? GLOBAL_SYMTAB : CURRENT_SYMTAB);
00224   ST_Init (new_blk, name, CLASS_BLOCK, sclass, EXPORT_LOCAL, 0);
00225   BLK_IDX blk_idx;
00226   (void) New_BLK(blk_idx);
00227   Set_ST_blk(new_blk, blk_idx);
00228   Set_STB_align(new_blk, align);
00229   Set_STB_size(new_blk, size);
00230   return new_blk;
00231 }
00232 
00233 extern ST*
00234 Copy_ST_Block (ST *orig_blk)
00235 {
00236   ST *new_blk = New_ST_Block (ST_name_idx(orig_blk), 
00237         ST_level(orig_blk) == GLOBAL_SYMTAB, 
00238         ST_sclass(orig_blk), STB_align(orig_blk), STB_size(orig_blk) );
00239   Set_STB_flags(new_blk, STB_flags(orig_blk));
00240   Set_STB_section_idx(new_blk, STB_section_idx(orig_blk));
00241   Set_STB_scninfo_idx(new_blk, STB_scninfo_idx(orig_blk));
00242   return new_blk;
00243 }
00244 
00245 
00246 /* ====================================================================
00247  *
00248  * Create_And_Set_ST_Base
00249  *
00250  * Set the ST_base for two blocks that are merged into one.  It
00251  * identify the container block, we call base, by checking the ST_base
00252  * of blk1.  If the ST_base is pointing to itself, that means the
00253  * container block has not be defined yet.  We create a new container
00254  * block for it.  The second block should not have a container block.
00255  * After we have identify the container block, we set the ST_base of
00256  * both blocks with this container block.
00257  *
00258  * ====================================================================
00259  */
00260 static ST *
00261 Create_And_Set_ST_Base(ST *blk1, ST *blk2, STACK_DIR dir)
00262 {
00263   ST *base;
00264   ST *blk1_base = Base_Symbol(blk1);
00265 #if 0
00266   Is_True(ST_sclass(blk1) != SCLASS_UNKNOWN &&
00267           ST_sclass(blk2) != SCLASS_UNKNOWN,
00268           ("Block_Merge: Invalid SCLASS %d, %d",
00269            ST_sclass(blk1), ST_sclass(blk2)));
00270 
00271   Is_True(ST_sclass(blk1) == ST_sclass(blk2),
00272           ("Block_Merge: Different SCLASS %d, %d",
00273            ST_sclass(blk1), ST_sclass(blk2)));
00274 
00275   FmtAssert(Has_No_Base_Block(blk2),
00276             ("Block_Merge: ST_base of blk2 is already initialized"));
00277 #endif
00278   if (ST_class(blk1_base) != CLASS_BLOCK) {
00279       base = New_ST_Block (Save_Str2(ST_name(blk1_base),".BLOCK"), 
00280         Is_Global_Symbol(blk1_base), 
00281         ST_sclass(blk1_base), Adjusted_Alignment(blk1_base), 
00282         ST_size(blk1_base));
00283       if (dir == DECREMENT) Set_STB_decrement(base);
00284       Set_ST_base(blk1_base, base);
00285       Enter_ST(base);
00286   }
00287   else if (ST_class(blk1) == CLASS_BLOCK) {
00288     base = blk1;
00289   } else {
00290     base = blk1_base;
00291   }
00292 
00293   Set_ST_base(blk2, base);
00294   return base;
00295 }
00296 
00297 
00298 
00299 /*===================================================================
00300  *
00301  * St_Block_Union
00302  *
00303  * Force two objects to use the same memory.
00304  * Merge second ST entry into the first ST entry's container block,
00305  * if these two ST entries belong to the same storage class.  It
00306  * creates a new container block for the first ST if there isn't one
00307  * yet. After setting the base, it performs data layout by assigning
00308  * both offsets to 0 (modulo alignment)
00309  *
00310  * ====================================================================
00311  */
00312 
00313 void St_Block_Union(ST *blk1, ST *blk2)
00314 {
00315   ST *base;
00316   INT64 size1,size2;
00317 
00318   Is_True(!ST_is_initialized(blk2),
00319           ("St_Block_Union: union an initialized ST is not allowed"));
00320   Is_True(ST_sclass(blk1) == ST_sclass(blk2),
00321           ("Block_Union: Different SCLASS for %s and %s",
00322                 ST_name(blk1), ST_name(blk2) ) );
00323 
00324   base = Create_And_Set_ST_Base(blk1,blk2, INCREMENT);
00325 
00326   size1 = ST_size(base);
00327   size2 = ST_size(blk2);
00328 
00329   Set_STB_align(base, MAX(STB_align(base), Adjusted_Alignment(blk2)));
00330   Set_STB_size(base, ROUNDUP(MAX(size1,size2),STB_align(base)));
00331   Set_ST_ofst(blk2,0);
00332 
00333   if (Is_Global_Symbol(base)) {
00334         // global symbols are allocated at beginning of be,
00335         // and routines like Process_Bss_Data expect global allocation
00336         // done at end of each PU, so allocat base now.
00337         Allocate_Object(base);
00338   }
00339 
00340   if ( Get_Trace(TP_DATALAYOUT, 1)) {
00341         fprintf(TFile, "union %s with %s, base = %s\n",
00342                 ST_name(blk1), ST_name(blk2), ST_name(base) );
00343   }
00344 }
00345 
00346 
00347 /* ====================================================================
00348  *
00349  * Offset_From_Base_Symbol
00350  *
00351  * Follow the chain of ST_base symbols and return the offset
00352  * from the "final" base symbol
00353  *
00354  * ====================================================================
00355  */
00356 INT64
00357 Offset_From_Base_Symbol ( ST *st )
00358 {
00359   INT64 ofst;
00360   ST    *base;
00361 
00362   Base_Symbol_And_Offset ( st, &base, &ofst );
00363   return ofst;
00364 }
00365 
00366 /* ====================================================================
00367  *
00368  * Base_Symbol
00369  *
00370  * Follow the chain of ST_base symbols and return the "final" base symbol
00371  *
00372  * ====================================================================
00373  */
00374 
00375 ST *
00376 Base_Symbol (ST *st) 
00377 {
00378   INT64 ofst;
00379   ST    *base;
00380 
00381   Base_Symbol_And_Offset ( st, &base, &ofst );
00382   return base;
00383 }
00384 
00385 
00386 // Create slink symbol in current PU
00387 void
00388 Create_Slink_Symbol (void)
00389 {
00390         // only create slink if a nested function.
00391         if ( ! PU_is_nested_func(Get_Current_PU())) return;
00392 
00393         ST *st = Gen_Temp_Symbol (MTYPE_To_TY(Pointer_type), "__slink_sym");
00394 }
00395 
00396 // return ST for __slink_sym if one exists in specified PU.
00397 
00398 struct is_slink_sym
00399 {
00400     BOOL operator () (UINT32, const ST *st) const {
00401         return (strncmp (ST_name (st), "__slink_sym", 11) == 0);
00402     }
00403 };
00404 
00405 ST *
00406 Find_Slink_Symbol (SYMTAB_IDX stab)
00407 {
00408     if (!PU_is_nested_func (Get_Scope_PU (stab)))
00409         return NULL;
00410 
00411     ST_IDX st_idx = For_all_until (St_Table, stab, is_slink_sym ());
00412 
00413     if (st_idx == 0)
00414         return NULL;
00415     else
00416         return &St_Table[st_idx];
00417 } // Find_Slink_Symbol
00418 
00419 
00420 /* ====================================================================
00421  *
00422  * Find_Slink_Sym_For_ST(ST *st)
00423  *
00424  * Return the slink_sym that can reference this st.
00425  *
00426  * The slink_sym will be in the symtab of the child 
00427  *
00428  * ====================================================================
00429  */
00430 
00431 ST *Find_Slink_For_ST(ST *st)
00432 {
00433   UINT level = ST_level(st);
00434   SYMTAB_IDX stab= CURRENT_SYMTAB;
00435 
00436   while(stab)
00437   {
00438     SYMTAB_IDX parent = SYMTAB_parent(stab);
00439 
00440     if (parent && (SYMTAB_level(parent) == level))
00441     {
00442       ST        *slink = Find_Slink_Symbol(stab);
00443       Is_True ((slink), ("no SYMTAB_slink_sym() "));
00444       return slink;
00445     }
00446     stab = parent;
00447   }
00448 
00449   FmtAssert(FALSE,
00450            ("Find_Slink_For_ST() cannot find symtab for %s (level=%d)",
00451              ST_name(st), ST_level(st)));
00452   /* NOTREACHED */
00453   return NULL;
00454 }
00455 
00456 
00457 /* ====================================================================
00458  *
00459  * Find_Slink_For_Scope(SYMTAB_IDX symtab, INT32 scope_id)
00460  *
00461  * Return the slink_sym at scope_id
00462  *
00463  * ====================================================================
00464  */
00465 
00466 ST *Find_Slink_For_Scope(ST *function, ST *sym)
00467 {
00468   SYMTAB_IDX symtab= CURRENT_SYMTAB;
00469   INT32 level = PU_lexical_level (function) - PU_lexical_level (sym);
00470 
00471   while(level-- > 0)
00472   {
00473     symtab= SYMTAB_parent(symtab);
00474 
00475     Is_True ((symtab), ("no symtab at correct level"));
00476   }
00477 
00478   {
00479     ST  *slink = Find_Slink_Symbol (symtab);
00480     Is_True ((slink), ("no SYMTAB_slink_sym() "));
00481     return slink;
00482   }
00483   /* NOTREACHED */
00484   return NULL;
00485 }
00486 
00487 BOOL ST_is_uplevelTemp(const ST *st)
00488 {
00489   if (ST_class(st) != CLASS_VAR         &&
00490       ST_class(st) != CLASS_BLOCK)
00491     return FALSE;
00492 
00493   if (Is_Global_Symbol(st) || Is_Local_Symbol(st)) 
00494     return FALSE;
00495 
00496   if (PU_has_altentry(Get_Current_PU()) && ST_declared_static(st))
00497     return FALSE;
00498 
00499   switch(ST_sclass(st))
00500   {
00501   case SCLASS_AUTO:
00502   case SCLASS_FORMAL:
00503     return TRUE;
00504   }
00505 
00506   return FALSE;
00507 }
00508 
00509 
00510 /* ====================================================================
00511  *
00512  * Base_Symbol_And_Offset_For_Addressing
00513  *      Input:  ST *sym                  Symbol to analyze
00514  *      Input:  INT64 ofst               Offset from sym
00515  *      Result: ST **base_symbol         base of st for addressing
00516  *      Result: INT64 *offset_from_base  offset from base
00517  *
00518  * This routine returns the <base_symbol> and <offset_from_base> that
00519  * should be used for addressing. There are some cases where we cannot
00520  * use the ST_base (for text symbols and preemptible symbols). For those
00521  * cases, we simply return the <sym> and <ofst> themselves.
00522  *
00523  * ====================================================================
00524  */
00525 void
00526 Base_Symbol_And_Offset_For_Addressing (
00527   ST *sym,
00528   INT64 ofst,
00529   ST **base_symbol,
00530   INT64 *offset_from_base)
00531 {
00532   /* 1. For text symbols, don't use the base_sym and base_ofst because
00533    *    they may not have been set yet. This happens for a forward
00534    *    reference to a text address.
00535    * 2. For preemptible symbols, we cannot use the base where the symbol
00536    *    is allocated since it could be preempted. 
00537    */
00538   INT64 tofst = 0;
00539   ST *base = sym;
00540 
00541   while ( (ST_base(base) != base  ) 
00542         && (ST_sclass(base) != SCLASS_TEXT) 
00543         && !((Gen_PIC_Shared || Gen_PIC_Call_Shared) && ST_is_preemptible(base)) )
00544   {
00545       tofst += ST_ofst(base);
00546       base = ST_base(base); 
00547   }
00548 
00549   *base_symbol      = base;
00550   *offset_from_base = tofst + ofst;
00551 }
00552 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines