Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
wn2f_load_store.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  *  12-Apr-95 - Original Version
00042  *
00043  * Description:
00044  *
00045  *   Translate a WN load/store subtree to Fortran by means of an inorder 
00046  *   recursive descent traversal of the WHIRL IR.  Note that the routines
00047  *   handle statements and expressions are in separate source files.
00048  *   Recursive translation of WN nodes should only use WN2F_Translate()!
00049  *
00050  * ====================================================================
00051  * ====================================================================
00052  */
00053 
00054 #ifdef _KEEP_RCS_ID
00055 /*REFERENCED*/
00056 #endif
00057 
00058 #include <climits>
00059 
00060 #include "whirl2f_common.h"
00061 #include "PUinfo.h"          /* In be/whirl2c directory */
00062 #include "pf_cg.h"
00063 #include "wn2f.h"
00064 #include "st2f.h"
00065 #include "ty2f.h"
00066 #include "tcon2f.h"
00067 #include "wn2f_load_store.h"
00068 #include "ty_ftn.h"
00069 
00070 #define DEB_Whirl2f_IR_TY_WN2F_Arrsection_Slots 0
00071 #define DEB_Whirl2f_IR_TY_WN2F_Arrsection_Slots_st1 0
00072 
00073 extern BOOL W2F_Only_Mark_Loads; /* Defined in w2f_driver.c */
00074 static void WN2F_Block(TOKEN_BUFFER tokens, ST * st, STAB_OFFSET off,WN2F_CONTEXT context) ;
00075 
00076 static WN *WN2F_ZeroInt_Ptr = NULL;
00077 static WN *WN2F_OneInt_Ptr = NULL;
00078 TY_IDX fld_type_z = 0;
00079 
00080 #define WN2F_INTCONST_ZERO\
00081    (WN2F_ZeroInt_Ptr == NULL? WN2F_ZeroInt_Ptr = WN2F_Initiate_ZeroInt() \
00082                             : WN2F_ZeroInt_Ptr)
00083 #define WN2F_INTCONST_ONE\
00084    (WN2F_OneInt_Ptr == NULL? WN2F_OneInt_Ptr = WN2F_Initiate_OneInt() \
00085                             : WN2F_OneInt_Ptr)
00086 
00087 void WN2F_Arrsection_Slots(TOKEN_BUFFER tokens, WN *wn,TY_IDX array_ty,WN2F_CONTEXT context,
00088                             BOOL parens);
00089 void WN2F_Array_Slots(TOKEN_BUFFER tokens, WN *wn,TY_IDX array_ty,WN2F_CONTEXT context,BOOL parens);
00090 
00091 /*------------------------- Utility Functions ------------------------*/
00092 /*--------------------------------------------------------------------*/
00093 
00094 static ST *
00095 WN2F_Get_Named_Param(const WN *pu, const char *param_name)
00096 {
00097    /* Find a parameter with a matching name, if possible, otherwise
00098     * return NULL.
00099     */
00100    ST *param_st = NULL;
00101    INT param, num_formals;
00102 
00103    if (WN_opcode(pu) == OPC_ALTENTRY)
00104       num_formals = WN_kid_count(pu);
00105    else
00106       num_formals = WN_num_formals(pu);
00107 
00108    /* Search through the parameter ST entries
00109     */
00110    for (param = 0; param_st == NULL && param < num_formals; param++)
00111    {
00112       if (ST_name(WN_st(WN_formal(pu, param))) != NULL &&
00113           strcmp(ST_name(WN_st(WN_formal(pu, param))), param_name) == 0)
00114          param_st = WN_st(WN_formal(pu, param));
00115    }
00116    return param_st;
00117 } /* WN2F_Get_Named_Param */
00118 
00119 static void
00120 WN2F_Translate_StringLEN(TOKEN_BUFFER tokens, ST *param_st)
00121 {
00122    INT dim;
00123    TY_IDX param_ty = (TY_Is_Pointer(ST_type(param_st))? 
00124                    TY_pointed(ST_type(param_st)) : ST_type(param_st));
00125 
00126    Append_Token_String(tokens, "LEN");
00127    Append_Token_Special(tokens, '(');
00128    Append_Token_String(tokens, W2CF_Symtab_Nameof_St(param_st));
00129 
00130    if (TY_Is_Array(param_ty) && !TY_Is_Character_String(param_ty))
00131    {
00132       /* Append index values (any arbitrary value will do for each dimension)
00133        */
00134       Append_Token_Special(tokens, '(');
00135 
00136 
00137       ARB_HANDLE arb_base = TY_arb(param_ty);
00138       dim = ARB_dimension(arb_base) - 1; 
00139 
00140       while ( dim >= 0)
00141       {
00142         ARB_HANDLE arb = arb_base[dim];
00143 
00144          Append_Token_String(tokens, "1");
00145          if (dim-- > 0)
00146             Append_Token_Special(tokens, ',');
00147       }
00148       Append_Token_Special(tokens, ')');
00149    }
00150    else
00151    {
00152       ASSERT_WARN(TY_Is_Character_String(param_ty), 
00153                   (DIAG_W2F_EXPECTED_PTR_TO_CHARACTER,
00154                     "WN2F_Translate_StringLEN"));
00155    }
00156    Append_Token_Special(tokens, ')');
00157 } /* WN2F_Translate_StringLEN */
00158 
00159 static WN *
00160 WN2F_Initiate_ZeroInt(void)
00161 {
00162    static char ZeroInt [sizeof (WN)];
00163    WN       *wn = (WN*) &ZeroInt;
00164    OPCODE    opcode = OPCODE_make_op(OPR_INTCONST, MTYPE_I4, MTYPE_V);
00165 
00166    memset(wn, '\0', sizeof(WN));
00167    WN_set_opcode(wn, opcode);
00168    WN_set_kid_count(wn, 0);
00169    WN_map_id(wn) =  WN_MAP_UNDEFINED;
00170    WN_const_val(wn) = 0LL;
00171    return wn;
00172 } /* WN2F_Initiate_ZeroInt */
00173 
00174 static WN *
00175 WN2F_Initiate_OneInt(void)
00176 {
00177    static char OneInt [sizeof (WN)];
00178    WN       *wn = (WN*) &OneInt;
00179    OPCODE    opcode = OPCODE_make_op(OPR_INTCONST, MTYPE_I4, MTYPE_V);
00180 
00181    memset(wn, '\0', sizeof(WN));
00182    WN_set_opcode(wn, opcode);
00183    WN_set_kid_count(wn, 0);
00184    WN_map_id(wn) =  WN_MAP_UNDEFINED;
00185    WN_const_val(wn) = 1LL;
00186    return wn;
00187 } /* WN2F_Initiate_ZeroInt */
00188 
00189 
00190 static BOOL
00191 WN2F_Expr_Plus_Literal(TOKEN_BUFFER tokens,
00192                        WN          *wn,
00193                        INT64        literal,
00194                        WN2F_CONTEXT context)
00195 {
00196    /* Returns TRUE if the resultant value is constant and different
00197     * from zero.
00198     */
00199    const BOOL parenthesize = !WN2F_CONTEXT_no_parenthesis(context);
00200    BOOL       is_const = TRUE;
00201    INT64      value;
00202    
00203    if (WN_opc_operator(wn) == OPR_INTCONST)
00204       value = WN_const_val(wn) + literal;
00205    else if (WN_opc_operator(wn) == OPR_CONST)
00206       value = Targ_To_Host(STC_val(WN_st(wn))) + literal;
00207    else
00208       is_const = FALSE;
00209    
00210    if (is_const)
00211    {
00212     if (WN_opc_operator(wn) == OPR_INTCONST) {
00213      switch (TCON_ty(Host_To_Targ(WN_opc_rtype(wn), value)))
00214       {
00215             case MTYPE_I1:
00216             case MTYPE_I2:
00217             case MTYPE_I4:
00218             case MTYPE_I8:
00219               if (TCON_ival(Host_To_Targ(WN_opc_rtype(wn), value))<0)  {
00220                   Append_Token_Special(tokens, '(');
00221                   TCON2F_translate(tokens,
00222                                    Host_To_Targ(WN_opc_rtype(wn), value),
00223                                    FALSE /*is_logical*/);
00224                    Append_Token_Special(tokens, ')');
00225                  }
00226                else
00227                   TCON2F_translate(tokens,
00228                                    Host_To_Targ(WN_opc_rtype(wn), value),
00229                                    FALSE/*is_logical*/);
00230                break;
00231 
00232               default:
00233                   TCON2F_translate(tokens,
00234                                    Host_To_Targ(WN_opc_rtype(wn), value),
00235                                    FALSE/*is_logical*/);
00236 
00237                    break;
00238 
00239              } /*switch*/
00240 
00241     } else {  //WN_opc_operator(wn) == OPR_CONST
00242      ; //Shouldn't be here
00243     
00244     }
00245  
00246    }
00247    else
00248    {
00249       if (parenthesize)
00250       {
00251          reset_WN2F_CONTEXT_no_parenthesis(context);
00252          Append_Token_Special(tokens, '(');
00253       }
00254    if (WN_opc_operator(wn) == OPR_IMPLICIT_BND)
00255         Append_Token_Special(tokens, '*');
00256    else
00257       WN2F_translate(tokens, wn, context);
00258 
00259       if (parenthesize)
00260          Append_Token_Special(tokens, ')');
00261    }
00262 
00263    return is_const && (value != 0LL);
00264 } /* WN2F_Expr_Plus_Literal */
00265 
00266 
00267 
00268 static WN2F_STATUS
00269 WN2F_OLD_Den_Arr_Idx(TOKEN_BUFFER tokens, 
00270                            WN          *idx_expr, 
00271                            WN2F_CONTEXT context)
00272 {
00273    const BOOL   parenthesize = !WN2F_CONTEXT_no_parenthesis(context);
00274    TOKEN_BUFFER tmp_tokens;
00275    BOOL         non_zero, cexpr_is_lhs;
00276    WN          *nexpr, *cexpr;
00277    INT64        plus_value;
00278    
00279    /* Given an index expression, translate it to Fortran and append
00280     * the tokens to the given token-buffer.  If the value of the idx
00281     * expression is "v", then the appended tokens should represent
00282     * the value "v+1".  This denormalization moves the base of the
00283     * array from index zero to index one.
00284     */
00285    if (WN_opc_operator(idx_expr) == OPR_ADD && 
00286        (WN_is_constant_expr(WN_kid1(idx_expr)) || 
00287         WN_is_constant_expr(WN_kid0(idx_expr))))
00288    {
00289       /* Do the "e+c" ==> "e+(c+1)" translation, using the property
00290        * that addition is commutative.
00291        */
00292       if (WN_is_constant_expr(WN_kid1(idx_expr)))
00293       {
00294          cexpr = WN_kid1(idx_expr);
00295          nexpr = WN_kid0(idx_expr);
00296       }
00297       else /* if (WN_is_constant_expr(WN_kid0(idx_expr))) */
00298       {
00299          cexpr = WN_kid0(idx_expr);
00300          nexpr = WN_kid1(idx_expr);
00301       }
00302       tmp_tokens = New_Token_Buffer();
00303       non_zero = WN2F_Expr_Plus_Literal(tmp_tokens, cexpr, 1LL, context);
00304       if (non_zero)
00305       {
00306          if (parenthesize)
00307          {
00308             reset_WN2F_CONTEXT_no_parenthesis(context);
00309             Append_Token_Special(tokens, '(');
00310          }
00311          WN2F_translate(tokens, nexpr, context);
00312          Append_Token_Special(tokens, '+');
00313          Append_And_Reclaim_Token_List(tokens, &tmp_tokens);
00314          if (parenthesize)
00315             Append_Token_Special(tokens, ')');
00316       }
00317       else
00318       {
00319          Reclaim_Token_Buffer(&tmp_tokens);
00320          WN2F_translate(tokens, nexpr, context);
00321       }
00322    }
00323    else if (WN_opc_operator(idx_expr) == OPR_SUB && 
00324             (WN_is_constant_expr(WN_kid1(idx_expr)) || 
00325              WN_is_constant_expr(WN_kid0(idx_expr))))
00326    {
00327       /* Do the "e-c" ==> "e-(c-1)" or the  "c-e" ==> "(c+1)-e"
00328        * translation.
00329        */
00330       cexpr_is_lhs = WN_is_constant_expr(WN_kid0(idx_expr));
00331       if (!cexpr_is_lhs)
00332       {
00333          cexpr = WN_kid1(idx_expr);
00334          nexpr = WN_kid0(idx_expr);
00335          plus_value = -1LL;
00336       }
00337       else
00338       {
00339          cexpr = WN_kid0(idx_expr);
00340          nexpr = WN_kid1(idx_expr);
00341          plus_value = 1LL;
00342       }
00343         
00344       /* Do the "e-c" ==> "e-(c-1)" or the  "c-e" ==> "(c+1)-e"
00345        * translation.
00346        */
00347       tmp_tokens = New_Token_Buffer();
00348       non_zero = 
00349          WN2F_Expr_Plus_Literal(tmp_tokens, cexpr, plus_value, context);
00350       if (non_zero)
00351       {
00352          if (parenthesize)
00353          {
00354             reset_WN2F_CONTEXT_no_parenthesis(context);
00355             Append_Token_Special(tokens, '(');
00356          }
00357          if (!cexpr_is_lhs)
00358          {
00359             WN2F_translate(tokens, nexpr, context);
00360             Append_Token_Special(tokens, '-');
00361             Append_And_Reclaim_Token_List(tokens, &tmp_tokens);
00362          }
00363          else
00364          {
00365             Append_And_Reclaim_Token_List(tokens, &tmp_tokens);
00366             Append_Token_Special(tokens, '-');
00367             WN2F_translate(tokens, nexpr, context);
00368          }
00369          if (parenthesize)
00370             Append_Token_Special(tokens, ')');
00371       }
00372       else
00373       {
00374          Reclaim_Token_Buffer(&tmp_tokens); 
00375          if (cexpr_is_lhs)
00376          {
00377             if (parenthesize)
00378             {
00379                reset_WN2F_CONTEXT_no_parenthesis(context);
00380                Append_Token_Special(tokens, '(');
00381             }
00382             Append_Token_Special(tokens, '-');
00383             WN2F_translate(tokens, nexpr, context);
00384             if (parenthesize)
00385                Append_Token_Special(tokens, ')');
00386          }
00387          else
00388          {
00389             WN2F_translate(tokens, nexpr, context);
00390          }
00391       }
00392    }
00393    else
00394    {
00395       WN2F_Expr_Plus_Literal(tokens, idx_expr, 1LL, context);
00396    }
00397    return EMPTY_WN2F_STATUS;
00398 } /* WN2F_OLD_Den_Arr_Idx */
00399 
00400 
00401 static WN2F_STATUS
00402 WN2F_Denormalize_Array_Idx(TOKEN_BUFFER tokens, 
00403                            WN          *idx_expr, 
00404                            WN2F_CONTEXT context)
00405 {
00406    const BOOL   parenthesize = !WN2F_CONTEXT_no_parenthesis(context);
00407    TOKEN_BUFFER tmp_tokens;
00408    BOOL         non_zero, cexpr_is_lhs;
00409    WN          *nexpr, *cexpr;
00410    INT64        plus_value;
00411    
00412    /* Given an index expression, translate it to Fortran and append
00413     * the tokens to the given token-buffer.  If the value of the idx
00414     * expression is "v", then the appended tokens should represent
00415     * the value "v+1".  This denormalization moves the base of the
00416     * array from index zero to index one.
00417     */
00418 if (idx_expr==NULL) return EMPTY_WN2F_STATUS;
00419 
00420    if (WN_opc_operator(idx_expr) == OPR_ADD && 
00421        (WN_is_constant_expr(WN_kid1(idx_expr)) || 
00422         WN_is_constant_expr(WN_kid0(idx_expr))))
00423    {
00424       /* Do the "e+c" ==> "e+(c+1)" translation, using the property
00425        * that addition is commutative.
00426        */
00427       if (WN_is_constant_expr(WN_kid1(idx_expr)))
00428       {
00429          cexpr = WN_kid1(idx_expr);
00430          nexpr = WN_kid0(idx_expr);
00431       }
00432       else /* if (WN_is_constant_expr(WN_kid0(idx_expr))) */
00433       {
00434          cexpr = WN_kid0(idx_expr);
00435          nexpr = WN_kid1(idx_expr);
00436       }
00437       tmp_tokens = New_Token_Buffer();
00438       non_zero = WN2F_Expr_Plus_Literal(tmp_tokens, cexpr, 0LL, context);
00439       if (non_zero)
00440       {
00441          if (parenthesize)
00442          {
00443             reset_WN2F_CONTEXT_no_parenthesis(context);
00444             Append_Token_Special(tokens, '(');
00445          }
00446          WN2F_translate(tokens, nexpr, context);
00447          Append_Token_Special(tokens, '+');
00448          Append_And_Reclaim_Token_List(tokens, &tmp_tokens);
00449          if (parenthesize)
00450             Append_Token_Special(tokens, ')');
00451       }
00452       else
00453       {
00454          Reclaim_Token_Buffer(&tmp_tokens);
00455          WN2F_translate(tokens, nexpr, context);
00456       }
00457    }
00458    else if (WN_opc_operator(idx_expr) == OPR_SUB && 
00459             (WN_is_constant_expr(WN_kid1(idx_expr)) || 
00460              WN_is_constant_expr(WN_kid0(idx_expr))))
00461    {
00462       /* Do the "e-c" ==> "e-(c-1)" or the  "c-e" ==> "(c+1)-e"
00463        * translation.
00464        */
00465       cexpr_is_lhs = WN_is_constant_expr(WN_kid0(idx_expr));
00466       if (!cexpr_is_lhs)
00467       {
00468          cexpr = WN_kid1(idx_expr);
00469          nexpr = WN_kid0(idx_expr);
00470          plus_value = 0LL;
00471       }
00472       else
00473       {
00474          cexpr = WN_kid0(idx_expr);
00475          nexpr = WN_kid1(idx_expr);
00476          plus_value = 0LL;
00477       }
00478         
00479       /* Do the "e-c" ==> "e-(c-1)" or the  "c-e" ==> "(c+1)-e"
00480        * translation.
00481        */
00482       tmp_tokens = New_Token_Buffer();
00483       non_zero = 
00484          WN2F_Expr_Plus_Literal(tmp_tokens, cexpr, plus_value, context);
00485       if (non_zero)
00486       {
00487          if (parenthesize)
00488          {
00489             reset_WN2F_CONTEXT_no_parenthesis(context);
00490             Append_Token_Special(tokens, '(');
00491          }
00492          if (!cexpr_is_lhs)
00493          {
00494             WN2F_translate(tokens, nexpr, context);
00495             Append_Token_Special(tokens, '-');
00496             Append_And_Reclaim_Token_List(tokens, &tmp_tokens);
00497          }
00498          else
00499          {
00500             Append_And_Reclaim_Token_List(tokens, &tmp_tokens);
00501             Append_Token_Special(tokens, '-');
00502             WN2F_translate(tokens, nexpr, context);
00503          }
00504          if (parenthesize)
00505             Append_Token_Special(tokens, ')');
00506       }
00507       else
00508       {
00509          Reclaim_Token_Buffer(&tmp_tokens); 
00510          if (cexpr_is_lhs)
00511          {
00512             if (parenthesize)
00513             {
00514                reset_WN2F_CONTEXT_no_parenthesis(context);
00515                Append_Token_Special(tokens, '(');
00516             }
00517             Append_Token_Special(tokens, '-');
00518             WN2F_translate(tokens, nexpr, context);
00519             if (parenthesize)
00520                Append_Token_Special(tokens, ')');
00521          }
00522          else
00523          {
00524             WN2F_translate(tokens, nexpr, context);
00525          }
00526       }
00527    }
00528    else
00529    {
00530       WN2F_Expr_Plus_Literal(tokens, idx_expr, 0LL, context); 
00531    }
00532    return EMPTY_WN2F_STATUS;
00533 } /* WN2F_Denormalize_Array_Idx */
00534 
00535 
00536 static void
00537 WN2F_Normalize_Idx_To_Onedim(TOKEN_BUFFER tokens, 
00538                              WN*          wn,
00539                              WN2F_CONTEXT context)
00540 {
00541    INT32 dim1, dim2;
00542 
00543    /* Parenthesize the normalized index expressions */
00544    reset_WN2F_CONTEXT_no_parenthesis(context);
00545 
00546    for (dim1 = 0; dim1 < WN_num_dim(wn); dim1++)
00547    {
00548       if (dim1 > 0)
00549          Append_Token_Special(tokens, '+');
00550 
00551       /* Multiply the index expression with the product of the sizes
00552        * of subordinate dimensions, where a higher dimension-number
00553        * means a more subordinate dimension.  Do not parenthesize the
00554        * least significant index expression.
00555        */   
00556       if (dim1+1 == WN_num_dim(wn))
00557          set_WN2F_CONTEXT_no_parenthesis(context);
00558       WN2F_Denormalize_Array_Idx(tokens, WN_array_index(wn, dim1), context);
00559       for (dim2 = dim1+1; dim2 < WN_num_dim(wn); dim2++)
00560       {
00561          Append_Token_Special(tokens, '*');
00562          (void)WN2F_translate(tokens, WN_array_dim(wn, dim2), context);
00563       } /*for*/
00564    } /*for*/
00565 } /* WN2F_Normalize_Idx_To_Onedim */
00566 
00567 
00568 static void
00569 WN2F_Substring(TOKEN_BUFFER tokens, 
00570                INT64        string_size,
00571                WN          *lower_bnd,
00572                WN          *substring_size,
00573                WN2F_CONTEXT context)
00574 {
00575    /* Given a substring offset from the base of a character string 
00576     * (lower_bnd), the size of the whole string, and the size of the
00577     * substring, generate the notation necessary as a suffix to the
00578     * string reference to denote the substring.
00579     */
00580    if (WN_opc_operator(lower_bnd) != OPR_INTCONST      ||
00581        WN_const_val(lower_bnd) != 0                    ||
00582        WN_opc_operator(substring_size) != OPR_INTCONST ||
00583        WN_const_val(substring_size) != string_size)
00584    {
00585       /* Need to generate substring expression "(l+1:l+size)" */
00586       Append_Token_Special(tokens, '(');
00587       set_WN2F_CONTEXT_no_parenthesis(context);
00588 /*      WN2F_Denormalize_Array_Idx(tokens, lower_bnd, context);*/
00589 
00590       WN2F_OLD_Den_Arr_Idx(tokens, lower_bnd, context);
00591 
00592       reset_WN2F_CONTEXT_no_parenthesis(context);
00593       Append_Token_Special(tokens, ':');
00594       if (WN_opc_operator(lower_bnd) != OPR_INTCONST ||
00595           WN_const_val(lower_bnd) != 0)
00596       {
00597          WN2F_translate(tokens, lower_bnd, context);
00598          Append_Token_Special(tokens, '+');
00599       }
00600       WN2F_translate(tokens, substring_size, context);
00601       Append_Token_Special(tokens, ')');
00602    }
00603 } /* WN2F_Substring */
00604 
00605 
00606 static void
00607 WN2F_Get_Substring_Info(WN **base,         /* Possibly OPR_ARRAY node (in/out) */
00608                         TY_IDX *string_ty, /* The string type (out) */
00609                         WN **lower_bnd,    /* The lower bound index (out) */
00610                         WN **length )
00611 {
00612    /* There are two possibilities concerning the array base expressions.
00613     * It can be a pointer to a complete character-string (array) or it
00614     * can be a pointer to a character within a character-string (single
00615     * character).  In the first instance, the offset off the base of 
00616     * string is zero.  In the latter case, the offset is given by the
00617     * array indexing operation.
00618     */
00619    TY_IDX ptr_ty = WN_Tree_Type(*base);
00620 
00621    *string_ty = TY_pointed(ptr_ty);
00622 
00623    if (TY_size(*string_ty) == 1 && 
00624        !TY_Is_Array(*string_ty) &&
00625        WN_opc_operator(*base) == OPR_ARRAY)
00626    {
00627       /* Let the base of the string be denoted as the base of the array
00628        * expression.
00629        */
00630       *string_ty = TY_pointed(WN_Tree_Type(WN_kid0(*base)));
00631       *lower_bnd = WN_array_index(*base, 0);
00632       *length    = WN_kid1(*base);
00633       *base = WN_kid0(*base);
00634    }
00635    else if (WN_opc_operator(*base) == OPR_ARRAY &&
00636             TY_Is_Array(*string_ty)             &&
00637             TY_AR_ndims(*string_ty) == 1        &&
00638             TY_Is_Character_String(*string_ty)  &&
00639             !TY_ptr_as_array(Ty_Table[ptr_ty]))
00640    {
00641       /* Presumably, the lower bound is given by the array operator
00642        */
00643       *lower_bnd = WN_array_index(*base, 0);
00644       *length    = WN_kid1(*base);
00645       *base = WN_kid0(*base);
00646    }
00647    else
00648    {
00649       *lower_bnd = WN2F_INTCONST_ZERO;
00650       *length    = WN2F_INTCONST_ZERO;
00651    }
00652 } /* WN2F_Get_Substring_Info */
00653 
00654 static WN *
00655 WN2F_Find_Base(WN *addr)
00656 {
00657   /* utility to find base of address tree */
00658 
00659   WN *res = addr;
00660 
00661   switch (WN_operator(addr))
00662   {
00663     case OPR_ARRAY: 
00664     case OPR_ILOAD:
00665     res=WN_kid0(addr);
00666     break;
00667 
00668     case OPR_ADD:
00669       if (WN_operator(WN_kid0(addr)) == OPR_INTCONST)
00670         res = WN2F_Find_Base(WN_kid1(addr));
00671       else
00672         res = WN2F_Find_Base(WN_kid0(addr));
00673     break;
00674 
00675   default:
00676     res = addr;
00677     break;
00678   }
00679   return res;
00680 }
00681 
00682 extern BOOL
00683 WN2F_Is_Address_Preg(WN * ad ,TY_IDX ptr_ty)
00684 {
00685   /* Does this look like a preg or variable being used as an address ? */
00686   /* These are propagated by opt/pfa                                   */
00687 
00688   BOOL is_somewhat_address_like = TY_kind(ptr_ty) == KIND_POINTER;
00689   
00690   if (TY_kind(ptr_ty) == KIND_SCALAR) 
00691   {
00692     TYPE_ID tid = TY_mtype(ptr_ty);
00693 
00694     is_somewhat_address_like |= (MTYPE_is_pointer(tid)) || (tid == MTYPE_I8) || (tid == MTYPE_I4) ;
00695   }
00696 
00697   if (is_somewhat_address_like)
00698   {
00699     WN * wn = WN2F_Find_Base(ad);
00700     
00701     if (WN_operator(wn) == OPR_LDID) 
00702     {
00703       ST * st = WN_st(wn) ;
00704       if (ST_class(st) == CLASS_PREG)
00705         return TRUE ;
00706       
00707       if (ST_class(st) == CLASS_VAR) 
00708       {
00709         if (TY_kind(ptr_ty) == KIND_SCALAR)
00710           return TRUE;
00711         
00712         if (TY_kind(WN_ty(wn)) == KIND_SCALAR)
00713         {
00714           TYPE_ID wtid = TY_mtype(WN_ty(wn));
00715           
00716           /* Looks like a Cray pointer (I4/I8) ? */
00717           
00718           if ((wtid == MTYPE_I8)|| (wtid == MTYPE_I4))
00719             if (ad != wn)
00720               return TRUE ;
00721           
00722           /* Looks like a VAR with a U4/U8? used  */
00723           /* only with offsets, or FORMALs would  */
00724           /* qualify, if intrinsic mtype          */
00725           
00726           if (MTYPE_is_pointer(wtid))
00727             if (TY_kind(ST_type(st)) != KIND_SCALAR)
00728               return TRUE;
00729         }
00730       }
00731     }
00732   }
00733   return FALSE;
00734 }
00735 
00736 /*---------------------- Prefetching Comments ------------------------*/
00737 /*--------------------------------------------------------------------*/
00738 
00739 static void
00740 WN2F_Append_Prefetch_Map(TOKEN_BUFFER tokens, WN *wn)
00741 {
00742    PF_POINTER* pfptr;
00743    const char *info_str;
00744    
00745    pfptr = (PF_POINTER*)WN_MAP_Get(WN_MAP_PREFETCH, wn);
00746    info_str = "prefetch (ptr, lrnum): ";
00747    if (pfptr->wn_pref_1L)
00748    {
00749       info_str = 
00750          Concat2_Strings(    info_str,
00751           Concat2_Strings(   "1st <", 
00752            Concat2_Strings(  Ptr_as_String(pfptr->wn_pref_1L),
00753             Concat2_Strings( ", ",
00754              Concat2_Strings(WHIRL2F_number_as_name(pfptr->lrnum_1L),
00755                              ">")))));
00756    }
00757    if (pfptr->wn_pref_2L)
00758    {
00759       info_str = 
00760          Concat2_Strings(    info_str,
00761           Concat2_Strings(   "2nd <", 
00762            Concat2_Strings(  Ptr_as_String(pfptr->wn_pref_2L),
00763             Concat2_Strings( ", ",
00764              Concat2_Strings(WHIRL2F_number_as_name(pfptr->lrnum_2L),
00765                              ">")))));
00766    }
00767    Append_Token_String(tokens, info_str);
00768 } /* WN2F_Append_Prefetch_Map */
00769 
00770 
00771 /*----------------------- Exported Functions ------------------------*/
00772 /*--------------------------------------------------------------------*/
00773 
00774 void WN2F_Load_Store_initialize(void)
00775 {
00776    /* Nothing to do at the moment */
00777 } /* WN2F_Load_Store_initialize */
00778 
00779 
00780 void WN2F_Load_Store_finalize(void)
00781 {
00782    /* Nothing to do at the moment */
00783 } /* WN2F_Load_Store_finalize */
00784 
00785 
00786 extern WN2F_STATUS
00787 WN2F_pstore(TOKEN_BUFFER tokens, WN *wn, WN2F_CONTEXT context)
00788 {
00789    TOKEN_BUFFER  lhs_tokens;
00790    TOKEN_BUFFER  rhs_tokens;
00791    TY_IDX        base_ty;
00792    ASSERT_DBG_FATAL(WN_opc_operator(wn) == OPR_PSTORE,
00793                     (DIAG_W2F_UNEXPECTED_OPC, "WN2F_pstore"));
00794 
00795    /* Get the base address into which we are storing a value */
00796    base_ty = WN_Tree_Type(WN_kid1(wn));
00797    if (!TY_Is_Pointer(base_ty))
00798       base_ty = WN_ty(wn);
00799 
00800    /* Get the lhs of the assignment (dereference address) */
00801       lhs_tokens = New_Token_Buffer();
00802 
00803       set_WN2F_CONTEXT_has_no_arr_elmt(context);
00804 
00805       WN2F_Offset_Memref(lhs_tokens,
00806                          WN_kid1(wn),           /* base-symbol */
00807                          base_ty,               /* base-type */
00808                          TY_pointed(WN_ty(wn)), /* object-type */
00809                          WN_store_offset(wn),   /* object-ofst */
00810                          context);
00811       reset_WN2F_CONTEXT_has_no_arr_elmt(context);
00812 
00813    /* The rhs */
00814    rhs_tokens = New_Token_Buffer();
00815    if (TY_is_logical(Ty_Table[TY_pointed(WN_ty(wn))]))
00816    {
00817       set_WN2F_CONTEXT_has_logical_arg(context);
00818       WN2F_translate(rhs_tokens, WN_kid0(wn), context);
00819       reset_WN2F_CONTEXT_has_logical_arg(context);
00820    }
00821    else
00822      {
00823 
00824       WN2F_translate(rhs_tokens, WN_kid0(wn), context);
00825      }
00826 
00827    /* See if we need to apply a "char" conversion to the rhs
00828     */
00829    if (TY_Is_Character_String(W2F_TY_pointed(WN_ty(wn), "PSTORE lhs")) &&
00830        TY_Is_Integral(WN_Tree_Type(WN_kid0(wn))))
00831    {
00832      
00833       Prepend_Token_Special(rhs_tokens, '(');
00834       Prepend_Token_String(rhs_tokens, "char");
00835       Append_Token_Special(rhs_tokens, ')');
00836    }
00837 
00838    /* Assign the rhs to the lhs.
00839     */
00840    if (Identical_Token_Lists(lhs_tokens, rhs_tokens))
00841    {
00842       /* Ignore this redundant assignment statement! */
00843       Reclaim_Token_Buffer(&lhs_tokens);
00844       Reclaim_Token_Buffer(&rhs_tokens);
00845    }
00846    else
00847    {
00848       /* See if there is any prefetch information with this store,
00849        * and if so insert information about it as a comment preceeding
00850        * the store.
00851        */
00852       if (W2F_Emit_Prefetch && WN_MAP_Get(WN_MAP_PREFETCH, wn))
00853       {
00854          Append_F77_Comment_Newline(tokens, 1, TRUE/*indent*/);
00855          WN2F_Append_Prefetch_Map(tokens, wn);
00856       }
00857 
00858       /* The assignment statement on a new line */
00859       WN2F_Stmt_Newline(tokens, NULL/*label*/, WN_linenum(wn), context);
00860       Append_And_Reclaim_Token_List(tokens, &lhs_tokens);
00861       Append_Token_String(tokens,"=>");
00862       Append_And_Reclaim_Token_List(tokens, &rhs_tokens);
00863    }
00864 
00865    return EMPTY_WN2F_STATUS;
00866 } /* WN2F_pstore */
00867 
00868 extern WN2F_STATUS 
00869 WN2F_istore(TOKEN_BUFFER tokens, WN *wn, WN2F_CONTEXT context)
00870 {
00871    TOKEN_BUFFER  lhs_tokens;
00872    TOKEN_BUFFER  rhs_tokens;
00873    TY_IDX        base_ty;
00874    TY_IDX        object_ty;
00875    
00876    ASSERT_DBG_FATAL(WN_opc_operator(wn) == OPR_ISTORE, 
00877                     (DIAG_W2F_UNEXPECTED_OPC, "WN2F_istore"));
00878 
00879    /* Get the base address into which we are storing a value */
00880    base_ty = WN_Tree_Type(WN_kid1(wn));
00881    object_ty = TY_pointed(WN_ty(wn));
00882 
00883    if (!TY_Is_Pointer(base_ty))
00884       base_ty = WN_ty(wn);
00885 
00886 //For pointer PP(:,...,:)
00887    if (TY_kind(TY_pointed(base_ty))==KIND_POINTER &&
00888         TY_is_f90_deferred_shape(TY_pointed(base_ty))) 
00889             base_ty = TY_pointed(base_ty);
00890 
00891    if (TY_kind(object_ty)==KIND_POINTER &&
00892         TY_is_f90_deferred_shape(object_ty)) 
00893             object_ty = TY_pointed(object_ty);
00894 
00895    /* Get the lhs of the assignment (dereference address) */
00896    lhs_tokens = New_Token_Buffer();
00897    if (WN_operator(WN_kid1(wn)) == OPR_LDA ||
00898        WN_operator(WN_kid1(wn)) == OPR_LDID )
00899             set_WN2F_CONTEXT_has_no_arr_elmt(context);
00900 #if 0 
00901    WN2F_Offset_Memref(lhs_tokens, 
00902                       WN_kid1(wn),           /* base-symbol */
00903                       base_ty,               /* base-type */
00904                       object_ty, /* object-type */
00905                       WN_store_offset(wn),   /* object-ofst */
00906                       context);
00907 #else 
00908       WN2F_translate(lhs_tokens, WN_kid1(wn), context);
00909 #endif
00910 
00911     reset_WN2F_CONTEXT_has_no_arr_elmt(context); 
00912 
00913    /* The rhs */
00914    rhs_tokens = New_Token_Buffer();
00915 
00916    if (TY_is_logical(Ty_Table[TY_pointed(WN_ty(wn))]))
00917    {
00918       set_WN2F_CONTEXT_has_logical_arg(context);
00919       WN2F_translate(rhs_tokens, WN_kid0(wn), context);
00920       reset_WN2F_CONTEXT_has_logical_arg(context);
00921    }
00922    else
00923       WN2F_translate(rhs_tokens, WN_kid0(wn), context);
00924 
00925    /* See if we need to apply a "char" conversion to the rhs
00926     */
00927 #if 0 
00928    if (TY_Is_Character_String(W2F_TY_pointed(WN_ty(wn), "ISTORE lhs")) &&
00929        TY_Is_Integral(WN_Tree_Type(WN_kid0(wn))))
00930    {
00931       Prepend_Token_Special(rhs_tokens, '(');
00932       Prepend_Token_String(rhs_tokens, "char");
00933       Append_Token_Special(rhs_tokens, ')');
00934    }
00935 #endif
00936 
00937    /* Assign the rhs to the lhs.
00938     */
00939    if (Identical_Token_Lists(lhs_tokens, rhs_tokens))
00940    {
00941       /* Ignore this redundant assignment statement! */
00942       Reclaim_Token_Buffer(&lhs_tokens);
00943       Reclaim_Token_Buffer(&rhs_tokens);
00944    }
00945    else
00946    {
00947       /* See if there is any prefetch information with this store,
00948        * and if so insert information about it as a comment preceeding
00949        * the store.
00950        */
00951       if (W2F_Emit_Prefetch && WN_MAP_Get(WN_MAP_PREFETCH, wn))
00952       {
00953          Append_F77_Comment_Newline(tokens, 1, TRUE/*indent*/);
00954          WN2F_Append_Prefetch_Map(tokens, wn);
00955       }
00956 
00957       /* The assignment statement on a new line */
00958       WN2F_Stmt_Newline(tokens, NULL/*label*/, WN_linenum(wn), context);
00959       Append_And_Reclaim_Token_List(tokens, &lhs_tokens);
00960       Append_Token_Special(tokens, '=');
00961       Append_And_Reclaim_Token_List(tokens, &rhs_tokens);
00962    }
00963 
00964    fld_type_z = 0;
00965 
00966    return EMPTY_WN2F_STATUS;
00967 } /* WN2F_istore */
00968 
00969 WN2F_STATUS 
00970 WN2F_istorex(TOKEN_BUFFER tokens, WN *wn, WN2F_CONTEXT context)
00971 {
00972    ASSERT_DBG_WARN(FALSE, (DIAG_UNIMPLEMENTED, "WN2F_istorex"));
00973    WN2F_Stmt_Newline(tokens, NULL/*label*/, WN_linenum(wn), context);
00974    Append_Token_String(tokens, WN_opc_name(wn));
00975 
00976    return EMPTY_WN2F_STATUS;
00977 } /* WN2F_istorex */
00978 
00979 WN2F_STATUS 
00980 WN2F_mstore(TOKEN_BUFFER tokens, WN *wn, WN2F_CONTEXT context)
00981 {
00982    TOKEN_BUFFER  lhs_tokens;
00983    TOKEN_BUFFER  rhs_tokens;
00984    TY_IDX        base_ty;
00985 
00986    /* Note that we make the assumption that this is just like an 
00987     * ISTORE, and handle it as though it were.  We do not handle
00988     * specially assignment-forms where the lhs is incompatible with
00989     * the rhs, since we assume this will never happen for Fortran
00990     * and we cannot easily get around this like we do in C (i.e.
00991     * with cast expressions.
00992     */
00993    ASSERT_DBG_FATAL(WN_opc_operator(wn) == OPR_MSTORE, 
00994                     (DIAG_W2F_UNEXPECTED_OPC, "WN2F_mstore"));
00995 #if 0
00996    ASSERT_DBG_WARN(WN_opc_operator(WN_kid0(wn)) == OPR_MLOAD,
00997                     (DIAG_W2F_UNEXPECTED_OPC, "rhs of WN2F_mstore"));
00998 
00999    //TODO: scalar expression allowed, but array/structure assignment assumed
01000    // with constant ie: should put out doloop?... call OFFSET_Memref?
01001 #endif
01002 
01003    /* Get the base address into which we are storing a value */
01004    base_ty = WN_Tree_Type(WN_kid1(wn));
01005    if (!TY_Is_Pointer(base_ty))
01006       base_ty = WN_ty(wn);
01007 
01008    /* Get the lhs of the assignment (dereference address) */
01009    lhs_tokens = New_Token_Buffer();
01010 #if 0  
01011    WN2F_Offset_Memref(lhs_tokens, 
01012                       WN_kid1(wn),           /* base-symbol */
01013                       base_ty,               /* base-type */
01014                       TY_pointed(WN_ty(wn)), /* object-type */
01015                       WN_store_offset(wn),   /* object-ofst */
01016                       context);
01017 #else
01018    WN2F_translate(lhs_tokens, WN_kid1(wn), context);
01019 #endif 
01020    
01021    
01022    /* The rhs */
01023    rhs_tokens = New_Token_Buffer();
01024    WN2F_translate(rhs_tokens, WN_kid0(wn), context);
01025 
01026    /* Assign the rhs to the lhs.
01027     */
01028    if (Identical_Token_Lists(lhs_tokens, rhs_tokens))
01029    {
01030       /* Ignore this redundant assignment statement! */
01031       Reclaim_Token_Buffer(&lhs_tokens);
01032       Reclaim_Token_Buffer(&rhs_tokens);
01033    }
01034    else
01035    {
01036       /* The assignment statement on a new line */
01037       WN2F_Stmt_Newline(tokens, NULL/*label*/, WN_linenum(wn), context);
01038       Append_And_Reclaim_Token_List(tokens, &lhs_tokens);
01039       Append_Token_Special(tokens, '=');
01040       Append_And_Reclaim_Token_List(tokens, &rhs_tokens);
01041    }
01042 
01043 
01044    return EMPTY_WN2F_STATUS;
01045 } /* WN2F_mstore */
01046 
01047 WN2F_STATUS 
01048 WN2F_stid(TOKEN_BUFFER tokens, WN *wn, WN2F_CONTEXT context)
01049 {
01050    TOKEN_BUFFER lhs_tokens, rhs_tokens;
01051    const BOOL parenthesize = !WN2F_CONTEXT_no_parenthesis(context);
01052    TY_IDX base_ty;
01053    TY_IDX object_ty;
01054 
01055 
01056     if (parenthesize)
01057        set_WN2F_CONTEXT_no_parenthesis(context);
01058    
01059    ASSERT_DBG_FATAL(WN_opc_operator(wn) == OPR_STID, 
01060                     (DIAG_W2F_UNEXPECTED_OPC, "WN2F_stid"));
01061 
01062    if (W2F_OpenAD 
01063        && 
01064        ST_is_temp_var(WN_st(wn))
01065        && 
01066        (
01067         strncmp("select_expr_",ST_name(WN_st(wn)),12)!=0
01068         && 
01069         !ST_keep_in_openad(WN_st(wn))))
01070       // emit assignments for symbols marked as to be kept and values of select expressions.
01071       // the hard coded name (see cwg_stmt.cxx:2271) 
01072       // is awful but not particularly worse than the other 
01073       // hacks done for select constructs
01074     return EMPTY_WN2F_STATUS;
01075 
01076    /* Get the lhs of the assignment */
01077    lhs_tokens = New_Token_Buffer();
01078    if (ST_class(WN_st(wn)) == CLASS_PREG)
01079    {
01080       ST2F_Use_Preg(lhs_tokens, ST_type(WN_st(wn)), WN_store_offset(wn));
01081    }
01082    else if (ST_sym_class(WN_st(wn))==CLASS_VAR && ST_is_not_used(WN_st(wn)))
01083    {
01084       /* This is a redundant assignment statement, so determined
01085        * by IPA, so just assign it to a temporary variable
01086        * instead.
01087        */
01088       UINT tmp_idx = Stab_Lock_Tmpvar(WN_ty(wn), &ST2F_Declare_Tempvar);
01089       Append_Token_String(lhs_tokens, W2CF_Symtab_Nameof_Tempvar(tmp_idx));
01090       Stab_Unlock_Tmpvar(tmp_idx);
01091    }
01092    else
01093    {
01094       base_ty = ST_type(WN_st(wn));
01095       if (TY_kind(base_ty)==KIND_POINTER &&
01096           TY_is_f90_pointer(base_ty)) 
01097          ;
01098       else
01099           base_ty = Stab_Pointer_To(base_ty);
01100 
01101       object_ty = WN_ty(wn);
01102       if ((TY_kind(object_ty)==KIND_POINTER) &&
01103           ( TY_is_f90_pointer(object_ty)))
01104            object_ty = TY_pointed(object_ty);
01105    
01106       WN2F_Offset_Symref(lhs_tokens, 
01107                          WN_st(wn),                        /* base-symbol */
01108                          base_ty,                          /* base_type   */
01109                          object_ty,                        /* object-type */
01110                          WN_store_offset(wn),              /* object-ofst */
01111                          context);
01112    }
01113    
01114    /* The rhs */
01115    rhs_tokens = New_Token_Buffer();
01116 
01117 //   const BOOL p11arenthesize = !WN2F_CONTEXT_no_parenthesis(context);
01118 
01119    if (TY_is_logical(Ty_Table[WN_ty(wn)]))
01120    {
01121       set_WN2F_CONTEXT_has_logical_arg(context);
01122       WN2F_translate(rhs_tokens, WN_kid0(wn), context);
01123       reset_WN2F_CONTEXT_has_logical_arg(context);
01124    }
01125    else {
01126     
01127 //      set_WN2F_CONTEXT_no_parenthesis(context);
01128       WN2F_translate(rhs_tokens, WN_kid0(wn), context);
01129 //      reset_WN2F_CONTEXT_no_parenthesis(context);
01130      }
01131 
01132    /* See if we need to apply a "char" conversion to the rhs
01133     */
01134 
01135    if (TY_Is_Character_String(WN_ty(wn)) && 
01136        TY_Is_Integral(WN_Tree_Type(WN_kid0(wn))))
01137    {
01138       Prepend_Token_Special(rhs_tokens, '(');
01139       Prepend_Token_String(rhs_tokens, "char");
01140       Append_Token_Special(rhs_tokens, ')');
01141    }
01142 
01143    /* Assign the rhs to the lhs.
01144     */
01145 
01146 
01147    if (!WN2F_CONTEXT_emit_stid(context) &&
01148        Identical_Token_Lists(lhs_tokens, rhs_tokens))
01149    {
01150       /* Ignore this redundant assignment statement! */
01151       Reclaim_Token_Buffer(&lhs_tokens);
01152       Reclaim_Token_Buffer(&rhs_tokens);
01153    }
01154    else
01155    { 
01156       /* The assignment statement on a new line */
01157       WN2F_Stmt_Newline(tokens, NULL/*label*/, WN_linenum(wn), context);
01158       Append_And_Reclaim_Token_List(tokens, &lhs_tokens);
01159       Append_Token_Special(tokens, '=');
01160       Append_And_Reclaim_Token_List(tokens, &rhs_tokens);
01161    }
01162 
01163 
01164    return EMPTY_WN2F_STATUS;
01165 } /* WN2F_stid */
01166 
01167 
01168 WN2F_STATUS
01169 WN2F_pstid(TOKEN_BUFFER tokens, WN *wn, WN2F_CONTEXT context)
01170 {
01171    TOKEN_BUFFER lhs_tokens, rhs_tokens;
01172 
01173    ASSERT_DBG_FATAL(WN_opc_operator(wn) == OPR_PSTID,
01174                     (DIAG_W2F_UNEXPECTED_OPC, "WN2F_pstid"));
01175 
01176    /* Get the lhs of the assignment */
01177    lhs_tokens = New_Token_Buffer();
01178    if (ST_class(WN_st(wn)) == CLASS_PREG)
01179    {
01180       ST2F_Use_Preg(lhs_tokens, ST_type(WN_st(wn)), WN_store_offset(wn));
01181    }
01182    else if (ST_sym_class(WN_st(wn))==CLASS_VAR && ST_is_not_used(WN_st(wn)))
01183    {
01184       /* This is a redundant assignment statement, so determined
01185        * by IPA, so just assign it to a temporary variable
01186        * instead.
01187        */
01188       UINT tmp_idx = Stab_Lock_Tmpvar(WN_ty(wn), &ST2F_Declare_Tempvar);
01189       Append_Token_String(lhs_tokens, W2CF_Symtab_Nameof_Tempvar(tmp_idx));
01190       Stab_Unlock_Tmpvar(tmp_idx);
01191    }
01192    else
01193    {
01194       WN2F_Offset_Symref(lhs_tokens,
01195                          WN_st(wn),                        /* base-symbol */
01196                          Stab_Pointer_To(ST_type(WN_st(wn))),/* base-type */
01197                          WN_ty(wn),                        /* object-type */
01198                          WN_store_offset(wn),              /* object-ofst */
01199                          context);
01200    }
01201 
01202    /* The rhs */
01203    rhs_tokens = New_Token_Buffer();
01204    if (TY_is_logical(Ty_Table[WN_ty(wn)]))
01205    {
01206       set_WN2F_CONTEXT_has_logical_arg(context);
01207       WN2F_translate(rhs_tokens, WN_kid0(wn), context);
01208       reset_WN2F_CONTEXT_has_logical_arg(context);
01209    }
01210    else
01211       WN2F_translate(rhs_tokens, WN_kid0(wn), context);
01212 
01213    /* See if we need to apply a "char" conversion to the rhs
01214     */
01215    if (TY_Is_Character_String(WN_ty(wn)) &&
01216        TY_Is_Integral(WN_Tree_Type(WN_kid0(wn))))
01217    {
01218       Prepend_Token_Special(rhs_tokens, '(');
01219       Prepend_Token_String(rhs_tokens, "char");
01220       Append_Token_Special(rhs_tokens, ')');
01221    }
01222 
01223    /* Assign the rhs to the lhs.
01224     */
01225    if (!WN2F_CONTEXT_emit_stid(context) &&
01226        Identical_Token_Lists(lhs_tokens, rhs_tokens))
01227    {
01228       /* Ignore this redundant assignment statement! */
01229       Reclaim_Token_Buffer(&lhs_tokens);
01230       Reclaim_Token_Buffer(&rhs_tokens);
01231    }
01232    else
01233    {
01234       /* The assignment statement on a new line */
01235       WN2F_Stmt_Newline(tokens, NULL/*label*/, WN_linenum(wn), context);
01236       Append_And_Reclaim_Token_List(tokens, &lhs_tokens);
01237       Append_Token_String(tokens,"=>");
01238       Append_And_Reclaim_Token_List(tokens, &rhs_tokens);
01239    }
01240 
01241    return EMPTY_WN2F_STATUS;
01242 } /* WN2F_pstid */
01243 
01244 
01245 WN2F_STATUS 
01246 WN2F_iload(TOKEN_BUFFER tokens, WN *wn, WN2F_CONTEXT context)
01247 {
01248    TY_IDX base_ty;
01249    TY_IDX object_ty;
01250    
01251    /* Note that we handle this just like we do the lhs of an ISTORE.
01252     */
01253    ASSERT_DBG_FATAL(WN_opc_operator(wn) == OPR_ILOAD, 
01254                     (DIAG_W2F_UNEXPECTED_OPC, "WN2F_iload"));
01255 
01256   
01257    if (WN_operator(WN_kid0(wn))==OPR_STRCTFLD){ //place-hold for pointer field
01258          WN2F_translate(tokens, WN_kid0(wn), context);   
01259          return EMPTY_WN2F_STATUS;
01260      }
01261 
01262    /* Special case for Purple (address values have no meaning, so emit
01263     * symbolic values for them).
01264     */
01265    if (W2F_Only_Mark_Loads && !TY_Is_Pointer(WN_ty(wn)))
01266    {
01267       char buf[64];
01268       sprintf(buf, "#<%p>#", wn);
01269       Append_Token_String(tokens, buf);
01270       return EMPTY_WN2F_STATUS;
01271    }
01272 
01273    /* Get the type of the base from which we are loading */
01274    base_ty = WN_Tree_Type(WN_kid0(wn));
01275    object_ty = TY_pointed(WN_load_addr_ty(wn));
01276 
01277    if (!TY_Is_Pointer(base_ty))
01278       base_ty = WN_load_addr_ty(wn);
01279     
01280     /*For pointer PP(:,...,:) */
01281    if (TY_kind(TY_pointed(base_ty))==KIND_POINTER &&
01282         TY_is_f90_deferred_shape(TY_pointed(base_ty))) 
01283             base_ty = TY_pointed(base_ty);
01284 
01285    if (TY_kind(object_ty)==KIND_POINTER &&
01286         TY_is_f90_deferred_shape(object_ty)) 
01287             object_ty = TY_pointed(object_ty);
01288     
01289    /* Get the object to be loaded (dereference address) */
01290    if (WN_opc_operator(WN_kid0(wn)) == OPR_LDA ||
01291        WN_opc_operator(WN_kid0(wn)) == OPR_LDID)
01292           set_WN2F_CONTEXT_has_no_arr_elmt(context);
01293 #if 0 
01294    WN2F_Offset_Memref(tokens, 
01295                       WN_kid0(wn),                     /* base-symbol */
01296                       base_ty,                         /* base-type */
01297                       object_ty,                       /* object-type */
01298                       WN_load_offset(wn),              /* object-ofst */
01299                       context);
01300 #else 
01301          WN2F_translate(tokens, WN_kid0(wn), context);   
01302 #endif
01303     reset_WN2F_CONTEXT_has_no_arr_elmt(context);
01304 
01305    /* See if there is any prefetch information with this load, and 
01306     * if so insert information about it as a comment on a separate
01307     * continuation line.
01308     */
01309    if (W2F_Emit_Prefetch && WN_MAP_Get(WN_MAP_PREFETCH, wn))
01310    {
01311       Set_Current_Indentation(Current_Indentation()+3);
01312       Append_F77_Indented_Continuation(tokens);
01313       Append_Token_Special(tokens, '!');
01314       WN2F_Append_Prefetch_Map(tokens, wn);
01315       Set_Current_Indentation(Current_Indentation()-3); 
01316       Append_F77_Indented_Continuation(tokens);
01317    }
01318    
01319    return EMPTY_WN2F_STATUS;
01320 } /* WN2F_iload */
01321 
01322 WN2F_STATUS 
01323 WN2F_iloadx(TOKEN_BUFFER tokens, WN *wn, WN2F_CONTEXT context)
01324 {
01325    ASSERT_DBG_WARN(FALSE, (DIAG_UNIMPLEMENTED, "WN2F_iloadx"));
01326    Append_Token_String(tokens, WN_opc_name(wn));
01327 
01328    return EMPTY_WN2F_STATUS;
01329 } /* WN2F_iloadx */
01330 
01331 
01332 WN2F_STATUS 
01333 WN2F_mload(TOKEN_BUFFER tokens, WN *wn, WN2F_CONTEXT context)
01334 {
01335    TY_IDX base_ty;
01336    
01337    /* This should only appear the as the rhs of an ISTORE.  Treat
01338     * it just like an ILOAD.
01339     */
01340    ASSERT_DBG_FATAL(WN_opc_operator(wn) == OPR_MLOAD, 
01341                     (DIAG_W2F_UNEXPECTED_OPC, "WN2F_mload"));
01342 
01343    /* Special case for Purple (cannot be a pointer value) */
01344    if (W2F_Only_Mark_Loads)
01345    {
01346       char buf[64];
01347       sprintf(buf, "#<%p>#", wn);
01348       Append_Token_String(tokens, buf);
01349       return EMPTY_WN2F_STATUS;
01350    }
01351 
01352    /* Get the type of the base from which we are loading */
01353    base_ty = WN_Tree_Type(WN_kid0(wn));
01354    if (!TY_Is_Pointer(base_ty))
01355       base_ty = WN_ty(wn);
01356 
01357    /* Get the object to be loaded */
01358    WN2F_Offset_Memref(tokens, 
01359                       WN_kid0(wn),                     /* base-symbol */
01360                       base_ty,                         /* base-type */
01361                       TY_pointed(WN_ty(wn)), /* object-type */
01362                       WN_load_offset(wn),              /* object-ofst */
01363                       context);
01364    return EMPTY_WN2F_STATUS;
01365 } /* WN2F_mload */
01366 
01367 
01368 WN2F_STATUS 
01369 WN2F_ldid(TOKEN_BUFFER tokens, WN *wn, WN2F_CONTEXT context)
01370 {
01371    const BOOL deref = WN2F_CONTEXT_deref_addr(context);
01372    TY_IDX    base_ptr_ty;
01373    TY_IDX    object_ty;
01374    
01375    ASSERT_DBG_FATAL(WN_opc_operator(wn) == OPR_LDID, 
01376                     (DIAG_W2F_UNEXPECTED_OPC, "WN2F_ldid"));
01377 
01378    /* Special recognition of a LEN intrinsic call
01379     */
01380    if (WN_load_offset(wn) == 0             &&
01381        TY_Is_Integral(WN_ty(wn))           &&
01382        ST_sclass(WN_st(wn))==SCLASS_FORMAL &&
01383        ST_is_value_parm(WN_st(wn))         &&
01384        strncmp(ST_name(WN_st(wn)), ".length.", strlen(".length.")) == 0)
01385    {
01386       /* Search the current PU parameters for a name that matches the
01387        * part of the ST_name that follows the ".length." prefix.
01388        */
01389       ST *st_param = 
01390          WN2F_Get_Named_Param(PUinfo_current_func,
01391                               ST_name(WN_st(wn)) + strlen(".length."));
01392 
01393       if (st_param != NULL)
01394       {
01395          WN2F_Translate_StringLEN(tokens, st_param);
01396          return EMPTY_WN2F_STATUS;
01397       }
01398    }
01399 
01400    /* Special case for Purple direct loads, except direct loads of
01401     * addresses (address values have no meaning in the purple output).
01402     */
01403    if (W2F_Only_Mark_Loads && !TY_Is_Pointer(WN_ty(wn)))
01404    {
01405       char buf[64];
01406       sprintf(buf, "#<%p>#", wn);
01407       Append_Token_String(tokens, buf);
01408       return EMPTY_WN2F_STATUS;
01409    }
01410 
01411    if (ST_class(WN_st(wn)) == CLASS_PREG ) 
01412    {
01413       char buffer[64];
01414       STAB_OFFSET addr_offset = WN_load_offset(wn);
01415       object_ty = PUinfo_Preg_Type(ST_type(WN_st(wn)), addr_offset);
01416 
01417 
01418       if (addr_offset == -1 ) {
01419          switch (TY_mtype(Ty_Table[WN_ty(wn)])) {
01420          case MTYPE_I8:
01421          case MTYPE_U8:
01422          case MTYPE_I1:
01423          case MTYPE_I2:
01424          case MTYPE_I4:
01425          case MTYPE_U1:
01426          case MTYPE_U2:
01427          case MTYPE_U4:
01428             sprintf(buffer, "reg%d", First_Int_Preg_Return_Offset);
01429             Append_Token_String(tokens, buffer);
01430             break;
01431          case MTYPE_F4:
01432          case MTYPE_F8:
01433          case MTYPE_FQ:
01434          case MTYPE_C4:
01435          case MTYPE_C8:
01436          case MTYPE_CQ:
01437             sprintf(buffer, "reg%d", First_Float_Preg_Return_Offset);
01438             Append_Token_String(tokens, buffer);
01439             break;
01440          case MTYPE_M:
01441             Fail_FmtAssertion ("MLDID of Return_Val_Preg not allowed in middle"
01442                " of expression");
01443             break;
01444          default:
01445             Fail_FmtAssertion ("Unexpected type in WN2C_ldid()");
01446             break;
01447          } 
01448       }
01449       else  
01450       {
01451          ST2F_Use_Preg(tokens, ST_type(WN_st(wn)), WN_load_offset(wn));
01452       } 
01453    } 
01454    else     
01455    {
01456       /* Get the base and object type symbols.
01457        */
01458       if (deref && TY_Is_Pointer(ST_type(WN_st(wn))))
01459       {
01460          /* Expect the loaded type to be a pointer to the type of object
01461           * to be dereferenced.  The only place (besides declaration sites)
01462           * where we expect to have to specially handle ptr_as_array 
01463           * objects.
01464           */
01465          if (TY_ptr_as_array(Ty_Table[WN_ty(wn)]))
01466             object_ty = Stab_Array_Of(TY_pointed(WN_ty(wn)), 0/*size*/);
01467          else
01468             object_ty = TY_pointed(WN_ty(wn));
01469 
01470          /* There are two possibilities for the base type:  A regular 
01471           * pointer or a pointer to be treated as a pointer to an array.
01472           * In either case, the "base_ptr_ty" is a pointer to the 
01473           * derefenced base type.  
01474           *
01475           * Note that this does not handle a pointer to a struct to be
01476           * treated as an array of structs, where the object type and
01477           * offset denote a member of the struct, since WN2F_Offset_Symref() 
01478           * cannot access a struct member through an array access.
01479           */
01480          if (TY_ptr_as_array(Ty_Table[ST_type(WN_st(wn))]))
01481             base_ptr_ty = 
01482                Stab_Pointer_To(Stab_Array_Of(TY_pointed(ST_type(WN_st(wn))),
01483                                                         0/*size*/));
01484          else
01485             base_ptr_ty = ST_type(WN_st(wn));
01486       }
01487       else
01488       {
01489          /* Either not a dereference, or possibly a dereference off a 
01490           * record/map/common/equivalence field.  The base symbol is
01491           * not a pointer, and any dereferencing on a field will occur
01492           * in WN2F_Offset_Symref().
01493           */
01494          object_ty = WN_ty(wn);
01495          if ((TY_kind(object_ty)==KIND_POINTER) &&
01496               (TY_is_f90_pointer(object_ty)))
01497                   object_ty = TY_pointed(object_ty);
01498 
01499          base_ptr_ty = ST_type(WN_st(wn));
01500          if ((TY_kind(base_ptr_ty)==KIND_POINTER) &&
01501               (TY_is_f90_pointer(base_ptr_ty)))
01502                  ;
01503          else 
01504              base_ptr_ty = Stab_Pointer_To(base_ptr_ty);
01505       }
01506 
01507       if (!deref && STAB_IS_POINTER_REF_PARAM(WN_st(wn)))
01508       {
01509          /* Since we do not wish to dereference a load of a reference 
01510           * parameter, this must mean we are taking the address of the
01511           * parameter.
01512           */
01513 
01514       }
01515       set_WN2F_CONTEXT_has_no_arr_elmt(context);
01516       WN2F_Offset_Symref(tokens, 
01517                          WN_st(wn),           /* base-symbol */
01518                          base_ptr_ty,         /* base-type */
01519                          object_ty,           /* object-type */
01520                          WN_load_offset(wn),  /* object-ofst */
01521                          context);
01522       reset_WN2F_CONTEXT_has_no_arr_elmt(context);
01523 
01524       if (!deref && STAB_IS_POINTER_REF_PARAM(WN_st(wn)))
01525       {
01526       }
01527    }
01528    return EMPTY_WN2F_STATUS;
01529 } /* WN2F_ldid */
01530 
01531 
01532 WN2F_STATUS 
01533 WN2F_lda(TOKEN_BUFFER tokens, WN *wn, WN2F_CONTEXT context)
01534 {
01535   const BOOL deref = WN2F_CONTEXT_deref_addr(context);
01536   
01537   ASSERT_DBG_FATAL(WN_opc_operator(wn) == OPR_LDA, 
01538                    (DIAG_W2F_UNEXPECTED_OPC, "WN2F_lda"));
01539   ASSERT_DBG_FATAL(ST_class(WN_st(wn)) != CLASS_PREG, 
01540                    (DIAG_W2F_CANNOT_LDA_PREG));
01541 
01542   TY_IDX object_ty;
01543   
01544   if (!deref)
01545     {
01546       /* A true address-of operation */
01547       set_WN2F_CONTEXT_no_parenthesis(context);
01548     }
01549   
01550   /* Sometimes we need to deal with buggy WHIRL code, where the TY
01551    * associated with an LDA is not a pointer type.  For such cases
01552    * we infer a type here.
01553    */
01554 
01555   if (TY_Is_Pointer(WN_ty(wn)) )
01556     {
01557       object_ty = TY_pointed(WN_ty(wn));
01558     }
01559   else
01560     {
01561       /* May be wrong, but the best we can do under these exceptional */
01562       /* circumstances. */
01563         
01564       object_ty = ST_type(WN_st(wn));
01565     }
01566 
01567 
01568   ST * st = WN_st(wn);
01569   TY_IDX ty ;
01570   TY_IDX ty_1;
01571   reset_WN2F_CONTEXT_deref_addr(context);
01572 
01573   if (ST_sym_class(st) == CLASS_BLOCK)
01574   {
01575     WN2F_Block(tokens,st,WN_lda_offset(wn),context);
01576   }
01577   else 
01578   {
01579     if (TY_is_f90_pointer(ST_type(st)))
01580          ty_1= TY_pointed(ST_type(st));
01581     else
01582          ty_1= ST_type(st);
01583      ty =  Stab_Pointer_To(ty_1);
01584 
01585    set_WN2F_CONTEXT_has_no_arr_elmt(context);
01586     WN2F_Offset_Symref(tokens, 
01587                        WN_st(wn),                           /* base-symbol */
01588                        ty,                                  /* base type   */
01589                        object_ty,                           /* object-type */
01590                        WN_lda_offset(wn),                   /* object-ofst */
01591                        context);
01592     reset_WN2F_CONTEXT_has_no_arr_elmt(context);
01593   }
01594 
01595   return EMPTY_WN2F_STATUS;
01596 } /* WN2F_lda */
01597 
01598  WN2F_STATUS
01599  WN2F_arrayexp(TOKEN_BUFFER tokens, WN *wn, WN2F_CONTEXT context)
01600 {
01601  WN    * kid;
01602  kid    = WN_kid0(wn);
01603  WN2F_translate(tokens, kid, context);
01604 
01605 return EMPTY_WN2F_STATUS;
01606 }
01607 
01608 /******************************************************************************\
01609 |*                                                                            *|
01610 |* for array section triplet node,kid0 is lower bound,it should plus 1LL for  *|
01611 |* adjusted bound,upper bound=kid0+k1*k2                                      *|
01612 |* kid0 evaluates to the starting integer value of the progression.           *|
01613 |* kid1 evaluates to an integer value that gives the stride in the progression*|
01614 |* kid2 evaluates to the number of values in the progression                  *|
01615 |*                                                                            *|
01616 \******************************************************************************/
01617  
01618 WN2F_STATUS
01619 WN2F_triplet(TOKEN_BUFFER tokens, WN *wn, WN2F_CONTEXT context)
01620 {
01621    WN      *kid0;
01622    WN      *kid1;
01623    WN      *kid2;
01624   kid0=WN_kid0(wn);
01625   kid1=WN_kid1(wn);
01626   kid2=WN_kid2(wn);
01627   (void)WN2F_Denormalize_Array_Idx(tokens,kid0,context);
01628  if ((WN_opc_operator(kid2) == OPR_INTCONST) &&
01629      (WN_const_val(kid2)==INT_MIN) )
01630    Append_Token_Special(tokens, ':');
01631  else  {
01632   Append_Token_Special(tokens, ':');
01633   if (WN_opc_operator(kid0) == OPR_INTCONST &&
01634       WN_opc_operator(kid1) == OPR_INTCONST &&
01635       WN_opc_operator(kid2) == OPR_INTCONST) {
01636      if ((WN_const_val(kid0)+WN_const_val(kid2)*WN_const_val(kid1))>=INT_MAX)
01637        TCON2F_translate(tokens,
01638                  Host_To_Targ(MTYPE_I8,   
01639                        WN_const_val(kid0)+
01640                        WN_const_val(kid2)*
01641                        WN_const_val(kid1)),
01642                       FALSE);
01643     else    
01644 
01645       TCON2F_translate(tokens,
01646                  Host_To_Targ(MTYPE_I4,   
01647                        WN_const_val(kid0)+
01648                        WN_const_val(kid2)*
01649                        WN_const_val(kid1)),
01650                       FALSE);
01651 
01652    } 
01653    else 
01654        if (WN_opc_operator(kid0) == OPR_INTCONST &&
01655            WN_opc_operator(kid1) == OPR_INTCONST ) {
01656            if (WN_const_val(kid1)==1) {
01657                if (WN_const_val(kid0)== 0) {
01658                    WN2F_translate(tokens, kid2, context);
01659                  }
01660                else {
01661                      WN2F_translate(tokens, kid1, context);
01662                      Append_Token_Special(tokens, '+');
01663                      WN2F_translate(tokens, kid2, context); }
01664             }
01665             else {
01666             if (WN_const_val(kid0)== 0){
01667             WN2F_translate(tokens, kid1, context);
01668              Append_Token_Special(tokens, '*');
01669              WN2F_translate(tokens, kid2, context); }
01670              else {
01671                   WN2F_translate(tokens, kid0, context);
01672                   Append_Token_Special(tokens, '+');
01673                   WN2F_translate(tokens, kid1, context);
01674                   Append_Token_Special(tokens, '*');
01675                   WN2F_translate(tokens, kid2, context); }
01676             }
01677           }
01678           else 
01679           if (WN_opc_operator(kid1) == OPR_INTCONST &&
01680               WN_opc_operator(kid2) == OPR_INTCONST) {
01681                    WN2F_translate(tokens, kid0, context);
01682                    Append_Token_Special(tokens, '+');
01683        
01684           if ((WN_const_val(kid1)*WN_const_val(kid2))>=INT_MAX)
01685  
01686                    TCON2F_translate(tokens,
01687                                 Host_To_Targ(MTYPE_I8,   
01688                                            WN_const_val(kid1)*
01689                                            WN_const_val(kid2)),
01690                                            FALSE);
01691           else 
01692                    TCON2F_translate(tokens,
01693                                 Host_To_Targ(MTYPE_I4,   
01694                                            WN_const_val(kid1)*
01695                                            WN_const_val(kid2)),
01696                                            FALSE);
01697           }
01698           else 
01699           if (WN_opc_operator(kid0) == OPR_INTCONST &&
01700               WN_opc_operator(kid2) == OPR_INTCONST) {
01701               if (WN_const_val(kid2)==1) {
01702                if (WN_const_val(kid0)== 0) {
01703                    WN2F_translate(tokens, kid1, context);
01704                 }
01705                else {
01706                      WN2F_translate(tokens, kid0, context);
01707                      Append_Token_Special(tokens, '+');
01708                      WN2F_translate(tokens, kid1, context); 
01709                     }
01710             }
01711             else {
01712             if (WN_const_val(kid0)== 0){
01713             WN2F_translate(tokens, kid2, context);
01714              Append_Token_Special(tokens, '*');
01715              WN2F_translate(tokens, kid1, context); }
01716              else {
01717                   WN2F_translate(tokens, kid0, context);
01718                   Append_Token_Special(tokens, '+');
01719                   WN2F_translate(tokens, kid1, context);
01720                   Append_Token_Special(tokens, '*');
01721                   WN2F_translate(tokens, kid2, context); }
01722               }
01723             }
01724            else 
01725            if (WN_opc_operator(kid0) == OPR_INTCONST){ 
01726               if (WN_const_val(kid0)==0) {
01727                   WN2F_translate(tokens, kid1, context);
01728                   Append_Token_Special(tokens, '*');
01729                   WN2F_translate(tokens, kid2, context);}
01730               else {
01731                  WN2F_translate(tokens, kid0, context);
01732                  Append_Token_Special(tokens, '+');
01733                  WN2F_translate(tokens, kid1, context);
01734                  Append_Token_Special(tokens, '*');
01735                  WN2F_translate(tokens, kid2, context);
01736                  }
01737             }
01738             else 
01739             if (WN_opc_operator(kid1) == OPR_INTCONST){
01740                 WN2F_translate(tokens, kid0, context);
01741                 Append_Token_Special(tokens, '+');
01742                 if (WN_const_val(kid1)==1){
01743                     WN2F_translate(tokens, kid2, context);}
01744                  else {
01745                       WN2F_translate(tokens, kid1, context);
01746                       Append_Token_Special(tokens, '*');
01747                       WN2F_translate(tokens, kid2, context);
01748                         }
01749             }
01750             else
01751             if (WN_opc_operator(kid2) == OPR_INTCONST) {
01752                   WN2F_translate(tokens, kid0, context);
01753                   Append_Token_Special(tokens, '+');
01754                   if (WN_const_val(kid2)==1)
01755                    WN2F_translate(tokens, kid1, context);
01756                   else
01757                     {
01758                             WN2F_translate(tokens, kid2, context);
01759                             Append_Token_Special(tokens, '*');
01760                              WN2F_translate(tokens, kid1, context);
01761                     }
01762               }
01763          if ((WN_opc_operator(kid1) == OPR_INTCONST) && 
01764                (WN_const_val(kid1)==1))  {
01765          } else {
01766                 Append_Token_Special(tokens, ':');
01767                 WN2F_translate(tokens, kid1, context);
01768                } 
01769     }  
01770     return EMPTY_WN2F_STATUS;
01771 
01772     }
01773 /******************************************************************************\
01774 |*                                                                            *|
01775 |*                                                                            *|
01776 \******************************************************************************/
01777 
01778 WN2F_STATUS
01779 WN2F_src_triplet(TOKEN_BUFFER tokens, WN *wn, WN2F_CONTEXT context)
01780 {
01781    WN      *kid0;
01782    WN      *kid1;
01783    WN      *kid2;
01784   kid0=WN_kid0(wn);
01785   kid1=WN_kid1(wn);
01786   kid2=WN_kid2(wn);
01787   WN2F_translate(tokens, kid0, context);
01788   Append_Token_Special(tokens, ':');
01789   WN2F_translate(tokens, kid1, context); 
01790 
01791   if (WN_operator(kid2) == OPR_INTCONST &&
01792       WN_const_val(kid2) == 1)
01793       ;
01794   else {
01795         Append_Token_Special(tokens, ':');
01796         WN2F_translate(tokens, kid2, context); 
01797        }
01798 
01799   return EMPTY_WN2F_STATUS;
01800 
01801     }
01802 
01803 WN2F_STATUS
01804 WN2F_arrsection(TOKEN_BUFFER tokens, WN *wn, WN2F_CONTEXT context)
01805 {
01806    /* Note that array indices have been normalized to assume the
01807     * array is based at index zero.  Since a base at index 1 is
01808     * the default for Fortran, we denormalize to base 1 here.
01809     */
01810    BOOL  deref = WN2F_CONTEXT_deref_addr(context);
01811    WN    * kid;
01812    TY_IDX ptr_ty;
01813    TY_IDX array_ty;
01814 
01815 
01816    ASSERT_DBG_FATAL(WN_opc_operator(wn) == OPR_ARRAY,
01817                     (DIAG_W2F_UNEXPECTED_OPC, "WN2F_array"));
01818 
01819    /* Only allow taking the address of an array element for F90!
01820     *
01821     */
01822 #if 0
01823  else
01824       ASSERT_DBG_WARN(deref,
01825                       (DIAG_UNIMPLEMENTED,
01826                        "taking the address of an array element"));
01827 #endif
01828 
01829    /* Get the array or, for ptr-as-array types, the element type */
01830 
01831    kid    = WN_kid0(wn);
01832    if (WN_operator(kid) == OPR_ILOAD  &&
01833        WN_operator(WN_kid0(kid)) == OPR_STRCTFLD) 
01834           kid = WN_kid0(kid) ;
01835 
01836    ptr_ty = WN_Tree_Type(kid);
01837 
01838         
01839 
01840    if (WN2F_Is_Address_Preg(kid,ptr_ty))
01841    {
01842        /* a preg or sym has been used as an address, usually after optimization
01843 */
01844        /* don't know base type, or anything else so use OPR_ARRAY to generate bounds
01845 */
01846 
01847      WN2F_translate(tokens, kid, context);
01848      WN2F_Arrsection_Slots(tokens,wn,ptr_ty,context,TRUE);
01849    }
01850    else
01851    {
01852 
01853      if (WN_operator(kid)==OPR_STRCTFLD)
01854           array_ty = WN_ty(kid);
01855      else
01856           array_ty = W2F_TY_pointed(ptr_ty, "base of OPC_ARRAY");
01857     
01858      if (WN_opc_operator(kid) == OPR_LDID       &&
01859          ST_sclass(WN_st(kid)) == SCLASS_FORMAL &&
01860          !ST_is_value_parm(WN_st(kid))          &&
01861          WN_element_size(wn) == TY_size(array_ty)       &&
01862          WN_num_dim(wn) == 1                            &&
01863          WN_opc_operator(WN_array_index(wn, 0)) == OPR_INTCONST &&
01864          WN_const_val(WN_array_index(wn, 0)) == 0       &&
01865          !TY_ptr_as_array(Ty_Table[WN_ty(kid)])           &&
01866          (!TY_Is_Array(array_ty) ||
01867           TY_size(TY_AR_etype(array_ty)) < TY_size(array_ty)))
01868      {
01869          /* This array access is just a weird representation for an implicit
01870           * reference parameter dereference.  Ignore the array indexing.
01871           */
01872 
01873        WN2F_translate(tokens, kid, context);
01874      }
01875      else if (!TY_ptr_as_array(Ty_Table[ptr_ty]) && TY_Is_Character_String(array_ty))
01876      {
01877          /* We assume that substring accesses are treated in the handling
01878           * of intrinsic functions, except when the substrings are to be
01879           * handled as integral types and thus are encountered here.
01880           */
01881 #if 0
01882        if (!WN2F_F90_pu)
01883        {
01884          Append_Token_String(tokens, "ichar");
01885          Append_Token_Special(tokens, '(');
01886        }
01887 # endif 
01888 
01889        WN2F_String_Argument(tokens, wn, WN2F_INTCONST_ONE, context);
01890 # if 0
01891 
01892        if (!WN2F_F90_pu)
01893          Append_Token_Special(tokens, ')');
01894 # endif
01895 
01896      }
01897      else /* A regular array access */
01898      {
01899            /* Get the base of the object to be indexed into, still using
01900             * WN2F_CONTEXT_deref_addr(context).
01901             */
01902        WN2F_translate(tokens, kid, context);
01903        reset_WN2F_CONTEXT_deref_addr(context);
01904 
01905    if ( WN2F_CONTEXT_has_no_arr_elmt(context))
01906             ;
01907    else
01908          WN2F_arrsection_bounds(tokens,wn,array_ty,context);
01909      }
01910    }
01911    return EMPTY_WN2F_STATUS;
01912 } /* WN2F_arrsection */
01913 
01914 
01915 WN2F_STATUS
01916 WN2F_where(TOKEN_BUFFER tokens, WN *wn, WN2F_CONTEXT context)
01917 {
01918 WN  *kid;
01919  WN2F_Stmt_Newline(tokens, NULL/*label*/, WN_linenum(wn), context);
01920  Append_Token_String(tokens,"WHERE");
01921  Append_Token_Special(tokens, '(');
01922   kid  =WN_kid0(wn);
01923  WN2F_translate(tokens, kid, context);
01924  Append_Token_Special(tokens, ')');
01925  kid   =WN_kid1(wn);
01926  WN2F_translate(tokens, kid, context);
01927  kid   = WN_kid2(wn);
01928  WN2F_Stmt_Newline(tokens, NULL/*label*/, WN_Get_Linenum(wn), context);
01929  Append_Token_String(tokens,"END WHERE");
01930  WN2F_translate(tokens, kid, context);
01931  return EMPTY_WN2F_STATUS;
01932 }
01933 
01934 
01935 WN2F_STATUS
01936 WN2F_array(TOKEN_BUFFER tokens, WN *wn, WN2F_CONTEXT context)
01937 {
01938    /* Note that array indices have been normalized to assume the
01939     * array is based at index zero.  Since a base at index 1 is
01940     * the default for Fortran, we denormalize to base 1 here.
01941     */
01942    BOOL  deref = WN2F_CONTEXT_deref_addr(context);
01943 
01944    WN    * kid;
01945    TY_IDX ptr_ty;
01946    TY_IDX array_ty;
01947 
01948    ASSERT_DBG_FATAL(WN_opc_operator(wn) == OPR_ARRAY, 
01949                     (DIAG_W2F_UNEXPECTED_OPC, "WN2F_array"));
01950 
01951    /* Only allow taking the address of an array element for F90!
01952     *
01953     */
01954 #if 0
01955  else
01956       ASSERT_DBG_WARN(deref,
01957                       (DIAG_UNIMPLEMENTED, 
01958                        "taking the address of an array element"));
01959 #endif
01960 
01961    /* Get the array or, for ptr-as-array types, the element type */
01962 
01963    kid    = WN_kid0(wn);
01964 
01965    if (WN_operator(kid)==OPR_ILOAD &&
01966           WN_operator(WN_kid0(kid))==OPR_STRCTFLD ) //F90 pointer
01967         kid = WN_kid0(kid);
01968 
01969    ptr_ty = WN_Tree_Type(kid);
01970 
01971    if (WN2F_Is_Address_Preg(kid,ptr_ty))
01972    {
01973        /* a preg or sym has been used as an address, usually after optimization      */
01974        /* don't know base type, or anything else so use OPR_ARRAY to generate bounds */
01975      WN2F_translate(tokens, kid, context);
01976      WN2F_Array_Slots(tokens,wn, ptr_ty, context,TRUE);     
01977 /* need to take example to see if it's OK to use ptr_ty here*/
01978    } 
01979    else 
01980    {
01981      array_ty = W2F_TY_pointed(ptr_ty, "base of OPC_ARRAY");
01982 
01983      if (WN_opc_operator(kid) == OPR_LDID       &&
01984          ST_sclass(WN_st(kid)) == SCLASS_FORMAL &&
01985          !ST_is_value_parm(WN_st(kid))          &&
01986          WN_element_size(wn) == TY_size(array_ty)       &&
01987          WN_num_dim(wn) == 1                            &&
01988          WN_opc_operator(WN_array_index(wn, 0)) == OPR_INTCONST &&
01989          WN_const_val(WN_array_index(wn, 0)) == 0       &&
01990          !TY_ptr_as_array(Ty_Table[WN_ty(kid)])           &&
01991          (!TY_Is_Array(array_ty) || 
01992           TY_size(TY_AR_etype(array_ty)) < TY_size(array_ty)))
01993      {
01994          /* This array access is just a weird representation for an implicit
01995           * reference parameter dereference.  Ignore the array indexing.
01996           */
01997        WN2F_translate(tokens, kid, context);
01998      }
01999      else if (!TY_ptr_as_array(Ty_Table[ptr_ty]) && 
02000                     TY_Is_Character_String(array_ty) )
02001      {
02002          /* We assume that substring accesses are treated in the handling
02003           * of intrinsic functions, except when the substrings are to be
02004           * handled as integral types and thus are encountered here.
02005           */
02006 # if 0
02007        if (!WN2F_F90_pu)
02008        {
02009          Append_Token_String(tokens, "ichar");
02010          Append_Token_Special(tokens, '(');
02011        }
02012 # endif
02013 
02014        WN2F_String_Argument(tokens, wn, WN2F_INTCONST_ONE, context);
02015 
02016 # if 0
02017        if (!WN2F_F90_pu)
02018          Append_Token_Special(tokens, ')');
02019 # endif
02020 
02021      }
02022      else /* A regular array access */
02023      {
02024            /* Get the base of the object to be indexed into, still using
02025             * WN2F_CONTEXT_deref_addr(context).
02026             */
02027 //     if (WN_operator(kid) == OPR_ADD || WN_operator(kid)==OPR_ARRAY)
02028      if (WN_operator(kid) == OPR_ADD)
02029       {
02030 
02031      STAB_OFFSET offset =(WN_operator(kid) == OPR_ADD)?WN_const_val(WN_kid1(kid)):0; 
02032 
02033        WN2F_translate(tokens,WN_kid0(kid),context);
02034 
02035 #if 0 
02036        FLD_PATH_INFO *fld_path;
02037        if (!fld_type_z)
02038             fld_type_z = array_ty; 
02039        fld_path = TY2F_Get_Fld_Path(fld_type_z,fld_type_z, offset);
02040 
02041        if (fld_path){
02042            TY2F_Fld_Separator(tokens);
02043            FLD_HANDLE f (fld_path->fld);
02044             fld_type_z = FLD_type(f); 
02045 
02046             while (TY_Is_Pointer(fld_type_z))
02047                fld_type_z = TY_pointed(fld_type_z);
02048        
02049             if (TY_kind(fld_type_z) == KIND_ARRAY)
02050                  fld_type_z = TY_etype(fld_type_z);
02051 
02052             Append_Token_String(tokens,
02053                            TY2F_Fld_Name(f,FALSE,FALSE));
02054            
02055          } else
02056           Append_Token_String(tokens,
02057                                Number_as_String(offset,
02058                                                 "<field-at-offset=%lld>"));
02059 #endif 
02060 
02061         }
02062      else {
02063            WN2F_translate(tokens, kid, context);
02064           }
02065 
02066        reset_WN2F_CONTEXT_deref_addr(context);
02067        WN2F_array_bounds(tokens,wn,array_ty,context);
02068      }
02069    }
02070    return EMPTY_WN2F_STATUS;
02071 } /* WN2F_array */
02072 
02073 
02074 void
02075 WN2F_Arrsection_Slots(TOKEN_BUFFER tokens, WN *wn,TY_IDX array_ty,WN2F_CONTEXT context,BOOL parens)
02076 {
02077   INT32 dim;
02078   WN * kidz;
02079   INT32 co_dim;
02080   INT32 array_dim;
02081   TY_IDX ttyy;
02082   ARB_HANDLE arb_base;
02083    WN* kid;
02084 
02085 
02086   /* Gets bounds from the slots of an OPC_ARRSECTION node  */
02087 
02088   /* Append the "denormalized" indexing expressions in reverse order
02089    * of the way they occur in the indexing expression, since Fortran
02090    * employs column-major array layout, meaning the leftmost indexing
02091    * expression represents array elements laid out in contiguous
02092    * memory locations.
02093    */
02094 
02095   ttyy = array_ty;
02096 
02097   if (TY_Is_Pointer(ttyy))  
02098      ttyy=TY_pointed(ttyy);
02099   if (TY_is_f90_pointer(ttyy))
02100      ttyy = TY_pointed(ttyy);
02101 
02102    arb_base = TY_arb(ttyy);
02103 
02104   dim =  ARB_dimension(arb_base);
02105   co_dim = ARB_co_dimension(arb_base);
02106 
02107 
02108   if (dim >  WN_num_dim(wn) ) {
02109 
02110      array_dim = dim-co_dim;
02111      co_dim = 0;
02112  }
02113  else {
02114          dim =  WN_num_dim(wn);
02115         array_dim = dim;
02116        }
02117 
02118 
02119 if (array_dim>0) {
02120   if (parens)
02121   {
02122     Append_Token_Special(tokens, '(');
02123     set_WN2F_CONTEXT_no_parenthesis(context);
02124   }
02125 # if 0 /* add co_array dimensions */
02126   for (dim = WN_num_dim(wn)-1; dim >= 0; dim--)
02127   {
02128     if (WN_opc_operator(WN_array_index(wn, dim))==OPR_SRCTRIPLET) {
02129           WN2F_translate(tokens, WN_array_index(wn, dim), context);    
02130       } 
02131     else {
02132     (void)WN2F_Denormalize_Array_Idx(tokens,
02133                                      WN_array_index(wn, dim),
02134                                      context);
02135     }
02136     if (dim > 0)
02137       Append_Token_Special(tokens, ',');
02138   }
02139 # endif
02140   for (dim = WN_num_dim(wn)-1; dim >= co_dim; dim--)
02141   {
02142     if (WN_opc_operator(WN_array_index(wn, dim))==OPR_SRCTRIPLET) {
02143           WN2F_translate(tokens, WN_array_index(wn, dim), context);
02144       }
02145     else {
02146     (void)WN2F_Denormalize_Array_Idx(tokens,
02147                                      WN_array_index(wn, dim),
02148                                      context);
02149     }
02150     if (dim > co_dim)
02151       Append_Token_Special(tokens, ',');
02152   }
02153   if (parens)
02154     Append_Token_Special(tokens, ')');
02155 }
02156 
02157 if (co_dim > 0) {
02158 
02159     if (parens)
02160     Append_Token_Special(tokens, '[');
02161 
02162   for (dim = co_dim-1; dim >= 0; dim--)
02163   {
02164     if (WN_opc_operator(WN_array_index(wn, dim))==OPR_SRCTRIPLET) {
02165           WN2F_translate(tokens, WN_array_index(wn, dim), context);
02166       }
02167     else {
02168     (void)WN2F_Denormalize_Array_Idx(tokens,
02169                                      WN_array_index(wn, dim),
02170                                      context);
02171     }
02172     if (dim > 0)
02173       Append_Token_Special(tokens, ',');
02174   }
02175 
02176 
02177   if (parens)
02178     Append_Token_Special(tokens, ']');
02179  }
02180 }
02181 
02182 void
02183 WN2F_Array_Slots(TOKEN_BUFFER tokens, WN *wn,TY_IDX array_ty,WN2F_CONTEXT context,BOOL parens)
02184 {
02185   INT32 dim;
02186   WN * kid;
02187   INT32 co_dim;
02188   INT32 array_dim;
02189   ARB_HANDLE arb_base;
02190   TY_IDX ttyy;
02191 
02192 
02193   /* get array's rank and co_rank information from kid0 of wn
02194    * kid0 should be OPR_LDA
02195    *coarray reference is legal without co_rank
02196    *so we have to use dim plus kid_number to 
02197    *see if there is co_rank or not
02198    */
02199 
02200   kid = WN_kid0(wn);
02201 
02202   if (WN_operator(kid)==OPR_LDA)
02203     {
02204       ttyy = array_ty;
02205 
02206       if (TY_Is_Pointer(ttyy))
02207           ttyy =TY_pointed(ttyy);
02208       if (TY_is_f90_pointer(ttyy))
02209           ttyy = TY_pointed(ttyy);
02210 
02211       arb_base = TY_arb(ttyy);
02212 
02213      dim =  ARB_dimension(arb_base);
02214      co_dim = ARB_co_dimension(arb_base);
02215     } else {
02216      co_dim =0;
02217      dim = WN_num_dim(wn);
02218     }
02219 
02220 
02221    if (dim >  WN_num_dim(wn) ) {
02222       array_dim = dim-co_dim;
02223       co_dim = 0;
02224      }
02225     else {
02226          dim =  WN_num_dim(wn);
02227          array_dim = dim-co_dim;
02228        }
02229 
02230 
02231 
02232   /* Gets bounds from the slots of an OPC_ARRAY node  */
02233 
02234   /* Append the "denormalized" indexing expressions in reverse order
02235    * of the way they occur in the indexing expression, since Fortran
02236    * employs column-major array layout, meaning the leftmost indexing
02237    * expression represents array elements laid out in contiguous 
02238    * memory locations.
02239    */
02240 
02241  if (array_dim > 0 ) {
02242     Append_Token_Special(tokens, '(');
02243     set_WN2F_CONTEXT_no_parenthesis(context);
02244 
02245 
02246   for (dim =  WN_num_dim(wn)-1; dim >= co_dim; dim--)
02247   {
02248     (void)WN2F_Denormalize_Array_Idx(tokens,
02249                                      WN_array_index(wn, dim),
02250                                      context);
02251        
02252     if (dim > co_dim)
02253       Append_Token_Special(tokens, ',');
02254   }
02255 
02256 
02257     Append_Token_Special(tokens, ')');
02258   } 
02259 
02260   /* for co_rank */
02261 
02262   if (co_dim > 0) {
02263      Append_Token_Special(tokens, '[');
02264      for (dim =  co_dim-1; dim >= 0; dim--)
02265      {
02266        (void)WN2F_Denormalize_Array_Idx(tokens,
02267                                         WN_array_index(wn, dim),
02268                                         context);
02269        
02270        if (dim > 0)
02271        Append_Token_Special(tokens, ',');
02272     }
02273 
02274     Append_Token_Special(tokens, ']');
02275  
02276     }
02277  }
02278 
02279 void
02280 WN2F_arrsection_bounds(TOKEN_BUFFER tokens, WN *wn, TY_IDX array_ty,WN2F_CONTEXT context)
02281 {
02282   /* This prints the array subscript expression. It was part of
02283    * WN2F_array, but was split so it could be used for bounds
02284    * of structure components.
02285    */
02286 
02287   INT32 dim;
02288 
02289   if (TY_is_f90_pointer(array_ty))
02290        array_ty = TY_pointed(array_ty);//Sept
02291 
02292   if (TY_Is_Array(array_ty) && TY_AR_ndims(array_ty) >= WN_num_dim(wn))
02293     {
02294       /* Cannot currently handle differing element sizes at place of
02295        * array declaration versus place of array access (TODO?).
02296        */
02297 
02298       ASSERT_DBG_WARN((TY_size(TY_AR_etype(array_ty)) == WN_element_size(wn)) ||
02299                       WN_element_size(wn) < 0 ||
02300                       TY_size(TY_AR_etype(array_ty)) == 0,
02301                       (DIAG_UNIMPLEMENTED,
02302                        "access/declaration mismatch in array element size"));
02303 
02304       WN2F_Arrsection_Slots(tokens,wn,array_ty,context,TRUE);
02305 
02306       /* We handle the case when an array is declared to have more
02307        * dimensions than that given by this array addressing expression.
02308        */
02309 # if 0 //could be co_array object
02310 
02311       if (TY_AR_ndims(array_ty) > WN_num_dim(wn))
02312         {
02313           /* Substitute in '1' for the missing dimensions */
02314           for (dim = TY_AR_ndims(array_ty) - WN_num_dim(wn); dim > 0; dim--)
02315             {
02316               Append_Token_Special(tokens, ',');
02317               Append_Token_String(tokens, "1");
02318             }
02319         }
02320 # endif
02321     }
02322   else /* Normalize array access to assume a single dimension */
02323     {
02324       ASSERT_DBG_WARN(!TY_Is_Array(array_ty) || TY_AR_ndims(array_ty) == 1,
02325                       (DIAG_UNIMPLEMENTED,
02326                        "access/declaration mismatch in array dimensions"));
02327 
02328       WN2F_Normalize_Idx_To_Onedim(tokens, wn, context);
02329     }
02330 
02331 }
02332 
02333 
02334 void
02335 WN2F_array_bounds(TOKEN_BUFFER tokens, WN *wn, TY_IDX array_ty,WN2F_CONTEXT context)
02336 {
02337   /* This prints the array subscript expression. It was part of
02338    * WN2F_array, but was split so it could be used for bounds 
02339    * of structure components.
02340    */
02341  
02342   INT32 dim;
02343   WN  * kid; 
02344 
02345 //   Append_Token_Special(tokens, '(');
02346 //  set_WN2F_CONTEXT_no_parenthesis(context);
02347 
02348    if (TY_is_f90_pointer(array_ty))
02349         array_ty = TY_pointed(array_ty); 
02350 
02351   if (TY_Is_Array(array_ty) && TY_AR_ndims(array_ty) >= WN_num_dim(wn) || TRUE) 
02352     {
02353       /* Cannot currently handle differing element sizes at place of
02354        * array declaration versus place of array access (TODO?).
02355        */
02356 
02357       ASSERT_DBG_WARN((TY_size(TY_AR_etype(array_ty)) == WN_element_size(wn)) ||
02358                       WN_element_size(wn) < 0 ||
02359                       TY_size(TY_AR_etype(array_ty)) == 0,
02360                       (DIAG_UNIMPLEMENTED, 
02361                        "access/declaration mismatch in array element size"));
02362 
02363       WN2F_Array_Slots(tokens,wn,array_ty,context,FALSE);
02364 
02365       /* We handle the case when an array is declared to have more 
02366        * dimensions than that given by this array addressing expression.
02367        * COMMENT ABOVE IS FROM ORIGINAL VERSION ,belowing added by zhao
02368        * this could be happend when co_rank doesn't appear,don't need add
02369        * 
02370        */
02371 #if 0 
02372       if (TY_AR_ndims(array_ty) > WN_num_dim(wn))
02373         {
02374      
02375           /* Substitute in '1' for the missing dimensions */
02376           for (dim = TY_AR_ndims(array_ty) - WN_num_dim(wn); dim > 0; dim--)
02377             {
02378               Append_Token_Special(tokens, ',');
02379               Append_Token_String(tokens, "1");
02380             }
02381         }
02382 #endif
02383 
02384     }
02385   else /* Normalize array access to assume a single dimension */
02386     {
02387       ASSERT_DBG_WARN(!TY_Is_Array(array_ty) || TY_AR_ndims(array_ty) == 1,
02388                       (DIAG_UNIMPLEMENTED, 
02389                        "access/declaration mismatch in array dimensions"));
02390 
02391      WN2F_Normalize_Idx_To_Onedim(tokens, wn, context);
02392     }
02393 //   Append_Token_Special(tokens, ')');
02394 }
02395 
02396 /*----------- Character String Manipulation Translation ---------------*/
02397 /*---------------------------------------------------------------------*/
02398 
02399 void
02400 WN2F_String_Argument(TOKEN_BUFFER  tokens,
02401                      WN           *base_parm,
02402                      WN           *length,
02403                      WN2F_CONTEXT  context)
02404 {
02405    /* Append the tokens denoting the substring expression represented
02406     * by the base-expression.
02407     *
02408     * There are two possibilities concerning the array base 
02409     * expressions.  It can be a pointer to a complete character-
02410     * string (array) or it can be a pointer to a character within 
02411     * a character-string (single character).  In the first instance,
02412     * the offset off the base of string is zero.  In the latter 
02413     * case, the offset is given by the array indexing operation.
02414     *
02415     * NOTE: In some cases (notably for IO_ITEMs), we may try to 
02416     * derive a substring off an OPC_VINTRINSIC_CALL node or a
02417     * VCALL node.  This should only happend when the returned value
02418     * is the first argument and the length is the second argument.
02419     */
02420    WN   *base = WN_Skip_Parm(base_parm);
02421    WN   *lower_bnd;
02422    WN   *length_new;
02423    WN   *arg_expr;
02424    TY_IDX str_ty;
02425    INT64 str_length;
02426 
02427    /* Skip any INTR_ADRTMP and INTR_VALTMP nodes */
02428    if (WN_opc_operator(base) == OPR_INTRINSIC_OP &&
02429        (INTR_is_adrtmp(WN_intrinsic(base)) || 
02430         INTR_is_valtmp(WN_intrinsic(base))))
02431    {
02432       base = WN_kid0(base);
02433    }
02434 
02435 
02436    if (WN_operator(base) == OPR_CVTL)  
02437    {
02438      /* probably CHAR(INT) within IO stmt. convert via CHAR & process rest elsewhere */
02439 
02440       Append_Token_Special(tokens, '(');
02441       Append_Token_String(tokens, "char");
02442       WN2F_translate(tokens,WN_kid0(base),context);
02443       Append_Token_Special(tokens, ')');
02444       return;
02445    }
02446   
02447  
02448    /* Handle VCALLs specially, since the string information is given
02449     * by the first two arguments to the call.  Note that we can 
02450     * always assume a lower bound of zero for these, as we never 
02451     * generate code for the return-address.  This should only occur
02452     * within an IO stmt.  Note that the type of VCALLs must be 
02453     * accessed in the context of an ADRTMP or VALTMP.
02454     */
02455    if (WN_opcode(base) == OPC_VCALL ||
02456        WN_opcode(base) == OPC_VINTRINSIC_CALL)
02457    {
02458       arg_expr  = WN_Skip_Parm(WN_kid1(base));
02459       lower_bnd = WN2F_INTCONST_ZERO;
02460 
02461       /* fixed size string? */
02462 
02463       if (WN_opc_operator(arg_expr) == OPR_INTCONST)
02464          str_length = WN_const_val(arg_expr);
02465       else
02466          str_length = -1 ;  
02467 
02468       set_WN2F_CONTEXT_deref_addr(context);
02469       WN2F_translate(tokens, base, context);
02470       reset_WN2F_CONTEXT_deref_addr(context);
02471 
02472    } 
02473    else 
02474    {
02475      /* A regular address expression as base */
02476 #if 0
02477       WN2F_Get_Substring_Info(&base, &str_ty, &lower_bnd,&length_new);
02478 
02479       /* Was this a character component of an array of derived type? */
02480       /* eg: vvv(2)%ccc(:)(1:5) - offset to ccc is added above base, */
02481       /* ADD(8,ARRAY(2,LDA VVV)) with array section for CCC on top   */
02482       /* of the ADD, and the substring above the array section. Take */
02483       /* the substring off the top, and process the rest             */
02484 
02485       if (TY_kind(str_ty) == KIND_STRUCT) 
02486       {
02487         FLD_PATH_INFO *fld_path ;
02488         FLD_HANDLE fld;
02489         TY_IDX  ty_idx ; 
02490 
02491         TY & ty = New_TY(ty_idx);
02492 
02493         TY_Init (ty, 1, KIND_SCALAR, MTYPE_U1, Save_Str(".w2fch."));
02494         Set_TY_is_character(ty);
02495 
02496         fld_path = TY2F_Get_Fld_Path(str_ty, 
02497                                      ty_idx,
02498                                      WN2F_Sum_Offsets(base));
02499 
02500         fld = TY2F_Last_Fld(fld_path);
02501         TY2F_Free_Fld_Path(fld_path);
02502 
02503         /* call memref for FLD offset, otherwise the ADD is */
02504         /* just another binary op                           */
02505         WN2F_Offset_Memref(tokens, 
02506                            WN_kid0(base),
02507                            WN_Tree_Type(base),
02508                            FLD_type(fld),
02509                            0,
02510                            context);
02511       } 
02512       else 
02513       {
02514         str_length = TY_size(str_ty);
02515 
02516         /* with optimization, may not have useful address TY 
02517          * when TreeType will return array of U1 from SubstringInfo */
02518 
02519         ASSERT_DBG_WARN(TY_Is_Character_String(str_ty) || TY_Is_Array_Of_UChars(str_ty),
02520                         (DIAG_W2F_EXPECTED_PTR_TO_CHARACTER,
02521                          "WN2F_String_Argument"));
02522 
02523         /* Get the string base and substring notation for the argument.  */
02524         set_WN2F_CONTEXT_deref_addr(context);
02525         WN2F_translate(tokens, base, context);
02526         reset_WN2F_CONTEXT_deref_addr(context);
02527       }
02528 
02529 if (length_new != WN2F_INTCONST_ZERO && !WN2F_CONTEXT_has_no_arr_elmt(context))
02530       WN2F_Substring(tokens, 
02531                      str_length,
02532                      lower_bnd,
02533 //                   WN_Skip_Parm(length),
02534                      length_new,
02535                      context);
02536 #else
02537 
02538   {
02539     WN * base1;
02540        if (WN_operator(base)==OPR_ARRAY)
02541                base1 = WN_kid0(base);
02542        else 
02543        if (WN_operator(base)==OPR_ARRAYEXP   &&
02544            WN_operator(WN_kid0(base))==OPR_ARRAY)
02545                base1 = WN_kid0(WN_kid0(base));
02546        else 
02547                base1 = base;
02548 
02549         WN2F_translate(tokens, base1, context);
02550    } 
02551 
02552         WN2F_Get_Substring_Info(&base, &str_ty, &lower_bnd,&length_new);
02553         str_length = TY_size(str_ty);
02554 
02555    if (length_new != WN2F_INTCONST_ZERO && !WN2F_CONTEXT_has_no_arr_elmt(context))
02556           WN2F_Substring(tokens, 
02557                          str_length,
02558                          lower_bnd,
02559                          length_new,
02560                          context);
02561    else 
02562         reset_WN2F_CONTEXT_has_no_arr_elmt(context);
02563 #endif
02564       return ;
02565    }
02566 } /* WN2F_String_Argument */
02567 
02568 
02569 /*----------- Miscellaneous  routines ---------------------------------*/
02570 /*---------------------------------------------------------------------*/
02571 
02572 static void
02573 WN2F_Block(TOKEN_BUFFER tokens, ST * st, STAB_OFFSET offset,WN2F_CONTEXT context)
02574 {
02575   /* An ST of CLASS_BLOCK may appear in f90 IO, at -O2 */
02576   /* put out something for the whirl browser           */
02577 
02578   ST2F_use_translate(tokens,st);
02579 
02580   if (offset != 0)
02581   {
02582       Append_Token_Special(tokens, '+');
02583       Append_Token_String(tokens, Number_as_String(offset, "%lld"));
02584   }
02585 }
02586 
02587 
02588 WN2F_STATUS 
02589 WN2F_strctfld(TOKEN_BUFFER tokens, WN *wn, WN2F_CONTEXT context)
02590 {
02591    TY_IDX ty1,ty2;
02592    char * fld_name;
02593    FLD_HANDLE  fld;
02594    UINT       field_id ;
02595 
02596    ASSERT_DBG_FATAL(WN_opc_operator(wn) == OPR_STRCTFLD, 
02597                     (DIAG_W2F_UNEXPECTED_OPC, "WN2F_strctfld"));
02598 
02599  if (!WN_kid0(wn))
02600     Append_Token_String(tokens,"Null kid here");
02601  else 
02602     WN2F_translate(tokens,WN_kid0(wn),context);
02603 
02604     ty2 = WN_load_addr_ty(wn);
02605     Is_True (TY_kind(ty2) == KIND_STRUCT, ("expecting KIND_STRUCT"));
02606     field_id = WN_field_id(wn);
02607     fld = TY_fld(ty2); 
02608     field_id--;
02609     while (field_id && !FLD_last_field(fld)) {
02610         --field_id ;
02611         fld = FLD_next(fld);
02612     }
02613    
02614 //TODO: add assertion about field_id ? Must be resonable value based
02615 //      on the structure and field type 
02616     fld_name = FLD_name(fld);
02617     Append_Token_Special(tokens,'%'); 
02618     Append_Token_String(tokens,fld_name); 
02619 
02620    return EMPTY_WN2F_STATUS;
02621 }
02622 
02623 
02624 WN2F_STATUS 
02625 WN2F_comma(TOKEN_BUFFER tokens, WN *wn, WN2F_CONTEXT context)
02626  {
02627     WN2F_translate(tokens,WN_kid1(wn),context);
02628     return EMPTY_WN2F_STATUS;
02629  }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines