OpenADFortTk (basic)
src/whirl2xaif/ty2xaif.cxx
Go to the documentation of this file.
00001 // ##########################################################
00002 // # This file is part of OpenADFortTk.                     #
00003 // # The full COPYRIGHT notice can be found in the top      #
00004 // # level directory of the OpenADFortTk source tree.       #
00005 // # For more information visit                             #
00006 // # http://www.mcs.anl.gov/openad                          #
00007 // ##########################################################
00008 
00009 #include <sstream> 
00010 
00011 #include "Open64IRInterface/Open64BasicTypes.h"
00012 
00013 #include "wn2xaif.h"
00014 #include "wn2xaif_mem.h"
00015 #include "st2xaif.h"
00016 #include "ty2xaif.h"
00017 
00018 namespace whirl2xaif { 
00019 
00020   extern WN* PU_Body;
00021   extern BOOL Array_Bnd_Temp_Var;
00022 
00023   /* TY2F_Handler[] maps a TY_kind to a function that translates
00024    * a type of the given kind into Fortran.  Should the ordinal
00025    * numbering of the KIND change in "../common/com/stab.h", then
00026    * a corresponding change must be made here.
00027    */
00028 
00029   typedef void (*TY2F_HANDLER_FUNC)(xml::ostream&, TY_IDX, PUXlationContext& ctxt);
00030 
00031   static void 
00032   TY2F_invalid(xml::ostream& xos, TY_IDX ty, PUXlationContext& ctxt);
00033   static void 
00034   TY2F_scalar(xml::ostream& xos, TY_IDX ty, PUXlationContext& ctxt);
00035   static void 
00036   TY2F_array(xml::ostream& xos, TY_IDX ty, PUXlationContext& ctxt);
00037   static void 
00038   TY2F_array_for_pointer(xml::ostream& xos, TY_IDX ty, PUXlationContext& ctxt);
00039   static void 
00040   TY2F_struct(xml::ostream& xos, TY_IDX ty, PUXlationContext& ctxt);
00041   static void 
00042   TY2F_2_struct(xml::ostream& xos,TY_IDX ty, PUXlationContext& ctxt);
00043   static void 
00044   TY2F_pointer(xml::ostream& xos, TY_IDX ty, PUXlationContext& ctxt);
00045   static void 
00046   TY2F_void(xml::ostream& xos, TY_IDX ty, PUXlationContext& ctxt);
00047 
00048   // ***************************************************************************
00049 
00050   static const TY2F_HANDLER_FUNC TY2F_Handler[KIND_LAST/*TY_KIND*/] = {
00051     &TY2F_invalid,   /* KIND_INVALID */
00052     &TY2F_scalar,    /* KIND_SCALAR */
00053     &TY2F_array,     /* KIND_ARRAY */
00054     &TY2F_struct,    /* KIND_STRUCT */
00055     &TY2F_pointer,   /* KIND_POINTER */
00056     &TY2F_invalid,   /* KIND_FUNCTION */
00057     &TY2F_void,      /* KIND_VOID */
00058   }; /* TY2F_Handler */
00059 
00060   /* detect parts of f90 dope vectors which should be output. Most are
00061      I4 boundaries except the bofst >16 - just for num_dims */
00062 #define NOT_BITFIELD_OR_IS_FIRST_OF_BITFIELD(f)                         \
00063   (!FLD_is_bit_field(f) || (FLD_is_bit_field(f) && (FLD_bofst(f) == 0) || FLD_bofst(f) > 16))
00064 
00065   // ***************************************************************************
00066 
00067   void
00068   TY2F_translate(xml::ostream& xos, TY_IDX ty, BOOL notyapp, PUXlationContext& ctxt)
00069   {
00070     // Dispatch the translation-task to the appropriate handler function.
00071     if (!notyapp)
00072       TY2F_Handler[TY_kind(Ty_Table[ty])](xos, ty, ctxt);
00073     else
00074       TY2F_2_struct(xos, ty, ctxt);
00075   }
00076 
00077   void 
00078   TY2F_translate(xml::ostream& xos, TY_IDX ty, PUXlationContext& ctxt)
00079   {
00080     TY2F_translate(xos, ty, 0, ctxt);
00081   }
00082 
00083 
00084   /*---------------------- A few utility routines -----------------------*/
00085   /*---------------------------------------------------------------------*/
00086 
00087   // static void
00088   // WN2F_tempvar_rhs(xml::ostream& xos, WN * wn)
00089   // {
00090   //   /* The rhs */
00091   //   PUXlationContext ctxt;
00092   //   whirl2xaif::TranslateWN(xos, WN_kid0(wn), ctxt);
00093   // }
00094 
00095   // static void
00096   // GetTmpVarTransInfo(xml::ostream& xos, ST_IDX arbnd, WN* wn)
00097   // {
00098   //   WN * stmt;
00099   //   stmt = WN_first(wn);
00100   //   while ((stmt !=NULL)
00101   //     && ((WN_operator(stmt)!=OPR_STID) || (WN_operator(stmt) ==OPR_STID)
00102   //         && strcmp(ST_name(WN_st(stmt)), ST_name(ST_ptr(arbnd)))))
00103   //     stmt = WN_next(stmt);
00104   //   if (stmt != NULL)
00105   //     WN2F_tempvar_rhs(xos, stmt);
00106   // }
00107 
00108   static std::string
00109   TY2F_Append_Array_Bnd_Ph(ST_IDX arbnd)
00110   {
00111     // FIXME: 
00112     std::ostringstream xos_abdstr;
00113     xml::ostream xos_abd(xos_abdstr.rdbuf());
00114 
00115 #if 0 // FIXME
00116     WN* wn = PU_Body; // FIXME--Yuck!!!
00117     GetTmpVarTransInfo(xos_abd, arbnd, wn);
00118 #endif
00119   
00120     return xos_abdstr.str();
00121   } 
00122 
00123   static void
00124   TY2F_Append_ARB(xml::ostream& xos, ARB_HANDLE arb, TY_IDX ty_idx, 
00125                   PUXlationContext& ctxt)
00126   {  
00127     if (TY_is_f90_deferred_shape(ty_idx)) {
00128 
00129       xos << xml::BegElem("xaif:Property") << xml::Attr("id", ctxt.currentXlationContext().getNewVertexId()) 
00130           << xml::Attr("name", "shape") << xml::Attr("value", ':') << xml::EndElem;
00131     
00132     } else {
00133 
00134       std::string lb, ub;
00135       if (ARB_const_lbnd(arb)) {
00136         lb = TCON2F_translate(Host_To_Targ(MTYPE_I4, ARB_lbnd_val(arb)), 
00137                               FALSE /*is_logical*/);
00138       } else if (ARB_lbnd_var(arb) != 0) {
00139         lb = TY2F_Append_Array_Bnd_Ph(ARB_lbnd_var(arb));
00140       }
00141     
00142       if (ARB_const_ubnd(arb)) {
00143         ub = TCON2F_translate(Host_To_Targ(MTYPE_I4, ARB_ubnd_val(arb)),
00144                               FALSE /*is_logical*/); 
00145       } else if (ARB_ubnd_var(arb) != 0) {
00146         ub = TY2F_Append_Array_Bnd_Ph(ARB_ubnd_var(arb));
00147       }
00148 
00149       xos << xml::BegElem("xaif:Property") << xml::Attr("id", ctxt.currentXlationContext().getNewVertexId()) 
00150           << xml::Attr("name", "lb") << xml::Attr("value", lb) << xml::EndElem;
00151       xos << xml::BegElem("xaif:Property") << xml::Attr("id", ctxt.currentXlationContext().getNewVertexId()) 
00152           << xml::Attr("name", "ub") << xml::Attr("value", ub) << xml::EndElem;
00153 
00154     }
00155   } 
00156 
00157   static BOOL
00158   TY2F_is_character(TY_IDX ty)
00159   {
00160     while (TY_kind(ty) == KIND_ARRAY)
00161       ty = TY_etype(ty);
00162 
00163     return TY_is_character(ty);
00164   }
00165   /*------ Utilities for accessing and declaring KIND_STRUCT FLDs ------
00166    *---------------------------------------------------------------------*/
00167 
00168 #define FLD_INFO_ALLOC_CHUNK 16
00169   static FLD_PATH_INFO *Free_Fld_Path_Info = NULL;
00170 
00171 
00172   static BOOL
00173   TY2F_Pointer_To_Dope(TY_IDX ty)
00174   {
00175     /* Is this a pointer to a dope vector base */
00176     return (strcmp(TY_name(TY_pointed(ty)),".base.") == 0) ;
00177   }
00178 
00179   static FLD_PATH_INFO *
00180   New_Fld_Path_Info(FLD_HANDLE fld)
00181   {
00182     /* Allocates a new FLD_PATH_INFO, reusing any that have earlier
00183      * been freed up.  Dynamic allocation occurs in chunks of 16
00184      * (FLD_INFO_ALLOC_CHUNK) FLD_PATH_INFOs at a time.
00185      */
00186     FLD_PATH_INFO *fld_info;
00187    
00188     if (Free_Fld_Path_Info != NULL)
00189       {
00190         fld_info = Free_Fld_Path_Info;
00191         Free_Fld_Path_Info = fld_info->next;
00192       }
00193     else
00194       {
00195         INT info_idx;
00196       
00197         /* Allocate a new chunk of path infos, and put all except the
00198          * first one on the free-list.
00199          */
00200         fld_info = TYPE_MEM_POOL_ALLOC_N(FLD_PATH_INFO, Malloc_Mem_Pool, 
00201                                          FLD_INFO_ALLOC_CHUNK);
00202         fld_info[FLD_INFO_ALLOC_CHUNK-1].next = Free_Fld_Path_Info;
00203         for (info_idx = FLD_INFO_ALLOC_CHUNK-2; info_idx > 0; info_idx--)
00204           fld_info[info_idx].next = &fld_info[info_idx+1];
00205         Free_Fld_Path_Info = &fld_info[1];
00206       }
00207 
00208     fld_info->next = NULL;
00209     fld_info->arr_elt = FALSE;
00210     fld_info->arr_ofst = 0;
00211     fld_info->arr_wn = NULL;
00212     fld_info->fld = fld;
00213     return fld_info;
00214   } /* New_Fld_Path_Info */
00215 
00216   static STAB_OFFSET
00217   TY2F_Fld_Size(FLD_HANDLE this_fld, mUINT64  max_size)
00218   {
00219     /* Returns the size of the field, taking into account the offset
00220      * to the next (non-equivalence) field and the maximum field-size
00221      * (based on the structure size).
00222      */
00223   
00224     mUINT64 fld_size = TY_size(FLD_type(this_fld));
00225 
00226     /* Restrict the fld_size to the max_size */
00227     if (fld_size > max_size)
00228       fld_size = max_size;
00229   
00230     /* If this_fld is an equivalence field, then just return the current
00231      * fld_size (cannot be any different), otherwise search for a non-
00232      * equivalent next_fld at a higher offset.
00233      * TODO: mfef90 & mfef77 set the flag slightly differently in COMMON.
00234      * this really works only for mfef77.
00235      */
00236 
00237     if (!FLD_equivalence(this_fld))
00238       {
00239         FLD_ITER fld_iter = Make_fld_iter(this_fld);
00240 
00241         if (!FLD_last_field (fld_iter)) 
00242           {
00243             ++fld_iter;
00244             BOOL found = FALSE;
00245             mUINT64 noffset = 0; 
00246 
00247             do
00248               {
00249                 FLD_HANDLE next_fld (fld_iter);
00250 
00251                 if (!FLD_is_bit_field(next_fld)) 
00252                   if (!(FLD_equivalence(next_fld) || FLD_ofst(this_fld) >= FLD_ofst(next_fld)))
00253                     {
00254                       found  = TRUE;
00255                       noffset =  FLD_ofst(next_fld) ;
00256                       break ;
00257                     }
00258               } while (!FLD_last_field (fld_iter ++ )) ;
00259 
00260             if (found) 
00261               if (fld_size > noffset - FLD_ofst(this_fld))
00262                 fld_size = noffset - FLD_ofst(this_fld) ;
00263           }
00264       }
00265     return fld_size;
00266   } /* TY2F_Fld_Size */
00267 
00268 
00269   static FLD_PATH_INFO *
00270   Select_Best_Fld_Path(FLD_PATH_INFO *path1,
00271                        FLD_PATH_INFO *path2,
00272                        TY_IDX         desired_ty,
00273                        mUINT64        desired_offset)
00274   {
00275     /* PRECONDITION: Both paths must be non-NULL and lead to a field
00276      *    at the desired_offset.
00277      *
00278      * Try to find the best of two paths to a field.  This routine
00279      * will be called for EVERY field at every place where a struct,
00280      * union, or equivalence field is accessed, so efficiency is of
00281      * uttmost importance.  The best path is returned, while the other
00282      * on is freed up.
00283      */
00284     FORTTK_ASSERT(path1 && path2, fortTkSupport::Diagnostics::UnexpectedInput);
00285    
00286     FLD_PATH_INFO *best_path;
00287     mUINT64        offs1, offs2;
00288     FLD_PATH_INFO *p1, *p2;
00289     TY_IDX         t1,  t2;
00290    
00291     /* Find the last field on each path */
00292     offs1 = FLD_ofst(path1->fld) + path1->arr_ofst;
00293     for (p1 = path1; p1->next != NULL; p1 = p1->next)
00294       offs1 += FLD_ofst(p1->next->fld) + p1->next->arr_ofst;
00295     offs2 = FLD_ofst(path2->fld) + path2->arr_ofst;
00296     for (p2 = path2; p2->next != NULL; p2 = p2->next)
00297       offs2 += FLD_ofst(p2->next->fld) + p2->next->arr_ofst;
00298 
00299     FORTTK_ASSERT(offs1 == desired_offset && offs2 == desired_offset,
00300                   "Unexpected offset");
00301 
00302     /* Get the element type (either the field type or the type of an
00303      * array element.
00304      */
00305     if (p1->arr_elt)
00306       t1 = TY_AR_etype(FLD_type(p1->fld));
00307     else
00308       t1 = FLD_type(p1->fld);
00309     if (p2->arr_elt)
00310       t2 = TY_AR_etype(FLD_type(p2->fld));
00311     else
00312       t2 = FLD_type(p2->fld);
00313 
00314     /* Compare types, in order of increasing accuracy */
00315     if (TY_mtype(t1) == TY_mtype(desired_ty) &&
00316         TY_mtype(t2) != TY_mtype(desired_ty))
00317       best_path = path1;
00318     else if (TY_mtype(t2) == TY_mtype(desired_ty) &&
00319              TY_mtype(t1) != TY_mtype(desired_ty))
00320       best_path = path2;
00321     else if (Stab_Identical_Types(t1, desired_ty,
00322                                   FALSE,  /* check_quals */
00323                                   TRUE,   /* check_scalars */
00324                                   FALSE)) /* ptrs_as_scalars */
00325       best_path = path1; /* path2 cannot possibly be any better */
00326     else if (Stab_Identical_Types(t2, desired_ty,
00327                                   FALSE,  /* check_quals */
00328                                   TRUE,   /* check_scalars */
00329                                   FALSE)) /* ptrs_as_scalars */
00330       best_path = path2;
00331     else
00332       best_path = path1;
00333 
00334     /* Free up the path not chosen */
00335     if (best_path == path1)
00336       TY2F_Free_Fld_Path(path2);
00337     else
00338       TY2F_Free_Fld_Path(path1);
00339 
00340     return best_path;
00341   } /* Select_Best_Fld_Path */
00342 
00343 
00344   static FLD_PATH_INFO *
00345   Construct_Fld_Path(FLD_HANDLE   fld,
00346                      TY_IDX    struct_ty,
00347                      TY_IDX    desired_ty,
00348                      mUINT64   desired_offset,
00349                      mUINT64   max_fld_size)
00350   {
00351     /* Returns the field path through "fld" found to best match the 
00352      * given offset and type.  As a minimum requirement, the offset 
00353      * must be as desired and the type must have the desired size
00354      * and alignment (with some concessions allowed for substrings).
00355      * The path is terminate with a NULL next pointer.  When no 
00356      * field matches the desired type and offset, NULL is returned.
00357      */
00358     FLD_PATH_INFO    *fld_path;
00359     const mUINT64     fld_offset = FLD_ofst(fld);
00360     TY_IDX            fld_ty = FLD_type(fld);
00361     BOOL              is_array_elt = FALSE;
00362     STAB_OFFSET       ofst_in_fld = 0;
00363   
00364     if (TY_is_f90_pointer(fld_ty))
00365       fld_ty = TY_pointed(fld_ty);
00366   
00367   
00368     /* This field cannot be on the path to a field with the given
00369      * attributes, unless the desired_offset is somewhere within
00370      * the field.
00371      */
00372 #if DBGPATH
00373     printf (" Construct: fld %s, struct %s, desired %s , des off %d \n",
00374             FLD_name(fld), TY_name(struct_ty), TY_name(desired_ty),
00375             desired_offset);
00376 #endif
00377 
00378     if (desired_offset < fld_offset ||
00379         desired_offset >= (fld_offset + TY_size(fld_ty))) {
00380       /* This field cannot be on the path to a field with the given
00381        * attributes, since the desired_offset is nowhere within
00382        * the field.
00383        */
00384       fld_path = NULL;
00385 #if DBGPATH
00386       printf ("     found NULL\n");
00387 #endif
00388     } else if (TY_Is_Array(fld_ty) && TY_is_character(fld_ty) &&
00389                TY_Is_Array(desired_ty) && TY_is_character(desired_ty)) {
00390 #if DBGPATH
00391       printf ("     found char substring\n");
00392 #endif
00393       /* A match is found! */
00394       ofst_in_fld = (desired_offset - fld_offset)/TY_size(TY_AR_etype(fld_ty));
00395       ofst_in_fld *= TY_size(TY_AR_etype(fld_ty));
00396       if ((ofst_in_fld + TY_size(desired_ty)) > TY_size(fld_ty)) {
00397         fld_path = NULL; /* The string does not fit */
00398       } else {
00399         fld_path = New_Fld_Path_Info(fld);
00400         if (TY_size(fld_ty) != TY_size(desired_ty)) {
00401           fld_path->arr_elt = TRUE;
00402           fld_path->arr_ofst = ofst_in_fld;
00403         } 
00404       }
00405     } else {
00406       /* See if the field we are looking for may be an array element */
00407     
00408       if (TY_kind(desired_ty)==KIND_POINTER)   
00409         desired_ty = TY_pointed(desired_ty);
00410       if (TY_kind(desired_ty)==KIND_ARRAY)
00411         desired_ty = TY_AR_etype(desired_ty);
00412 
00413       is_array_elt = (TY_Is_Array(fld_ty) &&
00414                       (TY_Is_Structured(TY_AR_etype(fld_ty))||
00415                        TY2F_is_character(fld_ty) ||
00416                        Stab_Identical_Types(TY_AR_etype(fld_ty), desired_ty,
00417                                             FALSE,   /* check_quals */
00418                                             FALSE,   /* check_scalars */
00419                                             TRUE))); /* ptrs_as_scalars */
00420 #if DBGPATH
00421       printf ("     is_array = %d, fld_ty %s \n",is_array_elt,TY_name(fld_ty));
00422 #endif
00423 
00424       if (is_array_elt) {
00425         fld_ty = TY_AR_etype(fld_ty);
00426         ofst_in_fld =
00427           ((desired_offset - fld_offset)/TY_size(fld_ty)) * TY_size(fld_ty);
00428       }
00429     
00430       if (TY_Is_Structured(fld_ty) &&
00431           !Stab_Identical_Types(fld_ty, desired_ty,
00432                                 FALSE,  /* check_quals */
00433                                 FALSE,  /* check_scalars */
00434                                 TRUE)) {  /* ptrs_as_scalars */
00435 #if DBGPATH
00436         printf ("     recurse \n");
00437 #endif
00438         FLD_PATH_INFO *fld_path2 = 
00439           TY2F_Get_Fld_Path(fld_ty, desired_ty, 
00440                             desired_offset - (fld_offset+ofst_in_fld));
00441       
00442         /* If a matching path was found, attach "fld" to the path */
00443         if (fld_path2 != NULL) {
00444           if (TY_split(Ty_Table[fld_ty]))
00445             fld_path = fld_path2; /* A stransparent substructure */
00446           else {
00447             fld_path = New_Fld_Path_Info(fld);
00448             fld_path->arr_elt = is_array_elt;
00449             fld_path->arr_ofst = ofst_in_fld;
00450             fld_path->next = fld_path2;
00451           }
00452         } else {
00453           fld_path = NULL;
00454         }
00455       } else { /* This may be a field we want to take into account */
00456         const STAB_OFFSET fld_size = TY2F_Fld_Size(fld, max_fld_size);
00457 
00458         /* We only match a field with the expected size, offset
00459          * and alignment.
00460          */
00461         if (desired_offset != fld_offset+ofst_in_fld || /* unexpected ofst */
00462             // fld_size < (TY_size(fld_ty)+ofst_in_fld) || /* unexpected size */
00463             TY_align(struct_ty) < TY_align(fld_ty)) {   /* unexpected align */
00464 #if DBGPATH
00465           printf ("     account - miss\n");
00466 #endif
00467         
00468           fld_path = NULL;
00469         } else { /* A match is found! */
00470 #if DBGPATH
00471           printf ("     account - match\n");
00472 #endif
00473           fld_path = New_Fld_Path_Info(fld);
00474           fld_path->arr_elt = is_array_elt;
00475           fld_path->arr_ofst = ofst_in_fld;
00476         }/*if*/
00477       } /*if*/
00478     } /*if*/
00479   
00480     return fld_path;
00481   } /* Construct_Fld_Path */
00482 
00483 
00484   static const char * 
00485   TY2F_Fld_Name(FLD_HANDLE fld, 
00486                 BOOL       common_or_equivalence,
00487                 BOOL       alt_return_name)
00488   {
00489     /* Since fields may be accessed in an unqualified manner in Fortran,
00490      * e.g. for common block members and equivalences, so we need to treat
00491      * them similar to the way we would treat regular objects.
00492      */
00493     const char *fld_name = NULL;
00494 
00495     if (common_or_equivalence && !alt_return_name) {
00496       fld_name = FLD_name(fld);
00497     } else {
00498       fld_name = FLD_name(fld);
00499     }
00500     if (fld_name == NULL || *fld_name == '\0') { fld_name = "anon-fld"; }
00501 
00502     return fld_name;
00503   } /* TY2F_Fld_Name */
00504 
00505 
00506   /*------ Utilities for accessing and declaring KIND_STRUCTs ------
00507    *----------------------------------------------------------------*/
00508 
00509   static void
00510   TY2F_Equivalence(xml::ostream& xos, 
00511                    const char  *equiv_name, 
00512                    const char  *fld_name,
00513                    STAB_OFFSET  fld_ofst)
00514   {
00515     /* Append one equivalence statement to the tokens buffer,
00516      * keeping in mind that the equiv_name is based at index 1. */
00517     xos << "EQUIVALENCE(" << equiv_name; /* equiv_name at given offset */
00518     xos << "(" << Num2Str(fld_ofst, "%lld") << "),";
00519     xos << fld_name << ")";  /* fld_name at offset zero */
00520   } /* TY2F_Equivalence */
00521 
00522 
00523   static void
00524   TY2F_Equivalence_FldList(xml::ostream& xos, 
00525                            FLD_HANDLE   fldlist,
00526                            UINT         equiv_var_idx,
00527                            mUINT64      ofst,
00528                            BOOL        *common_block_equivalenced)
00529   {
00530     FLD_ITER fld_iter = Make_fld_iter(fldlist);
00531 
00532     do {
00533       FLD_HANDLE fld (fld_iter);
00534 
00535       if (TY_split(Ty_Table[FLD_type(fld)]))
00536         {
00537           TY2F_Equivalence_FldList(xos, 
00538                                    TY_flist(Ty_Table[FLD_type(fld)]),
00539                                    equiv_var_idx,
00540                                    ofst + FLD_ofst(fld),
00541                                    common_block_equivalenced);
00542         }
00543       else if (FLD_equivalence(fld) || !*common_block_equivalenced)
00544         {
00545           xos << std::endl;
00546           const char* tmpvar = StrCat("tmp", Num2Str(equiv_var_idx, "%d"));
00547           TY2F_Equivalence(xos, tmpvar, TY2F_Fld_Name(fld_iter, TRUE/*equiv*/,
00548                                                       FALSE/*alt_ret*/),
00549                            ofst + FLD_ofst(fld));
00550           if (!FLD_equivalence(fld))
00551             *common_block_equivalenced = TRUE;
00552         }
00553 
00554     }
00555     while (!FLD_last_field (fld_iter++)) ;
00556 
00557   } /* TY2F_Equivalence_FldList */
00558 
00559 
00560   static void
00561   TY2F_Equivalence_List(xml::ostream& xos, 
00562                         const TY_IDX struct_ty)
00563   {
00564     /* Append a nameless EQUIVALENCE specification statement for
00565      * each equivalence field in the given struct.  Declare a 
00566      * dummy symbol as an array of INTEGER*1 elements to represent
00567      * the structure and each EQUIVALENCE specification will then 
00568      * equivalence a field to this dummy-symbol at the field offset.
00569      *
00570      * Group these declarations together by prepending each 
00571      * declaration (including the first one) with a newline.
00572      *
00573      * For COMMON blocks, it is also necessary to emit one element
00574      * that is not an equivalence!
00575      */
00576     TY_IDX     equiv_ty;
00577     UINT       equiv_var_idx;
00578     BOOL       common_block_equivalenced = FALSE;
00579 
00580     /* Declare an INTEGER*1 array (or CHARACTER string?) variable
00581      * to represent the whole equivalenced structure. Don't unlock
00582      * the tmpvar, or a similar equivalence group (ie: TY) will 
00583      * get the same temp.
00584      */
00585     equiv_ty = Stab_Array_Of(Stab_Mtype_To_Ty(MTYPE_I1), TY_size(struct_ty));
00586     equiv_var_idx = Stab_Lock_Tmpvar(equiv_ty, &ST2F_Declare_Tempvar);
00587 
00588     /* Relate every equivalence field to the temporary variable.
00589      */
00590     TY2F_Equivalence_FldList(xos, 
00591                              TY_flist(Ty_Table[struct_ty]),
00592                              equiv_var_idx,
00593                              0, /* Initial offset */
00594                              &common_block_equivalenced);
00595 
00596   } /* TY2F_Equivalence_List */
00597 
00598   // static void
00599   // TY2F_Translate_Structure(xml::ostream& xos, TY_IDX ty)
00600   // {
00601   //   FORTTK_ASSERT(TY_kind(ty) == KIND_STRUCT, "Unexpected type " << TY_kind(ty));
00602 
00603   //   FLD_ITER     fld_iter;
00604   //   TY& ty_rt  = Ty_Table[ty];
00605 
00606   //   PUXlationContext ctxt;// FIXME
00607 
00608   //   xos << std::endl;
00609   
00610   //   /* Emit structure header */
00611   //   xos << "TYPE " << TY_name(ty);
00612   
00613   //   if (TY_is_sequence(ty_rt)) {
00614   //     xos << std::endl << "SEQUENCE ";
00615   //   }
00616   
00617   //   /* Emit structure body */
00618   //   FLD_IDX flist = ty_rt.Fld();
00619   
00620   //   if (flist != 0) {
00621   //     fld_iter = Make_fld_iter(TY_flist(ty_rt));
00622   //     do {
00623   //       FLD_HANDLE fld (fld_iter);
00624       
00625   //       /* if it's a bitfield, then assume it's part of a dope vector & */
00626   //       /* just put out the name of the first bitfield in this I4       */
00627   //       if (NOT_BITFIELD_OR_IS_FIRST_OF_BITFIELD(fld_iter)) {
00628   //    /* See if this field starts a map or a union */
00629         
00630   //    xos << std::endl;
00631   //    if (FLD_begin_union(fld)) {
00632   //      xos << "  UNION" << std::endl;
00633   //    } else if (FLD_begin_map(fld)) {
00634   //      xos << "  MAP" << std::endl;
00635   //    }
00636         
00637   //    /* Declare this field */
00638   //    if (FLD_is_pointer(fld)) {
00639   //      xos << ",POINTER::";
00640   //    }
00641 
00642   //    xos << TY2F_Fld_Name(fld_iter, FALSE/*common*/, FALSE/*alt_ret_name*/);
00643         
00644   //    if (FLD_is_pointer(fld) && (TY_kind(FLD_type(fld)) == KIND_ARRAY)) {
00645   //      TY2F_array_for_pointer(xos, FLD_type(fld), ctxt);
00646   //    } else {
00647   //      TY2F_translate(xos, FLD_type(fld), ctxt);
00648   //    }
00649         
00650   //    /* See if this field terminates a map or union */
00651   //    if (FLD_end_union(fld)) {
00652   //      xos << std::endl << "END UNION";
00653   //    } else if (FLD_end_map(fld)) {
00654   //      xos << std::endl << "END MAP";
00655   //    }
00656   //       }       
00657   //     } while (!FLD_last_field (fld_iter++)) ;
00658   //   }
00659   
00660   //   /* Emit structure tail */
00661   //   xos << std::endl;
00662   //   xos << "END TYPE" << std::endl;
00663   // }
00664 
00665 
00666   static void
00667   TY2F_Translate_EquivCommon_PtrFld(xml::ostream& xos, FLD_HANDLE fld)
00668   {
00669     assert(0);
00670   }
00671 
00672   static void
00673   TY2F_Declare_Common_Flds(xml::ostream& xos,
00674                            FLD_HANDLE   fldlist, 
00675                            BOOL         alt_return, /* Alternate return points */
00676                            BOOL        *is_equiv)   /* out */
00677   {
00678     assert(0);
00679   } 
00680 
00681   static void
00682   TY2F_List_Common_Flds(xml::ostream& xos, FLD_HANDLE fldlist)
00683   {
00684     FLD_ITER fld_iter = Make_fld_iter(fldlist);
00685 
00686     do {
00687       FLD_HANDLE fld (fld_iter);
00688       TY & ty  = Ty_Table[FLD_type(fld)];       
00689     
00690       if (TY_split(ty)) {
00691         /* Treat a full split element as a transparent data-structure */
00692         TY2F_List_Common_Flds(xos, TY_flist(ty));
00693       } else if (!FLD_equivalence(fld)) {
00694         xos << TY2F_Fld_Name(fld_iter, TRUE/*common*/, FALSE/*alt_ret_name*/);
00695       }
00696     
00697       if (!FLD_last_field(fld)) {
00698         FLD_ITER  next_iter = fld_iter ;
00699         FLD_HANDLE next (++next_iter);
00700         if (!FLD_equivalence(next))
00701           xos << ',';
00702       }
00703     
00704     } while (!FLD_last_field (fld_iter++)) ;
00705 
00706   } /* TY2F_List_Common_Flds */
00707 
00708   /*------------- Hidden routines to declare variable types -------------*/
00709   /*---------------------------------------------------------------------*/
00710 
00711   static void
00712   TY2F_invalid(xml::ostream& xos, TY_IDX ty, PUXlationContext& ctxt)
00713   {
00714     FORTTK_DIE(fortTkSupport::Diagnostics::UnexpectedInput << TY_kind(Ty_Table[ty]));
00715   }
00716 
00717   static void
00718   TY2F_scalar(xml::ostream& xos, TY_IDX ty_idx, PUXlationContext& ctxt)
00719   {
00720     FORTTK_ASSERT(TY_kind(ty_idx) == KIND_SCALAR, fortTkSupport::Diagnostics::UnexpectedInput);
00721   
00722     TY&   ty = Ty_Table[ty_idx];
00723     MTYPE mt = TY_mtype(ty);
00724 
00725     const char* type_str;
00726     if (TY_is_character(ty)) {
00727       type_str = "CHARACTER";
00728     } else if (TY_is_logical(ty)) {
00729       type_str = "LOGICAL";
00730     } else {
00731       switch(mt) {
00732       case MTYPE_U1: // Strictly speaking unsigned integers not supported
00733       case MTYPE_U2: // in Fortran, but we are lenient and treat them
00734       case MTYPE_U4: // as the signed equivalent.
00735       case MTYPE_U8:
00736       
00737       case MTYPE_I1:
00738       case MTYPE_I2:
00739       case MTYPE_I4:
00740       case MTYPE_I8:
00741         type_str = "INTEGER";
00742         break;
00743       
00744       case MTYPE_F4:
00745       case MTYPE_F8:
00746       case MTYPE_FQ:
00747         type_str = "REAL";
00748         break;
00749       
00750       case MTYPE_C4:
00751       case MTYPE_C8:
00752       case MTYPE_CQ:
00753         type_str = "COMPLEX";
00754         break;
00755       
00756       case MTYPE_M:
00757         type_str = "memory block";
00758         break;
00759       
00760       default:
00761         FORTTK_DIE("Unexpected type " << MTYPE_name(mt));
00762       }
00763     }
00764   
00765     const char* size_str;
00766     INT64 size;
00767     if (TY_size(ty) > 0) {
00768       if (ctxt.isF90() && MTYPE_is_complex(mt)) {
00769         size = TY_size(ty) / 2; 
00770       } else {
00771         size = TY_size(ty);
00772       }
00773       size_str = Num2Str(size, "%lld");
00774     } else {
00775       if (mt == MTYPE_M) {
00776         size_str = ".mblock.";
00777       } else {
00778         FORTTK_ASSERT(TY_is_character(ty), 
00779                       "Unexpected type size " << TY_size(ty));
00780         size_str = "*";
00781       }
00782     }
00783 
00784     const char* str = StrCat(type_str, size_str);
00785 
00786     xos << xml::BegElem("xaif:Property") << xml::Attr("id", ctxt.currentXlationContext().getNewVertexId()) 
00787         << xml::Attr("name", "type") << xml::Attr("value", str) << xml::EndElem;
00788 
00789     xos << xml::BegElem("xaif:Property") << xml::Attr("id", ctxt.currentXlationContext().getNewVertexId()) 
00790         << xml::Attr("name", "whirltype") << xml::Attr("value", TY_name(ty)) << xml::EndElem;
00791   }
00792 
00793   static void
00794   TY2F_array(xml::ostream& xos, TY_IDX ty_idx, PUXlationContext& ctxt)
00795   {
00796     TY& ty = Ty_Table[ty_idx];
00797 
00798     FORTTK_ASSERT(TY_kind(ty) == KIND_ARRAY, fortTkSupport::Diagnostics::UnexpectedInput);
00799 
00800     xos << xml::BegElem("xaif:Property") << xml::Attr("id", ctxt.currentXlationContext().getNewVertexId()) 
00801         << xml::Attr("name", "whirlkind") << xml::Attr("value", "array") << xml::EndElem;
00802 
00803 
00804     if (TY_is_character(ty)) { // FIXME
00805       // A character string... 
00806       if (TY_size(ty) > 0) /* ... of known size */
00807         xos << "CHARACTER*" << Num2Str(TY_size(ty), "%lld");
00808       else /* ... of unknown size */
00809         xos << "CHARACTER*(*)";
00810 
00811     } else {
00812       // A regular array, so prepend the element type and append
00813       // the index bounds.
00814       ARB_HANDLE arb_base = TY_arb(ty);
00815       INT32 dim = ARB_dimension(arb_base) ;
00816       INT32 co_dim = ARB_co_dimension(arb_base);
00817       INT32 array_dim = dim - co_dim;
00818       INT32 revdim = 0;
00819 
00820       if (ARB_co_dimension(arb_base) <= 0) {
00821         co_dim = 0;
00822         array_dim = dim;
00823       }
00824 
00825       // 1. Translate element type
00826       xos << xml::BegElem("xaif:Property") << xml::Attr("id", ctxt.currentXlationContext().getNewVertexId()) 
00827           << xml::Attr("name", "ArrayElementType");
00828 
00829       // Do not permit pointers as elements of arrays, so just use
00830       // the corresponding integral type instead.  We do not expect
00831       // such pointers to be dereferenced anywhere. (FIXME)
00832       if (TY_Is_Pointer(TY_AR_etype(ty)))
00833         TY2F_translate(xos, Stab_Mtype_To_Ty(TY_mtype(TY_AR_etype(ty))), ctxt);
00834       else
00835         TY2F_translate(xos, TY_AR_etype(ty), ctxt);
00836     
00837       xos << xml::EndElem;
00838 
00839       // 2. Translate dimension attributes
00840       while (array_dim > 0) {
00841       
00842         xos << xml::BegElem("xaif:Property") << xml::Attr("id", ctxt.currentXlationContext().getNewVertexId()) 
00843             << xml::Attr("name", "ArrayDimensionAttr") << xml::Attr("dim", dim);
00844       
00845         ARB_HANDLE arb = arb_base[dim-1];
00846         TY2F_Append_ARB(xos, arb, ty_idx, ctxt);
00847       
00848         xos << xml::EndElem;
00849       
00850         array_dim--;
00851         dim--;
00852         revdim++;
00853       } 
00854 
00855       // 3. What is this???
00856       dim = ARB_dimension(arb_base);
00857       array_dim = dim - co_dim;
00858       --dim;
00859     
00860       if (co_dim > 0) {
00861         xos << '[';
00862         while (co_dim > 0) {
00863           ARB_HANDLE arb = arb_base[dim-array_dim];
00864         
00865 
00866           if (TY_is_f90_deferred_shape(ty))
00867             TY2F_Append_ARB(xos, arb, ty_idx, ctxt);
00868           else {
00869             if (co_dim == 1)
00870               TY2F_Append_ARB(xos, arb, ty_idx, ctxt); // TRUE
00871             else
00872               TY2F_Append_ARB(xos, arb, ty_idx, ctxt); // FALSE
00873           }
00874         
00875           dim--;
00876 
00877           if (co_dim > 1)
00878             xos << ',';
00879 
00880           co_dim--;
00881           ++revdim;
00882         }
00883         xos << ']';
00884       }
00885 
00886     }
00887   } /* TY2F_array */
00888 
00889 
00890   static void
00891   TY2F_array_for_pointer(xml::ostream& xos, TY_IDX ty_idx, PUXlationContext& ctxt)
00892   {
00893     TY& ty = Ty_Table[ty_idx] ;
00894 
00895     FORTTK_ASSERT(TY_kind(ty) == KIND_ARRAY, fortTkSupport::Diagnostics::UnexpectedInput);
00896   
00897     if (TY_is_character(ty)) {
00898       /* A character string...
00899        */
00900       if (TY_size(ty) > 0) /* ... of known size */
00901         xos << "CHARACTER*" << Num2Str(TY_size(ty), "%lld");
00902       else /* ... of unknown size */
00903         xos << "CHARACTER*(*)";
00904     } else {
00905       /* A regular array, so prepend the element type and append
00906        * the index bounds.
00907        */
00908       ARB_HANDLE arb_base = TY_arb(ty);
00909       INT32       dim = ARB_dimension(arb_base) ;
00910       INT32       co_dim = ARB_co_dimension(arb_base);
00911       INT32       array_dim = dim-co_dim;
00912       INT32       revdim = 0;
00913     
00914       /* Do not permit pointers as elements of arrays, so just use
00915        * the corresponding integral type instead.  We do not expect
00916        * such pointers to be dereferenced anywhere.
00917        */
00918       if (TY_Is_Pointer(TY_AR_etype(ty)))
00919         TY2F_translate(xos, Stab_Mtype_To_Ty(TY_mtype(TY_AR_etype(ty))), ctxt);
00920       else
00921         TY2F_translate(xos, TY_AR_etype(ty), ctxt);
00922     
00923       if (ARB_co_dimension(arb_base)<=0) {
00924         co_dim=0;
00925         array_dim = dim;
00926       }
00927     
00928       if (array_dim>0) {
00929         xos << "(";
00930       
00931         while (array_dim > 0) {
00932           ARB_HANDLE arb = arb_base[dim-1];
00933           xos << ':';
00934           if (array_dim-- > 1)
00935             xos << ',';
00936         
00937           --dim;
00938           ++revdim;
00939         }
00940       
00941         xos << ')';
00942       }
00943     
00944       dim = ARB_dimension(arb_base);
00945       array_dim = dim - co_dim;
00946       --dim;
00947     
00948       if (co_dim > 0) {
00949         xos << '[';
00950         while (co_dim > 0) {
00951           ARB_HANDLE arb = arb_base[dim-array_dim];
00952           xos << ':';
00953           dim--;
00954 
00955           if (co_dim-- > 1)
00956             xos << ',';
00957         
00958           ++revdim;
00959         }
00960         xos << ']';
00961       }
00962     }
00963   } /* TY2F_array_for_pointer */
00964 
00965 
00966   static void
00967   TY2F_struct(xml::ostream& xos, TY_IDX ty, PUXlationContext& ctxt)
00968   {
00969     /* Structs are supported by VAX-Fortran and Fortran-90.  Note
00970      * that we here emit a RECORD declaration, while we expect
00971      * the STRUCTURE to have been declared through a call to
00972      * TY2F_Translate_Structure().
00973      */
00974     TY& ty_rt = Ty_Table[ty];
00975     FORTTK_ASSERT(TY_kind(ty_rt) == KIND_STRUCT, fortTkSupport::Diagnostics::UnexpectedInput);
00976   
00977     xos << "(" << TY_name(ty) << ")" << "TYPE";
00978   
00979 #if 0 // see Open64 stab_attr.cxx; if needed simulate thru PUXlationContext
00980     if (!TY_is_translated_to_c(ty)) {
00981       TY2F_Translate_Structure(xos, ty);
00982       Set_TY_is_translated_to_c(ty); /* Really, translated to Fortran, not C */
00983     }
00984 #endif
00985   }
00986 
00987 
00988   static void
00989   TY2F_2_struct(xml::ostream& xos, TY_IDX ty, PUXlationContext& ctxt)
00990   {
00991     /* Structs are supported by VAX-Fortran and Fortran-90.  Note
00992      * that we here emit a RECORD declaration, while we expect
00993      * the STRUCTURE to have been declared through a call to
00994      * TY2F_Translate_Structure().
00995      */
00996     TY & ty_rt = Ty_Table[ty];
00997     FORTTK_ASSERT(TY_kind(ty_rt) == KIND_STRUCT, fortTkSupport::Diagnostics::UnexpectedInput);
00998 
00999 #if 0 // see Open64 stab_attr.cxx; if needed simulate thru PUXlationContext
01000     if (!TY_is_translated_to_c(ty)) {
01001       TY2F_Translate_Structure(xos, ty);
01002       Set_TY_is_translated_to_c(ty); /* Really, translated to Fortran, not C */
01003     }
01004 #endif
01005   }
01006 
01007 
01008   static void
01009   TY2F_pointer(xml::ostream& xos, TY_IDX ty, PUXlationContext& ctxt)
01010   {
01011     /* Is a dope vector base address? Put out an integer large enough */
01012     /* to hold an address for now. Don't really want POINTER because  */
01013     /* implies cray/f90 pointer instead of address slot               */
01014   
01015     if (TY2F_Pointer_To_Dope(ty)) {
01016 #if 0
01017       Prepend_Token_String(xos,",POINTER ::");
01018 #endif
01019       TY2F_translate(xos,Be_Type_Tbl(Pointer_Mtype), ctxt);
01020     } else {
01021       /* avoid recursive type declarations */
01022       if (TY_kind(TY_pointed(ty)) == KIND_STRUCT) {
01023 #if 0
01024         Prepend_Token_String(xos,",POINTER ::");
01025         Prepend_Token_String(xos, TY_name(TY_pointed(ty)));
01026 #endif
01027         TY2F_translate(xos,Be_Type_Tbl(Pointer_Mtype), ctxt);
01028       
01029       } else
01030         TY2F_translate(xos,TY_pointed(ty), ctxt);
01031     }
01032   } /* TY2F_pointer */
01033 
01034   static void
01035   TY2F_void(xml::ostream& xos, TY_IDX ty_idx, PUXlationContext& ctxt)
01036   {
01037     TY& ty = Ty_Table[ty_idx];
01038     FORTTK_ASSERT(TY_kind(ty) == KIND_VOID, fortTkSupport::Diagnostics::UnexpectedInput);
01039     xos << std::endl << "! <Void Type>";
01040   }
01041 
01042   /*------------------------ exported routines --------------------------*/
01043   /*---------------------------------------------------------------------*/
01044 
01045 
01046   // JU: I don't think the conditions under which this method is called
01047   // in the rest of the code are ever satisfied. 
01048   void 
01049   TY2F_Translate_ArrayElt(xml::ostream& xos, 
01050                           TY_IDX       arr_ty_idx,
01051                           STAB_OFFSET  arr_ofst)
01052   {  
01053         std::cout << "TEMP WARNING" << std::endl; 
01054   }
01055 
01056 
01057   void
01058   TY2F_Translate_Common(xml::ostream& xos, const char *name, TY_IDX ty_idx)
01059   {
01060     TY& ty = Ty_Table[ty_idx];
01061     BOOL is_equiv = FALSE;
01062   
01063     FORTTK_ASSERT(TY_kind(ty) == KIND_STRUCT, 
01064                   fortTkSupport::Diagnostics::UnexpectedInput << TY_kind(ty));
01065 
01066     // Emit specification statements for every element of the common
01067     // block, including equivalences.
01068     xos << xml::BegComment << "COMMON";
01069     if (name != NULL && *name != '\0') { xos << " name = " << name; }
01070     xos << xml::EndComment;
01071 
01072 #if 0 // FIXME
01073     TY2F_List_Common_Flds(xos, TY_flist(ty));
01074   
01075     // variables in common block type declaration
01076     TY2F_Declare_Common_Flds(xos, TY_flist(ty), FALSE /*alt_return*/, &is_equiv);
01077   
01078     // Emit equivalences, if there are any
01079     if (is_equiv)
01080       TY2F_Equivalence_List(xos, ty_idx /*struct_ty*/);
01081 #endif
01082   }
01083 
01084 
01085   void
01086   TY2F_Translate_Equivalence(xml::ostream& xos, TY_IDX ty_idx, BOOL alt_return)
01087   {
01088     /* When alt_return==TRUE, this represents an alternate return variable,
01089      * in which case we should declare the elements of the equivalence
01090      * with unmangled names and ignore the fact that they are in an
01091      * equivalence.  The first element in such an alternate return is
01092      * the function/subprogram return-variable, which we should never
01093      * declare.
01094      */
01095     TY& ty = Ty_Table[ty_idx];
01096 
01097     FLD_HANDLE first_fld;
01098     BOOL is_equiv;
01099    
01100     FORTTK_ASSERT(TY_kind(ty) == KIND_STRUCT, 
01101                   fortTkSupport::Diagnostics::UnexpectedInput << TY_kind(ty));
01102 
01103     if (alt_return) {
01104       first_fld = FLD_next(TY_flist(ty)); /* skip func_entry return var */
01105     } else {
01106       first_fld = TY_flist(ty);
01107     }
01108 
01109     /* Emit specification statements for every element of the
01110      * equivalence block.
01111      */  
01112     TY2F_Declare_Common_Flds(xos, first_fld, alt_return,
01113                              &is_equiv);  /* Redundant in this call */
01114 
01115     if (!alt_return)
01116       TY2F_Equivalence_List(xos, ty_idx /*struct_ty*/);
01117 
01118   } /* TY2F_Translate_Equivalence */
01119 
01120 
01121   FLD_PATH_INFO * 
01122   TY2F_Free_Fld_Path(FLD_PATH_INFO *fld_path)
01123   {
01124     FLD_PATH_INFO *free_list;
01125    
01126     if (fld_path != NULL) {
01127       free_list = Free_Fld_Path_Info;
01128       Free_Fld_Path_Info = fld_path;
01129       while (fld_path->next != NULL)
01130         fld_path = fld_path->next;
01131       fld_path->next = free_list;
01132     }
01133     return NULL;
01134   } /* TY2F_Free_Fld_Path */
01135 
01136 
01137   FLD_PATH_INFO * 
01138   TY2F_Get_Fld_Path(const TY_IDX struct_ty, const TY_IDX object_ty, 
01139                     STAB_OFFSET offset)
01140   {
01141     FLD_PATH_INFO* fld_path;
01142     FLD_PATH_INFO* fld_path2 = NULL;
01143     TY& s_ty = Ty_Table[struct_ty];
01144     FLD_ITER fld_iter;
01145 
01146     FORTTK_ASSERT(TY_kind(s_ty) == KIND_STRUCT, 
01147                   fortTkSupport::Diagnostics::UnexpectedInput << TY_kind(s_ty));
01148   
01149     /* Get the best matching field path into fld_path2 */
01150     fld_iter = Make_fld_iter(TY_flist(s_ty));
01151   
01152     do {
01153       FLD_HANDLE fld (fld_iter);
01154     
01155       if (NOT_BITFIELD_OR_IS_FIRST_OF_BITFIELD(fld_iter)) {
01156         fld_path = Construct_Fld_Path(fld_iter, struct_ty, object_ty,
01157                                       offset, TY_size(s_ty));
01158         if (fld_path2 == NULL)
01159           fld_path2 = fld_path;
01160         else if (fld_path != NULL)
01161           fld_path2 = Select_Best_Fld_Path(fld_path2, fld_path, object_ty,
01162                                            offset);
01163       }
01164     } while (!FLD_last_field (fld_iter++));
01165   
01166     /* POSTCONDITION: fld_path2 points to the best match found */
01167     return fld_path2;
01168   }
01169 
01170   void
01171   TY2F_Translate_Fld_Path(xml::ostream&   xos,
01172                           FLD_PATH_INFO *fld_path, 
01173                           BOOL           deref, 
01174                           BOOL           member_of_common, 
01175                           BOOL           alt_ret_name,
01176                           PUXlationContext& ctxt)
01177   {
01178     /* Append the name of each field to the tokens, separated them
01179      * from each other by the field-selection operator ('.').  The
01180      * first name on the path may optionally be emitted in unclobbered 
01181      * form, as it may represent an alternate return point.
01182      */
01183     while (fld_path != NULL) {
01184       FLD_HANDLE f (fld_path->fld);
01185       const char* str = TY2F_Fld_Name(f, member_of_common, alt_ret_name);
01186       if (deref && TY_Is_Pointer(FLD_type(f))) {
01187         str = StrCat("deref_", str); // W2CF_Symtab_Nameof_Fld_Pointee(f);
01188       }
01189       xos << xml::BegElem("TYFLD") << xml::Attr("***name", str) << xml::EndElem;
01190 
01191       member_of_common = FALSE; /* Can only be true first time around */
01192     
01193       /* if an array element, form the subscript list. If an OPC_ARRAY */
01194       /* provides the subscripts, use it o/w use offset                */
01195       if (fld_path->arr_elt) {
01196         if (fld_path->arr_wn != NULL)
01197           WN2F_array_bounds(xos, fld_path->arr_wn, FLD_type(f), ctxt);
01198       }
01199     
01200       /* Separate fields with the dot-notation. */
01201       fld_path = fld_path->next;
01202       if (fld_path != NULL) {
01203         TY2F_Fld_Separator(xos) ;
01204         alt_ret_name = FALSE; /* Only applies to first field on the path */
01205       }
01206     } /* while */
01207   
01208   } /* TY2F_Translate_Fld_Path */
01209 
01210 
01211   extern void
01212   TY2F_Fld_Separator(xml::ostream& xos)
01213   {
01214     /* puts out the appropriate structure component separator*/
01215     xos << '%';
01216   }
01217 
01218   extern FLD_HANDLE
01219   TY2F_Last_Fld(FLD_PATH_INFO *fld_path)
01220   {
01221     FLD_HANDLE f = FLD_HANDLE () ;
01222 
01223     while (fld_path != NULL) {
01224       f = fld_path->fld;
01225       fld_path = fld_path->next ;
01226     }
01227   
01228     return f;
01229   }
01230 
01231   extern FLD_PATH_INFO * 
01232   TY2F_Point_At_Path(FLD_PATH_INFO * path, STAB_OFFSET off)
01233   {
01234     /* given a fld path, return a pointer to */
01235     /* the slot at the given offset          */
01236     while (path != NULL) {
01237       if ((INT64)FLD_ofst(path->fld) >= off)
01238         break ;    
01239       path=path->next;
01240     }
01241     return path;
01242   }
01243 
01244   extern void
01245   TY2F_Dump_Fld_Path(FLD_PATH_INFO *fld_path)
01246   {
01247     printf ("path ::");
01248     while (fld_path != NULL) {
01249       FLD_HANDLE f = fld_path->fld;
01250     
01251       printf ("%s(#%d)",TY2F_Fld_Name(f,FALSE,FALSE),f.Idx ());
01252     
01253       if (fld_path->arr_elt)
01254         printf (" array");
01255     
01256       if (fld_path->arr_ofst)
01257         printf (" offset 0x%x",(mINT32) fld_path->arr_ofst);
01258     
01259       if (fld_path->arr_wn != NULL)
01260         printf (" tree 0x%p",fld_path->arr_wn);
01261     
01262       printf (" ::");
01263       fld_path = fld_path->next ;
01264     }
01265     printf ("\n");
01266   }
01267 
01268 
01269   // ***************************************************************************
01270   //
01271   // ***************************************************************************
01272 
01273 
01274   const char*
01275   TranslateTYToSymType(TY_IDX ty_idx)
01276   {
01277     TY& ty = Ty_Table[ty_idx];
01278     const char* str = NULL;
01279 
01280     if (TY_kind(ty) == KIND_SCALAR) {
01281       MTYPE mt = TY_mtype(ty);
01282       if (TY_is_character(ty)) {
01283         str = "char"; 
01284       } 
01285       else if (TY_is_logical(ty)) {
01286         str = "bool"; 
01287       } 
01288       else if (MTYPE_is_integral(mt)) {
01289         str = "integer"; 
01290       } 
01291       else if (MTYPE_is_complex(mt)) { /* must come before 'float' */
01292         str = "complex";
01293       } 
01294       else if (MTYPE_is_float(mt)) { 
01295         str = "real"; 
01296       }
01297     } 
01298     else if (TY_kind(ty) == KIND_ARRAY) {
01299       if (TY_is_character(ty)) { 
01300         str = "string"; 
01301       } 
01302       else {
01303         // Do not permit pointers as elements of arrays, so just use
01304         // the corresponding integral type instead.  We do not expect
01305         // such pointers to be dereferenced anywhere. (FIXME)
01306         TY_IDX ety_idx = TY_AR_etype(ty);
01307         if (TY_Is_Pointer(ety_idx)) {
01308           ety_idx = Stab_Mtype_To_Ty(TY_mtype(ety_idx));
01309         } 
01310         str = TranslateTYToSymType(ety_idx);
01311       }
01312     } 
01313     else if (TY_kind(ty) == KIND_STRUCT 
01314              || 
01315              TY_kind(ty) == KIND_INVALID) {
01316       // the latter applies to symbols that are f90 interface names
01317       str = "opaque";
01318     }  
01319     else if (TY_kind(ty) == KIND_FUNCTION) {
01320       str = "void";
01321     } 
01322     else if (TY_kind(ty) == KIND_POINTER) { 
01323       str = "opaque";
01324       if (TY_kind(TY_pointed(ty)) == KIND_FUNCTION) {
01325         str = "void";
01326       }
01327     } 
01328     else 
01329       FORTTK_DIE("whirl2xaif::TranslateTYToSymType: no logic to handle type of kind " << TY_kind(ty));
01330     return str;
01331   }
01332 
01333   const char*
01334   TranslateTYToMType(TY_IDX ty_idx) {
01335     TY& ty_r = Ty_Table[ty_idx];
01336     if (TY_kind(ty_r) == KIND_SCALAR) {
01337       return Mtype_Name(TY_mtype(ty_r));
01338     } 
01339     else if (TY_kind(ty_r) == KIND_ARRAY) {
01340       if (TY_is_character(ty_r)) { 
01341         return Mtype_Name(TY_mtype(ty_r));
01342       } 
01343       else {
01344         // Do not permit pointers as elements of arrays, so just use
01345         // the corresponding integral type instead.  We do not expect
01346         // such pointers to be dereferenced anywhere. (FIXME)
01347         TY_IDX ety_idx = TY_AR_etype(ty_r);
01348         if (TY_Is_Pointer(ety_idx)) {
01349           ety_idx = Stab_Mtype_To_Ty(TY_mtype(ety_idx));
01350         } 
01351         return TranslateTYToMType(ety_idx);
01352       }
01353     } 
01354     else if (TY_kind(ty_r) == KIND_STRUCT 
01355              || 
01356              TY_kind(ty_r) == KIND_INVALID
01357              ||
01358              TY_kind(ty_r) == KIND_FUNCTION) { 
01359       return Mtype_Name(TY_mtype(ty_r));
01360     } 
01361     else if (TY_kind(ty_r) == KIND_POINTER) { 
01362       return TranslateTYToMType(TY_pointed(ty_r));
01363     } 
01364     else 
01365       FORTTK_DIE("whirl2xaif::TranslateTYToMType: no logic to handle type of kind " << TY_kind(ty_r));
01366     return "";
01367   }
01368 
01369   const char*
01370   TranslateTYToSymShape(TY_IDX ty_idx)
01371   {
01372     TY& ty = Ty_Table[ty_idx];
01373     const char* str = NULL;
01374   
01375     if (TY_kind(ty) == KIND_SCALAR) {
01376       str = "scalar";
01377     } 
01378     else if (TY_kind(ty) == KIND_ARRAY) {
01379     
01380       ARB_HANDLE arb_base = TY_arb(ty);
01381       INT32 dim = ARB_dimension(arb_base);
01382       // ARB_co_dimension(arb_base) <= 0 FIXME
01383 
01384       if (TY_is_character(ty)) { 
01385         str = "scalar"; 
01386       } 
01387       else {
01388         switch (dim) {
01389         case 1:  str = "vector"; break;
01390         case 2:  str = "matrix"; break;
01391         case 3:  str = "three_tensor"; break;
01392         case 4:  str = "four_tensor"; break;
01393         case 5:  str = "five_tensor"; break;
01394         case 6:  str = "six_tensor"; break;
01395         case 7:  str = "seven_tensor"; break;
01396         default: 
01397           FORTTK_DIE("Invalid array dimension: " << dim);
01398         }
01399       }
01400 
01401     } 
01402     else if (TY_kind(ty) == KIND_STRUCT
01403              || 
01404              TY_kind(ty) == KIND_INVALID) {
01405       // the latter applies to symbols that are f90 interface names
01406       str = "scalar"; // FIXME
01407     }  
01408     else if ((TY_kind(ty) == KIND_POINTER) &&
01409              (TY_kind(TY_pointed(ty)) == KIND_FUNCTION)) {
01410       str = "void";
01411     }
01412   
01413     return str;
01414   }
01415 
01416 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines