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 /* ==================================================================== 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