Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
targ_em_const.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  *  10-Feb-95 - Original Version
00042  *
00043  * Description:
00044  *
00045  * This file was originally part of targ_const.c.  The CG-related routines
00046  * are moved into this file.
00047  *
00048  * Refer to targ_const.c for details of description.
00049  * ====================================================================
00050  * ====================================================================
00051  */
00052 
00053 #include <elf.h>
00054 #include <ctype.h>
00055 
00056 #define USE_STANDARD_TYPES 1 
00057 #include "defs.h"
00058 #include "targ_const.h"
00059 #include "targ_const_private.h"
00060 #include "erglob.h"                 /* EC_Inv_Mtype */
00061 #include "errors.h"                 /* Is_True(), ErrMsg(), etc. */
00062 #include "config_asm.h"             /* ASM_CMNT, etc. */
00063 
00064 #ifndef QIKKI_BE
00065 #include "stab.h"                   /* TY */
00066 #endif 
00068 #define APPEND_TO_DBUF(a,b) a = Targ_Append_To_Dbuf(a,b)
00069 
00070 
00071 // has char that can't be printed in string directive
00072 static BOOL
00073 Has_Control_Char (char *str, INT len)
00074 {
00075         INT i;
00076         for (i = 0; i < len; ++i) {
00077                 if (iscntrl(str[i]))
00078                         return TRUE;
00079                 if (str[i] == '"')
00080                         return TRUE;
00081                 if (str[i] == '\\')
00082                         return TRUE;
00083         }
00084         return FALSE;
00085 }
00086 
00087 /* ====================================================================
00088  *
00089  * Targ_Emit_String
00090  *
00091  * This routine emits constant strings to the file fl.  The string is
00092  * defined by a pointer (str) and a length (len).  This routine must
00093  * *always* output assembler commands which will occupy *exactly* len 
00094  * bytes in the .o file, since the caller is relying on that.  If the 
00095  * str[len-1] is not the null byte, then the caller must output one.
00096  * 
00097  * loc is the offset from the appropriate symbol at which we begin 
00098  * putting out characters.  This is used for a comment in the output 
00099  * .s file only, not for any real purpose. If loc is 0, the comment
00100  * is not written out (it has already been written out).
00101  *
00102  * ====================================================================
00103  */
00104 void
00105 Targ_Emit_String ( FILE *fl, char *str, INT32 len, INTSC loc )
00106 {
00107 #define MAX_LEN 8
00108     INT ch, i;
00109     INT16 n_on_line = 0;
00110     char dbuf[(1+MAX_LEN)*4], *dptr;
00111     dptr = dbuf;
00112 
00113     if (loc != 0)
00114         fprintf(fl, "\t%s offset %1ld\n", ASM_CMNT, loc);
00115     
00116     // if simple string, print as such
00117     if (len < 80 && str[len-1] == '\0' && ! Has_Control_Char(str,len-1)) {
00118         fprintf(fl, "\tstringz \"%s\"\n", str);
00119         return;
00120     }
00121     for ( i=0; i<len; ++i ) {
00122         ch = str[i];
00123         fprintf ( fl, n_on_line ? ", " : "\t%s\t", AS_BYTE );
00124         fprintf ( fl, "0x%x", ch );
00125         APPEND_TO_DBUF(dptr, ch);
00126         ++n_on_line;
00127         if ( n_on_line == MAX_LEN ) {
00128             *dptr = '\0';
00129             fprintf(fl, "\t%s %s", ASM_CMNT, dbuf);
00130             dptr = dbuf;
00131             fprintf ( fl, "\n" );
00132             n_on_line = 0;
00133         }
00134     }
00135     *dptr = '\0';
00136     fprintf(fl, "\t%s %s", ASM_CMNT, dbuf);
00137     dptr = dbuf;
00138     fprintf(fl, "\n");
00139 
00140 #if TARGET_88000 || TARGET_spc00
00141     INT l, line_len, ch, i;
00142 
00143     fprintf(fl, "\t%s loc %1d\n", ASM_CMNT, loc);
00144 #define MAX_LEN 60
00145     line_len = -1; 
00146     for (i=0; i<len; i++) {
00147         ch = str[i] & 0xff;
00148         if (ch < ' ' || ch > '~' || ch == '\\' || ch == '"')
00149             l = 4;
00150         else 
00151             l = 1;
00152         if (line_len > (MAX_LEN-l)) {
00153             fprintf(fl, "\"\n");
00154             line_len = -1;
00155         }
00156         if (line_len < 0) {
00157             fprintf(fl, "\t%s\t\"", AS_STRING );
00158             line_len = 0;
00159         } 
00160         if (l == 4)
00161             fprintf(fl, "\\%03o", ch);
00162         else
00163             fprintf(fl, "%c", ch);
00164         line_len +=  l;
00165     }
00166     Is_True(line_len, ("Expecting non zero line_len"));
00167     if (line_len >= 0) 
00168         fprintf(fl, "\"\n");
00169 #endif /* TARGET_88000 || TARGET_spc00 */
00170 } /* Targ_Emit_String */
00171 
00172 /* ====================================================================
00173  *
00174  * Emit_Repeated_Constant
00175  *
00176  * Emit a simple numeric constant one or more times.
00177  * To conserve space we try to emit more than one value per directive.
00178  *
00179  * ====================================================================
00180  */
00181 
00182 static void Emit_Repeated_Constant(
00183   FILE *fl,                     /* file which to write */
00184   const char *dir,              /* directive name */
00185   INT64 val,                    /* value to be written */
00186   INTSC rc,                     /* repeat count */
00187   INTSC maxc)                   /* max count per directive */
00188 {
00189   INTSC this_rc;
00190   do {
00191     INT i;
00192     this_rc = MIN(rc, maxc);
00193     fprintf(fl, "\t%s\t%lld", dir, val);
00194     for (i = 1; i < this_rc; ++i) fprintf(fl, ", %lld", val);
00195     fprintf(fl, "\n");
00196   } while (rc -= this_rc);
00197 }
00198 
00199 /* ====================================================================
00200  *
00201  * Targ_Emit_Const
00202  *
00203  * Print routine to be used to print constants on the assembly file.
00204  *
00205  * NOTE: There is a parallel routine to this one that writes out TCONs
00206  *       to elf sections. Any changes here should be reflected in the 
00207  *       Em_Targ_Emit_Const routine .
00208  *
00209  * ====================================================================
00210  */
00211 
00212 void
00213 Targ_Emit_Const (FILE *fl,          /* File to which to write */
00214                  TCON tc,           /* Constant to be written */
00215                  BOOL add_null,     /* whether to add null to strings */
00216                  INTSC rc,          /* Repeat count */
00217                  INTSC loc )        /* Location (i.e. offset from some base) */
00218 {
00219     Is_True ( rc > 0, ("Targ_Emit_Const: repeat count is %d", rc ) );
00220     
00221     /* loc only used here (in a comment in the output file) */
00222     fprintf(fl, "\t%s offset %1ld\n", ASM_CMNT, loc);
00223 
00224     /* Loop until the repeat count is exhausted. For simple constants we'll
00225      * optimize the emission, otherwise we just repeat the whole directive.
00226      */
00227     while (rc) {
00228       switch (TCON_ty(tc)) {
00229       case MTYPE_I1:
00230       case MTYPE_U1:
00231         Emit_Repeated_Constant ( fl, AS_BYTE, TCON_v0(tc) & 0xff, rc, 10 );
00232         rc = 0;
00233         break;
00234 
00235       case MTYPE_I2:
00236       case MTYPE_U2:
00237         Emit_Repeated_Constant ( fl,
00238                 ((loc % 2) == 0 ? AS_HALF : AS_HALF_UNALIGNED), 
00239                 TCON_v0(tc) & 0xffff, rc, 8 );
00240         rc = 0;
00241         break;
00242 
00243       case MTYPE_I4:
00244       case MTYPE_U4:
00245         Emit_Repeated_Constant ( fl, 
00246                 ((loc % 4) == 0 ? AS_WORD : AS_WORD_UNALIGNED), 
00247                 TCON_v0(tc), rc, 4 );
00248         rc = 0;
00249         break;
00250 
00251       case MTYPE_I8:
00252       case MTYPE_U8:
00253         Emit_Repeated_Constant ( fl, 
00254                 ((loc % 8) == 0 ? AS_DWORD : AS_DWORD_UNALIGNED), 
00255                 TCON_I8(tc), rc, 2 );
00256         rc = 0;
00257         break;
00258 
00259       case MTYPE_F4: {
00260         char *p = (char *) & TCON_R4(tc);
00261         fprintf ( fl, "\t%s\t\"", AS_STRING );
00262         for (INT i = 0; i < sizeof(TCON_R4(tc)); i++)
00263           fprintf ( fl, "\\x%02x", *(p+i) );
00264         fprintf(fl, "\"\t%s float %#g\n", ASM_CMNT, TCON_R4(tc) );
00265         --rc;
00266         break;
00267         }
00268 
00269       case MTYPE_C4: {
00270         INT i;
00271         char *p = (char *) & TCON_R4(tc);
00272         fprintf ( fl, "\t%s\t\"", AS_STRING );
00273         for (i = 0; i < sizeof(TCON_R4(tc)); i++)
00274           fprintf ( fl, "\\x%02x", *(p+i) );
00275         fprintf(fl, "\"\t%s complex float real part %#g\n", ASM_CMNT, TCON_R4(tc) );
00276 
00277         p = (char *) & TCON_IR4(tc);
00278         fprintf ( fl, "\t%s\t\"", AS_STRING );
00279         for (i = 0; i < sizeof(TCON_IR4(tc)); i++)
00280           fprintf ( fl, "\\x%02x", *(p+i) );
00281         fprintf(fl, "\"\t%s complex float imag part %#g\n", ASM_CMNT, TCON_IR4(tc) );
00282         --rc;
00283         break;
00284         }
00285 
00286       case MTYPE_F8: {
00287         char *p = (char *) & TCON_R8(tc);
00288         fprintf ( fl, "\t%s\t\"", AS_STRING );
00289         for (INT i = 0; i < sizeof(TCON_R8(tc)); i++)
00290           fprintf ( fl, "\\x%02x", *(p+i) );
00291         fprintf(fl, "\"\t%s double %#g\n", ASM_CMNT, TCON_R8(tc) );
00292         --rc;
00293         break;
00294         }
00295 
00296       case MTYPE_C8: {
00297         INT i;
00298         char *p = (char *) & TCON_R8(tc);
00299         fprintf ( fl, "\t%s\t\"", AS_STRING );
00300         for (i = 0; i < sizeof(TCON_R8(tc)); i++)
00301           fprintf ( fl, "\\x%02x", *(p+i) );
00302         fprintf(fl, "\"\t%s complex double real part %#g\n", ASM_CMNT, TCON_R8(tc) );
00303 
00304         p = (char *) & TCON_IR8(tc);
00305         fprintf ( fl, "\t%s\t\"", AS_STRING );
00306         for (i = 0; i < sizeof(TCON_IR8(tc)); i++)
00307           fprintf ( fl, "\\x%02x", *(p+i) );
00308         fprintf(fl, "\"\t%s complex double imag part %#g\n", ASM_CMNT, TCON_IR8(tc) );
00309         --rc;
00310         break;
00311         }
00312 
00313       case MTYPE_FQ: {
00314         char *p = (char *) & TCON_R16(tc);
00315         fprintf ( fl, "\t%s\t\"", AS_STRING );
00316         for (INT i = 0; i < sizeof(TCON_R16(tc)); i++)
00317           fprintf ( fl, "\\x%02x", *(p+i) );
00318         fprintf(fl, "\"\t%s quad %#lg\n", ASM_CMNT, TCON_R16(tc) );
00319         --rc;
00320         break;
00321         }
00322 
00323       case MTYPE_CQ: {
00324         INT i;
00325         char *p = (char *) & TCON_R16(tc);
00326         fprintf ( fl, "\t%s\t\"", AS_STRING );
00327         for (i = 0; i < sizeof(TCON_R16(tc)); i++)
00328           fprintf ( fl, "\\x%02x", *(p+i) );
00329         fprintf(fl, "\"\t%s complex quad real part %#lg\n", ASM_CMNT, TCON_R16(tc) );
00330 
00331         p = (char *) & TCON_IR16(tc);
00332         fprintf ( fl, "\t%s\t\"", AS_STRING );
00333         for (i = 0; i < sizeof(TCON_IR16(tc)); i++)
00334           fprintf ( fl, "\\x%02x", *(p+i) );
00335         fprintf(fl, "\"\t%s complex quad imag part %#lg\n", ASM_CMNT, TCON_IR16(tc) );
00336         --rc;
00337         break;
00338         }
00339 
00340       case MTYPE_STRING: {
00341         INTSC count;
00342         for (count=0; count<rc; ++count) {
00343           char *p = Index_to_char_array (TCON_cp(tc));
00344           Targ_Emit_String ( fl, p, TCON_len(tc) + (add_null ? 1 : 0), 0 );
00345         }
00346         rc = 0;
00347         break;
00348         }
00349 
00350       default:
00351         ErrMsg ( EC_Inv_Mtype, Mtype_Name(TCON_ty(tc)),
00352                 "Targ_Emit_Const" );
00353     }
00354   }
00355 } /* Targ_Emit_Const */
00356 
00357 #if defined(BACK_END) || defined(QIKKI_BE)
00358 /* ====================================================================
00359  *
00360  * Em_Targ_Emit_Const
00361  *
00362  * Write out constant to the section.
00363  *
00364  * ====================================================================
00365  */
00366 
00367 #include <elf.h>
00368 #include "em_elf.h"
00369 
00370 void
00371 Em_Targ_Emit_Const (void *scn,      /* Section to which to write */
00372                     TCON tc,        /* Constant to be written */
00373                     BOOL add_null,  /* whether to add null to strings */
00374                     INTSC rc)       /* Repeat count */
00375 {
00376     INTSC count;
00377     pSCNINFO section = (pSCNINFO)scn;
00378 
00379     Is_True ( rc > 0,  ("Em_Targ_Emit_Const: repeat count is %d", rc ) );
00380 
00381     switch (TCON_ty(tc)) {
00382     case MTYPE_I1:
00383     case MTYPE_U1:
00384         for (count = 0; count < rc; count++) {
00385             mINT8 value = TCON_v0(tc);
00386             Em_Add_Bytes_To_Scn (section, (char *) &value, sizeof(value), 1);
00387         }
00388         break;
00389 
00390     case MTYPE_I2:
00391     case MTYPE_U2:
00392         for (count = 0; count < rc; count++) {
00393             mINT16 value = TCON_v0(tc);
00394             Em_Add_Bytes_To_Scn (section, (char *) &value, sizeof(value), 1);
00395         }
00396         break;
00397 
00398     case MTYPE_I4:
00399     case MTYPE_U4:
00400         for (count = 0; count < rc; count++) {
00401             mINT32 value = TCON_v0(tc);
00402             Em_Add_Bytes_To_Scn (section, (char *) &value, sizeof(value), 1);
00403         }
00404         break;
00405 
00406     case MTYPE_I8:
00407     case MTYPE_U8:
00408         for (count = 0; count < rc; count++) {
00409             mUINT64 value = TCON_U8(tc);
00410             Em_Add_Bytes_To_Scn (section, (char *) &value, sizeof(value), 1);
00411         }
00412         break;
00413 
00414     case MTYPE_F4:
00415         for (count = 0; count < rc; count++) {
00416             float value = TCON_R4(tc);
00417             Em_Add_Bytes_To_Scn (section, (char *) &value, sizeof(value), 1);
00418         }
00419         break;
00420 
00421     case MTYPE_C4:
00422         for (count = 0; count < rc; count++) {
00423             float value = TCON_R4(tc);
00424             Em_Add_Bytes_To_Scn (section, (char *) &value, sizeof(value), 1);
00425             value = TCON_IR4(tc);
00426             Em_Add_Bytes_To_Scn (section, (char *) &value, sizeof(value), 1);
00427         }
00428         break;
00429 
00430     case MTYPE_F8:
00431         for (count = 0; count < rc; count++) {
00432             double value = TCON_R8(tc);
00433             Em_Add_Bytes_To_Scn (section, (char *) &value, sizeof(value), 1);
00434         }
00435         break;
00436 
00437     case MTYPE_C8:
00438         for (count = 0; count < rc; count++) {
00439             double value = TCON_R8(tc);
00440             Em_Add_Bytes_To_Scn (section, (char *) &value, sizeof(value), 1);
00441             value = TCON_IR8(tc);
00442             Em_Add_Bytes_To_Scn (section, (char *) &value, sizeof(value), 1);
00443         }
00444         break;
00445 
00446     case MTYPE_FQ:
00447         for (count = 0; count < rc; count++) {
00448             double *pvalue = &(TCON_R8(tc));
00449             Em_Add_Bytes_To_Scn (section, (char *) pvalue, sizeof(double), 1);
00450             Em_Add_Bytes_To_Scn (section, (char *) (pvalue+1), sizeof(double), 1);
00451         }
00452         break;
00453 
00454     case MTYPE_CQ:
00455         for (count = 0; count < rc; count++) {
00456             double *pvalue = &(TCON_R8(tc));
00457             Em_Add_Bytes_To_Scn (section, (char *) pvalue, sizeof(double), 1);
00458             Em_Add_Bytes_To_Scn (section, (char *) (pvalue+1), sizeof(double), 1);
00459             pvalue = &(TCON_IR8(tc));
00460             Em_Add_Bytes_To_Scn (section, (char *) pvalue, sizeof(double), 1);
00461             Em_Add_Bytes_To_Scn (section, (char *) (pvalue+1), sizeof(double), 1);
00462         }
00463         break;
00464 
00465     case MTYPE_STRING:
00466         for (count = 0; count < rc; count++) {
00467             Em_Add_Bytes_To_Scn (section,
00468                                  Index_to_char_array (TCON_cp(tc)),
00469                 TCON_len(tc) + (add_null ? 1 : 0), 
00470                 1);
00471         }
00472         break;
00473 
00474     default:
00475         Is_True ( FALSE, ( "Targ_Emit_Const can not handle type %s", 
00476                           Mtype_Name(TCON_ty(tc)) ) );
00477     }
00478 } /* Em_Targ_Emit_Const */
00479 #endif /* BACK_END */
00480 
00481 #if !defined(MONGOOSE_BE) && !defined(QIKKI_BE)
00482 void
00483 Targ_Emit_Space( FILE *fl, INT len, INT loc)
00484 {
00485     fprintf(fl, "\t%s %1d\t%s %1d\n", AS_SPACE, len, ASM_CMNT, loc);
00486 }
00487 
00488 void
00489 Targ_Emit_Cmt(fl, str)
00490 FILE *fl;
00491 char *str;
00492 {
00493     fprintf(fl, "\t%s %s\n", ASM_CMNT, str);
00494 }
00495 
00496 /*----------------------------------------------------------------------
00497  *      Print on the file 'fl' the length of the dimension described
00498  *      as going from 'tree_lower' to 'tree_upper'.  This can only be
00499  *      done correctly at compile-time when both 'tree_lower' and
00500  *      'tree_upper' are NDs for constants (maybe even integer
00501  *      constants?).  If they are not both integer constants, just print
00502  *      a default dimension of '1'.
00503  *--------------------------------------------------------------------*/
00504 void
00505 Targ_Emit_Dim (FILE *fl, TY *ty, INT dim)
00506 {
00507 #if TODO_MONGOOSE
00508     INT32 coff_dim = 1;             /* default value */
00509     ND *tree_lower;
00510     ND *tree_upper;
00511   
00512     Is_True(TY_kind(ty) == KIND_ARRAY, ("Non-array in Targ_Emit_Dim"));
00513     Is_True(dim >= 0 && dim < TY_AR_ndims(ty),
00514             ("Illegal dimension %d in Targ_Emit_Dim", dim));
00515 
00516     tree_lower = TY_AR_fbnd(ty,dim);
00517     tree_upper = TY_AR_tbnd(ty,dim);
00518     if ( (tree_upper != NULL) && (tree_lower != NULL) ) {
00519         TCON tc_upper, tc_lower;
00520         if ( (Is_Const(tree_upper,&tc_upper) == MTYPE_I4) &&
00521             (Is_Const(tree_lower,&tc_lower) == MTYPE_I4) ) {
00522             INT32 upper_bound = TCON_v0(tc_upper);
00523             INT32 lower_bound = TCON_v0(tc_lower);
00524             coff_dim = upper_bound - lower_bound + 1;
00525         }
00526     }
00527 
00528     fprintf ( fl, "%d", coff_dim );
00529 #endif /* TODO_MONGOOSE */
00530 } /* Targ_Emit_Dim */
00531 #endif /* !defined(MONGOOSE_BE) && !defined(QIKKI_BE) */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines