|
|
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.