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