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