Open64 (mfef90, whirl2f, and IR tools)
TAG: version-openad; SVN changeset: 916
|
00001 /* 00002 Copyright (C) 2000, 2001 Silicon Graphics, Inc. All Rights Reserved. 00003 00004 This program is free software; you can redistribute it and/or modify it 00005 under the terms of version 2 of the GNU General Public License as 00006 published by the Free Software Foundation. 00007 00008 This program is distributed in the hope that it would be useful, but 00009 WITHOUT ANY WARRANTY; without even the implied warranty of 00010 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00011 00012 Further, this software is distributed without any warranty that it is 00013 free of the rightful claim of any third person regarding infringement 00014 or the like. Any license provided herein, whether implied or 00015 otherwise, applies only to this software file. Patent licenses, if 00016 any, provided herein do not apply to combinations of this program with 00017 other software, or any other product whatsoever. 00018 00019 You should have received a copy of the GNU General Public License along 00020 with this program; if not, write the Free Software Foundation, Inc., 59 00021 Temple Place - Suite 330, Boston MA 02111-1307, USA. 00022 00023 Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pky, 00024 Mountain View, CA 94043, or: 00025 00026 http://www.sgi.com 00027 00028 For further information regarding this notice, see: 00029 00030 http://oss.sgi.com/projects/GenInfo/NoticeExplan 00031 00032 */ 00033 00034 00035 /* ==================================================================== 00036 * ==================================================================== 00037 * 00038 * 00039 * Description: This static data initialization 00040 * 00041 * ==================================================================== 00042 *==================================================================== 00043 */ 00044 00045 static char *source_file = __FILE__; 00046 00047 #ifdef _KEEP_RCS_ID 00048 #endif /* _KEEP_RCS_ID */ 00049 00050 /* sgi includes */ 00051 00052 #include "defs.h" 00053 #include "glob.h" 00054 #include "stab.h" 00055 #include "strtab.h" 00056 #include "erfe90.h" 00057 #include "errors.h" 00058 #include "targ_const.h" 00059 #include "config_targ.h" 00060 #include "const.h" 00061 #include "wn.h" 00062 #include "wn_util.h" 00063 #include "irbdata.h" 00064 #include "cxx_memory.h" 00065 00066 /* Cray includes */ 00067 00068 #include "i_cvrt.h" 00069 00070 /* conversion includes */ 00071 00072 #include "cwh_defines.h" 00073 #include "cwh_types.h" 00074 #include "cwh_addr.h" 00075 #include "cwh_stmt.h" 00076 #include "cwh_preg.h" 00077 #include "cwh_stab.h" 00078 #include "cwh_auxst.h" 00079 #include "cwh_stk.h" 00080 #include "cwh_expr.h" 00081 #include "cwh_data.h" 00082 00083 #include "cwh_data.i" 00084 /* #define DATA_DEBUG 1*/ 00085 00086 /*================================================================ 00087 * fei_static_base 00088 * Get the base for the static initialization. 00089 * Also set up the initialization object structure. 00090 *================================================================ 00091 */ 00092 extern void 00093 fei_static_base(INTPTR sym_idx) 00094 { 00095 STB_pkt *p ; 00096 ST *base; 00097 INT64 offset; 00098 BOOL init_common_or_module; 00099 00100 p = cast_to_STB(sym_idx); 00101 DevAssert((p->form == is_ST),("Odd object ref")); 00102 00103 current_st = (ST *) p->item; 00104 orig_st = current_st; 00105 current_ty = ST_type(current_st); 00106 current_pos = 0; 00107 array_pos = 0; 00108 init_common_or_module = FALSE; 00109 offset = 0; 00110 base = current_st; 00111 /* Check for based as a symbol in common */ 00112 00113 00114 00115 // while (ST_base(base) != base) { 00116 00117 /* if use "while" stmt,for common block at last base will go */ 00118 /* to pu's name,because for source level thinking we already */ 00119 /* set common block's base is pu's st instead itself. fzhao*/ 00120 00121 00122 if (ST_base(base) != base && (ST_sclass(ST_base(base))!=SCLASS_TEXT)) { 00123 // Since for PU is module,we change base_idx point to the PU_st 00124 // have to keep data initializer's st point to st instead of base_st 00125 00126 // offset += ST_ofst(base); set all initializers in common block have 00127 // themselves INITO entry,such must set offset always is 0 00128 00129 base = ST_base(base); 00130 } 00131 00132 00133 // for debug cwh_auxst_dump (base); 00134 00135 if ((ST_sclass(base) == SCLASS_DGLOBAL) || 00136 (ST_sclass(base) == SCLASS_COMMON)) {// June || 00137 // (ST_sclass(base) == SCLASS_MODULE )){ 00138 00139 /* convert the COMMON into a DGLOBAL, makeing sure the sclasses 00140 * are consistent, and the the ST_initialized flag is set. This 00141 * includes equivalence classes 00142 */ 00143 00144 Set_ST_sclass(base, SCLASS_DGLOBAL); 00145 00146 cwh_data_set_init_flag(base,l_COMLIST); 00147 00148 current_pos = offset; 00149 init_common_or_module = TRUE; 00150 00151 } else if (base != current_st) { 00152 00153 /* equivalenced item */ 00154 00155 cwh_data_set_init_flag(base,l_EQVLIST); 00156 current_pos = offset; 00157 Set_ST_is_initialized(base); 00158 init_common_or_module = TRUE; 00159 } 00160 00161 00162 Set_ST_is_initialized(current_st); 00163 00164 # if 0 00165 if (ST_sclass(current_st)!=SCLASS_MODULE) 00166 Set_ST_sclass(current_st,SCLASS_PSTATIC); // June 00167 # endif 00168 // current_st = base; 00169 00170 if (TY_kind(current_ty) == KIND_ARRAY) { 00171 is_struct_or_array = TRUE; 00172 00173 current_bytesize = TY_size(TY_etype(current_ty)); 00174 } else { 00175 if (TY_kind(current_ty) == KIND_STRUCT) { 00176 is_struct_or_array = TRUE; 00177 } else { 00178 is_struct_or_array = FALSE; 00179 } 00180 current_bytesize = TY_size(current_ty); 00181 } 00182 if (init_common_or_module) { 00183 is_struct_or_array = TRUE; 00184 } 00185 00186 current_data_info = ST_auxst_data_info(current_st); 00187 if (!current_data_info) { 00188 current_data_info = CXX_NEW(data_info_s(current_st),FE_Mempool); 00189 Set_ST_auxst_data_info(current_st,current_data_info); 00190 } 00191 current_inito = current_data_info->Get_Inito(); 00192 return; 00193 } 00194 00195 /*================================================================ * * fei_static_subscripts 00196 * 00197 * Get the subscripts for a static initialization. The FE provides 00198 * subscripts with the least-contiguous subscript in 00199 * static_subscripts[0] & in the ARB, the least-contiguous dimension 00200 * is the lowest (first) idx. 00201 * 00202 * 00203 *================================================================ 00204 */ 00205 extern void 00206 fei_static_subscripts( INT64 static_subscripts[STATIC_SUBSCRIPT_SIZE] ) 00207 { 00208 INT i; 00209 INT rank; 00210 INT64 offset; 00211 00212 00213 ARB_HANDLE arb; 00214 00215 /* Create an initial start subscript position from the data given */ 00216 DevAssert((TY_kind(current_ty)==KIND_ARRAY),("Not an array ty")); 00217 rank = TY_AR_ndims(Ty_Table[current_ty]); 00218 offset = 0; 00219 00220 arb = TY_arb(Ty_Table[current_ty])[rank - 1]; 00221 00222 for (i=rank-1; i >= 0; i--) { 00223 offset += (static_subscripts[i] - 00224 ARB_lbnd_val(arb))* 00225 ARB_stride_val(arb); 00226 arb = arb[-1]; 00227 } 00228 00229 array_pos += offset; 00230 return; 00231 } 00232 00233 /*================================================================ 00234 * fei_static_substr 00235 * Get the position in a string to initialize. 00236 *================================================================ 00237 */ 00238 extern void 00239 fei_static_substr( INT32 start) 00240 { 00241 00242 /* Create an initial start subscript position from the data given */ 00243 /* For a CHARACTER object, the lower bound is always 1 */ 00244 array_pos += start - 1; 00245 return; 00246 } 00247 00248 /*================================================================ 00249 * fei_static_member 00250 * Get the position of a member to initialize 00251 *================================================================ 00252 */ 00253 extern 00254 void fei_static_member (INT32 st_idx ) 00255 { 00256 FLD_IDX fld; 00257 00258 fld = (FLD_IDX)st_idx; 00259 00260 FLD_HANDLE f (fld); 00261 DevAssert((FLD_bofst(f) == 0),("Can't handle non 0 bofst")); 00262 current_pos += FLD_ofst(f); 00263 00264 current_ty = FLD_type(f); 00265 if (TY_kind(current_ty) == KIND_ARRAY) { 00266 current_bytesize = TY_size(TY_etype(current_ty)); 00267 } else { 00268 current_bytesize = TY_size(current_ty); 00269 } 00270 } 00271 00272 /* Get the size of a TCON */ 00273 static INT32 get_TCON_size(TCON_IDX tc) 00274 { 00275 TYPE_ID t; 00276 INT32 esize; 00277 if (tc == 0) { 00278 /* Must be doing an init of a symbol, rather than 00279 * a constant. Return Pointer_Size. 00280 */ 00281 esize = Pointer_Size; 00282 } else { 00283 TCON& tcon = Tcon_Table[tc]; 00284 t = TCON_ty(tcon); 00285 if (t == MTYPE_STR) { 00286 esize = Targ_String_Length(tcon); 00287 } else { 00288 esize = MTYPE_size_min(t)/8; 00289 } 00290 } 00291 return (esize); 00292 } 00293 00294 /* Get a TCON from a WHIRL node */ 00295 static TCON_IDX TCON_from_stack(void) 00296 { 00297 TCON_IDX tcp; 00298 ST *cst; 00299 WN *slen; 00300 WN *w; 00301 TY_IDX ty; 00302 00303 switch (cwh_stk_get_class()) { 00304 case STR_item: 00305 cwh_stk_pop_STR(); 00306 slen = cwh_stk_pop_WN(); 00307 WN_DELETE_Tree(slen); 00308 cst = cwh_stk_pop_ST(); 00309 tcp = ST_tcon(cst); 00310 break; 00311 00312 case PCONST_item: 00313 cst = (ST *) cwh_stk_pop_PCONST(); 00314 tcp = ST_tcon(cst); 00315 break; 00316 00317 case WN_item: 00318 case WN_item_whole_array: 00319 ty = cwh_stk_get_TY(); 00320 w = cwh_stk_pop_WN(); 00321 if (WNOPR(w) == OPR_INTCONST) { 00322 if (ty) { 00323 tcp = Enter_tcon(Host_To_Targ(TY_mtype(ty),WN_const_val(w))); 00324 } else { 00325 tcp = Enter_tcon(Host_To_Targ(WN_rtype(w),WN_const_val(w))); 00326 } 00327 } else if (WNOPR(w) == OPR_CONST) { 00328 tcp = Enter_tcon(Const_Val(w)); 00329 } else { 00330 DevAssert((0),("not a const node")); 00331 } 00332 WN_Delete(w); 00333 break; 00334 } 00335 return (tcp); 00336 } 00337 00338 /*================================================================ 00339 * get_base_and_offset(WN *wn) 00340 * 00341 * Given a WHIRL node, return an ST and an offset 00342 * from the base of the ST. 00343 * It assumes all addressing that is done is with constant sizes, 00344 * offsets, etc. 00345 * 00346 *================================================================ 00347 */ 00348 00349 static 00350 b_and_o get_base_and_offset(WN *wn) 00351 { 00352 b_and_o r,t1,t2; 00353 INT64 offset; 00354 INT ndim,i; 00355 INT64 esize; 00356 INT64 smult; 00357 WN *adim, *aindex; 00358 INT64 adim_val,aindex_val; 00359 00360 r.base = NULL; 00361 r.offset = 0; 00362 00363 switch (WN_operator(wn)) { 00364 case OPR_ADD: 00365 t1 = get_base_and_offset(WN_kid0(wn)); 00366 t2 = get_base_and_offset(WN_kid1(wn)); 00367 r.offset = t1.offset + t2.offset; 00368 if (t1.base) { 00369 r.base = t1.base; 00370 } else if (t2.base) { 00371 r.base = t2.base; 00372 } else { 00373 DevAssert((0),("No base found")); 00374 } 00375 break; 00376 00377 case OPR_SUB: 00378 t1 = get_base_and_offset(WN_kid0(wn)); 00379 t2 = get_base_and_offset(WN_kid1(wn)); 00380 r.offset = t1.offset - t2.offset; 00381 if (t1.base) { 00382 r.base = t1.base; 00383 } else { 00384 DevAssert((0),("No base or bad base")); 00385 } 00386 break; 00387 00388 case OPR_INTCONST: 00389 r.base = NULL; 00390 r.offset = WN_const_val(wn); 00391 break; 00392 00393 case OPR_LDA: 00394 r.base = WN_st(wn); 00395 r.offset = WN_offset(wn); 00396 00397 # ifdef linux 00398 /* Check for based as a symbol in common */ 00399 while (ST_base(r.base) != r.base) { 00400 r.offset += ST_ofst(r.base); 00401 r.base = ST_base(r.base); 00402 } 00403 # endif 00404 break; 00405 00406 case OPR_ARRAYEXP: 00407 r = get_base_and_offset(WN_kid0(wn)); 00408 break; 00409 00410 case OPR_ARRAY: 00411 case OPR_ARRSECTION: 00412 /* Build up an offset from the ARRAY portion, and add it to the base */ 00413 r = get_base_and_offset(WN_kid0(wn)); 00414 esize = WN_element_size(wn); 00415 ndim = WN_num_dim(wn); 00416 offset = 0; 00417 00418 smult = 1; 00419 for (i = ndim-1; i >= 0; i--) { 00420 aindex = WN_array_index(wn,i); 00421 adim = WN_array_dim(wn,i); 00422 DevAssert((WN_operator(aindex)==OPR_INTCONST),("Non-constant index")); 00423 DevAssert((WN_operator(adim)==OPR_INTCONST),("Non-constant dim")); 00424 aindex_val = WN_const_val(aindex); 00425 adim_val = WN_const_val(adim); 00426 if (esize < 0) { 00427 /* Non-contiguous */ 00428 offset += aindex_val * adim_val; 00429 } else { 00430 /* contiguous */ 00431 offset += aindex_val * smult; 00432 smult *= adim_val; 00433 } 00434 } 00435 00436 /* Scale by element_size */ 00437 if (esize > 0) { 00438 offset *= esize; 00439 } else { 00440 offset *= (-esize); 00441 } 00442 /* add into rest */ 00443 r.offset += offset; 00444 break; 00445 00446 case OPR_COMMA: 00447 r = get_base_and_offset(WN_kid1(wn)); 00448 break; 00449 00450 default: 00451 /* Don't know what to do here */ 00452 DevAssert((0),("strange offset expression")); 00453 break; 00454 } 00455 return (r); 00456 } 00457 00458 00459 /*================================================================ 00460 * static_simple_init_helper 00461 * Build up the init for a given symbol 00462 * dup_count - number of times to duplicate 00463 * stride - step for multiple inits 00464 * value - pointer to a TCON for a value init 00465 * bo - pointer to a base and offset for a symbol init 00466 *================================================================ 00467 */ 00468 00469 00470 /* Create an initv node for use by the initializing routines */ 00471 static INITV_IDX create_initv(INITO_IDX ino, INT32 repeat, TCON_IDX tc, 00472 b_and_o *bo) 00473 { 00474 if (tc) { 00475 return (Irb_Init_Val(ino, 0, repeat, tc)); 00476 } else { 00477 return (Irb_Init_Symoff(ino, 0, repeat, bo->base, bo->offset)); 00478 } 00479 } 00480 00481 static 00482 void static_simple_init_helper (INT64 dup_count, 00483 INT64 stride, 00484 TCON_IDX value, 00485 b_and_o *bo) 00486 00487 { 00488 INT64 byte_stride; 00489 INT32 init_size; 00490 INT64 i; 00491 INT64 element_offset; 00492 00493 if (!is_struct_or_array) { 00494 create_initv(current_inito,1,value, bo); 00495 return; 00496 } 00497 00498 if (dup_count == 0) return; 00499 element_offset = array_pos; 00500 00501 byte_stride = stride/8; 00502 if (byte_stride < 0) { 00503 /* Need to turn this around so it runs upward */ 00504 element_offset += byte_stride*(dup_count-1); 00505 byte_stride = -byte_stride; 00506 } 00507 00508 init_size = get_TCON_size(value); 00509 if (byte_stride == 0) byte_stride = init_size; 00510 00511 /* Multiple inserts */ 00512 current_data_info->Reserve(dup_count); 00513 for (i=0; i < dup_count; i++) { 00514 current_data_info->Add_Data_Element(current_pos+element_offset,value,bo,init_size); 00515 element_offset += byte_stride; 00516 } 00517 00518 return; 00519 } 00520 00521 00522 extern 00523 void fei_static_simple_init (INT64 dup_count, 00524 INT64 stride, 00525 INT32 ignore_types, 00526 INT32 string_literal) 00527 00528 { 00529 TCON_IDX value; 00530 value = TCON_from_stack(); 00531 static_simple_init_helper(dup_count,stride,value,NULL); 00532 } 00533 00534 00535 /*================================================================ 00536 * fei_static_next_simple_init 00537 * Build up the init for a given symbol 00538 *================================================================ 00539 */ 00540 extern 00541 void fei_static_next_simple_init ( INT64 bit_increment, 00542 INT64 dup_count, 00543 INT64 init_offset, 00544 INT32 string_literal ) 00545 { 00546 array_pos += (init_offset >> 3); 00547 fei_static_simple_init(dup_count,bit_increment,0,string_literal); 00548 } 00549 00550 /*================================================================ 00551 * fei_static_simple_reloc_init 00552 * Build up the init for a given symbol 00553 *================================================================ 00554 */ 00555 00556 extern 00557 void fei_static_simple_reloc_init ( INT64 bit_offset, 00558 INT64 dup_count, 00559 INT64 stride, 00560 INT64 bit_size, 00561 INT32 ignore_types ) 00562 { 00563 WN *addr; 00564 b_and_o value; 00565 00566 /* Pull apart the address to get a symbol and an offset */ 00567 /* Everything should be constant */ 00568 addr = cwh_expr_operand(NULL); 00569 value = get_base_and_offset(addr); 00570 WN_DELETE_Tree(addr); 00571 DevAssert((value.base),("NULL base found")); 00572 cwh_expr_set_flags(value.base,f_T_SAVED); 00573 00574 static_simple_init_helper(dup_count,stride,0,&value); 00575 } 00576 00577 00578 //================================================================ 00579 // 00580 // Emit initializations for a symbol 00581 // 00582 //================================================================ 00583 00584 static void emit_inits_for_symbol(ST_IDX st_idx, ST *st) 00585 { 00586 DATA_INFO d; 00587 INITO_IDX inito; 00588 DATA_ELEMENTS *v; 00589 INT vsize,i; 00590 INT64 pos; 00591 00592 INITV_IDX pad; 00593 INITV_IDX initv; 00594 INITV_IDX prev_initv; 00595 INT64 offset; 00596 INT64 init_size; 00597 INT64 pad_size; 00598 00599 if (ST_sym_class(st) != CLASS_VAR) return; // Only emit inits for variables 00600 00601 d = ST_auxst_data_info(st); 00602 if (d==NULL) return; 00603 if (d->Get_Data_Elements()==NULL) return; 00604 00605 // Get the inito for the symbol 00606 inito = d->Get_Inito(); 00607 // Sort the data 00608 d->sort_data(st); 00609 v = d->Get_Data_Elements(); 00610 00611 // v is now an array of sorted size/offset/initv triples. 00612 vsize = v->size(); 00613 if (vsize == 0) return; 00614 00615 #ifdef DATA_DEBUG 00616 printf("Emitting inits for %s ====================\n",ST_name(st)); 00617 #endif 00618 00619 prev_initv = 0; 00620 pos = 0; 00621 for (i = 0; i < vsize; i++) { 00622 if (!(*v)[i].is_valid) continue; 00623 offset = (*v)[i].offset; 00624 init_size = (*v)[i].initv_size; 00625 initv = (*v)[i].create_initv(); 00626 00627 // Do we need to pad before? 00628 pad_size = offset - pos; 00629 if (pad_size > 0) { 00630 pad = Irb_Init_Pad(0,prev_initv,pad_size); 00631 if (prev_initv == 0) { 00632 prev_initv = Irb_Init_Block(inito,0,1); 00633 Set_INITV_blk(prev_initv,pad); 00634 } else { 00635 Set_INITV_next(prev_initv,pad); 00636 } 00637 prev_initv = pad; 00638 } 00639 00640 #ifdef DATA_DEBUG 00641 printf("pad %lld, offset %lld, size %lld, next %lld\n",pad_size, 00642 offset,init_size, offset + init_size); 00643 #endif 00644 00645 // Add the initv to the chain 00646 if (prev_initv == 0) { 00647 prev_initv = Irb_Init_Block(inito,0,1); 00648 Set_INITV_blk(prev_initv,initv); 00649 } else { 00650 Set_INITV_next(prev_initv,initv); 00651 } 00652 prev_initv = initv; 00653 pos = offset + init_size; 00654 } 00655 00656 // Do we need to pad the end? 00657 pad_size = TY_size(ST_type(st)) - pos; 00658 if (pad_size > 0) { 00659 pad = Irb_Init_Pad(0,prev_initv,pad_size); 00660 } 00661 00662 // Delete the structure 00663 CXX_DELETE(d,FE_Mempool); 00664 Set_ST_auxst_data_info(st,NULL); 00665 00666 return; 00667 } 00668 00669 00670 00671 //================================================================ 00672 // 00673 // Emit initializations for all symbols in a symbol level 00674 // 00675 //================================================================ 00676 00677 extern void 00678 cwh_data_emit_symbol_inits(SYMTAB_IDX level) 00679 { 00680 For_all(St_Table, level,&emit_inits_for_symbol); 00681 } 00682 00683 /*================================================================ 00684 * 00685 * cwh_data_set_init_flag 00686 * 00687 * sets ST_initialized flag on COMMON or EQUIVALENCE components. 00688 * also sets the base of components to that of base. Ditto CRI 00689 * pointer pointee pairs. 00690 * 00691 * Utility for fei_static_base. 00692 * 00693 *================================================================ 00694 */ 00695 static void 00696 cwh_data_set_init_flag(ST * st, enum list_name list) 00697 { 00698 00699 ITEM * el = NULL; 00700 00701 while ((el = cwh_auxst_next_element(st,el,list)) != NULL) { 00702 00703 ST * el_st = I_element(el); 00704 if (ST_sclass(el_st)!=SCLASS_AUTO) 00705 Set_ST_sclass(el_st, ST_sclass(st)); 00706 else 00707 Set_ST_sclass(el_st,SCLASS_PSTATIC); // June 00708 Set_ST_is_initialized(el_st); 00709 00710 ST * p_st = cwh_auxst_cri_pointee(el_st,0); 00711 00712 if (p_st) { 00713 00714 if (ST_sclass(p_st)!= SCLASS_AUTO) 00715 Set_ST_sclass(p_st, ST_sclass(st)); 00716 else 00717 Set_ST_sclass(p_st,SCLASS_PSTATIC); // June 00718 00719 Set_ST_is_initialized(p_st); 00720 } 00721 00722 if (list == l_COMLIST) 00723 cwh_data_set_init_flag(el_st, l_EQVLIST); 00724 } 00725 } 00726