|
|
1.1 ! root 1: /* Output dbx-format symbol table information from GNU compiler. ! 2: Copyright (C) 1987, 1988, 1992 Free Software Foundation, Inc. ! 3: ! 4: This file is part of GNU CC. ! 5: ! 6: GNU CC is free software; you can redistribute it and/or modify ! 7: it under the terms of the GNU General Public License as published by ! 8: the Free Software Foundation; either version 2, or (at your option) ! 9: any later version. ! 10: ! 11: GNU CC is distributed in the hope that it will be useful, ! 12: but WITHOUT ANY WARRANTY; without even the implied warranty of ! 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 14: GNU General Public License for more details. ! 15: ! 16: You should have received a copy of the GNU General Public License ! 17: along with GNU CC; see the file COPYING. If not, write to ! 18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ! 19: ! 20: ! 21: /* Output dbx-format symbol table data. ! 22: This consists of many symbol table entries, each of them ! 23: a .stabs assembler pseudo-op with four operands: ! 24: a "name" which is really a description of one symbol and its type, ! 25: a "code", which is a symbol defined in stab.h whose name starts with N_, ! 26: an unused operand always 0, ! 27: and a "value" which is an address or an offset. ! 28: The name is enclosed in doublequote characters. ! 29: ! 30: Each function, variable, typedef, and structure tag ! 31: has a symbol table entry to define it. ! 32: The beginning and end of each level of name scoping within ! 33: a function are also marked by special symbol table entries. ! 34: ! 35: The "name" consists of the symbol name, a colon, a kind-of-symbol letter, ! 36: and a data type number. The data type number may be followed by ! 37: "=" and a type definition; normally this will happen the first time ! 38: the type number is mentioned. The type definition may refer to ! 39: other types by number, and those type numbers may be followed ! 40: by "=" and nested definitions. ! 41: ! 42: This can make the "name" quite long. ! 43: When a name is more than 80 characters, we split the .stabs pseudo-op ! 44: into two .stabs pseudo-ops, both sharing the same "code" and "value". ! 45: The first one is marked as continued with a double-backslash at the ! 46: end of its "name". ! 47: ! 48: The kind-of-symbol letter distinguished function names from global ! 49: variables from file-scope variables from parameters from auto ! 50: variables in memory from typedef names from register variables. ! 51: See `dbxout_symbol'. ! 52: ! 53: The "code" is mostly redundant with the kind-of-symbol letter ! 54: that goes in the "name", but not entirely: for symbols located ! 55: in static storage, the "code" says which segment the address is in, ! 56: which controls how it is relocated. ! 57: ! 58: The "value" for a symbol in static storage ! 59: is the core address of the symbol (actually, the assembler ! 60: label for the symbol). For a symbol located in a stack slot ! 61: it is the stack offset; for one in a register, the register number. ! 62: For a typedef symbol, it is zero. ! 63: ! 64: If DEBUG_SYMS_TEXT is defined, all debugging symbols must be ! 65: output while in the text section. ! 66: ! 67: For more on data type definitions, see `dbxout_type'. */ ! 68: ! 69: /* Include these first, because they may define MIN and MAX. */ ! 70: #include <stdio.h> ! 71: #include <sys/param.h> ! 72: #include <errno.h> ! 73: ! 74: #include "config.h" ! 75: #include "tree.h" ! 76: #include "rtl.h" ! 77: #include "flags.h" ! 78: #include "regs.h" ! 79: #include "insn-config.h" ! 80: #include "reload.h" ! 81: ! 82: #ifndef errno ! 83: extern int errno; ! 84: #endif ! 85: ! 86: #ifndef ASM_STABS_OP ! 87: #define ASM_STABS_OP ".stabs" ! 88: #endif ! 89: ! 90: #ifndef ASM_STABN_OP ! 91: #define ASM_STABN_OP ".stabn" ! 92: #endif ! 93: ! 94: /* Nonzero means if the type has methods, only output debugging ! 95: information if methods are actually written to the asm file. */ ! 96: ! 97: static int flag_minimal_debug = 1; ! 98: ! 99: /* Nonzero if we have actually used any of the GDB extensions ! 100: to the debugging format. The idea is that we use them for the ! 101: first time only if there's a strong reason, but once we have done that, ! 102: we use them whenever convenient. */ ! 103: ! 104: static int have_used_extensions = 0; ! 105: ! 106: /* Virtually every UN*X system now in common use (except for pre-4.3-tahoe ! 107: BSD systems) now provides getcwd as called for by POSIX. Allow for ! 108: the few exceptions to the general rule here. */ ! 109: ! 110: #if !(defined (USG) || defined (VMS)) ! 111: extern char *getwd (); ! 112: #define getcwd(buf,len) getwd(buf) ! 113: #define GUESSPATHLEN (MAXPATHLEN + 1) ! 114: #else /* (defined (USG) || defined (VMS)) */ ! 115: extern char *getcwd (); ! 116: /* We actually use this as a starting point, not a limit. */ ! 117: #define GUESSPATHLEN 100 ! 118: #endif /* (defined (USG) || defined (VMS)) */ ! 119: ! 120: /* Typical USG systems don't have stab.h, and they also have ! 121: no use for DBX-format debugging info. */ ! 122: ! 123: #ifdef DBX_DEBUGGING_INFO ! 124: ! 125: #ifdef DEBUG_SYMS_TEXT ! 126: #define FORCE_TEXT text_section (); ! 127: #else ! 128: #define FORCE_TEXT ! 129: #endif ! 130: ! 131: #if defined (USG) || defined (MIPS) ! 132: #include "gstab.h" /* If doing DBX on sysV, use our own stab.h. */ ! 133: #else ! 134: #include <stab.h> /* On BSD, use the system's stab.h. */ ! 135: ! 136: /* This is a GNU extension we need to reference in this file. */ ! 137: #ifndef N_CATCH ! 138: #define N_CATCH 0x54 ! 139: #endif ! 140: #endif /* not USG */ ! 141: ! 142: #ifdef __GNU_STAB__ ! 143: #define STAB_CODE_TYPE enum __stab_debug_code ! 144: #else ! 145: #define STAB_CODE_TYPE int ! 146: #endif ! 147: ! 148: /* 1 if PARM is passed to this function in memory. */ ! 149: ! 150: #define PARM_PASSED_IN_MEMORY(PARM) \ ! 151: (GET_CODE (DECL_INCOMING_RTL (PARM)) == MEM) ! 152: ! 153: /* A C expression for the integer offset value of an automatic variable ! 154: (N_LSYM) having address X (an RTX). */ ! 155: #ifndef DEBUGGER_AUTO_OFFSET ! 156: #define DEBUGGER_AUTO_OFFSET(X) \ ! 157: (GET_CODE (X) == PLUS ? INTVAL (XEXP (X, 1)) : 0) ! 158: #endif ! 159: ! 160: /* A C expression for the integer offset value of an argument (N_PSYM) ! 161: having address X (an RTX). The nominal offset is OFFSET. */ ! 162: #ifndef DEBUGGER_ARG_OFFSET ! 163: #define DEBUGGER_ARG_OFFSET(OFFSET, X) (OFFSET) ! 164: #endif ! 165: ! 166: /* Stream for writing to assembler file. */ ! 167: ! 168: static FILE *asmfile; ! 169: ! 170: /* Last source file name mentioned in a NOTE insn. */ ! 171: ! 172: static char *lastfile; ! 173: ! 174: /* Current working directory. */ ! 175: ! 176: static char *cwd; ! 177: static enum {not_gotten, gotten, error_getting} cwd_status = not_gotten; ! 178: ! 179: enum typestatus {TYPE_UNSEEN, TYPE_XREF, TYPE_DEFINED}; ! 180: ! 181: /* Vector recording the status of describing C data types. ! 182: When we first notice a data type (a tree node), ! 183: we assign it a number using next_type_number. ! 184: That is its index in this vector. ! 185: The vector element says whether we have yet output ! 186: the definition of the type. TYPE_XREF says we have ! 187: output it as a cross-reference only. */ ! 188: ! 189: enum typestatus *typevec; ! 190: ! 191: /* Number of elements of space allocated in `typevec'. */ ! 192: ! 193: static int typevec_len; ! 194: ! 195: /* In dbx output, each type gets a unique number. ! 196: This is the number for the next type output. ! 197: The number, once assigned, is in the TYPE_SYMTAB_ADDRESS field. */ ! 198: ! 199: static int next_type_number; ! 200: ! 201: /* In dbx output, we must assign symbol-blocks id numbers ! 202: in the order in which their beginnings are encountered. ! 203: We output debugging info that refers to the beginning and ! 204: end of the ranges of code in each block ! 205: with assembler labels LBBn and LBEn, where n is the block number. ! 206: The labels are generated in final, which assigns numbers to the ! 207: blocks in the same way. */ ! 208: ! 209: static int next_block_number; ! 210: ! 211: /* These variables are for dbxout_symbol to communicate to ! 212: dbxout_finish_symbol. ! 213: current_sym_code is the symbol-type-code, a symbol N_... define in stab.h. ! 214: current_sym_value and current_sym_addr are two ways to address the ! 215: value to store in the symtab entry. ! 216: current_sym_addr if nonzero represents the value as an rtx. ! 217: If that is zero, current_sym_value is used. This is used ! 218: when the value is an offset (such as for auto variables, ! 219: register variables and parms). */ ! 220: ! 221: static STAB_CODE_TYPE current_sym_code; ! 222: static int current_sym_value; ! 223: static rtx current_sym_addr; ! 224: ! 225: /* Number of chars of symbol-description generated so far for the ! 226: current symbol. Used by CHARS and CONTIN. */ ! 227: ! 228: static int current_sym_nchars; ! 229: ! 230: /* Report having output N chars of the current symbol-description. */ ! 231: ! 232: #define CHARS(N) (current_sym_nchars += (N)) ! 233: ! 234: /* Break the current symbol-description, generating a continuation, ! 235: if it has become long. */ ! 236: ! 237: #ifndef DBX_CONTIN_LENGTH ! 238: #define DBX_CONTIN_LENGTH 80 ! 239: #endif ! 240: ! 241: #if DBX_CONTIN_LENGTH > 0 ! 242: #define CONTIN \ ! 243: do {if (current_sym_nchars > DBX_CONTIN_LENGTH) dbxout_continue ();} while (0) ! 244: #else ! 245: #define CONTIN ! 246: #endif ! 247: ! 248: void dbxout_types (); ! 249: void dbxout_args (); ! 250: void dbxout_symbol (); ! 251: static void dbxout_type_name (); ! 252: static void dbxout_type (); ! 253: static void dbxout_typedefs (); ! 254: static void dbxout_prepare_symbol (); ! 255: static void dbxout_finish_symbol (); ! 256: static void dbxout_continue (); ! 257: static void print_int_cst_octal (); ! 258: static void print_octal (); ! 259: ! 260: #if 0 /* Not clear we will actually need this. */ ! 261: ! 262: /* Return the absolutized filename for the given relative ! 263: filename. Note that if that filename is already absolute, it may ! 264: still be returned in a modified form because this routine also ! 265: eliminates redundant slashes and single dots and eliminates double ! 266: dots to get a shortest possible filename from the given input ! 267: filename. The absolutization of relative filenames is made by ! 268: assuming that the given filename is to be taken as relative to ! 269: the first argument (cwd) or to the current directory if cwd is ! 270: NULL. */ ! 271: ! 272: static char * ! 273: abspath (rel_filename) ! 274: char *rel_filename; ! 275: { ! 276: /* Setup the current working directory as needed. */ ! 277: char *abs_buffer ! 278: = (char *) alloca (strlen (cwd) + strlen (rel_filename) + 1); ! 279: char *endp = abs_buffer; ! 280: char *outp, *inp; ! 281: char *value; ! 282: ! 283: /* Copy the filename (possibly preceeded by the current working ! 284: directory name) into the absolutization buffer. */ ! 285: ! 286: { ! 287: char *src_p; ! 288: ! 289: if (rel_filename[0] != '/') ! 290: { ! 291: src_p = cwd; ! 292: while (*endp++ = *src_p++) ! 293: continue; ! 294: *(endp-1) = '/'; /* overwrite null */ ! 295: } ! 296: src_p = rel_filename; ! 297: while (*endp++ = *src_p++) ! 298: continue; ! 299: if (endp[-1] == '/') ! 300: *endp = '\0'; ! 301: } ! 302: ! 303: /* Now make a copy of abs_buffer into abs_buffer, shortening the ! 304: filename (by taking out slashes and dots) as we go. */ ! 305: ! 306: outp = inp = abs_buffer; ! 307: *outp++ = *inp++; /* copy first slash */ ! 308: for (;;) ! 309: { ! 310: if (!inp[0]) ! 311: break; ! 312: else if (inp[0] == '/' && outp[-1] == '/') ! 313: { ! 314: inp++; ! 315: continue; ! 316: } ! 317: else if (inp[0] == '.' && outp[-1] == '/') ! 318: { ! 319: if (!inp[1]) ! 320: break; ! 321: else if (inp[1] == '/') ! 322: { ! 323: inp += 2; ! 324: continue; ! 325: } ! 326: else if ((inp[1] == '.') && (inp[2] == 0 || inp[2] == '/')) ! 327: { ! 328: inp += (inp[2] == '/') ? 3 : 2; ! 329: outp -= 2; ! 330: while (outp >= abs_buffer && *outp != '/') ! 331: outp--; ! 332: if (outp < abs_buffer) ! 333: { ! 334: /* Catch cases like /.. where we try to backup to a ! 335: point above the absolute root of the logical file ! 336: system. */ ! 337: ! 338: fprintf (stderr, "%s: invalid file name: %s\n", ! 339: pname, rel_filename); ! 340: exit (1); ! 341: } ! 342: *++outp = '\0'; ! 343: continue; ! 344: } ! 345: } ! 346: *outp++ = *inp++; ! 347: } ! 348: ! 349: /* On exit, make sure that there is a trailing null, and make sure that ! 350: the last character of the returned string is *not* a slash. */ ! 351: ! 352: *outp = '\0'; ! 353: if (outp[-1] == '/') ! 354: *--outp = '\0'; ! 355: ! 356: /* Make a copy (in the heap) of the stuff left in the absolutization ! 357: buffer and return a pointer to the copy. */ ! 358: ! 359: value = (char *) oballoc (strlen (abs_buffer) + 1); ! 360: strcpy (value, abs_buffer); ! 361: return value; ! 362: } ! 363: #endif /* 0 */ ! 364: ! 365: /* At the beginning of compilation, start writing the symbol table. ! 366: Initialize `typevec' and output the standard data types of C. */ ! 367: ! 368: void ! 369: dbxout_init (asm_file, input_file_name, syms) ! 370: FILE *asm_file; ! 371: char *input_file_name; ! 372: tree syms; ! 373: { ! 374: char ltext_label_name[100]; ! 375: ! 376: asmfile = asm_file; ! 377: ! 378: typevec_len = 100; ! 379: typevec = (enum typestatus *) xmalloc (typevec_len * sizeof typevec[0]); ! 380: bzero (typevec, typevec_len * sizeof typevec[0]); ! 381: ! 382: /* Convert Ltext into the appropriate format for local labels in case ! 383: the system doesn't insert underscores in front of user generated ! 384: labels. */ ! 385: ASM_GENERATE_INTERNAL_LABEL (ltext_label_name, "Ltext", 0); ! 386: ! 387: /* Put the current working directory in an N_SO symbol. */ ! 388: { ! 389: int size; ! 390: ! 391: if (cwd_status == not_gotten) ! 392: { ! 393: char *value; ! 394: ! 395: /* Read the working directory, avoiding arbitrary limit. */ ! 396: size = GUESSPATHLEN; ! 397: while (1) ! 398: { ! 399: cwd = (char *) xmalloc (size); ! 400: value = getcwd (cwd, size); ! 401: if (value != 0 || errno != ERANGE) ! 402: break; ! 403: free (cwd); ! 404: size *= 2; ! 405: } ! 406: ! 407: if (value != 0) ! 408: cwd_status = gotten; ! 409: else ! 410: cwd_status = error_getting; ! 411: } ! 412: ! 413: if (cwd_status == gotten) ! 414: { ! 415: #ifdef DBX_OUTPUT_MAIN_SOURCE_DIRECTORY ! 416: DBX_OUTPUT_MAIN_SOURCE_DIRECTORY (asmfile, cwd); ! 417: #else /* no DBX_OUTPUT_MAIN_SOURCE_DIRECTORY */ ! 418: fprintf (asmfile, "%s \"%s/\",%d,0,0,%s\n", ASM_STABS_OP, ! 419: cwd, N_SO, <ext_label_name[1]); ! 420: #endif /* no DBX_OUTPUT_MAIN_SOURCE_DIRECTORY */ ! 421: } ! 422: } ! 423: ! 424: #ifdef DBX_OUTPUT_MAIN_SOURCE_FILENAME ! 425: /* This should NOT be DBX_OUTPUT_SOURCE_FILENAME. That ! 426: would give us an N_SOL, and we want an N_SO. */ ! 427: DBX_OUTPUT_MAIN_SOURCE_FILENAME (asmfile, input_file_name); ! 428: #else /* no DBX_OUTPUT_MAIN_SOURCE_FILENAME */ ! 429: /* We include outputting `Ltext:' here, ! 430: because that gives you a way to override it. */ ! 431: /* Used to put `Ltext:' before the reference, but that loses on sun 4. */ ! 432: fprintf (asmfile, "%s \"%s\",%d,0,0,%s\n", ASM_STABS_OP, input_file_name, ! 433: N_SO, <ext_label_name[1]); ! 434: text_section (); ! 435: ASM_OUTPUT_INTERNAL_LABEL (asmfile, "Ltext", 0); ! 436: #endif /* no DBX_OUTPUT_MAIN_SOURCE_FILENAME */ ! 437: ! 438: lastfile = input_file_name; ! 439: ! 440: next_type_number = 1; ! 441: next_block_number = 2; ! 442: ! 443: /* Make sure that types `int' and `char' have numbers 1 and 2. ! 444: Definitions of other integer types will refer to those numbers. ! 445: (Actually it should no longer matter what their numbers are. ! 446: Also, if any types with tags have been defined, dbxout_symbol ! 447: will output them first, so the numbers won't be 1 and 2. That ! 448: happens in C++. So it's a good thing it should no longer matter). */ ! 449: ! 450: #ifdef DBX_OUTPUT_STANDARD_TYPES ! 451: DBX_OUTPUT_STANDARD_TYPES (syms); ! 452: #else ! 453: dbxout_symbol (TYPE_NAME (integer_type_node), 0); ! 454: dbxout_symbol (TYPE_NAME (char_type_node), 0); ! 455: #endif ! 456: ! 457: /* Get all permanent types that have typedef names, ! 458: and output them all, except for those already output. */ ! 459: ! 460: dbxout_typedefs (syms); ! 461: } ! 462: ! 463: /* Output any typedef names for types described by TYPE_DECLs in SYMS, ! 464: in the reverse order from that which is found in SYMS. */ ! 465: ! 466: static void ! 467: dbxout_typedefs (syms) ! 468: tree syms; ! 469: { ! 470: if (syms) ! 471: { ! 472: dbxout_typedefs (TREE_CHAIN (syms)); ! 473: if (TREE_CODE (syms) == TYPE_DECL) ! 474: { ! 475: tree type = TREE_TYPE (syms); ! 476: if (TYPE_NAME (type) ! 477: && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL ! 478: && ! TREE_ASM_WRITTEN (TYPE_NAME (type))) ! 479: dbxout_symbol (TYPE_NAME (type), 0); ! 480: } ! 481: } ! 482: } ! 483: ! 484: /* Output debugging info to FILE to switch to sourcefile FILENAME. */ ! 485: ! 486: void ! 487: dbxout_source_file (file, filename) ! 488: FILE *file; ! 489: char *filename; ! 490: { ! 491: char ltext_label_name[100]; ! 492: ! 493: if (filename && (lastfile == 0 || strcmp (filename, lastfile))) ! 494: { ! 495: #ifdef DBX_OUTPUT_SOURCE_FILENAME ! 496: DBX_OUTPUT_SOURCE_FILENAME (file, filename); ! 497: #else ! 498: ASM_GENERATE_INTERNAL_LABEL (ltext_label_name, "Ltext", 0); ! 499: fprintf (file, "%s \"%s\",%d,0,0,%s\n", ASM_STABS_OP, ! 500: filename, N_SOL, <ext_label_name[1]); ! 501: #endif ! 502: lastfile = filename; ! 503: } ! 504: } ! 505: ! 506: /* At the end of compilation, finish writing the symbol table. ! 507: Unless you define DBX_OUTPUT_MAIN_SOURCE_FILE_END, the default is ! 508: to do nothing. */ ! 509: ! 510: void ! 511: dbxout_finish (file, filename) ! 512: FILE *file; ! 513: char *filename; ! 514: { ! 515: #ifdef DBX_OUTPUT_MAIN_SOURCE_FILE_END ! 516: DBX_OUTPUT_MAIN_SOURCE_FILE_END (file, filename); ! 517: #endif /* DBX_OUTPUT_MAIN_SOURCE_FILE_END */ ! 518: } ! 519: ! 520: /* Continue a symbol-description that gets too big. ! 521: End one symbol table entry with a double-backslash ! 522: and start a new one, eventually producing something like ! 523: .stabs "start......\\",code,0,value ! 524: .stabs "...rest",code,0,value */ ! 525: ! 526: static void ! 527: dbxout_continue () ! 528: { ! 529: #ifdef DBX_CONTIN_CHAR ! 530: fprintf (asmfile, "%c", DBX_CONTIN_CHAR); ! 531: #else ! 532: fprintf (asmfile, "\\\\"); ! 533: #endif ! 534: dbxout_finish_symbol (0); ! 535: fprintf (asmfile, "%s \"", ASM_STABS_OP); ! 536: current_sym_nchars = 0; ! 537: } ! 538: ! 539: /* Subtroutine of `dbxout_type'. Output the type fields of TYPE. ! 540: This must be a separate function because anonymous unions require ! 541: recursive calls. */ ! 542: ! 543: static void ! 544: dbxout_type_fields (type) ! 545: tree type; ! 546: { ! 547: tree tem; ! 548: for (tem = TYPE_FIELDS (type); tem; tem = TREE_CHAIN (tem)) ! 549: { ! 550: /* Output the name, type, position (in bits), size (in bits) ! 551: of each field. */ ! 552: if (DECL_NAME (tem) == NULL_TREE ! 553: && TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE) ! 554: dbxout_type_fields (TREE_TYPE (tem)); ! 555: /* Omit here local type decls until we know how to support them. */ ! 556: else if (TREE_CODE (tem) == TYPE_DECL) ! 557: continue; ! 558: /* Omit here the nameless fields that are used to skip bits. */ ! 559: else if (DECL_NAME (tem) != 0 && TREE_CODE (tem) != CONST_DECL) ! 560: { ! 561: /* Continue the line if necessary, ! 562: but not before the first field. */ ! 563: if (tem != TYPE_FIELDS (type)) ! 564: CONTIN; ! 565: ! 566: if (use_gdb_dbx_extensions ! 567: && flag_minimal_debug ! 568: && TREE_CODE (tem) == FIELD_DECL ! 569: && DECL_VIRTUAL_P (tem) ! 570: && DECL_ASSEMBLER_NAME (tem)) ! 571: { ! 572: have_used_extensions = 1; ! 573: CHARS (3 + IDENTIFIER_LENGTH (DECL_NAME (TYPE_NAME (DECL_FCONTEXT (tem))))); ! 574: fputs (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (tem)), asmfile); ! 575: dbxout_type (DECL_FCONTEXT (tem), 0); ! 576: fprintf (asmfile, ":"); ! 577: dbxout_type (TREE_TYPE (tem), 0); ! 578: fprintf (asmfile, ",%d;", ! 579: TREE_INT_CST_LOW (DECL_FIELD_BITPOS (tem))); ! 580: continue; ! 581: } ! 582: ! 583: fprintf (asmfile, "%s:", IDENTIFIER_POINTER (DECL_NAME (tem))); ! 584: CHARS (2 + IDENTIFIER_LENGTH (DECL_NAME (tem))); ! 585: ! 586: if (use_gdb_dbx_extensions ! 587: && (TREE_PRIVATE (tem) || TREE_PROTECTED (tem) ! 588: || TREE_CODE (tem) != FIELD_DECL)) ! 589: { ! 590: have_used_extensions = 1; ! 591: putc ('/', asmfile); ! 592: putc ((TREE_PRIVATE (tem) ? '0' ! 593: : TREE_PROTECTED (tem) ? '1' : '2'), ! 594: asmfile); ! 595: CHARS (2); ! 596: } ! 597: ! 598: dbxout_type ((TREE_CODE (tem) == FIELD_DECL ! 599: && DECL_BIT_FIELD_TYPE (tem)) ! 600: ? DECL_BIT_FIELD_TYPE (tem) ! 601: : TREE_TYPE (tem), 0); ! 602: ! 603: if (TREE_CODE (tem) == VAR_DECL) ! 604: { ! 605: if (TREE_STATIC (tem) && use_gdb_dbx_extensions) ! 606: { ! 607: char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (tem)); ! 608: have_used_extensions = 1; ! 609: ! 610: #if 0 /* ??? Comment below makes it clear this is unacceptable. */ ! 611: /* Adding 1 here only works on systems ! 612: which flush an initial underscore from ! 613: the .stabs entry. This loses for static names ! 614: which have an initial leading '_' on systems which ! 615: don't use leading underscores. */ ! 616: if (name[0] == '_') ! 617: name += 1; ! 618: #endif ! 619: ! 620: fprintf (asmfile, ":%s;", name); ! 621: CHARS (strlen (name)); ! 622: } ! 623: else ! 624: { ! 625: /* If TEM is non-static, GDB won't understand it. */ ! 626: fprintf (asmfile, ",0,0;"); ! 627: } ! 628: } ! 629: else if (TREE_CODE (DECL_FIELD_BITPOS (tem)) == INTEGER_CST) ! 630: { ! 631: fprintf (asmfile, ",%d,%d;", ! 632: TREE_INT_CST_LOW (DECL_FIELD_BITPOS (tem)), ! 633: TREE_INT_CST_LOW (DECL_SIZE (tem))); ! 634: } ! 635: else ! 636: /* This has yet to be implemented. */ ! 637: abort (); ! 638: CHARS (23); ! 639: } ! 640: } ! 641: } ! 642: ! 643: /* Subtroutine of `dbxout_type_methods'. Output debug info about the ! 644: method described DECL. DEBUG_NAME is an encoding of the method's ! 645: type signature. ??? We may be able to do without DEBUG_NAME altogether ! 646: now. */ ! 647: ! 648: static void ! 649: dbxout_type_method_1 (decl, debug_name) ! 650: tree decl; ! 651: char *debug_name; ! 652: { ! 653: tree firstarg = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (decl))); ! 654: char c1 = 'A', c2; ! 655: ! 656: if (TREE_CODE (TREE_TYPE (decl)) == FUNCTION_TYPE) ! 657: c2 = '?'; ! 658: else /* it's a METHOD_TYPE. */ ! 659: { ! 660: /* A for normal functions. ! 661: B for `const' member functions. ! 662: C for `volatile' member functions. ! 663: D for `const volatile' member functions. */ ! 664: if (TYPE_READONLY (TREE_TYPE (firstarg))) ! 665: c1 += 1; ! 666: if (TYPE_VOLATILE (TREE_TYPE (firstarg))) ! 667: c1 += 2; ! 668: ! 669: if (DECL_VINDEX (decl)) ! 670: c2 = '*'; ! 671: else ! 672: c2 = '.'; ! 673: } ! 674: ! 675: fprintf (asmfile, ":%s;%c%c%c", debug_name, ! 676: TREE_PRIVATE (decl) ? '0' : TREE_PROTECTED (decl) ? '1' : '2', c1, c2); ! 677: CHARS (IDENTIFIER_LENGTH (DECL_ASSEMBLER_NAME (decl)) + 6 ! 678: - (debug_name - IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)))); ! 679: if (DECL_VINDEX (decl)) ! 680: { ! 681: fprintf (asmfile, "%d;", ! 682: TREE_INT_CST_LOW (DECL_VINDEX (decl))); ! 683: dbxout_type (DECL_CONTEXT (decl), 0); ! 684: fprintf (asmfile, ";"); ! 685: CHARS (8); ! 686: } ! 687: } ! 688: ! 689: /* Subroutine of `dbxout_type'. Output debug info about the methods defined ! 690: in TYPE. */ ! 691: ! 692: static void ! 693: dbxout_type_methods (type) ! 694: register tree type; ! 695: { ! 696: /* C++: put out the method names and their parameter lists */ ! 697: tree ctor_name; ! 698: tree methods = TYPE_METHODS (type); ! 699: register tree fndecl; ! 700: register tree last; ! 701: register int type_identifier_length; ! 702: ! 703: if (methods == NULL_TREE) ! 704: return; ! 705: ! 706: ctor_name = DECL_NAME (TYPE_NAME (type)); ! 707: type_identifier_length = IDENTIFIER_LENGTH (ctor_name); ! 708: if (TREE_CODE (methods) == FUNCTION_DECL) ! 709: fndecl = methods; ! 710: else if (TREE_VEC_ELT (methods, 0) != NULL_TREE) ! 711: fndecl = TREE_VEC_ELT (methods, 0); ! 712: else fndecl = TREE_VEC_ELT (methods, 1); ! 713: ! 714: if (TREE_CODE (type) == RECORD_TYPE && DECL_NAME (fndecl) == ctor_name) ! 715: { ! 716: tree ctor = fndecl; ! 717: tree dtor; ! 718: ! 719: /* Destructors lie in a special place. ! 720: n.b. TYPE_HAS_DESTRUCTOR == TYPE_LANG_FLAG_2 */ ! 721: if (TYPE_LANG_FLAG_2 (type)) ! 722: { ! 723: dtor = fndecl; ! 724: fndecl = ctor = TREE_CHAIN (dtor); ! 725: } ! 726: else ! 727: dtor = NULL_TREE; ! 728: ! 729: CHARS (2); ! 730: ! 731: if (ctor) ! 732: { ! 733: int need_prefix = 1; ! 734: ! 735: while (ctor) ! 736: { ! 737: /* Output the name of the field (after overloading), as ! 738: well as the name of the field before overloading, along ! 739: with its parameter list. */ ! 740: char *debug_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (ctor)); ! 741: int old_minimal_debug = flag_minimal_debug; ! 742: ! 743: CONTIN; ! 744: ! 745: if (DECL_NAME (ctor) == ctor_name && ! DECL_IGNORED_P (ctor)) ! 746: { ! 747: if (need_prefix) ! 748: { ! 749: fprintf (asmfile, "%s::", IDENTIFIER_POINTER (DECL_NAME (ctor))); ! 750: CHARS (IDENTIFIER_LENGTH (DECL_NAME (ctor)) + 3); ! 751: need_prefix = 0; ! 752: } ! 753: ! 754: if (ctor == dtor) ! 755: /* Always output destructors with full information. */ ! 756: flag_minimal_debug = 0; ! 757: ! 758: dbxout_type (TREE_TYPE (ctor), 0); ! 759: flag_minimal_debug = old_minimal_debug; ! 760: ! 761: if (flag_minimal_debug && ctor != dtor) ! 762: { ! 763: /* Cut down on debugging information by not outputting ! 764: the parts of the name we can just as easily ! 765: have the debugger figure out. */ ! 766: ! 767: /* Get past '__'. */ ! 768: debug_name += 2; ! 769: /* Get past const and volatile qualifiers. */ ! 770: while (*debug_name == 'C' || *debug_name == 'V') ! 771: debug_name++; ! 772: /* Get past numeric type length prefix. */ ! 773: while (*debug_name >= '0' && *debug_name <= '9') ! 774: debug_name++; ! 775: /* Get past type of `this'. */ ! 776: debug_name += type_identifier_length; ! 777: } ! 778: dbxout_type_method_1 (ctor, debug_name); ! 779: } ! 780: ! 781: if (ctor == dtor) ! 782: break; ! 783: ! 784: ctor = TREE_CHAIN (ctor); ! 785: if (ctor == NULL_TREE || DECL_NAME (ctor) != ctor_name) ! 786: { ! 787: fndecl = ctor; ! 788: ctor = dtor; ! 789: } ! 790: } ! 791: if (! need_prefix) ! 792: putc (';', asmfile); ! 793: } ! 794: } ! 795: ! 796: while (fndecl) ! 797: { ! 798: tree name = DECL_NAME (fndecl); ! 799: fprintf (asmfile, "%s::", IDENTIFIER_POINTER (name)); ! 800: CHARS (IDENTIFIER_LENGTH (name) + 3); ! 801: ! 802: for (last = NULL_TREE; ! 803: fndecl && (last == NULL_TREE || DECL_NAME (fndecl) == DECL_NAME (last)); ! 804: fndecl = TREE_CHAIN (fndecl)) ! 805: /* Output the name of the field (after overloading), as ! 806: well as the name of the field before overloading, along ! 807: with its parameter list */ ! 808: { ! 809: char *debug_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl)); ! 810: ! 811: CONTIN; ! 812: ! 813: last = fndecl; ! 814: dbxout_type (TREE_TYPE (fndecl), 0); ! 815: if (flag_minimal_debug) ! 816: { ! 817: debug_name += IDENTIFIER_LENGTH (DECL_NAME (fndecl)) + 2; ! 818: /* Get past const and volatile qualifiers. */ ! 819: while (*debug_name == 'C' || *debug_name == 'V') ! 820: debug_name++; ! 821: while (*debug_name >= '0' && *debug_name <= '9') ! 822: debug_name++; ! 823: debug_name += type_identifier_length; ! 824: } ! 825: dbxout_type_method_1 (fndecl, debug_name); ! 826: } ! 827: putc (';', asmfile); ! 828: CHARS (1); ! 829: } ! 830: } ! 831: ! 832: /* Output a reference to a type. If the type has not yet been ! 833: described in the dbx output, output its definition now. ! 834: For a type already defined, just refer to its definition ! 835: using the type number. ! 836: ! 837: If FULL is nonzero, and the type has been described only with ! 838: a forward-reference, output the definition now. ! 839: If FULL is zero in this case, just refer to the forward-reference ! 840: using the number previously allocated. */ ! 841: ! 842: static void ! 843: dbxout_type (type, full) ! 844: tree type; ! 845: int full; ! 846: { ! 847: register tree tem; ! 848: ! 849: /* If there was an input error and we don't really have a type, ! 850: avoid crashing and write something that is at least valid ! 851: by assuming `int'. */ ! 852: if (type == error_mark_node) ! 853: type = integer_type_node; ! 854: else ! 855: { ! 856: type = TYPE_MAIN_VARIANT (type); ! 857: if (TYPE_NAME (type) ! 858: && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL ! 859: && DECL_IGNORED_P (TYPE_NAME (type))) ! 860: full = 0; ! 861: } ! 862: ! 863: if (TYPE_SYMTAB_ADDRESS (type) == 0) ! 864: { ! 865: /* Type has no dbx number assigned. Assign next available number. */ ! 866: TYPE_SYMTAB_ADDRESS (type) = next_type_number++; ! 867: ! 868: /* Make sure type vector is long enough to record about this type. */ ! 869: ! 870: if (next_type_number == typevec_len) ! 871: { ! 872: typevec = (enum typestatus *) xrealloc (typevec, typevec_len * 2 * sizeof typevec[0]); ! 873: bzero (typevec + typevec_len, typevec_len * sizeof typevec[0]); ! 874: typevec_len *= 2; ! 875: } ! 876: } ! 877: ! 878: /* Output the number of this type, to refer to it. */ ! 879: fprintf (asmfile, "%d", TYPE_SYMTAB_ADDRESS (type)); ! 880: CHARS (3); ! 881: ! 882: /* If this type's definition has been output or is now being output, ! 883: that is all. */ ! 884: ! 885: switch (typevec[TYPE_SYMTAB_ADDRESS (type)]) ! 886: { ! 887: case TYPE_UNSEEN: ! 888: break; ! 889: case TYPE_XREF: ! 890: if (! full) ! 891: return; ! 892: break; ! 893: case TYPE_DEFINED: ! 894: return; ! 895: } ! 896: ! 897: #ifdef DBX_NO_XREFS ! 898: /* For systems where dbx output does not allow the `=xsNAME:' syntax, ! 899: leave the type-number completely undefined rather than output ! 900: a cross-reference. */ ! 901: if (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE ! 902: || TREE_CODE (type) == ENUMERAL_TYPE) ! 903: ! 904: if ((TYPE_NAME (type) != 0 && !full) ! 905: || TYPE_SIZE (type) == 0) ! 906: { ! 907: typevec[TYPE_SYMTAB_ADDRESS (type)] = TYPE_XREF; ! 908: return; ! 909: } ! 910: #endif ! 911: ! 912: /* Output a definition now. */ ! 913: ! 914: fprintf (asmfile, "="); ! 915: CHARS (1); ! 916: ! 917: /* Mark it as defined, so that if it is self-referent ! 918: we will not get into an infinite recursion of definitions. */ ! 919: ! 920: typevec[TYPE_SYMTAB_ADDRESS (type)] = TYPE_DEFINED; ! 921: ! 922: switch (TREE_CODE (type)) ! 923: { ! 924: case VOID_TYPE: ! 925: case LANG_TYPE: ! 926: /* For a void type, just define it as itself; ie, "5=5". ! 927: This makes us consider it defined ! 928: without saying what it is. The debugger will make it ! 929: a void type when the reference is seen, and nothing will ! 930: ever override that default. */ ! 931: fprintf (asmfile, "%d", TYPE_SYMTAB_ADDRESS (type)); ! 932: CHARS (3); ! 933: break; ! 934: ! 935: case INTEGER_TYPE: ! 936: if (type == char_type_node && ! TREE_UNSIGNED (type)) ! 937: /* Output the type `char' as a subrange of itself! ! 938: I don't understand this definition, just copied it ! 939: from the output of pcc. ! 940: This used to use `r2' explicitly and we used to ! 941: take care to make sure that `char' was type number 2. */ ! 942: fprintf (asmfile, "r%d;0;127;", TYPE_SYMTAB_ADDRESS (type)); ! 943: #ifdef WINNING_GDB ! 944: else if (TYPE_PRECISION (type) > BITS_PER_WORD) ! 945: { ! 946: /* This used to say `r1' and we used to take care ! 947: to make sure that `int' was type number 1. */ ! 948: fprintf (asmfile, "r%d;", TYPE_SYMTAB_ADDRESS (integer_type_node)); ! 949: print_int_cst_octal (TYPE_MIN_VALUE (type)); ! 950: fprintf (asmfile, ";"); ! 951: print_int_cst_octal (TYPE_MAX_VALUE (type)); ! 952: fprintf (asmfile, ";"); ! 953: } ! 954: #endif ! 955: else ! 956: /* Output other integer types as subranges of `int'. */ ! 957: /* This used to say `r1' and we used to take care ! 958: to make sure that `int' was type number 1. */ ! 959: fprintf (asmfile, "r%d;%d;%d;", ! 960: TYPE_SYMTAB_ADDRESS (integer_type_node), ! 961: TREE_INT_CST_LOW (TYPE_MIN_VALUE (type)), ! 962: TREE_INT_CST_LOW (TYPE_MAX_VALUE (type))); ! 963: CHARS (25); ! 964: break; ! 965: ! 966: case REAL_TYPE: ! 967: /* This used to say `r1' and we used to take care ! 968: to make sure that `int' was type number 1. */ ! 969: fprintf (asmfile, "r%d;%d;0;", TYPE_SYMTAB_ADDRESS (integer_type_node), ! 970: TREE_INT_CST_LOW (size_in_bytes (type))); ! 971: CHARS (16); ! 972: break; ! 973: ! 974: case ARRAY_TYPE: ! 975: /* Output "a" followed by a range type definition ! 976: for the index type of the array ! 977: followed by a reference to the target-type. ! 978: ar1;0;N;M for an array of type M and size N. */ ! 979: /* This used to say `r1' and we used to take care ! 980: to make sure that `int' was type number 1. */ ! 981: fprintf (asmfile, "ar%d;0;%d;", TYPE_SYMTAB_ADDRESS (integer_type_node), ! 982: ! 983: (TYPE_DOMAIN (type) ! 984: ? TREE_INT_CST_LOW (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) ! 985: : -1)); ! 986: CHARS (17); ! 987: dbxout_type (TREE_TYPE (type), 0); ! 988: break; ! 989: ! 990: case RECORD_TYPE: ! 991: case UNION_TYPE: ! 992: { ! 993: int i, n_baseclasses = 0; ! 994: ! 995: if (TYPE_BINFO (type) != 0 && TYPE_BINFO_BASETYPES (type) != 0) ! 996: n_baseclasses = TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (type)); ! 997: ! 998: /* Output a structure type. */ ! 999: if ((TYPE_NAME (type) != 0 && !full) ! 1000: || TYPE_SIZE (type) == 0) ! 1001: { ! 1002: /* If the type is just a cross reference, output one ! 1003: and mark the type as partially described. ! 1004: If it later becomes defined, we will output ! 1005: its real definition. ! 1006: If the type has a name, don't nest its definition within ! 1007: another type's definition; instead, output an xref ! 1008: and let the definition come when the name is defined. */ ! 1009: fprintf (asmfile, (TREE_CODE (type) == RECORD_TYPE) ? "xs" : "xu"); ! 1010: CHARS (3); ! 1011: #if 0 /* This assertion is legitimately false in C++. */ ! 1012: /* We shouldn't be outputting a reference to a type before its ! 1013: definition unless the type has a tag name. ! 1014: A typedef name without a tag name should be impossible. */ ! 1015: if (TREE_CODE (TYPE_NAME (type)) != IDENTIFIER_NODE) ! 1016: abort (); ! 1017: #endif ! 1018: dbxout_type_name (type); ! 1019: fprintf (asmfile, ":"); ! 1020: typevec[TYPE_SYMTAB_ADDRESS (type)] = TYPE_XREF; ! 1021: break; ! 1022: } ! 1023: tem = size_in_bytes (type); ! 1024: ! 1025: /* The code below assumes the size is an integer constant. */ ! 1026: if (TREE_CODE (tem) != INTEGER_CST) ! 1027: abort (); ! 1028: ! 1029: /* Identify record or union, and print its size. */ ! 1030: fprintf (asmfile, (TREE_CODE (type) == RECORD_TYPE) ? "s%d" : "u%d", ! 1031: TREE_INT_CST_LOW (tem)); ! 1032: ! 1033: if (use_gdb_dbx_extensions) ! 1034: { ! 1035: if (n_baseclasses) ! 1036: { ! 1037: have_used_extensions = 1; ! 1038: fprintf (asmfile, "!%d,", n_baseclasses); ! 1039: CHARS (8); ! 1040: } ! 1041: } ! 1042: for (i = 0; i < n_baseclasses; i++) ! 1043: { ! 1044: tree child = TREE_VEC_ELT (BINFO_BASETYPES (TYPE_BINFO (type)), i); ! 1045: if (use_gdb_dbx_extensions) ! 1046: { ! 1047: have_used_extensions = 1; ! 1048: putc (TREE_VIA_VIRTUAL (child) ? '1' ! 1049: : '0', ! 1050: asmfile); ! 1051: putc (TREE_VIA_PUBLIC (child) ? '2' ! 1052: : '0', ! 1053: asmfile); ! 1054: fprintf (asmfile, "%d,", ! 1055: TREE_INT_CST_LOW (BINFO_OFFSET (child)) * BITS_PER_UNIT); ! 1056: CHARS (15); ! 1057: dbxout_type (BINFO_TYPE (child), 0); ! 1058: putc (';', asmfile); ! 1059: } ! 1060: else ! 1061: { ! 1062: /* Print out the base class information with fields ! 1063: which have the same names at the types they hold. */ ! 1064: dbxout_type_name (BINFO_TYPE (child)); ! 1065: putc (':', asmfile); ! 1066: dbxout_type (BINFO_TYPE (child), full); ! 1067: fprintf (asmfile, ",%d,%d;", ! 1068: TREE_INT_CST_LOW (BINFO_OFFSET (child)) * BITS_PER_UNIT, ! 1069: TREE_INT_CST_LOW (DECL_SIZE (TYPE_NAME (BINFO_TYPE (child)))) * BITS_PER_UNIT); ! 1070: CHARS (20); ! 1071: } ! 1072: } ! 1073: } ! 1074: ! 1075: CHARS (11); ! 1076: ! 1077: /* Write out the field declarations. */ ! 1078: dbxout_type_fields (type); ! 1079: if (use_gdb_dbx_extensions) ! 1080: { ! 1081: have_used_extensions = 1; ! 1082: dbxout_type_methods (type); ! 1083: } ! 1084: putc (';', asmfile); ! 1085: ! 1086: if (use_gdb_dbx_extensions && TREE_CODE (type) == RECORD_TYPE ! 1087: /* Avoid the ~ if we don't really need it--it confuses dbx. */ ! 1088: && TYPE_VFIELD (type)) ! 1089: { ! 1090: have_used_extensions = 1; ! 1091: ! 1092: /* Tell GDB+ that it may keep reading. */ ! 1093: putc ('~', asmfile); ! 1094: ! 1095: /* We need to write out info about what field this class ! 1096: uses as its "main" vtable pointer field, because if this ! 1097: field is inherited from a base class, GDB cannot necessarily ! 1098: figure out which field it's using in time. */ ! 1099: if (TYPE_VFIELD (type)) ! 1100: { ! 1101: putc ('%', asmfile); ! 1102: dbxout_type (DECL_FCONTEXT (TYPE_VFIELD (type)), 0); ! 1103: } ! 1104: putc (';', asmfile); ! 1105: CHARS (3); ! 1106: } ! 1107: break; ! 1108: ! 1109: case ENUMERAL_TYPE: ! 1110: if ((TYPE_NAME (type) != 0 && !full ! 1111: && (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL ! 1112: && ! DECL_IGNORED_P (TYPE_NAME (type)))) ! 1113: || TYPE_SIZE (type) == 0) ! 1114: { ! 1115: fprintf (asmfile, "xe"); ! 1116: CHARS (3); ! 1117: dbxout_type_name (type); ! 1118: typevec[TYPE_SYMTAB_ADDRESS (type)] = TYPE_XREF; ! 1119: fprintf (asmfile, ":"); ! 1120: return; ! 1121: } ! 1122: putc ('e', asmfile); ! 1123: CHARS (1); ! 1124: for (tem = TYPE_VALUES (type); tem; tem = TREE_CHAIN (tem)) ! 1125: { ! 1126: fprintf (asmfile, "%s:%d,", IDENTIFIER_POINTER (TREE_PURPOSE (tem)), ! 1127: TREE_INT_CST_LOW (TREE_VALUE (tem))); ! 1128: CHARS (11 + IDENTIFIER_LENGTH (TREE_PURPOSE (tem))); ! 1129: if (TREE_CHAIN (tem) != 0) ! 1130: CONTIN; ! 1131: } ! 1132: putc (';', asmfile); ! 1133: CHARS (1); ! 1134: break; ! 1135: ! 1136: case POINTER_TYPE: ! 1137: putc ('*', asmfile); ! 1138: CHARS (1); ! 1139: dbxout_type (TREE_TYPE (type), 0); ! 1140: break; ! 1141: ! 1142: case METHOD_TYPE: ! 1143: if (use_gdb_dbx_extensions) ! 1144: { ! 1145: have_used_extensions = 1; ! 1146: putc ('#', asmfile); ! 1147: CHARS (1); ! 1148: if (flag_minimal_debug) ! 1149: { ! 1150: putc ('#', asmfile); ! 1151: dbxout_type (TREE_TYPE (type), 0); ! 1152: putc (';', asmfile); ! 1153: CHARS (1); ! 1154: } ! 1155: else ! 1156: { ! 1157: dbxout_type (TYPE_METHOD_BASETYPE (type), 0); ! 1158: putc (',', asmfile); ! 1159: CHARS (1); ! 1160: dbxout_type (TREE_TYPE (type), 0); ! 1161: dbxout_args (TYPE_ARG_TYPES (type)); ! 1162: putc (';', asmfile); ! 1163: CHARS (1); ! 1164: } ! 1165: } ! 1166: else ! 1167: { ! 1168: /* Treat it as a function type. */ ! 1169: dbxout_type (TREE_TYPE (type), 0); ! 1170: } ! 1171: break; ! 1172: ! 1173: case OFFSET_TYPE: ! 1174: if (use_gdb_dbx_extensions) ! 1175: { ! 1176: have_used_extensions = 1; ! 1177: putc ('@', asmfile); ! 1178: CHARS (1); ! 1179: dbxout_type (TYPE_OFFSET_BASETYPE (type), 0); ! 1180: putc (',', asmfile); ! 1181: CHARS (1); ! 1182: dbxout_type (TREE_TYPE (type), 0); ! 1183: } ! 1184: else ! 1185: { ! 1186: /* Should print as an int, because it is really ! 1187: just an offset. */ ! 1188: dbxout_type (integer_type_node, 0); ! 1189: } ! 1190: break; ! 1191: ! 1192: case REFERENCE_TYPE: ! 1193: if (use_gdb_dbx_extensions) ! 1194: have_used_extensions = 1; ! 1195: putc (use_gdb_dbx_extensions ? '&' : '*', asmfile); ! 1196: CHARS (1); ! 1197: dbxout_type (TREE_TYPE (type), 0); ! 1198: break; ! 1199: ! 1200: case FUNCTION_TYPE: ! 1201: putc ('f', asmfile); ! 1202: CHARS (1); ! 1203: dbxout_type (TREE_TYPE (type), 0); ! 1204: break; ! 1205: ! 1206: default: ! 1207: abort (); ! 1208: } ! 1209: } ! 1210: ! 1211: /* Print the value of integer constant C, in octal, ! 1212: handling double precision. */ ! 1213: ! 1214: static void ! 1215: print_int_cst_octal (c) ! 1216: tree c; ! 1217: { ! 1218: unsigned int high = TREE_INT_CST_HIGH (c); ! 1219: unsigned int low = TREE_INT_CST_LOW (c); ! 1220: int excess = (3 - (HOST_BITS_PER_INT % 3)); ! 1221: ! 1222: fprintf (asmfile, "0"); ! 1223: ! 1224: if (excess == 3) ! 1225: { ! 1226: print_octal (high, HOST_BITS_PER_INT / 3); ! 1227: print_octal (low, HOST_BITS_PER_INT / 3); ! 1228: } ! 1229: else ! 1230: { ! 1231: unsigned int beg = high >> excess; ! 1232: unsigned int middle ! 1233: = ((high & ((1 << excess) - 1)) << (3 - excess) ! 1234: | (low >> (HOST_BITS_PER_INT / 3 * 3))); ! 1235: unsigned int end = low & ((1 << (HOST_BITS_PER_INT / 3 * 3)) - 1); ! 1236: fprintf (asmfile, "%o%01o", beg, middle); ! 1237: print_octal (end, HOST_BITS_PER_INT / 3); ! 1238: } ! 1239: } ! 1240: ! 1241: static void ! 1242: print_octal (value, digits) ! 1243: unsigned int value; ! 1244: int digits; ! 1245: { ! 1246: int i; ! 1247: ! 1248: for (i = digits - 1; i >= 0; i--) ! 1249: fprintf (asmfile, "%01o", ((value >> (3 * i)) & 7)); ! 1250: } ! 1251: ! 1252: /* Output the name of type TYPE, with no punctuation. ! 1253: Such names can be set up either by typedef declarations ! 1254: or by struct, enum and union tags. */ ! 1255: ! 1256: static void ! 1257: dbxout_type_name (type) ! 1258: register tree type; ! 1259: { ! 1260: tree t; ! 1261: if (TYPE_NAME (type) == 0) ! 1262: abort (); ! 1263: if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE) ! 1264: { ! 1265: t = TYPE_NAME (type); ! 1266: } ! 1267: else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL) ! 1268: { ! 1269: t = DECL_NAME (TYPE_NAME (type)); ! 1270: } ! 1271: else ! 1272: abort (); ! 1273: ! 1274: fprintf (asmfile, "%s", IDENTIFIER_POINTER (t)); ! 1275: CHARS (IDENTIFIER_LENGTH (t)); ! 1276: } ! 1277: ! 1278: /* Output a .stabs for the symbol defined by DECL, ! 1279: which must be a ..._DECL node in the normal namespace. ! 1280: It may be a CONST_DECL, a FUNCTION_DECL, a PARM_DECL or a VAR_DECL. ! 1281: LOCAL is nonzero if the scope is less than the entire file. */ ! 1282: ! 1283: void ! 1284: dbxout_symbol (decl, local) ! 1285: tree decl; ! 1286: int local; ! 1287: { ! 1288: int letter = 0; ! 1289: tree type = TREE_TYPE (decl); ! 1290: tree context = NULL_TREE; ! 1291: int regno = -1; ! 1292: ! 1293: /* Cast avoids warning in old compilers. */ ! 1294: current_sym_code = (STAB_CODE_TYPE) 0; ! 1295: current_sym_value = 0; ! 1296: current_sym_addr = 0; ! 1297: ! 1298: /* Ignore nameless syms, but don't ignore type tags. */ ! 1299: ! 1300: if ((DECL_NAME (decl) == 0 && TREE_CODE (decl) != TYPE_DECL) ! 1301: || DECL_IGNORED_P (decl)) ! 1302: return; ! 1303: ! 1304: dbxout_prepare_symbol (decl); ! 1305: ! 1306: /* The output will always start with the symbol name, ! 1307: so always count that in the length-output-so-far. */ ! 1308: ! 1309: if (DECL_NAME (decl) != 0) ! 1310: current_sym_nchars = 2 + IDENTIFIER_LENGTH (DECL_NAME (decl)); ! 1311: ! 1312: switch (TREE_CODE (decl)) ! 1313: { ! 1314: case CONST_DECL: ! 1315: /* Enum values are defined by defining the enum type. */ ! 1316: break; ! 1317: ! 1318: case FUNCTION_DECL: ! 1319: if (DECL_RTL (decl) == 0) ! 1320: return; ! 1321: if (TREE_EXTERNAL (decl)) ! 1322: break; ! 1323: /* Don't mention a nested function under its parent. */ ! 1324: context = decl_function_context (decl); ! 1325: if (context == current_function_decl) ! 1326: break; ! 1327: if (GET_CODE (DECL_RTL (decl)) != MEM ! 1328: || GET_CODE (XEXP (DECL_RTL (decl), 0)) != SYMBOL_REF) ! 1329: break; ! 1330: FORCE_TEXT; ! 1331: ! 1332: fprintf (asmfile, "%s \"%s:%c", ASM_STABS_OP, ! 1333: IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)), ! 1334: TREE_PUBLIC (decl) ? 'F' : 'f'); ! 1335: ! 1336: current_sym_code = N_FUN; ! 1337: current_sym_addr = XEXP (DECL_RTL (decl), 0); ! 1338: ! 1339: if (TREE_TYPE (type)) ! 1340: dbxout_type (TREE_TYPE (type), 0); ! 1341: else ! 1342: dbxout_type (void_type_node, 0); ! 1343: ! 1344: /* For a nested function, when that function is compiled, ! 1345: mention the containing function name ! 1346: as well as (since dbx wants it) our own assembler-name. */ ! 1347: if (context != 0) ! 1348: fprintf (asmfile, ",%s,%s", ! 1349: IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)), ! 1350: IDENTIFIER_POINTER (DECL_NAME (context))); ! 1351: ! 1352: dbxout_finish_symbol (decl); ! 1353: break; ! 1354: ! 1355: case TYPE_DECL: ! 1356: #if 0 ! 1357: /* This seems all wrong. Outputting most kinds of types gives no name ! 1358: at all. A true definition gives no name; a cross-ref for a ! 1359: structure can give the tag name, but not a type name. ! 1360: It seems that no typedef name is defined by outputting a type. */ ! 1361: ! 1362: /* If this typedef name was defined by outputting the type, ! 1363: don't duplicate it. */ ! 1364: if (typevec[TYPE_SYMTAB_ADDRESS (type)] == TYPE_DEFINED ! 1365: && TYPE_NAME (TREE_TYPE (decl)) == decl) ! 1366: return; ! 1367: #endif ! 1368: /* Don't output the same typedef twice. ! 1369: And don't output what language-specific stuff doesn't want output. */ ! 1370: if (TREE_ASM_WRITTEN (decl) || DECL_IGNORED_P (decl)) ! 1371: return; ! 1372: ! 1373: FORCE_TEXT; ! 1374: ! 1375: if (DECL_NAME (decl)) ! 1376: { ! 1377: /* Output typedef name. */ ! 1378: fprintf (asmfile, "%s \"%s:", ASM_STABS_OP, ! 1379: IDENTIFIER_POINTER (DECL_NAME (decl))); ! 1380: ! 1381: /* If there is a typedecl for this type with the same name ! 1382: as the tag, output an abbreviated form for that typedecl. */ ! 1383: if (use_gdb_dbx_extensions && have_used_extensions ! 1384: && (TREE_CODE (type) == RECORD_TYPE ! 1385: || TREE_CODE (type) == UNION_TYPE) ! 1386: && (TYPE_NAME (type) == decl)) ! 1387: { ! 1388: putc ('T', asmfile); ! 1389: TREE_ASM_WRITTEN (TYPE_NAME (type)) = 1; ! 1390: } ! 1391: putc ('t', asmfile); ! 1392: current_sym_code = N_LSYM; ! 1393: ! 1394: dbxout_type (type, 1); ! 1395: dbxout_finish_symbol (decl); ! 1396: } ! 1397: else if (TYPE_NAME (type) != 0 && !TREE_ASM_WRITTEN (TYPE_NAME (type))) ! 1398: { ! 1399: /* Output a tag (a TYPE_DECL with no name, but the type has a name). ! 1400: This is what represents `struct foo' with no typedef. */ ! 1401: /* In C++, the name of a type is the corresponding typedef. ! 1402: In C, it is an IDENTIFIER_NODE. */ ! 1403: tree name = TYPE_NAME (type); ! 1404: if (TREE_CODE (name) == TYPE_DECL) ! 1405: name = DECL_NAME (name); ! 1406: ! 1407: current_sym_code = N_LSYM; ! 1408: current_sym_value = 0; ! 1409: current_sym_addr = 0; ! 1410: current_sym_nchars = 2 + IDENTIFIER_LENGTH (name); ! 1411: ! 1412: fprintf (asmfile, "%s \"%s:T", ASM_STABS_OP, ! 1413: IDENTIFIER_POINTER (name)); ! 1414: dbxout_type (type, 1); ! 1415: dbxout_finish_symbol (0); ! 1416: } ! 1417: ! 1418: /* Prevent duplicate output of a typedef. */ ! 1419: TREE_ASM_WRITTEN (decl) = 1; ! 1420: break; ! 1421: ! 1422: case PARM_DECL: ! 1423: /* Parm decls go in their own separate chains ! 1424: and are output by dbxout_reg_parms and dbxout_parms. */ ! 1425: abort (); ! 1426: ! 1427: case RESULT_DECL: ! 1428: /* Named return value, treat like a VAR_DECL. */ ! 1429: case VAR_DECL: ! 1430: if (DECL_RTL (decl) == 0) ! 1431: return; ! 1432: /* Don't mention a variable that is external. ! 1433: Let the file that defines it describe it. */ ! 1434: if (TREE_EXTERNAL (decl)) ! 1435: break; ! 1436: ! 1437: /* If the variable is really a constant ! 1438: and not written in memory, inform the debugger. */ ! 1439: if (TREE_STATIC (decl) && TREE_READONLY (decl) ! 1440: && DECL_INITIAL (decl) != 0 ! 1441: && ! TREE_ASM_WRITTEN (decl) ! 1442: && (DECL_FIELD_CONTEXT (decl) == NULL_TREE ! 1443: || TREE_CODE (DECL_FIELD_CONTEXT (decl)) == BLOCK)) ! 1444: { ! 1445: if (TREE_PUBLIC (decl) == 0) ! 1446: { ! 1447: /* The sun4 assembler does not grok this. */ ! 1448: char *name = IDENTIFIER_POINTER (DECL_NAME (decl)); ! 1449: if (TREE_CODE (TREE_TYPE (decl)) == INTEGER_TYPE ! 1450: || TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE) ! 1451: { ! 1452: int ival = TREE_INT_CST_LOW (DECL_INITIAL (decl)); ! 1453: #ifdef DBX_OUTPUT_CONSTANT_SYMBOL ! 1454: DBX_OUTPUT_CONSTANT_SYMBOL (asmfile, name, ival); ! 1455: #else ! 1456: fprintf (asmfile, "%s \"%s:c=i%d\",0x%x,0,0,0\n", ! 1457: ASM_STABS_OP, name, ival, N_LSYM); ! 1458: #endif ! 1459: return; ! 1460: } ! 1461: else if (TREE_CODE (TREE_TYPE (decl)) == REAL_TYPE) ! 1462: { ! 1463: /* don't know how to do this yet. */ ! 1464: } ! 1465: break; ! 1466: } ! 1467: /* else it is something we handle like a normal variable. */ ! 1468: } ! 1469: ! 1470: DECL_RTL (decl) = eliminate_regs (DECL_RTL (decl)); ! 1471: #ifdef LEAF_REG_REMAP ! 1472: if (leaf_function) ! 1473: leaf_renumber_regs_insn (DECL_RTL (decl)); ! 1474: #endif ! 1475: ! 1476: /* Don't mention a variable at all ! 1477: if it was completely optimized into nothingness. ! 1478: ! 1479: If DECL was from an inline function, then it's rtl ! 1480: is not identically the rtl that was used in this ! 1481: particular compilation. */ ! 1482: if (GET_CODE (DECL_RTL (decl)) == REG) ! 1483: { ! 1484: regno = REGNO (DECL_RTL (decl)); ! 1485: if (regno >= FIRST_PSEUDO_REGISTER) ! 1486: regno = reg_renumber[REGNO (DECL_RTL (decl))]; ! 1487: if (regno < 0) ! 1488: break; ! 1489: } ! 1490: else if (GET_CODE (DECL_RTL (decl)) == SUBREG) ! 1491: { ! 1492: rtx value = DECL_RTL (decl); ! 1493: int offset = 0; ! 1494: while (GET_CODE (value) == SUBREG) ! 1495: { ! 1496: offset += SUBREG_WORD (value); ! 1497: value = SUBREG_REG (value); ! 1498: } ! 1499: if (GET_CODE (value) == REG) ! 1500: { ! 1501: regno = REGNO (value); ! 1502: if (regno >= FIRST_PSEUDO_REGISTER) ! 1503: regno = reg_renumber[REGNO (value)]; ! 1504: if (regno >= 0) ! 1505: regno += offset; ! 1506: } ! 1507: } ! 1508: ! 1509: /* The kind-of-variable letter depends on where ! 1510: the variable is and on the scope of its name: ! 1511: G and N_GSYM for static storage and global scope, ! 1512: S for static storage and file scope, ! 1513: V for static storage and local scope, ! 1514: for those two, use N_LCSYM if data is in bss segment, ! 1515: N_STSYM if in data segment, N_FUN otherwise. ! 1516: (We used N_FUN originally, then changed to N_STSYM ! 1517: to please GDB. However, it seems that confused ld. ! 1518: Now GDB has been fixed to like N_FUN, says Kingdon.) ! 1519: no letter at all, and N_LSYM, for auto variable, ! 1520: r and N_RSYM for register variable. */ ! 1521: ! 1522: if (GET_CODE (DECL_RTL (decl)) == MEM ! 1523: && GET_CODE (XEXP (DECL_RTL (decl), 0)) == SYMBOL_REF) ! 1524: { ! 1525: if (TREE_PUBLIC (decl)) ! 1526: { ! 1527: letter = 'G'; ! 1528: current_sym_code = N_GSYM; ! 1529: } ! 1530: else ! 1531: { ! 1532: current_sym_addr = XEXP (DECL_RTL (decl), 0); ! 1533: ! 1534: letter = TREE_PERMANENT (decl) ? 'S' : 'V'; ! 1535: ! 1536: if (!DECL_INITIAL (decl)) ! 1537: current_sym_code = N_LCSYM; ! 1538: else if (TREE_READONLY (decl) && ! TREE_THIS_VOLATILE (decl)) ! 1539: /* This is not quite right, but it's the closest ! 1540: of all the codes that Unix defines. */ ! 1541: current_sym_code = N_FUN; ! 1542: else ! 1543: { ! 1544: /* Ultrix `as' seems to need this. */ ! 1545: #ifdef DBX_STATIC_STAB_DATA_SECTION ! 1546: data_section (); ! 1547: #endif ! 1548: current_sym_code = N_STSYM; ! 1549: } ! 1550: } ! 1551: } ! 1552: else if (regno >= 0) ! 1553: { ! 1554: letter = 'r'; ! 1555: current_sym_code = N_RSYM; ! 1556: current_sym_value = DBX_REGISTER_NUMBER (regno); ! 1557: } ! 1558: else if (GET_CODE (DECL_RTL (decl)) == SUBREG) ! 1559: { ! 1560: rtx value = DECL_RTL (decl); ! 1561: int offset = 0; ! 1562: while (GET_CODE (value) == SUBREG) ! 1563: { ! 1564: offset += SUBREG_WORD (value); ! 1565: value = SUBREG_REG (value); ! 1566: } ! 1567: letter = 'r'; ! 1568: current_sym_code = N_RSYM; ! 1569: current_sym_value = DBX_REGISTER_NUMBER (REGNO (value) + offset); ! 1570: } ! 1571: else if (GET_CODE (DECL_RTL (decl)) == MEM ! 1572: && (GET_CODE (XEXP (DECL_RTL (decl), 0)) == MEM ! 1573: || (GET_CODE (XEXP (DECL_RTL (decl), 0)) == REG ! 1574: && REGNO (XEXP (DECL_RTL (decl), 0)) != FRAME_POINTER_REGNUM))) ! 1575: /* If the value is indirect by memory or by a register ! 1576: that isn't the frame pointer ! 1577: then it means the object is variable-sized and address through ! 1578: that register or stack slot. DBX has no way to represent this ! 1579: so all we can do is output the variable as a pointer. ! 1580: If it's not a parameter, ignore it. ! 1581: (VAR_DECLs like this can be made by integrate.c.) */ ! 1582: { ! 1583: if (GET_CODE (XEXP (DECL_RTL (decl), 0)) == REG) ! 1584: { ! 1585: letter = 'r'; ! 1586: current_sym_code = N_RSYM; ! 1587: current_sym_value = DBX_REGISTER_NUMBER (REGNO (XEXP (DECL_RTL (decl), 0))); ! 1588: } ! 1589: else ! 1590: { ! 1591: current_sym_code = N_LSYM; ! 1592: /* DECL_RTL looks like (MEM (MEM (PLUS (REG...) (CONST_INT...)))). ! 1593: We want the value of that CONST_INT. */ ! 1594: current_sym_value ! 1595: = DEBUGGER_AUTO_OFFSET (XEXP (XEXP (DECL_RTL (decl), 0), 0)); ! 1596: } ! 1597: ! 1598: /* Effectively do build_pointer_type, but don't cache this type, ! 1599: since it might be temporary whereas the type it points to ! 1600: might have been saved for inlining. */ ! 1601: type = make_node (REFERENCE_TYPE); ! 1602: TREE_TYPE (type) = TREE_TYPE (decl); ! 1603: } ! 1604: else if (GET_CODE (DECL_RTL (decl)) == MEM ! 1605: && GET_CODE (XEXP (DECL_RTL (decl), 0)) == REG) ! 1606: { ! 1607: current_sym_code = N_LSYM; ! 1608: current_sym_value = DEBUGGER_AUTO_OFFSET (XEXP (DECL_RTL (decl), 0)); ! 1609: } ! 1610: else if (GET_CODE (DECL_RTL (decl)) == MEM ! 1611: && GET_CODE (XEXP (DECL_RTL (decl), 0)) == PLUS ! 1612: && GET_CODE (XEXP (XEXP (DECL_RTL (decl), 0), 1)) == CONST_INT) ! 1613: { ! 1614: current_sym_code = N_LSYM; ! 1615: /* DECL_RTL looks like (MEM (PLUS (REG...) (CONST_INT...))) ! 1616: We want the value of that CONST_INT. */ ! 1617: current_sym_value = DEBUGGER_AUTO_OFFSET (XEXP (DECL_RTL (decl), 0)); ! 1618: } ! 1619: else ! 1620: /* Address might be a MEM, when DECL is a variable-sized object. ! 1621: Or it might be const0_rtx, meaning previous passes ! 1622: want us to ignore this variable. */ ! 1623: break; ! 1624: ! 1625: /* Ok, start a symtab entry and output the variable name. */ ! 1626: FORCE_TEXT; ! 1627: /* One slight hitch: if this is a VAR_DECL which is a static ! 1628: class member, we must put out the mangled name instead of the ! 1629: DECL_NAME. */ ! 1630: { ! 1631: char *name; ! 1632: /* Note also that static member (variable) names DO NOT begin ! 1633: with underscores in .stabs directives. */ ! 1634: if (DECL_LANG_SPECIFIC (decl)) ! 1635: { ! 1636: name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); ! 1637: ! 1638: #if 0 /* Tiemann says get rid of this. */ ! 1639: /* Adding 1 here only works on systems ! 1640: which flush an initial underscore. */ ! 1641: if (name[0] == '_') ! 1642: name += 1; ! 1643: #endif ! 1644: } ! 1645: else ! 1646: name = IDENTIFIER_POINTER (DECL_NAME (decl)); ! 1647: fprintf (asmfile, "%s \"%s:", ASM_STABS_OP, name); ! 1648: } ! 1649: if (letter) putc (letter, asmfile); ! 1650: dbxout_type (type, 0); ! 1651: dbxout_finish_symbol (decl); ! 1652: break; ! 1653: } ! 1654: } ! 1655: ! 1656: static void ! 1657: dbxout_prepare_symbol (decl) ! 1658: tree decl; ! 1659: { ! 1660: #ifdef WINNING_GDB ! 1661: char *filename = DECL_SOURCE_FILE (decl); ! 1662: ! 1663: dbxout_source_file (asmfile, filename); ! 1664: #endif ! 1665: } ! 1666: ! 1667: static void ! 1668: dbxout_finish_symbol (sym) ! 1669: tree sym; ! 1670: { ! 1671: int line = 0; ! 1672: #ifdef WINNING_GDB ! 1673: if (sym != 0) ! 1674: line = DECL_SOURCE_LINE (sym); ! 1675: #endif ! 1676: fprintf (asmfile, "\",%d,0,%d,", current_sym_code, line); ! 1677: if (current_sym_addr) ! 1678: output_addr_const (asmfile, current_sym_addr); ! 1679: else ! 1680: fprintf (asmfile, "%d", current_sym_value); ! 1681: putc ('\n', asmfile); ! 1682: } ! 1683: ! 1684: /* Output definitions of all the decls in a chain. */ ! 1685: ! 1686: static void ! 1687: dbxout_syms (syms) ! 1688: tree syms; ! 1689: { ! 1690: while (syms) ! 1691: { ! 1692: dbxout_symbol (syms, 1); ! 1693: syms = TREE_CHAIN (syms); ! 1694: } ! 1695: } ! 1696: ! 1697: /* The following two functions output definitions of function parameters. ! 1698: Each parameter gets a definition locating it in the parameter list. ! 1699: Each parameter that is a register variable gets a second definition ! 1700: locating it in the register. ! 1701: ! 1702: Printing or argument lists in gdb uses the definitions that ! 1703: locate in the parameter list. But reference to the variable in ! 1704: expressions uses preferentially the definition as a register. */ ! 1705: ! 1706: /* Output definitions, referring to storage in the parmlist, ! 1707: of all the parms in PARMS, which is a chain of PARM_DECL nodes. */ ! 1708: ! 1709: static void ! 1710: dbxout_parms (parms) ! 1711: tree parms; ! 1712: { ! 1713: for (; parms; parms = TREE_CHAIN (parms)) ! 1714: if (DECL_NAME (parms) && TREE_TYPE (parms) != error_mark_node) ! 1715: { ! 1716: dbxout_prepare_symbol (parms); ! 1717: ! 1718: /* Perform any necessary register eliminations on the parameter's rtl, ! 1719: so that the debugging output will be accurate. */ ! 1720: DECL_INCOMING_RTL (parms) ! 1721: = eliminate_regs (DECL_INCOMING_RTL (parms), 0, 0); ! 1722: DECL_RTL (parms) = eliminate_regs (DECL_RTL (parms), 0, 0); ! 1723: #ifdef LEAF_REG_REMAP ! 1724: if (leaf_function) ! 1725: { ! 1726: leaf_renumber_regs_insn (DECL_INCOMING_RTL (parms)); ! 1727: leaf_renumber_regs_insn (DECL_RTL (parms)); ! 1728: } ! 1729: #endif ! 1730: ! 1731: if (PARM_PASSED_IN_MEMORY (parms)) ! 1732: { ! 1733: rtx addr = XEXP (DECL_INCOMING_RTL (parms), 0); ! 1734: ! 1735: /* ??? Here we assume that the parm address is indexed ! 1736: off the frame pointer or arg pointer. ! 1737: If that is not true, we produce meaningless results, ! 1738: but do not crash. */ ! 1739: if (GET_CODE (addr) == PLUS ! 1740: && GET_CODE (XEXP (addr, 1)) == CONST_INT) ! 1741: current_sym_value = INTVAL (XEXP (addr, 1)); ! 1742: else ! 1743: current_sym_value = 0; ! 1744: ! 1745: current_sym_code = N_PSYM; ! 1746: current_sym_addr = 0; ! 1747: ! 1748: FORCE_TEXT; ! 1749: if (DECL_NAME (parms)) ! 1750: { ! 1751: current_sym_nchars = 2 + IDENTIFIER_LENGTH (DECL_NAME (parms)); ! 1752: ! 1753: fprintf (asmfile, "%s \"%s:p", ASM_STABS_OP, ! 1754: IDENTIFIER_POINTER (DECL_NAME (parms))); ! 1755: } ! 1756: else ! 1757: { ! 1758: current_sym_nchars = 8; ! 1759: fprintf (asmfile, "%s \"(anon):p", ASM_STABS_OP); ! 1760: } ! 1761: ! 1762: if (GET_CODE (DECL_RTL (parms)) == REG ! 1763: && REGNO (DECL_RTL (parms)) >= 0 ! 1764: && REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER) ! 1765: dbxout_type (DECL_ARG_TYPE (parms), 0); ! 1766: else ! 1767: { ! 1768: int original_value = current_sym_value; ! 1769: ! 1770: /* This is the case where the parm is passed as an int or double ! 1771: and it is converted to a char, short or float and stored back ! 1772: in the parmlist. In this case, describe the parm ! 1773: with the variable's declared type, and adjust the address ! 1774: if the least significant bytes (which we are using) are not ! 1775: the first ones. */ ! 1776: #if BYTES_BIG_ENDIAN ! 1777: if (TREE_TYPE (parms) != DECL_ARG_TYPE (parms)) ! 1778: current_sym_value += (GET_MODE_SIZE (TYPE_MODE (DECL_ARG_TYPE (parms))) ! 1779: - GET_MODE_SIZE (GET_MODE (DECL_RTL (parms)))); ! 1780: #endif ! 1781: ! 1782: if (GET_CODE (DECL_RTL (parms)) == MEM ! 1783: && GET_CODE (XEXP (DECL_RTL (parms), 0)) == PLUS ! 1784: && GET_CODE (XEXP (XEXP (DECL_RTL (parms), 0), 1)) == CONST_INT ! 1785: && INTVAL (XEXP (XEXP (DECL_RTL (parms), 0), 1)) == current_sym_value) ! 1786: dbxout_type (TREE_TYPE (parms), 0); ! 1787: else ! 1788: { ! 1789: current_sym_value = original_value; ! 1790: dbxout_type (DECL_ARG_TYPE (parms), 0); ! 1791: } ! 1792: } ! 1793: current_sym_value = DEBUGGER_ARG_OFFSET (current_sym_value, addr); ! 1794: dbxout_finish_symbol (parms); ! 1795: } ! 1796: else if (GET_CODE (DECL_RTL (parms)) == REG) ! 1797: { ! 1798: rtx best_rtl; ! 1799: /* Parm passed in registers and lives in registers or nowhere. */ ! 1800: ! 1801: current_sym_code = N_RSYM; ! 1802: current_sym_addr = 0; ! 1803: ! 1804: /* If parm lives in a register, use that register; ! 1805: pretend the parm was passed there. It would be more consistent ! 1806: to describe the register where the parm was passed, ! 1807: but in practice that register usually holds something else. */ ! 1808: if (REGNO (DECL_RTL (parms)) >= 0 ! 1809: && REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER) ! 1810: best_rtl = DECL_RTL (parms); ! 1811: /* If the parm lives nowhere, ! 1812: use the register where it was passed. */ ! 1813: else ! 1814: best_rtl = DECL_INCOMING_RTL (parms); ! 1815: current_sym_value = DBX_REGISTER_NUMBER (REGNO (best_rtl)); ! 1816: ! 1817: FORCE_TEXT; ! 1818: if (DECL_NAME (parms)) ! 1819: { ! 1820: current_sym_nchars = 2 + IDENTIFIER_LENGTH (DECL_NAME (parms)); ! 1821: fprintf (asmfile, "%s \"%s:P", ASM_STABS_OP, ! 1822: IDENTIFIER_POINTER (DECL_NAME (parms))); ! 1823: } ! 1824: else ! 1825: { ! 1826: current_sym_nchars = 8; ! 1827: fprintf (asmfile, "%s \"(anon):P", ASM_STABS_OP); ! 1828: } ! 1829: ! 1830: dbxout_type (DECL_ARG_TYPE (parms), 0); ! 1831: dbxout_finish_symbol (parms); ! 1832: } ! 1833: else if (GET_CODE (DECL_RTL (parms)) == MEM ! 1834: && XEXP (DECL_RTL (parms), 0) != const0_rtx) ! 1835: { ! 1836: /* Parm was passed in registers but lives on the stack. */ ! 1837: ! 1838: current_sym_code = N_PSYM; ! 1839: /* DECL_RTL looks like (MEM (PLUS (REG...) (CONST_INT...))), ! 1840: in which case we want the value of that CONST_INT, ! 1841: or (MEM (REG ...)) or (MEM (MEM ...)), ! 1842: in which case we use a value of zero. */ ! 1843: if (GET_CODE (XEXP (DECL_RTL (parms), 0)) == REG ! 1844: || GET_CODE (XEXP (DECL_RTL (parms), 0)) == MEM) ! 1845: current_sym_value = 0; ! 1846: else ! 1847: current_sym_value = INTVAL (XEXP (XEXP (DECL_RTL (parms), 0), 1)); ! 1848: current_sym_addr = 0; ! 1849: ! 1850: FORCE_TEXT; ! 1851: if (DECL_NAME (parms)) ! 1852: { ! 1853: current_sym_nchars = 2 + strlen (IDENTIFIER_POINTER (DECL_NAME (parms))); ! 1854: ! 1855: fprintf (asmfile, "%s \"%s:p", ASM_STABS_OP, ! 1856: IDENTIFIER_POINTER (DECL_NAME (parms))); ! 1857: } ! 1858: else ! 1859: { ! 1860: current_sym_nchars = 8; ! 1861: fprintf (asmfile, "%s \"(anon):p", ASM_STABS_OP); ! 1862: } ! 1863: ! 1864: current_sym_value ! 1865: = DEBUGGER_ARG_OFFSET (current_sym_value, ! 1866: XEXP (DECL_RTL (parms), 0)); ! 1867: dbxout_type (TREE_TYPE (parms), 0); ! 1868: dbxout_finish_symbol (parms); ! 1869: } ! 1870: } ! 1871: } ! 1872: ! 1873: /* Output definitions for the places where parms live during the function, ! 1874: when different from where they were passed, when the parms were passed ! 1875: in memory. ! 1876: ! 1877: It is not useful to do this for parms passed in registers ! 1878: that live during the function in different registers, because it is ! 1879: impossible to look in the passed register for the passed value, ! 1880: so we use the within-the-function register to begin with. ! 1881: ! 1882: PARMS is a chain of PARM_DECL nodes. */ ! 1883: ! 1884: static void ! 1885: dbxout_reg_parms (parms) ! 1886: tree parms; ! 1887: { ! 1888: for (; parms; parms = TREE_CHAIN (parms)) ! 1889: if (DECL_NAME (parms)) ! 1890: { ! 1891: dbxout_prepare_symbol (parms); ! 1892: ! 1893: /* Report parms that live in registers during the function ! 1894: but were passed in memory. */ ! 1895: if (GET_CODE (DECL_RTL (parms)) == REG ! 1896: && REGNO (DECL_RTL (parms)) >= 0 ! 1897: && REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER ! 1898: && PARM_PASSED_IN_MEMORY (parms)) ! 1899: { ! 1900: current_sym_code = N_RSYM; ! 1901: current_sym_value = DBX_REGISTER_NUMBER (REGNO (DECL_RTL (parms))); ! 1902: current_sym_addr = 0; ! 1903: ! 1904: FORCE_TEXT; ! 1905: if (DECL_NAME (parms)) ! 1906: { ! 1907: current_sym_nchars = 2 + IDENTIFIER_LENGTH (DECL_NAME (parms)); ! 1908: fprintf (asmfile, "%s \"%s:r", ASM_STABS_OP, ! 1909: IDENTIFIER_POINTER (DECL_NAME (parms))); ! 1910: } ! 1911: else ! 1912: { ! 1913: current_sym_nchars = 8; ! 1914: fprintf (asmfile, "%s \"(anon):r", ASM_STABS_OP); ! 1915: } ! 1916: dbxout_type (TREE_TYPE (parms), 0); ! 1917: dbxout_finish_symbol (parms); ! 1918: } ! 1919: /* Report parms that live in memory but not where they were passed. */ ! 1920: else if (GET_CODE (DECL_RTL (parms)) == MEM ! 1921: && GET_CODE (XEXP (DECL_RTL (parms), 0)) == PLUS ! 1922: && GET_CODE (XEXP (XEXP (DECL_RTL (parms), 0), 1)) == CONST_INT ! 1923: && PARM_PASSED_IN_MEMORY (parms) ! 1924: && ! rtx_equal_p (DECL_RTL (parms), DECL_INCOMING_RTL (parms))) ! 1925: { ! 1926: #if 0 /* ??? It is not clear yet what should replace this. */ ! 1927: int offset = DECL_OFFSET (parms) / BITS_PER_UNIT; ! 1928: /* A parm declared char is really passed as an int, ! 1929: so it occupies the least significant bytes. ! 1930: On a big-endian machine those are not the low-numbered ones. */ ! 1931: #if BYTES_BIG_ENDIAN ! 1932: if (offset != -1 && TREE_TYPE (parms) != DECL_ARG_TYPE (parms)) ! 1933: offset += (GET_MODE_SIZE (TYPE_MODE (DECL_ARG_TYPE (parms))) ! 1934: - GET_MODE_SIZE (GET_MODE (DECL_RTL (parms)))); ! 1935: #endif ! 1936: if (INTVAL (XEXP (XEXP (DECL_RTL (parms), 0), 1)) != offset) {...} ! 1937: #endif ! 1938: current_sym_code = N_LSYM; ! 1939: current_sym_value = DEBUGGER_AUTO_OFFSET (XEXP (DECL_RTL (parms), 0)); ! 1940: current_sym_addr = 0; ! 1941: FORCE_TEXT; ! 1942: if (DECL_NAME (parms)) ! 1943: { ! 1944: current_sym_nchars = 2 + IDENTIFIER_LENGTH (DECL_NAME (parms)); ! 1945: fprintf (asmfile, "%s \"%s:", ASM_STABS_OP, ! 1946: IDENTIFIER_POINTER (DECL_NAME (parms))); ! 1947: } ! 1948: else ! 1949: { ! 1950: current_sym_nchars = 8; ! 1951: fprintf (asmfile, "%s \"(anon):", ASM_STABS_OP); ! 1952: } ! 1953: dbxout_type (TREE_TYPE (parms), 0); ! 1954: dbxout_finish_symbol (parms); ! 1955: } ! 1956: } ! 1957: } ! 1958: ! 1959: /* Given a chain of ..._TYPE nodes (as come in a parameter list), ! 1960: output definitions of those names, in raw form */ ! 1961: ! 1962: void ! 1963: dbxout_args (args) ! 1964: tree args; ! 1965: { ! 1966: while (args) ! 1967: { ! 1968: putc (',', asmfile); ! 1969: dbxout_type (TREE_VALUE (args), 0); ! 1970: CHARS (1); ! 1971: args = TREE_CHAIN (args); ! 1972: } ! 1973: } ! 1974: ! 1975: /* Given a chain of ..._TYPE nodes, ! 1976: find those which have typedef names and output those names. ! 1977: This is to ensure those types get output. */ ! 1978: ! 1979: void ! 1980: dbxout_types (types) ! 1981: register tree types; ! 1982: { ! 1983: while (types) ! 1984: { ! 1985: if (TYPE_NAME (types) ! 1986: && TREE_CODE (TYPE_NAME (types)) == TYPE_DECL ! 1987: && ! TREE_ASM_WRITTEN (TYPE_NAME (types))) ! 1988: dbxout_symbol (TYPE_NAME (types), 1); ! 1989: types = TREE_CHAIN (types); ! 1990: } ! 1991: } ! 1992: ! 1993: /* Output everything about a symbol block (a BLOCK node ! 1994: that represents a scope level), ! 1995: including recursive output of contained blocks. ! 1996: ! 1997: BLOCK is the BLOCK node. ! 1998: DEPTH is its depth within containing symbol blocks. ! 1999: ARGS is usually zero; but for the outermost block of the ! 2000: body of a function, it is a chain of PARM_DECLs for the function parameters. ! 2001: We output definitions of all the register parms ! 2002: as if they were local variables of that block. ! 2003: ! 2004: If -g1 was used, we count blocks just the same, but output nothing ! 2005: except for the outermost block. ! 2006: ! 2007: Actually, BLOCK may be several blocks chained together. ! 2008: We handle them all in sequence. */ ! 2009: ! 2010: static void ! 2011: dbxout_block (block, depth, args) ! 2012: register tree block; ! 2013: int depth; ! 2014: tree args; ! 2015: { ! 2016: int blocknum; ! 2017: ! 2018: while (block) ! 2019: { ! 2020: /* Ignore blocks never expanded or otherwise marked as real. */ ! 2021: if (TREE_USED (block)) ! 2022: { ! 2023: #ifndef DBX_LBRAC_FIRST ! 2024: /* In dbx format, the syms of a block come before the N_LBRAC. */ ! 2025: if (debug_info_level != DINFO_LEVEL_TERSE || depth == 0) ! 2026: dbxout_syms (BLOCK_VARS (block)); ! 2027: if (args) ! 2028: dbxout_reg_parms (args); ! 2029: #endif ! 2030: ! 2031: /* Now output an N_LBRAC symbol to represent the beginning of ! 2032: the block. Use the block's tree-walk order to generate ! 2033: the assembler symbols LBBn and LBEn ! 2034: that final will define around the code in this block. */ ! 2035: if (depth > 0 && debug_info_level != DINFO_LEVEL_TERSE) ! 2036: { ! 2037: char buf[20]; ! 2038: blocknum = next_block_number++; ! 2039: ASM_GENERATE_INTERNAL_LABEL (buf, "LBB", blocknum); ! 2040: ! 2041: if (BLOCK_HANDLER_BLOCK (block)) ! 2042: { ! 2043: /* A catch block. Must precede N_LBRAC. */ ! 2044: tree decl = BLOCK_VARS (block); ! 2045: while (decl) ! 2046: { ! 2047: #ifdef DBX_OUTPUT_CATCH ! 2048: DBX_OUTPUT_CATCH (asmfile, decl, buf); ! 2049: #else ! 2050: fprintf (asmfile, "%s \"%s:C1\",%d,0,0,", ASM_STABS_OP, ! 2051: IDENTIFIER_POINTER (DECL_NAME (decl)), N_CATCH); ! 2052: assemble_name (asmfile, buf); ! 2053: fprintf (asmfile, "\n"); ! 2054: #endif ! 2055: decl = TREE_CHAIN (decl); ! 2056: } ! 2057: } ! 2058: ! 2059: fprintf (asmfile, "%s %d,0,0,", ASM_STABN_OP, N_LBRAC); ! 2060: assemble_name (asmfile, buf); ! 2061: fprintf (asmfile, "\n"); ! 2062: } ! 2063: else if (depth > 0) ! 2064: /* Count blocks the same way regardless of debug_info_level. */ ! 2065: next_block_number++; ! 2066: ! 2067: #ifdef DBX_LBRAC_FIRST ! 2068: /* On some weird machines, the syms of a block ! 2069: come after the N_LBRAC. */ ! 2070: if (debug_info_level != DINFO_LEVEL_TERSE || depth == 0) ! 2071: dbxout_syms (BLOCK_VARS (block)); ! 2072: if (args) ! 2073: dbxout_reg_parms (args); ! 2074: #endif ! 2075: ! 2076: /* Output the subblocks. */ ! 2077: dbxout_block (BLOCK_SUBBLOCKS (block), depth + 1, 0); ! 2078: ! 2079: /* Refer to the marker for the end of the block. */ ! 2080: if (depth > 0 && debug_info_level != DINFO_LEVEL_TERSE) ! 2081: { ! 2082: char buf[20]; ! 2083: ASM_GENERATE_INTERNAL_LABEL (buf, "LBE", blocknum); ! 2084: fprintf (asmfile, "%s %d,0,0,", ASM_STABN_OP, N_RBRAC); ! 2085: assemble_name (asmfile, buf); ! 2086: fprintf (asmfile, "\n"); ! 2087: } ! 2088: } ! 2089: block = BLOCK_CHAIN (block); ! 2090: } ! 2091: } ! 2092: ! 2093: /* Output the information about a function and its arguments and result. ! 2094: Usually this follows the function's code, ! 2095: but on some systems, it comes before. */ ! 2096: ! 2097: static void ! 2098: dbxout_really_begin_function (decl) ! 2099: tree decl; ! 2100: { ! 2101: dbxout_symbol (decl, 0); ! 2102: dbxout_parms (DECL_ARGUMENTS (decl)); ! 2103: if (DECL_NAME (DECL_RESULT (decl)) != 0) ! 2104: dbxout_symbol (DECL_RESULT (decl), 1); ! 2105: } ! 2106: ! 2107: /* Called at beginning of output of function definition. */ ! 2108: ! 2109: void ! 2110: dbxout_begin_function (decl) ! 2111: tree decl; ! 2112: { ! 2113: #ifdef DBX_FUNCTION_FIRST ! 2114: dbxout_really_begin_function (decl); ! 2115: #endif ! 2116: } ! 2117: ! 2118: /* Output dbx data for a function definition. ! 2119: This includes a definition of the function name itself (a symbol), ! 2120: definitions of the parameters (locating them in the parameter list) ! 2121: and then output the block that makes up the function's body ! 2122: (including all the auto variables of the function). */ ! 2123: ! 2124: void ! 2125: dbxout_function (decl) ! 2126: tree decl; ! 2127: { ! 2128: #ifndef DBX_FUNCTION_FIRST ! 2129: dbxout_really_begin_function (decl); ! 2130: #endif ! 2131: dbxout_block (DECL_INITIAL (decl), 0, DECL_ARGUMENTS (decl)); ! 2132: #ifdef DBX_OUTPUT_FUNCTION_END ! 2133: DBX_OUTPUT_FUNCTION_END (asmfile, decl); ! 2134: #endif ! 2135: } ! 2136: ! 2137: #else /* not DBX_DEBUGGING_INFO */ ! 2138: ! 2139: void ! 2140: dbxout_init (asm_file, input_file_name) ! 2141: FILE *asm_file; ! 2142: char *input_file_name; ! 2143: {} ! 2144: ! 2145: void ! 2146: dbxout_symbol (decl, local) ! 2147: tree decl; ! 2148: int local; ! 2149: {} ! 2150: ! 2151: void ! 2152: dbxout_types (types) ! 2153: register tree types; ! 2154: {} ! 2155: ! 2156: void ! 2157: dbxout_function (decl) ! 2158: tree decl; ! 2159: {} ! 2160: ! 2161: #endif /* DBX_DEBUGGING_INFO */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.