Annotation of researchv10dc/cmd/gcc/dbxout.c, revision 1.1

1.1     ! root        1: /* Output dbx-format symbol table information from GNU compiler.
        !             2:    Copyright (C) 1987 Free Software Foundation, Inc.
        !             3: 
        !             4: This file is part of GNU CC.
        !             5: 
        !             6: GNU CC is distributed in the hope that it will be useful,
        !             7: but WITHOUT ANY WARRANTY.  No author or distributor
        !             8: accepts responsibility to anyone for the consequences of using it
        !             9: or for whether it serves any particular purpose or works at all,
        !            10: unless he says so in writing.  Refer to the GNU CC General Public
        !            11: License for full details.
        !            12: 
        !            13: Everyone is granted permission to copy, modify and redistribute
        !            14: GNU CC, but only under the conditions described in the
        !            15: GNU CC General Public License.   A copy of this license is
        !            16: supposed to have been given to you along with GNU CC so you
        !            17: can know your rights and responsibilities.  It should be in a
        !            18: file named COPYING.  Among other things, the copyright notice
        !            19: and this notice must be preserved on all copies.  */
        !            20: 
        !            21: 
        !            22: /* Output dbx-format symbol table data.
        !            23:    This consists of many symbol table entries, each of them
        !            24:    a .stabs assembler pseudo-op with four operands:
        !            25:    a "name" which is really a description of one symbol and its type,
        !            26:    a "code", which is a symbol defined in stab.h whose name starts with N_,
        !            27:    an unused operand always 0,
        !            28:    and a "value" which is an address or an offset.
        !            29:    The name is enclosed in doublequote characters.
        !            30: 
        !            31:    Each function, variable, typedef, and structure tag
        !            32:    has a symbol table entry to define it.
        !            33:    The beginning and end of each level of name scoping within
        !            34:    a function are also marked by special symbol table entries.
        !            35: 
        !            36:    The "name" consists of the symbol name, a colon, a kind-of-symbol letter,
        !            37:    and a data type number.  The data type number may be followed by
        !            38:    "=" and a type definition; normally this will happen the first time
        !            39:    the type number is mentioned.  The type definition may refer to
        !            40:    other types by number, and those type numbers may be followed
        !            41:    by "=" and nested definitions.
        !            42: 
        !            43:    This can make the "name" quite long.
        !            44:    When a name is more than 80 characters, we split the .stabs pseudo-op
        !            45:    into two .stabs pseudo-ops, both sharing the same "code" and "value".
        !            46:    The first one is marked as continued with a double-backslash at the
        !            47:    end of its "name".
        !            48: 
        !            49:    The kind-of-symbol letter distinguished function names from global
        !            50:    variables from file-scope variables from parameters from auto
        !            51:    variables in memory from typedef names from register variables.
        !            52:    See `dbxout_symbol'.
        !            53: 
        !            54:    The "code" is mostly redundant with the kind-of-symbol letter
        !            55:    that goes in the "name", but not entirely: for symbols located
        !            56:    in static storage, the "code" says which segment the address is in,
        !            57:    which controls how it is relocated.
        !            58: 
        !            59:    The "value" for a symbol in static storage
        !            60:    is the core address of the symbol (actually, the assembler
        !            61:    label for the symbol).  For a symbol located in a stack slot
        !            62:    it is the stack offset; for one in a register, the register number.
        !            63:    For a typedef symbol, it is zero.
        !            64: 
        !            65:    For more on data type definitions, see `dbxout_type'.  */
        !            66: 
        !            67: #include "config.h"
        !            68: #include "tree.h"
        !            69: #include "rtl.h"
        !            70: #include <stdio.h>
        !            71: 
        !            72: /* Typical USG systems don't have stab.h, and they also have
        !            73:    no use for DBX-format debugging info.  */
        !            74: 
        !            75: #ifndef NO_DBX_FORMAT
        !            76: 
        !            77: #include <stab.h>
        !            78: 
        !            79: /* Stream for writing to assembler file.  */
        !            80: 
        !            81: static FILE *asmfile;
        !            82: 
        !            83: enum typestatus {TYPE_UNSEEN, TYPE_XREF, TYPE_DEFINED};
        !            84: 
        !            85: /* Vector recording the status of describing C data types.
        !            86:    When we first notice a data type (a tree node),
        !            87:    we assign it a number using next_type_number.
        !            88:    That is its index in this vector.
        !            89:    The vector element says whether we have yet output
        !            90:    the definition of the type.  TYPE_XREF says we have
        !            91:    output it as a cross-reference only.  */
        !            92: 
        !            93: enum typestatus *typevec;
        !            94: 
        !            95: /* Number of elements of space allocated in `typevec'.  */
        !            96: 
        !            97: static int typevec_len;
        !            98: 
        !            99: /* In dbx output, each type gets a unique number.
        !           100:    This is the number for the next type output.
        !           101:    The number, once assigned, is in the TYPE_SYMTAB_ADDRESS field.  */
        !           102: 
        !           103: static int next_type_number;
        !           104: 
        !           105: /* In dbx output, we must assign symbol-blocks id numbers
        !           106:    in the order in which their beginnings are encountered.
        !           107:    We output debugging info that refers to the beginning and
        !           108:    end of the ranges of code in each block
        !           109:    with assembler labels LBBn and LBEn, where n is the block number.
        !           110:    The labels are generated in final, which assigns numbers to the
        !           111:    blocks in the same way.  */
        !           112: 
        !           113: static int next_block_number;
        !           114: 
        !           115: /* These variables are for dbxout_symbol to communicate to
        !           116:    dbxout_finish_symbol.
        !           117:    current_sym_code is the symbol-type-code, a symbol N_... define in stab.h.
        !           118:    current_sym_value and current_sym_addr are two ways to address the
        !           119:    value to store in the symtab entry.
        !           120:    current_sym_addr if nonzero represents the value as an rtx.
        !           121:    If that is zero, current_sym_value is used.  This is used
        !           122:    when the value is an offset (such as for auto variables,
        !           123:    register variables and parms).  */
        !           124: 
        !           125: static int current_sym_code;
        !           126: static int current_sym_value;
        !           127: static rtx current_sym_addr;
        !           128: 
        !           129: /* Number of chars of symbol-description generated so far for the
        !           130:    current symbol.  Used by CHARS and CONTIN.  */
        !           131: 
        !           132: static int current_sym_nchars;
        !           133: 
        !           134: /* Report having output N chars of the current symbol-description.  */
        !           135: 
        !           136: #define CHARS(N) (current_sym_nchars += (N))
        !           137: 
        !           138: /* Break the current symbol-description, generating a continuation,
        !           139:    if it has become long.  */
        !           140: 
        !           141: #ifndef DBX_CONTIN_LENGTH
        !           142: #define DBX_CONTIN_LENGTH 80
        !           143: #endif
        !           144: 
        !           145: #if DBX_CONTIN_LENGTH > 0
        !           146: #define CONTIN  \
        !           147:   do {if (current_sym_nchars > DBX_CONTIN_LENGTH) dbxout_continue ();} while (0)
        !           148: #else
        !           149: #define CONTIN
        !           150: #endif
        !           151: 
        !           152: void dbxout_types ();
        !           153: void dbxout_tags ();
        !           154: static void dbxout_type_name ();
        !           155: static void dbxout_type ();
        !           156: static void dbxout_type_def ();
        !           157: static void dbxout_finish_symbol ();
        !           158: static void dbxout_continue ();
        !           159: 
        !           160: /* At the beginning of compilation, start writing the symbol table.
        !           161:    Initialize `typevec' and output the standard data types of C.  */
        !           162: 
        !           163: void
        !           164: dbxout_init (asm_file, input_file_name)
        !           165:      FILE *asm_file;
        !           166:      char *input_file_name;
        !           167: {
        !           168:   asmfile = asm_file;
        !           169: 
        !           170:   typevec_len = 100;
        !           171:   typevec = (enum typestatus *) xmalloc (typevec_len * sizeof typevec[0]);
        !           172:   bzero (typevec, typevec_len * sizeof typevec[0]);
        !           173:   
        !           174:   fprintf (asmfile,
        !           175:           "Ltext:\t.stabs \"%s\",%d,0,0,Ltext\n",
        !           176:           input_file_name, N_SO);
        !           177: 
        !           178:   next_type_number = 1;
        !           179:   next_block_number = 2;
        !           180: 
        !           181:   /* Make sure that types `int' and `char' have numbers 1 and 2.
        !           182:      Definitions of other integer types will refer to those numbers.  */
        !           183: 
        !           184:   dbxout_type_def (integer_type_node);
        !           185:   dbxout_type_def (char_type_node);
        !           186: 
        !           187:   /* Get all permanent types not yet gotten, and output them.  */
        !           188: 
        !           189:   dbxout_types (get_permanent_types ());
        !           190: }
        !           191: 
        !           192: /* Continue a symbol-description that gets too big.
        !           193:    End one symbol table entry with a double-backslash
        !           194:    and start a new one, eventually producing something like
        !           195:    .stabs "start......\\",code,0,value
        !           196:    .stabs "...rest",code,0,value   */
        !           197: 
        !           198: static void
        !           199: dbxout_continue ()
        !           200: {
        !           201: #ifdef DBX_CONTIN_CHAR
        !           202:   fprintf (asmfile, "%c", DBX_CONTIN_CHAR);
        !           203: #else
        !           204:   fprintf (asmfile, "\\\\");
        !           205: #endif
        !           206:   dbxout_finish_symbol ();
        !           207:   fprintf (asmfile, ".stabs \"");
        !           208:   current_sym_nchars = 0;
        !           209: }
        !           210: 
        !           211: /* Output a reference to a type.  If the type has not yet been
        !           212:    described in the dbx output, output its definition now.
        !           213:    For a type already defined, just refer to its definition
        !           214:    using the type number.
        !           215: 
        !           216:    If FULL is nonzero, and the type has been described only with
        !           217:    a forward-reference, output the definition now.
        !           218:    If FULL is zero in this case, just refer to the forward-reference
        !           219:    using the number previously allocated.  */
        !           220: 
        !           221: static void
        !           222: dbxout_type (type, full)
        !           223:      tree type;
        !           224:      int full;
        !           225: {
        !           226:   register tree tem;
        !           227: 
        !           228:   /* If there was an input error and we don't really have a type,
        !           229:      avoid crashing and write something that is at least valid
        !           230:      by assuming `int'.  */
        !           231:   if (type == error_mark_node)
        !           232:     type = integer_type_node;
        !           233:   else if (TYPE_SIZE (type) == 0)
        !           234:     type = TYPE_MAIN_VARIANT (type);
        !           235: 
        !           236:   if (TYPE_SYMTAB_ADDRESS (type) == 0)
        !           237:     {
        !           238:       /* Type has no dbx number assigned.  Assign next available number.  */
        !           239:       TYPE_SYMTAB_ADDRESS (type) = next_type_number++;
        !           240: 
        !           241:       /* Make sure type vector is long enough to record about this type.  */
        !           242: 
        !           243:       if (next_type_number == typevec_len)
        !           244:        {
        !           245:          typevec = (enum typestatus *) xrealloc (typevec, typevec_len * 2 * sizeof typevec[0]);
        !           246:          bzero (typevec + typevec_len, typevec_len * sizeof typevec[0]);
        !           247:          typevec_len *= 2;
        !           248:        }
        !           249:     }
        !           250: 
        !           251:   /* Output the number of this type, to refer to it.  */
        !           252:   fprintf (asmfile, "%d", TYPE_SYMTAB_ADDRESS (type));
        !           253:   CHARS (3);
        !           254: 
        !           255:   /* If this type's definition has been output or is now being output,
        !           256:      that is all.  */
        !           257: 
        !           258:   switch (typevec[TYPE_SYMTAB_ADDRESS (type)])
        !           259:     {
        !           260:     case TYPE_UNSEEN:
        !           261:       break;
        !           262:     case TYPE_XREF:
        !           263:       if (! full)
        !           264:        return;
        !           265:       break;
        !           266:     case TYPE_DEFINED:
        !           267:       return;
        !           268:     }
        !           269: 
        !           270: #ifdef DBX_NO_XREFS
        !           271:   /* For systems where dbx output does not allow the `=xsNAME:' syntax,
        !           272:      leave the type-number completely undefined rather than output
        !           273:      a cross-reference.  */
        !           274:   if (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE
        !           275:       || TREE_CODE (type) == ENUMERAL_TYPE)
        !           276: 
        !           277:     if ((TYPE_NAME (type) != 0 && !full)
        !           278:        || TYPE_SIZE (type) == 0)
        !           279:       {
        !           280:        typevec[TYPE_SYMTAB_ADDRESS (type)] = TYPE_XREF;
        !           281:        return;
        !           282:       }
        !           283: #endif
        !           284: 
        !           285:   /* Output a definition now.  */
        !           286: 
        !           287:   fprintf (asmfile, "=");
        !           288:   CHARS (1);
        !           289: 
        !           290:   /* Mark it as defined, so that if it is self-referent
        !           291:      we will not get into an infinite recursion of definitions.  */
        !           292: 
        !           293:   typevec[TYPE_SYMTAB_ADDRESS (type)] = TYPE_DEFINED;
        !           294: 
        !           295:   switch (TREE_CODE (type))
        !           296:     {
        !           297:     case VOID_TYPE:
        !           298:       /* For a void type, just define it as itself; ie, "5=5".
        !           299:         This makes us consider it defined
        !           300:         without saying what it is.  The debugger will make it
        !           301:         a void type when the reference is seen, and nothing will
        !           302:         ever override that default.  */
        !           303:       fprintf (asmfile, "%d", TYPE_SYMTAB_ADDRESS (type));
        !           304:       CHARS (3);
        !           305:       break;
        !           306: 
        !           307:     case INTEGER_TYPE:
        !           308:       if (type == char_type_node && ! TREE_UNSIGNED (type))
        !           309:        /* Output the type `char' as a subrange of itself!
        !           310:           I don't understand this definition, just copied it
        !           311:           from the output of pcc.  */
        !           312:        fprintf (asmfile, "r2;0;127;");
        !           313:       else
        !           314:        /* Output other integer types as subranges of `int'.  */
        !           315:        fprintf (asmfile, "r1;%d;%d;",
        !           316:                 TREE_INT_CST_LOW (TYPE_MIN_VALUE (type)),
        !           317:                 TREE_INT_CST_LOW (TYPE_MAX_VALUE (type)));
        !           318:       CHARS (25);
        !           319:       break;
        !           320: 
        !           321:     case REAL_TYPE:
        !           322:       /* This must be magic.  */
        !           323:       fprintf (asmfile, "r1;%d;0;",
        !           324:               TREE_INT_CST_LOW (size_in_bytes (type)));
        !           325:       CHARS (16);
        !           326:       break;
        !           327: 
        !           328:     case ARRAY_TYPE:
        !           329:       /* Output "a" followed by a range type definition
        !           330:         for the index type of the array
        !           331:         followed by a reference to the target-type.
        !           332:         ar1;0;N;M for an array of type M and size N.  */
        !           333:       fprintf (asmfile, "ar1;0;%d;",
        !           334:               (TYPE_DOMAIN (type)
        !           335:                ? TREE_INT_CST_LOW (TYPE_MAX_VALUE (TYPE_DOMAIN (type)))
        !           336:                : -1));
        !           337:       CHARS (17);
        !           338:       dbxout_type (TREE_TYPE (type), 0);
        !           339:       break;
        !           340: 
        !           341:     case RECORD_TYPE:
        !           342:     case UNION_TYPE:
        !           343:       /* Output a structure type.  */
        !           344:       if ((TYPE_NAME (type) != 0 && !full)
        !           345:          || TYPE_SIZE (type) == 0)
        !           346:        {
        !           347:          /* If the type is just a cross reference, output one
        !           348:             and mark the type as partially described.
        !           349:             If it later becomes defined, we will output
        !           350:             its real definition.
        !           351:             If the type has a name, don't nest its name within
        !           352:             another type's definition; instead, output an xref
        !           353:             and let the definition come when the name is defined.  */
        !           354:          fprintf (asmfile, (TREE_CODE (type) == RECORD_TYPE) ? "xs" : "xu");
        !           355:          CHARS (3);
        !           356:          dbxout_type_name (type);
        !           357:          fprintf (asmfile, ":");
        !           358:          typevec[TYPE_SYMTAB_ADDRESS (type)] = TYPE_XREF;
        !           359:          break;
        !           360:        }
        !           361:       tem = size_in_bytes (type);
        !           362:       fprintf (asmfile, (TREE_CODE (type) == RECORD_TYPE) ? "s%d" : "u%d",
        !           363:               TREE_INT_CST_LOW (tem));
        !           364:       CHARS (11);
        !           365:       for (tem = TYPE_FIELDS (type); tem; tem = TREE_CHAIN (tem))
        !           366:        /* Output the name, type, position (in bits), size (in bits)
        !           367:           of each field.  */
        !           368:        /* Omit here the nameless fields that are used to skip bits.  */
        !           369:        if (DECL_NAME (tem) != 0)
        !           370:          {
        !           371:            fprintf (asmfile, "<%d:%d>", current_sym_nchars, DBX_CONTIN_LENGTH);
        !           372:            /* Continue the line if necessary,
        !           373:               but not before the first field.  */
        !           374:            if (tem != TYPE_FIELDS (type))
        !           375:              CONTIN;
        !           376:            fprintf (asmfile, "%s:", IDENTIFIER_POINTER (DECL_NAME (tem)));
        !           377:            CHARS (1 + strlen (IDENTIFIER_POINTER (DECL_NAME (tem))));
        !           378:            dbxout_type (TREE_TYPE (tem), 0);
        !           379:            fprintf (asmfile, ",%d,%d;", DECL_OFFSET (tem),
        !           380:                     TREE_INT_CST_LOW (DECL_SIZE (tem)) * DECL_SIZE_UNIT (tem));
        !           381:            CHARS (23);
        !           382:          }
        !           383:       putc (';', asmfile);
        !           384:       CHARS (1);
        !           385:       break;
        !           386: 
        !           387:     case ENUMERAL_TYPE:
        !           388:       if ((TYPE_NAME (type) != 0 && !full)
        !           389:          || TYPE_SIZE (type) == 0)
        !           390:        {
        !           391:          fprintf (asmfile, "xe");
        !           392:          CHARS (3);
        !           393:          dbxout_type_name (type);
        !           394:          typevec[TYPE_SYMTAB_ADDRESS (type)] = TYPE_XREF;
        !           395:          fprintf (asmfile, ":");
        !           396:          return;
        !           397:        }
        !           398:       putc ('e', asmfile);
        !           399:       CHARS (1);
        !           400:       for (tem = TYPE_VALUES (type); tem; tem = TREE_CHAIN (tem))
        !           401:        {
        !           402:          fprintf (asmfile, "%s:%d,", IDENTIFIER_POINTER (TREE_PURPOSE (tem)),
        !           403:                   TREE_INT_CST_LOW (TREE_VALUE (tem)));
        !           404:          CHARS (11 + strlen (IDENTIFIER_POINTER (TREE_PURPOSE (tem))));
        !           405:          if (TREE_CHAIN (tem) != 0)
        !           406:            CONTIN;
        !           407:        }
        !           408:       putc (';', asmfile);
        !           409:       CHARS (1);
        !           410:       break;
        !           411: 
        !           412:     case POINTER_TYPE:
        !           413:       putc ('*', asmfile);
        !           414:       CHARS (1);
        !           415:       dbxout_type (TREE_TYPE (type), 0);
        !           416:       break;
        !           417: 
        !           418:     case FUNCTION_TYPE:
        !           419:       putc ('f', asmfile);
        !           420:       CHARS (1);
        !           421:       dbxout_type (TREE_TYPE (type), 0);
        !           422:       break;
        !           423:     }
        !           424: }
        !           425: 
        !           426: /* Output the name of type TYPE, with no punctuation.
        !           427:    Such names can be set up either by typedef declarations
        !           428:    or by struct, enum and union tags.  */
        !           429: 
        !           430: static void
        !           431: dbxout_type_name (type)
        !           432:      register tree type;
        !           433: {
        !           434:   register char *name;
        !           435:   if (TYPE_NAME (type) == 0)
        !           436:     abort ();
        !           437:   if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
        !           438:     name = IDENTIFIER_POINTER (TYPE_NAME (type));
        !           439:   else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL)
        !           440:     name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
        !           441:   else
        !           442:     abort ();
        !           443: 
        !           444:   fprintf (asmfile, "%s", name);
        !           445:   CHARS (strlen (name));
        !           446: }
        !           447: 
        !           448: /* Output a .stabs for the symbol defined by DECL,
        !           449:    which must be a ..._DECL node in the normal namespace.
        !           450:    It may be a CONST_DECL, a FUNCTION_DECL, a PARM_DECL or a VAR_DECL.
        !           451:    LOCAL is nonzero if the scope is less than the entire file.  */
        !           452: 
        !           453: void
        !           454: dbxout_symbol (decl, local)
        !           455:      tree decl;
        !           456:      int local;
        !           457: {
        !           458:   int letter = 0;
        !           459:   tree type = TREE_TYPE (decl);
        !           460: 
        !           461:   /* If global, first output all types and all
        !           462:      struct, enum and union tags that have been created
        !           463:      and not yet output.  */
        !           464: 
        !           465:   if (local == 0)
        !           466:     {
        !           467:       dbxout_tags (gettags ());
        !           468:       dbxout_types (get_permanent_types ());
        !           469:     }
        !           470: 
        !           471:   current_sym_code = 0;
        !           472:   current_sym_value = 0;
        !           473:   current_sym_addr = 0;
        !           474: 
        !           475:   /* The output will always start with the symbol name,
        !           476:      so count that always in the length-output-so-far.  */
        !           477: 
        !           478:   current_sym_nchars = 2 + strlen (IDENTIFIER_POINTER (DECL_NAME (decl)));
        !           479: 
        !           480:   switch (TREE_CODE (decl))
        !           481:     {
        !           482:     case CONST_DECL:
        !           483:       /* Enum values are defined by defining the enum type.  */
        !           484:       break;
        !           485: 
        !           486:     case FUNCTION_DECL:
        !           487:       if (DECL_RTL (decl) == 0)
        !           488:        return;
        !           489:       if (TREE_EXTERNAL (decl))
        !           490:        break;
        !           491:       if (GET_CODE (DECL_RTL (decl)) != MEM
        !           492:          || GET_CODE (XEXP (DECL_RTL (decl), 0)) != SYMBOL_REF)
        !           493:        break;
        !           494:       fprintf (asmfile, ".stabs \"%s:%c",
        !           495:               IDENTIFIER_POINTER (DECL_NAME (decl)),
        !           496:               TREE_PUBLIC (decl) ? 'F' : 'f');
        !           497: 
        !           498:       current_sym_code = N_FUN;
        !           499:       current_sym_addr = XEXP (DECL_RTL (decl), 0);
        !           500: 
        !           501:       if (TREE_TYPE (TREE_TYPE (decl)))
        !           502:        dbxout_type (TREE_TYPE (TREE_TYPE (decl)), 0);
        !           503:       else
        !           504:        dbxout_type (void_type_node, 0);
        !           505:       dbxout_finish_symbol ();
        !           506:       break;
        !           507: 
        !           508:     case TYPE_DECL:
        !           509:       /* If this typedef name was defined by outputting the type,
        !           510:         don't duplicate it.  */
        !           511:       if (typevec[TYPE_SYMTAB_ADDRESS (type)] == TYPE_DEFINED
        !           512:          && TYPE_NAME (TREE_TYPE (decl)) == decl)
        !           513:        return;
        !           514: 
        !           515:       /* Output typedef name.  */
        !           516:       fprintf (asmfile, ".stabs \"%s:t",
        !           517:               IDENTIFIER_POINTER (DECL_NAME (decl)));
        !           518: 
        !           519:       current_sym_code = N_LSYM;
        !           520: 
        !           521:       dbxout_type (TREE_TYPE (decl), 1);
        !           522:       dbxout_finish_symbol ();
        !           523:       break;
        !           524:       
        !           525:     case PARM_DECL:
        !           526:       /* Parm decls go in their own separate chains
        !           527:         and are output by dbxout_reg_parms and dbxout_parms.  */
        !           528:       abort ();
        !           529: 
        !           530:     case VAR_DECL:
        !           531:       if (DECL_RTL (decl) == 0)
        !           532:        return;
        !           533:       /* Don't mention a variable that is external.
        !           534:         Let the file that defines it describe it.  */
        !           535:       if (TREE_EXTERNAL (decl))
        !           536:        break;
        !           537: 
        !           538:       /* Don't mention a variable at all
        !           539:         if it was completely optimized into nothingness.  */
        !           540:       if (GET_CODE (DECL_RTL (decl)) == REG
        !           541:          && (REGNO (DECL_RTL (decl)) < 0
        !           542:              || REGNO (DECL_RTL (decl)) >= FIRST_PSEUDO_REGISTER))
        !           543:        break;
        !           544: 
        !           545:       /* Ok, start a symtab entry and output the variable name.  */
        !           546:       fprintf (asmfile, ".stabs \"%s:",
        !           547:               IDENTIFIER_POINTER (DECL_NAME (decl)));
        !           548: 
        !           549:       /* The kind-of-variable letter depends on where
        !           550:         the variable is and on the scope of its name:
        !           551:         G and N_GSYM for static storage and global scope,
        !           552:         S for static storage and file scope,
        !           553:         v for static storage and local scope,
        !           554:            for those two, use N_LCSYM if data is in bss segment,
        !           555:            N_STSYM if it is in data segment, or N_FUN if in text segment.
        !           556:         no letter at all, and N_LSYM, for auto variable,
        !           557:         r and N_RSYM for register variable.  */
        !           558: 
        !           559:       if (GET_CODE (DECL_RTL (decl)) == MEM
        !           560:          && GET_CODE (XEXP (DECL_RTL (decl), 0)) == SYMBOL_REF)
        !           561:        {
        !           562:          if (TREE_PUBLIC (decl))
        !           563:            {
        !           564:              letter = 'G';
        !           565:              current_sym_code = N_GSYM;
        !           566:            }
        !           567:          else
        !           568:            {
        !           569:              current_sym_addr = XEXP (DECL_RTL (decl), 0);
        !           570: 
        !           571:              letter = TREE_PERMANENT (decl) ? 'S' : 'v';
        !           572: 
        !           573:              if (!DECL_INITIAL (decl))
        !           574:                current_sym_code = N_LCSYM;
        !           575:              else if (TREE_READONLY (decl) && ! TREE_VOLATILE (decl))
        !           576:                /* This is not quite right, but it's the closest
        !           577:                   of all the codes that Unix defines.  */
        !           578:                current_sym_code = N_FUN;
        !           579:              else
        !           580:                current_sym_code = N_STSYM;
        !           581:            }
        !           582:        }
        !           583:       else if (GET_CODE (DECL_RTL (decl)) == REG)
        !           584:        {
        !           585:          letter = 'r';
        !           586:          current_sym_code = N_RSYM;
        !           587:          current_sym_value = DBX_REGISTER_NUMBER (REGNO (DECL_RTL (decl)));
        !           588:        }
        !           589:       else if (GET_CODE (DECL_RTL (decl)) == MEM
        !           590:               && (GET_CODE (XEXP (DECL_RTL (decl), 0)) == MEM
        !           591:                   || (GET_CODE (XEXP (DECL_RTL (decl), 0)) == REG
        !           592:                       && REGNO (XEXP (DECL_RTL (decl), 0)) != FRAME_POINTER_REGNUM)))
        !           593:        /* If the value is indirect by memory or by a register
        !           594:           that isn't the frame pointer
        !           595:           then it means the object is variable-sized and address through
        !           596:           that register or stack slot.  DBX has no way to represent this
        !           597:           so all we can do is output the variable as a pointer.  */
        !           598:        {
        !           599:          if (GET_CODE (XEXP (DECL_RTL (decl), 0)) == REG)
        !           600:            {
        !           601:              letter = 'r';
        !           602:              current_sym_code = N_RSYM;
        !           603:              current_sym_value = DBX_REGISTER_NUMBER (REGNO (XEXP (DECL_RTL (decl), 0)));
        !           604:            }
        !           605:          else
        !           606:            {
        !           607:              current_sym_code = N_LSYM;
        !           608:              /* DECL_RTL looks like (MEM (MEM (PLUS (REG...) (CONST_INT...)))).
        !           609:                 We want the value of that CONST_INT.  */
        !           610:              current_sym_value = INTVAL (XEXP (XEXP (XEXP (DECL_RTL (decl), 0), 0), 1));
        !           611:            }
        !           612: 
        !           613:          type = build_pointer_type (TREE_TYPE (decl));
        !           614:        }
        !           615:       else if (GET_CODE (DECL_RTL (decl)) == MEM
        !           616:               && XEXP (DECL_RTL (decl), 0) != const0_rtx)
        !           617:        /* const0_rtx is used as the address for a variable that
        !           618:           is a dummy due to an erroneous declaration.
        !           619:           Ignore such vars.  */
        !           620:        {
        !           621:          current_sym_code = N_LSYM;
        !           622:          if (GET_CODE (XEXP (DECL_RTL (decl), 0)) == REG)
        !           623:            current_sym_value = 0;
        !           624:          else
        !           625:            /* DECL_RTL looks like (MEM (PLUS (REG...) (CONST_INT...)))
        !           626:               We want the value of that CONST_INT.  */
        !           627:            current_sym_value = INTVAL (XEXP (XEXP (DECL_RTL (decl), 0), 1));
        !           628:        }
        !           629:       if (letter) putc (letter, asmfile);
        !           630:       dbxout_type (type, 0);
        !           631:       dbxout_finish_symbol ();
        !           632:       break;
        !           633:     }
        !           634: }
        !           635: 
        !           636: static void
        !           637: dbxout_finish_symbol ()
        !           638: {
        !           639:   fprintf (asmfile, "\",%d,0,0,", current_sym_code);
        !           640:   if (current_sym_addr)
        !           641:     output_addr_const (asmfile, current_sym_addr);
        !           642:   else
        !           643:     fprintf (asmfile, "%d", current_sym_value);
        !           644:   putc ('\n', asmfile);
        !           645: }
        !           646: 
        !           647: /* Output definitions of all the decls in a chain.  */
        !           648: 
        !           649: static void
        !           650: dbxout_syms (syms)
        !           651:      tree syms;
        !           652: {
        !           653:   while (syms)
        !           654:     {
        !           655:       dbxout_symbol (syms, 1);
        !           656:       syms = TREE_CHAIN (syms);
        !           657:     }
        !           658: }
        !           659: 
        !           660: /* The following two functions output definitions of function parameters.
        !           661:    Each parameter gets a definition locating it in the parameter list.
        !           662:    Each parameter that is a register variable gets a second definition
        !           663:    locating it in the register.
        !           664: 
        !           665:    Printing or argument lists in gdb uses the definitions that
        !           666:    locate in the parameter list.  But reference to the variable in
        !           667:    expressions uses preferentially the definition as a register.  */
        !           668: 
        !           669: /* Output definitions, referring to storage in the parmlist,
        !           670:    of all the parms in PARMS, which is a chain of PARM_DECL nodes.  */
        !           671: 
        !           672: static void
        !           673: dbxout_parms (parms)
        !           674:      tree parms;
        !           675: {
        !           676:   for (; parms; parms = TREE_CHAIN (parms))
        !           677:     {
        !           678:       if (DECL_OFFSET (parms) >= 0)
        !           679:        {
        !           680:          current_sym_code = N_PSYM;
        !           681:          current_sym_value = DECL_OFFSET (parms) / BITS_PER_UNIT;
        !           682:          current_sym_addr = 0;
        !           683:          current_sym_nchars = 2 + strlen (IDENTIFIER_POINTER (DECL_NAME (parms)));
        !           684: 
        !           685:          fprintf (asmfile, ".stabs \"%s:p",
        !           686:                   IDENTIFIER_POINTER (DECL_NAME (parms)));
        !           687: 
        !           688:          if (GET_CODE (DECL_RTL (parms)) == REG
        !           689:              && REGNO (DECL_RTL (parms)) >= 0
        !           690:              && REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER)
        !           691:            dbxout_type (DECL_ARG_TYPE (parms), 0);
        !           692:          else
        !           693:            {
        !           694:              /* This is the case where the parm is passed as an int or double
        !           695:                 and it is converted to a char, short or float and stored back
        !           696:                 in the parmlist.  In this case, describe the parm
        !           697:                 with the variable's declared type, and adjust the address
        !           698:                 if the least significant bytes (which we are using) are not
        !           699:                 the first ones.  */
        !           700: #ifdef BYTES_BIG_ENDIAN
        !           701:              if (TREE_TYPE (parms) != DECL_ARG_TYPE (parms))
        !           702:                current_sym_value += (GET_MODE_SIZE (TYPE_MODE (DECL_ARG_TYPE (parms)))
        !           703:                                      - GET_MODE_SIZE (GET_MODE (DECL_RTL (parms))));
        !           704: #endif
        !           705: 
        !           706:              if (GET_CODE (DECL_RTL (parms)) == MEM
        !           707:                  && GET_CODE (XEXP (DECL_RTL (parms), 0)) == PLUS
        !           708:                  && GET_CODE (XEXP (XEXP (DECL_RTL (parms), 0), 1)) == CONST_INT
        !           709:                  && INTVAL (XEXP (XEXP (DECL_RTL (parms), 0), 1)) == current_sym_value)
        !           710:                dbxout_type (TREE_TYPE (parms), 0);
        !           711:              else
        !           712:                {
        !           713:                  current_sym_value = DECL_OFFSET (parms) / BITS_PER_UNIT;
        !           714:                  dbxout_type (DECL_ARG_TYPE (parms), 0);
        !           715:                }
        !           716:            }
        !           717:          dbxout_finish_symbol ();
        !           718:        }
        !           719:       /* Parm was passed in registers.
        !           720:         If it is in a register, output a "regparm" symbol
        !           721:         for the register it lives in.  */
        !           722:       else if (GET_CODE (DECL_RTL (parms)) == REG)
        !           723:        {
        !           724:          current_sym_code = N_RSYM;
        !           725:          current_sym_value = DBX_REGISTER_NUMBER (REGNO (DECL_RTL (parms)));
        !           726:          current_sym_addr = 0;
        !           727:          current_sym_nchars = 2 + strlen (IDENTIFIER_POINTER (DECL_NAME (parms)));
        !           728: 
        !           729:          fprintf (asmfile, ".stabs \"%s:P",
        !           730:                   IDENTIFIER_POINTER (DECL_NAME (parms)));
        !           731: 
        !           732:          dbxout_type (DECL_ARG_TYPE (parms), 0);
        !           733:          dbxout_finish_symbol ();
        !           734:        }
        !           735:       else if (GET_CODE (DECL_RTL (parms)) == MEM
        !           736:               && XEXP (DECL_RTL (parms), 0) != const0_rtx)
        !           737:        {
        !           738:          current_sym_code = N_LSYM;
        !           739:          /* DECL_RTL looks like (MEM (PLUS (REG...) (CONST_INT...))).
        !           740:             We want the value of that CONST_INT.  */
        !           741:          current_sym_value = INTVAL (XEXP (XEXP (DECL_RTL (parms), 0), 1));
        !           742:          current_sym_addr = 0;
        !           743:          current_sym_nchars = 2 + strlen (IDENTIFIER_POINTER (DECL_NAME (parms)));
        !           744: 
        !           745:          fprintf (asmfile, ".stabs \"%s:p",
        !           746:                   IDENTIFIER_POINTER (DECL_NAME (parms)));
        !           747: 
        !           748:          /* This is the case where the parm is passed as an int or double
        !           749:             and it is converted to a char, short or float and stored back
        !           750:             in the parmlist.  In this case, describe the parm
        !           751:             with the variable's declared type, and adjust the address
        !           752:             if the least significant bytes (which we are using) are not
        !           753:             the first ones.  */
        !           754: #ifdef BYTES_BIG_ENDIAN
        !           755:          if (TREE_TYPE (parms) != DECL_ARG_TYPE (parms))
        !           756:            current_sym_value += (GET_MODE_SIZE (TYPE_MODE (DECL_ARG_TYPE (parms)))
        !           757:                                  - GET_MODE_SIZE (GET_MODE (DECL_RTL (parms))));
        !           758: #endif
        !           759: 
        !           760:          dbxout_type (TREE_TYPE (parms), 0);
        !           761:          dbxout_finish_symbol ();
        !           762:        }
        !           763: 
        !           764:     }
        !           765: }
        !           766: 
        !           767: /* Output definitions, referring to registers,
        !           768:    of all the parms in PARMS which are stored in registers during the function.
        !           769:    PARMS is a chain of PARM_DECL nodes.  */
        !           770: 
        !           771: static void
        !           772: dbxout_reg_parms (parms)
        !           773:      tree parms;
        !           774: {
        !           775:   while (parms)
        !           776:     {
        !           777:       /* Report parms that live in registers during the function.  */
        !           778:       if (GET_CODE (DECL_RTL (parms)) == REG
        !           779:          && REGNO (DECL_RTL (parms)) >= 0
        !           780:          && REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER
        !           781:          && DECL_OFFSET (parms) >= 0)
        !           782:        {
        !           783:          current_sym_code = N_RSYM;
        !           784:          current_sym_value = DBX_REGISTER_NUMBER (REGNO (DECL_RTL (parms)));
        !           785:          current_sym_addr = 0;
        !           786:          current_sym_nchars = 2 + strlen (IDENTIFIER_POINTER (DECL_NAME (parms)));
        !           787:          fprintf (asmfile, ".stabs \"%s:r",
        !           788:                   IDENTIFIER_POINTER (DECL_NAME (parms)));
        !           789:          dbxout_type (TREE_TYPE (parms), 0);
        !           790:          dbxout_finish_symbol ();
        !           791:        }
        !           792:       /* Report parms that live in memory but outside the parmlist.  */
        !           793:       else if (GET_CODE (DECL_RTL (parms)) == MEM
        !           794:               && GET_CODE (XEXP (DECL_RTL (parms), 0)) == PLUS
        !           795:               && GET_CODE (XEXP (XEXP (DECL_RTL (parms), 0), 1)) == CONST_INT)
        !           796:        {
        !           797:          int offset = DECL_OFFSET (parms) / BITS_PER_UNIT;
        !           798:          /* A parm declared char is really passed as an int,
        !           799:             so it occupies the least significant bytes.
        !           800:             On a big-endian machine those are not the low-numbered ones.  */
        !           801: #ifdef BYTES_BIG_ENDIAN
        !           802:          if (offset != -1 && TREE_TYPE (parms) != DECL_ARG_TYPE (parms))
        !           803:            offset += (GET_MODE_SIZE (TYPE_MODE (DECL_ARG_TYPE (parms)))
        !           804:                       - GET_MODE_SIZE (GET_MODE (DECL_RTL (parms))));
        !           805: #endif
        !           806:          if (INTVAL (XEXP (XEXP (DECL_RTL (parms), 0), 1)) != offset)
        !           807:            {
        !           808:              current_sym_code = N_LSYM;
        !           809:              current_sym_value = INTVAL (XEXP (XEXP (DECL_RTL (parms), 0), 1));
        !           810:              current_sym_addr = 0;
        !           811:              current_sym_nchars = 2 + strlen (IDENTIFIER_POINTER (DECL_NAME (parms)));
        !           812:              fprintf (asmfile, ".stabs \"%s:",
        !           813:                       IDENTIFIER_POINTER (DECL_NAME (parms)));
        !           814:              dbxout_type (TREE_TYPE (parms), 0);
        !           815:              dbxout_finish_symbol ();
        !           816:            }
        !           817:        }
        !           818:       parms = TREE_CHAIN (parms);
        !           819:     }
        !           820: }
        !           821: 
        !           822: /* Given a chain of ..._TYPE nodes, all of which have names,
        !           823:    output definitions of those names, as typedefs.  */
        !           824: 
        !           825: void
        !           826: dbxout_types (types)
        !           827:      register tree types;
        !           828: {
        !           829:   while (types)
        !           830:     {
        !           831:       if (TYPE_NAME (types)
        !           832:          && TREE_CODE (TYPE_NAME (types)) == TYPE_DECL)
        !           833:        dbxout_type_def (types);
        !           834:       types = TREE_CHAIN (types);
        !           835:     }
        !           836: }
        !           837: 
        !           838: /* Output a definition of a typedef name.
        !           839:    It works much like any other kind of symbol definition.
        !           840:    Output nothing if TYPE's definition has been output already.  */
        !           841: 
        !           842: static void
        !           843: dbxout_type_def (type)
        !           844:      tree type;
        !           845: {
        !           846:   /* This fn is called an extra time for int and char types.  Do nothing.  */
        !           847:   /* This `if' used to reject any type already output,
        !           848:      but that caused some type NAMES not to be defined,
        !           849:      whose TYPES were defined already.  */
        !           850:   if (TYPE_SYMTAB_ADDRESS (type) != 0
        !           851:       && typevec[TYPE_SYMTAB_ADDRESS (type)] == TYPE_DEFINED
        !           852:       && (type == integer_type_node || type == char_type_node))
        !           853:     return;
        !           854: 
        !           855:   current_sym_code = N_LSYM;
        !           856:   current_sym_value = 0;
        !           857:   current_sym_addr = 0;
        !           858:   current_sym_nchars = 0;
        !           859:   current_sym_nchars
        !           860:     = 2 + strlen (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))));
        !           861: 
        !           862:   fprintf (asmfile, ".stabs \"%s:t",
        !           863:           IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))));
        !           864:   dbxout_type (type, 1);
        !           865:   dbxout_finish_symbol ();
        !           866: }
        !           867: 
        !           868: /* Output the tags (struct, union and enum definitions with names) for a block,
        !           869:    given a list of them (a chain of TREE_LIST nodes) in TAGS.
        !           870:    We must check to include those that have been mentioned already with
        !           871:    only a cross-reference.  */
        !           872: 
        !           873: void
        !           874: dbxout_tags (tags)
        !           875:      tree tags;
        !           876: {
        !           877:   register tree link;
        !           878:   for (link = tags; link; link = TREE_CHAIN (link))
        !           879:     {
        !           880:       register tree type = TYPE_MAIN_VARIANT (TREE_VALUE (link));
        !           881:       if (TREE_PURPOSE (link) != 0
        !           882:          && ! TREE_ASM_WRITTEN (link)
        !           883:          && TYPE_SIZE (type) != 0)
        !           884:        {
        !           885:          TREE_ASM_WRITTEN (link) = 1;
        !           886:          current_sym_code = N_LSYM;
        !           887:          current_sym_value = 0;
        !           888:          current_sym_addr = 0;
        !           889:          current_sym_nchars = 2 + strlen (IDENTIFIER_POINTER (TREE_PURPOSE (link)));
        !           890: 
        !           891:          fprintf (asmfile, ".stabs \"%s:T",
        !           892:                   IDENTIFIER_POINTER (TREE_PURPOSE (link)));
        !           893:          dbxout_type (type, 1);
        !           894:          dbxout_finish_symbol ();
        !           895:        }
        !           896:     }
        !           897: }
        !           898: 
        !           899: /* Output everything about a symbol block (that is to say, a LET_STMT node
        !           900:    that represents a scope level),
        !           901:    including recursive output of contained blocks.
        !           902: 
        !           903:    STMT is the LET_STMT node.
        !           904:    DEPTH is its depth within containing symbol blocks.
        !           905:    ARGS is usually zero; but for the outermost block of the
        !           906:    body of a function, it is a chain of PARM_DECLs for the function parameters.
        !           907:    We output definitions of all the register parms
        !           908:    as if they were local variables of that block.
        !           909: 
        !           910:    Actually, STMT may be several statements chained together.
        !           911:    We handle them all in sequence.  */
        !           912: 
        !           913: static void
        !           914: dbxout_block (stmt, depth, args)
        !           915:      register tree stmt;
        !           916:      int depth;
        !           917:      tree args;
        !           918: {
        !           919:   int blocknum;
        !           920: 
        !           921:   while (stmt)
        !           922:     {
        !           923:       switch (TREE_CODE (stmt))
        !           924:        {
        !           925:        case COMPOUND_STMT:
        !           926:        case LOOP_STMT:
        !           927:          dbxout_block (STMT_BODY (stmt), depth, 0);
        !           928:          break;
        !           929: 
        !           930:        case IF_STMT:
        !           931:          dbxout_block (STMT_THEN (stmt), depth, 0);
        !           932:          dbxout_block (STMT_ELSE (stmt), depth, 0);
        !           933:          break;
        !           934: 
        !           935:        case LET_STMT:
        !           936:          /* In dbx format, the syms of a block come before the N_LBRAC.  */
        !           937:          dbxout_tags (STMT_TYPE_TAGS (stmt));
        !           938:          dbxout_syms (STMT_VARS (stmt));
        !           939:          if (args)
        !           940:            dbxout_reg_parms (args);
        !           941: 
        !           942:          /* Now output an N_LBRAC symbol to represent the beginning of
        !           943:             the block.  Use the block's tree-walk order to generate
        !           944:             the assembler symbols LBBn and LBEn
        !           945:             that final will define around the code in this block.  */
        !           946:          if (depth > 0)
        !           947:            {
        !           948:              blocknum = next_block_number++;
        !           949:              fprintf (asmfile, ".stabn %d,0,0,LBB%d\n", N_LBRAC, blocknum);
        !           950:            }
        !           951: 
        !           952:          /* Output the interior of the block.  */
        !           953:          dbxout_block (STMT_BODY (stmt), depth + 1, 0);
        !           954: 
        !           955:          /* Refer to the marker for the end of the block.  */
        !           956:          if (depth > 0)
        !           957:            fprintf (asmfile, ".stabn %d,0,0,LBE%d\n", N_RBRAC, blocknum);
        !           958:        }
        !           959:       stmt = TREE_CHAIN (stmt);
        !           960:     }
        !           961: }
        !           962: 
        !           963: /* Output dbx data for a function definition.
        !           964:    This includes a definition of the function name itself (a symbol),
        !           965:    definitions of the parameters (locating them in the parameter list)
        !           966:    and then output the block that makes up the function's body
        !           967:    (including all the auto variables of the function).  */
        !           968: 
        !           969: void
        !           970: dbxout_function (decl)
        !           971:      tree decl;
        !           972: {
        !           973:   dbxout_symbol (decl, 0);
        !           974:   dbxout_parms (DECL_ARGUMENTS (decl));
        !           975:   dbxout_block (DECL_INITIAL (decl), 0, DECL_ARGUMENTS (decl));
        !           976: }
        !           977: 
        !           978: #else /* NO_DBX_FORMAT */
        !           979: 
        !           980: void
        !           981: dbxout_init (asm_file, input_file_name)
        !           982:      FILE *asm_file;
        !           983:      char *input_file_name;
        !           984: {}
        !           985: 
        !           986: void
        !           987: dbxout_symbol (decl, local)
        !           988:      tree decl;
        !           989:      int local;
        !           990: {}
        !           991: 
        !           992: void
        !           993: dbxout_types (types)
        !           994:      register tree types;
        !           995: {}
        !           996: 
        !           997: void
        !           998: dbxout_tags (tags)
        !           999:      tree tags;
        !          1000: {}
        !          1001: 
        !          1002: void
        !          1003: dbxout_function (decl)
        !          1004:      tree decl;
        !          1005: {}
        !          1006: 
        !          1007: #endif /* NO_DBX_FORMAT */
        !          1008: 
        !          1009: fprd(f, val)
        !          1010:        FILE *f;
        !          1011:        double val;
        !          1012: {
        !          1013:        long *l = (long *)&val;
        !          1014:        fprintf (f, "\t.long 0x%x,0x%x\n", l[0], l[1]);
        !          1015: }
        !          1016: 
        !          1017: fprf(f, val)
        !          1018:        FILE *f;
        !          1019:        float val;
        !          1020: {
        !          1021:        long *l = (long *)&val;
        !          1022:        fprintf (f, "\t.long 0x%x\n", l[0]);
        !          1023: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.