|
|
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);
1.1.1.2 ! root 346: if (TREE_CODE (node) != FUNCTION_DECL)
! 347: fprintf (file, " align %d", DECL_ALIGN (node));
! 348: else if (TREE_INLINE (node))
! 349: fprintf (file, " frame_size %d", DECL_FRAME_SIZE (node));
! 350: else if (DECL_BUILT_IN (node))
! 351: fprintf (file, " built-in code %d", DECL_FUNCTION_CODE (node));
1.1 root 352: if (TREE_CODE (node) == FIELD_DECL)
353: print_node (file, "bitpos", DECL_FIELD_BITPOS (node), indent + 4);
354: print_node_brief (file, "context", DECL_CONTEXT (node), indent + 4);
355:
356: print_node (file, "arguments", DECL_ARGUMENTS (node), indent + 4);
357: print_node (file, "result", DECL_RESULT (node), indent + 4);
358: print_node_brief (file, "initial", DECL_INITIAL (node), indent + 4);
359:
360: print_lang_decl (file, node, indent);
361:
362: if (DECL_RTL (node) != 0)
363: {
364: indent_to (file, indent + 4);
365: print_rtl (file, DECL_RTL (node));
366: }
367:
368: if (DECL_SAVED_INSNS (node) != 0)
369: {
370: indent_to (file, indent + 4);
371: if (TREE_CODE (node) == PARM_DECL)
372: {
373: fprintf (file, "incoming-rtl ");
374: print_rtl (file, DECL_INCOMING_RTL (node));
375: }
376: else if (TREE_CODE (node) == FUNCTION_DECL)
377: fprintf (file, "saved-insns 0x%x", DECL_SAVED_INSNS (node));
378: }
379:
380: /* Print the decl chain only if decl is at second level. */
381: if (indent == 4)
382: print_node (file, "chain", TREE_CHAIN (node), indent + 4);
383: else
384: print_node_brief (file, "chain", TREE_CHAIN (node), indent + 4);
385: break;
386:
387: case 't':
388: if (TYPE_NO_FORCE_BLK (node))
389: fputs (" no_force_blk", file);
390: if (TYPE_LANG_FLAG_0 (node))
391: fputs (" type_0", file);
392: if (TYPE_LANG_FLAG_1 (node))
393: fputs (" type_1", file);
394: if (TYPE_LANG_FLAG_2 (node))
395: fputs (" type_2", file);
396: if (TYPE_LANG_FLAG_3 (node))
397: fputs (" type_3", file);
398: if (TYPE_LANG_FLAG_4 (node))
399: fputs (" type_4", file);
400: if (TYPE_LANG_FLAG_5 (node))
401: fputs (" type_5", file);
402: if (TYPE_LANG_FLAG_6 (node))
403: fputs (" type_6", file);
404:
405: mode = TYPE_MODE (node);
406: fprintf (file, " %s", mode_name[(int) mode]);
407:
408: print_node (file, "size", TYPE_SIZE (node), indent + 4);
409: indent_to (file, indent + 3);
410:
411: fprintf (file, " align %d", TYPE_ALIGN (node));
412: fprintf (file, " symtab %d", TYPE_SYMTAB_ADDRESS (node));
413:
414: if (TREE_CODE (node) == ARRAY_TYPE || TREE_CODE (node) == SET_TYPE)
415: print_node (file, "domain", TYPE_DOMAIN (node), indent + 4);
416: else if (TREE_CODE (node) == INTEGER_TYPE)
417: {
418: fprintf (file, " precision %d", TYPE_PRECISION (node));
419: print_node (file, "min", TYPE_MIN_VALUE (node), indent + 4);
420: print_node (file, "max", TYPE_MAX_VALUE (node), indent + 4);
421: }
422: else if (TREE_CODE (node) == ENUMERAL_TYPE)
423: {
424: fprintf (file, " precision %d", TYPE_PRECISION (node));
425: print_node (file, "min", TYPE_MIN_VALUE (node), indent + 4);
426: print_node (file, "max", TYPE_MAX_VALUE (node), indent + 4);
427: print_node (file, "values", TYPE_VALUES (node), indent + 4);
428: }
429: else if (TREE_CODE (node) == REAL_TYPE)
430: fprintf (file, " precision %d", TYPE_PRECISION (node));
431: else if (TREE_CODE (node) == RECORD_TYPE || TREE_CODE (node) == UNION_TYPE)
432: print_node (file, "fields", TYPE_FIELDS (node), indent + 4);
433: else if (TREE_CODE (node) == FUNCTION_TYPE || TREE_CODE (node) == METHOD_TYPE)
434: {
435: if (TYPE_METHOD_BASETYPE (node))
436: print_node_brief (file, "method basetype", TYPE_METHOD_BASETYPE (node), indent + 4);
437: print_node (file, "arg-types", TYPE_ARG_TYPES (node), indent + 4);
438: }
439: if (TYPE_CONTEXT (node))
440: print_node_brief (file, "context", TYPE_CONTEXT (node), indent + 4);
441:
442: print_lang_type (file, node, indent);
443:
444: if (TYPE_POINTER_TO (node) || TREE_CHAIN (node))
445: indent_to (file, indent + 3);
446: print_node_brief (file, "pointer_to_this", TYPE_POINTER_TO (node), indent + 4);
447: print_node_brief (file, "reference_to_this", TYPE_REFERENCE_TO (node), indent + 4);
448: print_node_brief (file, "chain", TREE_CHAIN (node), indent + 4);
449: break;
450:
451: case 'e':
452: case '<':
453: case '1':
454: case '2':
455: case 'r':
456: case 's':
457: switch (TREE_CODE (node))
458: {
459: case BLOCK:
460: print_node (file, "vars", BLOCK_VARS (node), indent + 4);
461: print_node (file, "tags", BLOCK_TYPE_TAGS (node), indent + 4);
462: print_node (file, "supercontext", BLOCK_SUPERCONTEXT (node), indent + 4);
463: print_node (file, "subblocks", BLOCK_SUBBLOCKS (node), indent + 4);
464: print_node (file, "chain", BLOCK_CHAIN (node), indent + 4);
465: return;
466:
467: case BIND_EXPR:
468: print_node (file, "vars", TREE_OPERAND (node, 0), indent + 4);
469: print_node (file, "body", TREE_OPERAND (node, 1), indent + 4);
1.1.1.2 ! root 470: print_node (file, "block", TREE_OPERAND (node, 2), indent + 4);
1.1 root 471: return;
472: }
473:
474: first_rtl = len = tree_code_length[(int) TREE_CODE (node)];
475: /* These kinds of nodes contain rtx's, not trees,
476: after a certain point. Print the rtx's as rtx's. */
477: switch (TREE_CODE (node))
478: {
479: case SAVE_EXPR:
480: first_rtl = 2;
481: break;
482: case CALL_EXPR:
483: first_rtl = 2;
484: break;
485: case METHOD_CALL_EXPR:
486: first_rtl = 3;
487: break;
488: case WITH_CLEANUP_EXPR:
489: /* Should be defined to be 2. */
490: first_rtl = 1;
491: break;
492: case RTL_EXPR:
493: first_rtl = 0;
494: }
495: for (i = 0; i < len; i++)
496: {
497: if (i >= first_rtl)
498: {
499: indent_to (file, indent + 4);
500: fprintf (file, "rtl %d ", i);
501: if (TREE_OPERAND (node, i))
502: print_rtl (file, TREE_OPERAND (node, i));
503: else
504: fprintf (file, "(nil)");
505: fprintf (file, "\n");
506: }
507: else
508: {
509: char temp[10];
510:
511: sprintf (temp, "arg %d", i);
512: print_node (file, temp, TREE_OPERAND (node, i), indent + 4);
513: }
514: }
515: break;
516:
517: case 'c':
518: case 'x':
519: switch (TREE_CODE (node))
520: {
521: case INTEGER_CST:
522: if (TREE_INT_CST_HIGH (node) == 0)
523: fprintf (file, " %1u", TREE_INT_CST_LOW (node));
524: else if (TREE_INT_CST_HIGH (node) == -1
525: && TREE_INT_CST_LOW (node) != 0)
526: fprintf (file, " -%1u", -TREE_INT_CST_LOW (node));
527: else
528: fprintf (file, " 0x%x%08x",
529: TREE_INT_CST_HIGH (node),
530: TREE_INT_CST_LOW (node));
531: break;
532:
533: case REAL_CST:
534: #ifndef REAL_IS_NOT_DOUBLE
535: fprintf (file, " %e", TREE_REAL_CST (node));
536: #else
537: {
538: char *p = (char *) &TREE_REAL_CST (node);
539: fprintf (file, " 0x");
540: for (i = 0; i < sizeof TREE_REAL_CST (node); i++)
541: fprintf (file, "%02x", *p++);
542: fprintf (file, "");
543: }
544: #endif /* REAL_IS_NOT_DOUBLE */
545: break;
546:
547: case COMPLEX_CST:
548: print_node (file, "real", TREE_REALPART (node), indent + 4);
549: print_node (file, "imag", TREE_IMAGPART (node), indent + 4);
550: break;
551:
552: case STRING_CST:
553: fprintf (file, " \"%s\"", TREE_STRING_POINTER (node));
554: break;
555:
556: case IDENTIFIER_NODE:
557: print_lang_identifier (file, node, indent);
558: break;
559:
560: case TREE_LIST:
561: print_node (file, "purpose", TREE_PURPOSE (node), indent + 4);
562: print_node (file, "value", TREE_VALUE (node), indent + 4);
563: print_node (file, "chain", TREE_CHAIN (node), indent + 4);
564: break;
565:
566: case TREE_VEC:
567: len = TREE_VEC_LENGTH (node);
568: for (i = 0; i < len; i++)
569: {
570: char temp[10];
571: sprintf (temp, "elt %d", i);
572: indent_to (file, indent + 4);
573: print_node_brief (file, temp, TREE_VEC_ELT (node, i), 0);
574: }
575: break;
576:
577: case OP_IDENTIFIER:
578: print_node (file, "op1", TREE_PURPOSE (node), indent + 4);
579: print_node (file, "op2", TREE_VALUE (node), indent + 4);
580: }
581:
582: break;
583: }
584: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.