|
|
1.1 root 1: /* Prints out tree in human readable form - GNU C-compiler
2: Copyright (C) 1990, 1991 Free Software Foundation, Inc.
3:
4: This file is part of GNU CC.
5:
6: GNU CC is free software; you can redistribute it and/or modify
7: it under the terms of the GNU General Public License as published by
8: the Free Software Foundation; either version 2, or (at your option)
9: any later version.
10:
11: GNU CC is distributed in the hope that it will be useful,
12: but WITHOUT ANY WARRANTY; without even the implied warranty of
13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14: GNU General Public License for more details.
15:
16: You should have received a copy of the GNU General Public License
17: along with GNU CC; see the file COPYING. If not, write to
18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19:
20:
21: #include "config.h"
22: #include "tree.h"
23: #include <stdio.h>
24:
25: extern char **tree_code_name;
26:
27: extern char *mode_name[];
28:
29: void print_node ();
30: void indent_to ();
31:
32: /* Define the hash table of nodes already seen.
33: Such nodes are not repeated; brief cross-references are used. */
34:
35: #define HASH_SIZE 37
36:
37: struct bucket
38: {
39: tree node;
40: struct bucket *next;
41: };
42:
43: static struct bucket **table;
44:
45: /* Print the node NODE on standard error, for debugging.
46: Most nodes referred to by this one are printed recursively
47: down to a depth of six. */
48:
49: void
50: debug_tree (node)
51: tree node;
52: {
53: char *object = (char *) oballoc (0);
54: table = (struct bucket **) oballoc (HASH_SIZE * sizeof (struct bucket *));
55: bzero (table, HASH_SIZE * sizeof (struct bucket *));
56: print_node (stderr, "", node, 0);
57: table = 0;
58: obfree (object);
59: fprintf (stderr, "\n");
60: }
61:
62: /* Print a node in brief fashion, with just the code, address and name. */
63:
64: void
65: print_node_brief (file, prefix, node, indent)
66: FILE *file;
67: char *prefix;
68: tree node;
69: int indent;
70: {
71: char class;
72:
73: if (node == 0)
74: return;
75:
76: class = TREE_CODE_CLASS (TREE_CODE (node));
77:
78: /* Always print the slot this node is in, and its code, address and
79: name if any. */
80: if (indent > 0)
81: fprintf (file, " ");
82: fprintf (file, "%s <%s %x", prefix,
83: tree_code_name[(int) TREE_CODE (node)], (int) node);
84:
85: if (class == 'd')
86: {
87: if (DECL_NAME (node))
88: fprintf (file, " %s", IDENTIFIER_POINTER (DECL_NAME (node)));
89: }
90: else if (class == 't')
91: {
92: if (TYPE_NAME (node))
93: {
94: if (TREE_CODE (TYPE_NAME (node)) == IDENTIFIER_NODE)
95: fprintf (file, " %s", IDENTIFIER_POINTER (TYPE_NAME (node)));
96: else if (TREE_CODE (TYPE_NAME (node)) == TYPE_DECL
97: && DECL_NAME (TYPE_NAME (node)))
98: fprintf (file, " %s",
99: IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (node))));
100: }
101: }
102: if (TREE_CODE (node) == IDENTIFIER_NODE)
103: fprintf (file, " %s", IDENTIFIER_POINTER (node));
104: /* We might as well always print the value of an integer. */
105: if (TREE_CODE (node) == INTEGER_CST)
106: {
107: if (TREE_INT_CST_HIGH (node) == 0)
108: fprintf (file, " %1u", TREE_INT_CST_LOW (node));
109: else if (TREE_INT_CST_HIGH (node) == -1
110: && TREE_INT_CST_LOW (node) != 0)
111: fprintf (file, " -%1u", -TREE_INT_CST_LOW (node));
112: else
113: fprintf (file, " 0x%x%08x",
114: TREE_INT_CST_HIGH (node),
115: TREE_INT_CST_LOW (node));
116: }
117: if (TREE_CODE (node) == REAL_CST)
118: {
119: #ifndef REAL_IS_NOT_DOUBLE
120: fprintf (file, " %e", TREE_REAL_CST (node));
121: #else
122: {
123: int i;
124: char *p = (char *) &TREE_REAL_CST (node);
125: fprintf (file, " 0x");
126: for (i = 0; i < sizeof TREE_REAL_CST (node); i++)
127: fprintf (file, "%02x", *p++);
128: fprintf (file, "");
129: }
130: #endif /* REAL_IS_NOT_DOUBLE */
131: }
132:
133: fprintf (file, ">");
134: }
135:
136: void
137: indent_to (file, column)
138: FILE *file;
139: int column;
140: {
141: int i;
142:
143: /* Since this is the long way, indent to desired column. */
144: if (column > 0)
145: fprintf (file, "\n");
146: for (i = 0; i < column; i++)
147: fprintf (file, " ");
148: }
149:
150: /* Print the node NODE in full on file FILE, preceded by PREFIX,
151: starting in column INDENT. */
152:
153: void
154: print_node (file, prefix, node, indent)
155: FILE *file;
156: char *prefix;
157: tree node;
158: int indent;
159: {
160: int hash;
161: struct bucket *b;
162: enum machine_mode mode;
163: char class;
164: int len;
165: int first_rtl;
166: int i;
167:
168: if (node == 0)
169: return;
170:
171: class = TREE_CODE_CLASS (TREE_CODE (node));
172:
173: /* Don't get too deep in nesting. If the user wants to see deeper,
174: it is easy to use the address of a lowest-level node
175: as an argument in another call to debug_tree. */
176:
177: if (indent > 24)
178: {
179: print_node_brief (file, prefix, node, indent);
180: return;
181: }
182:
183: if (indent > 8 && (class == 't' || class == 'd'))
184: {
185: print_node_brief (file, prefix, node, indent);
186: return;
187: }
188:
189: /* It is unsafe to look at any other filds of an ERROR_MARK node. */
190: if (TREE_CODE (node) == ERROR_MARK)
191: {
192: print_node_brief (file, prefix, node, indent);
193: return;
194: }
195:
196: hash = ((int) node & ~(1 << (HOST_BITS_PER_INT - 1))) % HASH_SIZE;
197:
198: /* If node is in the table, just mention its address. */
199: for (b = table[hash]; b; b = b->next)
200: if (b->node == node)
201: {
202: print_node_brief (file, prefix, node, indent);
203: return;
204: }
205:
206: /* Add this node to the table. */
207: b = (struct bucket *) oballoc (sizeof (struct bucket));
208: b->node = node;
209: b->next = table[hash];
210: table[hash] = b;
211:
212: /* Indent to the specified column, since this is the long form. */
213: indent_to (file, indent);
214:
215: /* Print the slot this node is in, and its code, and address. */
216: fprintf (file, "%s <%s %x", prefix,
217: tree_code_name[(int) TREE_CODE (node)], (int) node);
218:
219: /* Print the name, if any. */
220: if (class == 'd')
221: {
222: if (DECL_NAME (node))
223: fprintf (file, " %s", IDENTIFIER_POINTER (DECL_NAME (node)));
224: }
225: else if (class == 't')
226: {
227: if (TYPE_NAME (node))
228: {
229: if (TREE_CODE (TYPE_NAME (node)) == IDENTIFIER_NODE)
230: fprintf (file, " %s", IDENTIFIER_POINTER (TYPE_NAME (node)));
231: else if (TREE_CODE (TYPE_NAME (node)) == TYPE_DECL
232: && DECL_NAME (TYPE_NAME (node)))
233: fprintf (file, " %s",
234: IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (node))));
235: }
236: }
237: if (TREE_CODE (node) == IDENTIFIER_NODE)
238: fprintf (file, " %s", IDENTIFIER_POINTER (node));
239:
240: if (TREE_CODE (node) == INTEGER_CST)
241: {
242: if (indent <= 4)
243: print_node_brief (file, "type", TREE_TYPE (node), indent + 4);
244: }
245: else
246: {
247: print_node (file, "type", TREE_TYPE (node), indent + 4);
248: if (TREE_TYPE (node))
249: indent_to (file, indent + 3);
250: }
251:
252: /* If a permanent object is in the wrong obstack, or the reverse, warn. */
253: if (object_permanent_p (node) != TREE_PERMANENT (node))
254: {
255: if (TREE_PERMANENT (node))
256: fputs (" !!permanent object in non-permanent obstack!!", file);
257: else
258: fputs (" !!non-permanent object in permanent obstack!!", file);
259: indent_to (file, indent + 3);
260: }
261:
262: if (TREE_SIDE_EFFECTS (node))
263: fputs (" side-effects", file);
264: if (TREE_READONLY (node))
265: fputs (" readonly", file);
266: if (TREE_CONSTANT (node))
267: fputs (" constant", file);
268: if (TREE_ADDRESSABLE (node))
269: fputs (" addressable", file);
270: if (TREE_THIS_VOLATILE (node))
271: fputs (" volatile", file);
272: if (TREE_UNSIGNED (node))
273: fputs (" unsigned", file);
274: if (TREE_ASM_WRITTEN (node))
275: fputs (" asm_written", file);
276: if (TREE_USED (node))
277: fputs (" used", file);
278: if (TREE_PERMANENT (node))
279: fputs (" permanent", file);
280: if (TREE_PUBLIC (node))
281: fputs (" public", file);
282: if (TREE_STATIC (node))
283: fputs (" static", file);
284: if (TREE_LANG_FLAG_0 (node))
285: fputs (" tree_0", file);
286: if (TREE_LANG_FLAG_1 (node))
287: fputs (" tree_1", file);
288: if (TREE_LANG_FLAG_2 (node))
289: fputs (" tree_2", file);
290: if (TREE_LANG_FLAG_3 (node))
291: fputs (" tree_3", file);
292: if (TREE_LANG_FLAG_4 (node))
293: fputs (" tree_4", file);
294: if (TREE_LANG_FLAG_5 (node))
295: fputs (" tree_5", file);
296: if (TREE_LANG_FLAG_6 (node))
297: fputs (" tree_6", file);
298:
299: /* DECL_ nodes have additional attributes. */
300:
301: switch (TREE_CODE_CLASS (TREE_CODE (node)))
302: {
303: case 'd':
304: mode = DECL_MODE (node);
305:
306: if (TREE_EXTERNAL (node))
307: fputs (" external", file);
308: if (TREE_NONLOCAL (node))
309: fputs (" nonlocal", file);
310: if (TREE_REGDECL (node))
311: fputs (" regdecl", file);
312: if (TREE_INLINE (node))
313: fputs (" inline", file);
314: if (DECL_BIT_FIELD (node))
315: fputs (" bit-field", file);
316: if (DECL_VIRTUAL_P (node))
317: fputs (" virtual", file);
318: if (DECL_FROM_INLINE (node))
319: fputs (" from_inline", file);
320: if (DECL_IGNORED_P (node))
321: fputs (" ignored", file);
322: if (DECL_LANG_FLAG_0 (node))
323: fputs (" decl_0", file);
324: if (DECL_LANG_FLAG_1 (node))
325: fputs (" decl_1", file);
326: if (DECL_LANG_FLAG_2 (node))
327: fputs (" decl_2", file);
328: if (DECL_LANG_FLAG_3 (node))
329: fputs (" decl_3", file);
330: if (DECL_LANG_FLAG_4 (node))
331: fputs (" decl_4", file);
332: if (DECL_LANG_FLAG_5 (node))
333: fputs (" decl_5", file);
334: if (DECL_LANG_FLAG_6 (node))
335: fputs (" decl_6", file);
336: if (DECL_LANG_FLAG_7 (node))
337: fputs (" decl_7", file);
338:
339: fprintf (file, " %s", mode_name[(int) mode]);
340:
341: fprintf (file, " file %s line %d",
342: DECL_SOURCE_FILE (node), DECL_SOURCE_LINE (node));
343:
344: print_node (file, "size", DECL_SIZE (node), indent + 4);
345: indent_to (file, indent + 3);
346: fprintf (file, " align %d", DECL_ALIGN (node));
347: fprintf (file, " frame_size %d", DECL_FRAME_SIZE (node));
348: if (TREE_CODE (node) == FIELD_DECL)
349: print_node (file, "bitpos", DECL_FIELD_BITPOS (node), indent + 4);
350: print_node_brief (file, "context", DECL_CONTEXT (node), indent + 4);
351:
352: print_node (file, "arguments", DECL_ARGUMENTS (node), indent + 4);
353: print_node (file, "result", DECL_RESULT (node), indent + 4);
354: print_node_brief (file, "initial", DECL_INITIAL (node), indent + 4);
355:
356: print_lang_decl (file, node, indent);
357:
358: if (DECL_RTL (node) != 0)
359: {
360: indent_to (file, indent + 4);
361: print_rtl (file, DECL_RTL (node));
362: }
363:
364: if (DECL_SAVED_INSNS (node) != 0)
365: {
366: indent_to (file, indent + 4);
367: if (TREE_CODE (node) == PARM_DECL)
368: {
369: fprintf (file, "incoming-rtl ");
370: print_rtl (file, DECL_INCOMING_RTL (node));
371: }
372: else if (TREE_CODE (node) == FUNCTION_DECL)
373: fprintf (file, "saved-insns 0x%x", DECL_SAVED_INSNS (node));
374: }
375:
376: /* Print the decl chain only if decl is at second level. */
377: if (indent == 4)
378: print_node (file, "chain", TREE_CHAIN (node), indent + 4);
379: else
380: print_node_brief (file, "chain", TREE_CHAIN (node), indent + 4);
381: break;
382:
383: case 't':
384: if (TYPE_NO_FORCE_BLK (node))
385: fputs (" no_force_blk", file);
386: if (TYPE_LANG_FLAG_0 (node))
387: fputs (" type_0", file);
388: if (TYPE_LANG_FLAG_1 (node))
389: fputs (" type_1", file);
390: if (TYPE_LANG_FLAG_2 (node))
391: fputs (" type_2", file);
392: if (TYPE_LANG_FLAG_3 (node))
393: fputs (" type_3", file);
394: if (TYPE_LANG_FLAG_4 (node))
395: fputs (" type_4", file);
396: if (TYPE_LANG_FLAG_5 (node))
397: fputs (" type_5", file);
398: if (TYPE_LANG_FLAG_6 (node))
399: fputs (" type_6", file);
400:
401: mode = TYPE_MODE (node);
402: fprintf (file, " %s", mode_name[(int) mode]);
403:
404: print_node (file, "size", TYPE_SIZE (node), indent + 4);
405: indent_to (file, indent + 3);
406:
407: fprintf (file, " align %d", TYPE_ALIGN (node));
408: fprintf (file, " symtab %d", TYPE_SYMTAB_ADDRESS (node));
409:
410: if (TREE_CODE (node) == ARRAY_TYPE || TREE_CODE (node) == SET_TYPE)
411: print_node (file, "domain", TYPE_DOMAIN (node), indent + 4);
412: else if (TREE_CODE (node) == INTEGER_TYPE)
413: {
414: fprintf (file, " precision %d", TYPE_PRECISION (node));
415: print_node (file, "min", TYPE_MIN_VALUE (node), indent + 4);
416: print_node (file, "max", TYPE_MAX_VALUE (node), indent + 4);
417: }
418: else if (TREE_CODE (node) == ENUMERAL_TYPE)
419: {
420: fprintf (file, " precision %d", TYPE_PRECISION (node));
421: print_node (file, "min", TYPE_MIN_VALUE (node), indent + 4);
422: print_node (file, "max", TYPE_MAX_VALUE (node), indent + 4);
423: print_node (file, "values", TYPE_VALUES (node), indent + 4);
424: }
425: else if (TREE_CODE (node) == REAL_TYPE)
426: fprintf (file, " precision %d", TYPE_PRECISION (node));
427: else if (TREE_CODE (node) == RECORD_TYPE || TREE_CODE (node) == UNION_TYPE)
428: print_node (file, "fields", TYPE_FIELDS (node), indent + 4);
429: else if (TREE_CODE (node) == FUNCTION_TYPE || TREE_CODE (node) == METHOD_TYPE)
430: {
431: if (TYPE_METHOD_BASETYPE (node))
432: print_node_brief (file, "method basetype", TYPE_METHOD_BASETYPE (node), indent + 4);
433: print_node (file, "arg-types", TYPE_ARG_TYPES (node), indent + 4);
434: }
435: if (TYPE_CONTEXT (node))
436: print_node_brief (file, "context", TYPE_CONTEXT (node), indent + 4);
437:
438: print_lang_type (file, node, indent);
439:
440: if (TYPE_POINTER_TO (node) || TREE_CHAIN (node))
441: indent_to (file, indent + 3);
442: print_node_brief (file, "pointer_to_this", TYPE_POINTER_TO (node), indent + 4);
443: print_node_brief (file, "reference_to_this", TYPE_REFERENCE_TO (node), indent + 4);
444: print_node_brief (file, "chain", TREE_CHAIN (node), indent + 4);
445: break;
446:
447: case 'e':
448: case '<':
449: case '1':
450: case '2':
451: case 'r':
452: case 's':
453: switch (TREE_CODE (node))
454: {
455: case BLOCK:
456: print_node (file, "vars", BLOCK_VARS (node), indent + 4);
457: print_node (file, "tags", BLOCK_TYPE_TAGS (node), indent + 4);
458: print_node (file, "supercontext", BLOCK_SUPERCONTEXT (node), indent + 4);
459: print_node (file, "subblocks", BLOCK_SUBBLOCKS (node), indent + 4);
460: print_node (file, "chain", BLOCK_CHAIN (node), indent + 4);
461: return;
462:
463: case BIND_EXPR:
464: print_node (file, "vars", TREE_OPERAND (node, 0), indent + 4);
465: print_node (file, "body", TREE_OPERAND (node, 1), indent + 4);
466: return;
467: }
468:
469: first_rtl = len = tree_code_length[(int) TREE_CODE (node)];
470: /* These kinds of nodes contain rtx's, not trees,
471: after a certain point. Print the rtx's as rtx's. */
472: switch (TREE_CODE (node))
473: {
474: case SAVE_EXPR:
475: first_rtl = 2;
476: break;
477: case CALL_EXPR:
478: first_rtl = 2;
479: break;
480: case METHOD_CALL_EXPR:
481: first_rtl = 3;
482: break;
483: case WITH_CLEANUP_EXPR:
484: /* Should be defined to be 2. */
485: first_rtl = 1;
486: break;
487: case RTL_EXPR:
488: first_rtl = 0;
489: }
490: for (i = 0; i < len; i++)
491: {
492: if (i >= first_rtl)
493: {
494: indent_to (file, indent + 4);
495: fprintf (file, "rtl %d ", i);
496: if (TREE_OPERAND (node, i))
497: print_rtl (file, TREE_OPERAND (node, i));
498: else
499: fprintf (file, "(nil)");
500: fprintf (file, "\n");
501: }
502: else
503: {
504: char temp[10];
505:
506: sprintf (temp, "arg %d", i);
507: print_node (file, temp, TREE_OPERAND (node, i), indent + 4);
508: }
509: }
510: break;
511:
512: case 'c':
513: case 'x':
514: switch (TREE_CODE (node))
515: {
516: case INTEGER_CST:
517: if (TREE_INT_CST_HIGH (node) == 0)
518: fprintf (file, " %1u", TREE_INT_CST_LOW (node));
519: else if (TREE_INT_CST_HIGH (node) == -1
520: && TREE_INT_CST_LOW (node) != 0)
521: fprintf (file, " -%1u", -TREE_INT_CST_LOW (node));
522: else
523: fprintf (file, " 0x%x%08x",
524: TREE_INT_CST_HIGH (node),
525: TREE_INT_CST_LOW (node));
526: break;
527:
528: case REAL_CST:
529: #ifndef REAL_IS_NOT_DOUBLE
530: fprintf (file, " %e", TREE_REAL_CST (node));
531: #else
532: {
533: char *p = (char *) &TREE_REAL_CST (node);
534: fprintf (file, " 0x");
535: for (i = 0; i < sizeof TREE_REAL_CST (node); i++)
536: fprintf (file, "%02x", *p++);
537: fprintf (file, "");
538: }
539: #endif /* REAL_IS_NOT_DOUBLE */
540: break;
541:
542: case COMPLEX_CST:
543: print_node (file, "real", TREE_REALPART (node), indent + 4);
544: print_node (file, "imag", TREE_IMAGPART (node), indent + 4);
545: break;
546:
547: case STRING_CST:
548: fprintf (file, " \"%s\"", TREE_STRING_POINTER (node));
549: break;
550:
551: case IDENTIFIER_NODE:
552: print_lang_identifier (file, node, indent);
553: break;
554:
555: case TREE_LIST:
556: print_node (file, "purpose", TREE_PURPOSE (node), indent + 4);
557: print_node (file, "value", TREE_VALUE (node), indent + 4);
558: print_node (file, "chain", TREE_CHAIN (node), indent + 4);
559: break;
560:
561: case TREE_VEC:
562: len = TREE_VEC_LENGTH (node);
563: for (i = 0; i < len; i++)
564: {
565: char temp[10];
566: sprintf (temp, "elt %d", i);
567: indent_to (file, indent + 4);
568: print_node_brief (file, temp, TREE_VEC_ELT (node, i), 0);
569: }
570: break;
571:
572: case OP_IDENTIFIER:
573: print_node (file, "op1", TREE_PURPOSE (node), indent + 4);
574: print_node (file, "op2", TREE_VALUE (node), indent + 4);
575: }
576:
577: break;
578: }
579: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.