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