190075Sobrien/* Tree-dumping functionality for intermediate representation. 2169689Skan Copyright (C) 1999, 2000, 2002, 2003, 2004, 2005, 2006 3169689Skan Free Software Foundation, Inc. 490075Sobrien Written by Mark Mitchell <mark@codesourcery.com> 590075Sobrien 690075SobrienThis file is part of GCC. 790075Sobrien 890075SobrienGCC is free software; you can redistribute it and/or modify it under 990075Sobrienthe terms of the GNU General Public License as published by the Free 1090075SobrienSoftware Foundation; either version 2, or (at your option) any later 1190075Sobrienversion. 1290075Sobrien 1390075SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY 1490075SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or 1590075SobrienFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1690075Sobrienfor more details. 1790075Sobrien 1890075SobrienYou should have received a copy of the GNU General Public License 1990075Sobrienalong with GCC; see the file COPYING. If not, write to the Free 20169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 21169689Skan02110-1301, USA. */ 2290075Sobrien 2390075Sobrien#include "config.h" 2490075Sobrien#include "system.h" 25132718Skan#include "coretypes.h" 26132718Skan#include "tm.h" 2790075Sobrien#include "tree.h" 2890075Sobrien#include "splay-tree.h" 2990075Sobrien#include "diagnostic.h" 3090075Sobrien#include "toplev.h" 3190075Sobrien#include "tree-dump.h" 32169689Skan#include "tree-pass.h" 3390075Sobrien#include "langhooks.h" 34169689Skan#include "tree-iterator.h" 35169689Skan#include "real.h" 3690075Sobrien 37132718Skanstatic unsigned int queue (dump_info_p, tree, int); 38132718Skanstatic void dump_index (dump_info_p, unsigned int); 39132718Skanstatic void dequeue_and_dump (dump_info_p); 40132718Skanstatic void dump_new_line (dump_info_p); 41132718Skanstatic void dump_maybe_newline (dump_info_p); 42169689Skanstatic int dump_enable_all (int, int); 4390075Sobrien 4490075Sobrien/* Add T to the end of the queue of nodes to dump. Returns the index 4590075Sobrien assigned to T. */ 4690075Sobrien 4790075Sobrienstatic unsigned int 48132718Skanqueue (dump_info_p di, tree t, int flags) 4990075Sobrien{ 5090075Sobrien dump_queue_p dq; 5190075Sobrien dump_node_info_p dni; 5290075Sobrien unsigned int index; 5390075Sobrien 5490075Sobrien /* Assign the next available index to T. */ 5590075Sobrien index = ++di->index; 5690075Sobrien 5790075Sobrien /* Obtain a new queue node. */ 5890075Sobrien if (di->free_list) 5990075Sobrien { 6090075Sobrien dq = di->free_list; 6190075Sobrien di->free_list = dq->next; 6290075Sobrien } 6390075Sobrien else 64169689Skan dq = XNEW (struct dump_queue); 6590075Sobrien 6690075Sobrien /* Create a new entry in the splay-tree. */ 67169689Skan dni = XNEW (struct dump_node_info); 6890075Sobrien dni->index = index; 6990075Sobrien dni->binfo_p = ((flags & DUMP_BINFO) != 0); 70117395Skan dq->node = splay_tree_insert (di->nodes, (splay_tree_key) t, 7190075Sobrien (splay_tree_value) dni); 7290075Sobrien 7390075Sobrien /* Add it to the end of the queue. */ 7490075Sobrien dq->next = 0; 7590075Sobrien if (!di->queue_end) 7690075Sobrien di->queue = dq; 7790075Sobrien else 7890075Sobrien di->queue_end->next = dq; 7990075Sobrien di->queue_end = dq; 8090075Sobrien 8190075Sobrien /* Return the index. */ 8290075Sobrien return index; 8390075Sobrien} 8490075Sobrien 8590075Sobrienstatic void 86132718Skandump_index (dump_info_p di, unsigned int index) 8790075Sobrien{ 8890075Sobrien fprintf (di->stream, "@%-6u ", index); 8990075Sobrien di->column += 8; 9090075Sobrien} 9190075Sobrien 9290075Sobrien/* If T has not already been output, queue it for subsequent output. 9390075Sobrien FIELD is a string to print before printing the index. Then, the 9490075Sobrien index of T is printed. */ 9590075Sobrien 9690075Sobrienvoid 97132718Skanqueue_and_dump_index (dump_info_p di, const char *field, tree t, int flags) 9890075Sobrien{ 9990075Sobrien unsigned int index; 10090075Sobrien splay_tree_node n; 10190075Sobrien 10290075Sobrien /* If there's no node, just return. This makes for fewer checks in 10390075Sobrien our callers. */ 10490075Sobrien if (!t) 10590075Sobrien return; 10690075Sobrien 10790075Sobrien /* See if we've already queued or dumped this node. */ 10890075Sobrien n = splay_tree_lookup (di->nodes, (splay_tree_key) t); 10990075Sobrien if (n) 11090075Sobrien index = ((dump_node_info_p) n->value)->index; 11190075Sobrien else 11290075Sobrien /* If we haven't, add it to the queue. */ 11390075Sobrien index = queue (di, t, flags); 11490075Sobrien 11590075Sobrien /* Print the index of the node. */ 11690075Sobrien dump_maybe_newline (di); 11790075Sobrien fprintf (di->stream, "%-4s: ", field); 11890075Sobrien di->column += 6; 11990075Sobrien dump_index (di, index); 12090075Sobrien} 12190075Sobrien 12290075Sobrien/* Dump the type of T. */ 12390075Sobrien 12490075Sobrienvoid 125132718Skanqueue_and_dump_type (dump_info_p di, tree t) 12690075Sobrien{ 12790075Sobrien queue_and_dump_index (di, "type", TREE_TYPE (t), DUMP_NONE); 12890075Sobrien} 12990075Sobrien 13090075Sobrien/* Dump column control */ 13190075Sobrien#define SOL_COLUMN 25 /* Start of line column. */ 13290075Sobrien#define EOL_COLUMN 55 /* End of line column. */ 13390075Sobrien#define COLUMN_ALIGNMENT 15 /* Alignment. */ 13490075Sobrien 13590075Sobrien/* Insert a new line in the dump output, and indent to an appropriate 13690075Sobrien place to start printing more fields. */ 13790075Sobrien 13890075Sobrienstatic void 139132718Skandump_new_line (dump_info_p di) 14090075Sobrien{ 14190075Sobrien fprintf (di->stream, "\n%*s", SOL_COLUMN, ""); 14290075Sobrien di->column = SOL_COLUMN; 14390075Sobrien} 14490075Sobrien 14590075Sobrien/* If necessary, insert a new line. */ 14690075Sobrien 14790075Sobrienstatic void 148132718Skandump_maybe_newline (dump_info_p di) 14990075Sobrien{ 15090075Sobrien int extra; 151117395Skan 15290075Sobrien /* See if we need a new line. */ 15390075Sobrien if (di->column > EOL_COLUMN) 15490075Sobrien dump_new_line (di); 15590075Sobrien /* See if we need any padding. */ 15690075Sobrien else if ((extra = (di->column - SOL_COLUMN) % COLUMN_ALIGNMENT) != 0) 15790075Sobrien { 15890075Sobrien fprintf (di->stream, "%*s", COLUMN_ALIGNMENT - extra, ""); 15990075Sobrien di->column += COLUMN_ALIGNMENT - extra; 16090075Sobrien } 16190075Sobrien} 16290075Sobrien 16390075Sobrien/* Dump pointer PTR using FIELD to identify it. */ 16490075Sobrien 16590075Sobrienvoid 166132718Skandump_pointer (dump_info_p di, const char *field, void *ptr) 16790075Sobrien{ 16890075Sobrien dump_maybe_newline (di); 169259948Spfg fprintf (di->stream, "%-4s: %-8lx ", field, (unsigned long) ptr); 17090075Sobrien di->column += 15; 17190075Sobrien} 17290075Sobrien 17390075Sobrien/* Dump integer I using FIELD to identify it. */ 17490075Sobrien 17590075Sobrienvoid 176132718Skandump_int (dump_info_p di, const char *field, int i) 17790075Sobrien{ 17890075Sobrien dump_maybe_newline (di); 17990075Sobrien fprintf (di->stream, "%-4s: %-7d ", field, i); 18090075Sobrien di->column += 14; 18190075Sobrien} 18290075Sobrien 183169689Skan/* Dump the floating point value R, using FIELD to identify it. */ 184169689Skan 185169689Skanstatic void 186169689Skandump_real (dump_info_p di, const char *field, const REAL_VALUE_TYPE *r) 187169689Skan{ 188169689Skan char buf[32]; 189169689Skan real_to_decimal (buf, r, sizeof (buf), 0, true); 190169689Skan dump_maybe_newline (di); 191169689Skan fprintf (di->stream, "%-4s: %s ", field, buf); 192169689Skan di->column += strlen (buf) + 7; 193169689Skan} 194169689Skan 195169689Skan 19690075Sobrien/* Dump the string S. */ 19790075Sobrien 19890075Sobrienvoid 199132718Skandump_string (dump_info_p di, const char *string) 20090075Sobrien{ 20190075Sobrien dump_maybe_newline (di); 20290075Sobrien fprintf (di->stream, "%-13s ", string); 20390075Sobrien if (strlen (string) > 13) 20490075Sobrien di->column += strlen (string) + 1; 20590075Sobrien else 20690075Sobrien di->column += 14; 20790075Sobrien} 20890075Sobrien 20990075Sobrien/* Dump the string field S. */ 21090075Sobrien 211169689Skanvoid 212132718Skandump_string_field (dump_info_p di, const char *field, const char *string) 21390075Sobrien{ 21490075Sobrien dump_maybe_newline (di); 21590075Sobrien fprintf (di->stream, "%-4s: %-7s ", field, string); 21690075Sobrien if (strlen (string) > 7) 21790075Sobrien di->column += 6 + strlen (string) + 1; 21890075Sobrien else 21990075Sobrien di->column += 14; 22090075Sobrien} 22190075Sobrien 22290075Sobrien/* Dump the next node in the queue. */ 22390075Sobrien 224117395Skanstatic void 225132718Skandequeue_and_dump (dump_info_p di) 22690075Sobrien{ 22790075Sobrien dump_queue_p dq; 22890075Sobrien splay_tree_node stn; 22990075Sobrien dump_node_info_p dni; 23090075Sobrien tree t; 23190075Sobrien unsigned int index; 23290075Sobrien enum tree_code code; 233169689Skan enum tree_code_class code_class; 23490075Sobrien const char* code_name; 23590075Sobrien 23690075Sobrien /* Get the next node from the queue. */ 23790075Sobrien dq = di->queue; 23890075Sobrien stn = dq->node; 23990075Sobrien t = (tree) stn->key; 24090075Sobrien dni = (dump_node_info_p) stn->value; 24190075Sobrien index = dni->index; 24290075Sobrien 24390075Sobrien /* Remove the node from the queue, and put it on the free list. */ 24490075Sobrien di->queue = dq->next; 24590075Sobrien if (!di->queue) 24690075Sobrien di->queue_end = 0; 24790075Sobrien dq->next = di->free_list; 24890075Sobrien di->free_list = dq; 24990075Sobrien 25090075Sobrien /* Print the node index. */ 25190075Sobrien dump_index (di, index); 25290075Sobrien /* And the type of node this is. */ 25390075Sobrien if (dni->binfo_p) 25490075Sobrien code_name = "binfo"; 25590075Sobrien else 25690075Sobrien code_name = tree_code_name[(int) TREE_CODE (t)]; 25790075Sobrien fprintf (di->stream, "%-16s ", code_name); 25890075Sobrien di->column = 25; 25990075Sobrien 26090075Sobrien /* Figure out what kind of node this is. */ 26190075Sobrien code = TREE_CODE (t); 26290075Sobrien code_class = TREE_CODE_CLASS (code); 26390075Sobrien 26490075Sobrien /* Although BINFOs are TREE_VECs, we dump them specially so as to be 26590075Sobrien more informative. */ 26690075Sobrien if (dni->binfo_p) 26790075Sobrien { 268132718Skan unsigned ix; 269169689Skan tree base; 270169689Skan VEC(tree,gc) *accesses = BINFO_BASE_ACCESSES (t); 271132718Skan 272132718Skan dump_child ("type", BINFO_TYPE (t)); 273132718Skan 274169689Skan if (BINFO_VIRTUAL_P (t)) 275169689Skan dump_string_field (di, "spec", "virt"); 276117395Skan 277169689Skan dump_int (di, "bases", BINFO_N_BASE_BINFOS (t)); 278169689Skan for (ix = 0; BINFO_BASE_ITERATE (t, ix, base); ix++) 279132718Skan { 280169689Skan tree access = (accesses ? VEC_index (tree, accesses, ix) 281132718Skan : access_public_node); 282132718Skan const char *string = NULL; 28390075Sobrien 284132718Skan if (access == access_public_node) 285132718Skan string = "pub"; 286132718Skan else if (access == access_protected_node) 287132718Skan string = "prot"; 288132718Skan else if (access == access_private_node) 289132718Skan string = "priv"; 290132718Skan else 291169689Skan gcc_unreachable (); 292132718Skan 293169689Skan dump_string_field (di, "accs", string); 294132718Skan queue_and_dump_index (di, "binf", base, DUMP_BINFO); 295132718Skan } 296132718Skan 29790075Sobrien goto done; 29890075Sobrien } 29990075Sobrien 30090075Sobrien /* We can knock off a bunch of expression nodes in exactly the same 30190075Sobrien way. */ 30290075Sobrien if (IS_EXPR_CODE_CLASS (code_class)) 30390075Sobrien { 30490075Sobrien /* If we're dumping children, dump them now. */ 30590075Sobrien queue_and_dump_type (di, t); 30690075Sobrien 30790075Sobrien switch (code_class) 30890075Sobrien { 309169689Skan case tcc_unary: 31090075Sobrien dump_child ("op 0", TREE_OPERAND (t, 0)); 31190075Sobrien break; 312117395Skan 313169689Skan case tcc_binary: 314169689Skan case tcc_comparison: 31590075Sobrien dump_child ("op 0", TREE_OPERAND (t, 0)); 31690075Sobrien dump_child ("op 1", TREE_OPERAND (t, 1)); 31790075Sobrien break; 318117395Skan 319169689Skan case tcc_expression: 320169689Skan case tcc_reference: 321169689Skan case tcc_statement: 32290075Sobrien /* These nodes are handled explicitly below. */ 32390075Sobrien break; 324117395Skan 32590075Sobrien default: 326169689Skan gcc_unreachable (); 32790075Sobrien } 32890075Sobrien } 32990075Sobrien else if (DECL_P (t)) 33090075Sobrien { 331169689Skan expanded_location xloc; 33290075Sobrien /* All declarations have names. */ 33390075Sobrien if (DECL_NAME (t)) 33490075Sobrien dump_child ("name", DECL_NAME (t)); 335117395Skan if (DECL_ASSEMBLER_NAME_SET_P (t) 33690075Sobrien && DECL_ASSEMBLER_NAME (t) != DECL_NAME (t)) 33790075Sobrien dump_child ("mngl", DECL_ASSEMBLER_NAME (t)); 338169689Skan if (DECL_ABSTRACT_ORIGIN (t)) 339169689Skan dump_child ("orig", DECL_ABSTRACT_ORIGIN (t)); 34090075Sobrien /* And types. */ 34190075Sobrien queue_and_dump_type (di, t); 34290075Sobrien dump_child ("scpe", DECL_CONTEXT (t)); 34390075Sobrien /* And a source position. */ 344169689Skan xloc = expand_location (DECL_SOURCE_LOCATION (t)); 345169689Skan if (xloc.file) 34690075Sobrien { 347169689Skan const char *filename = strrchr (xloc.file, '/'); 34890075Sobrien if (!filename) 349169689Skan filename = xloc.file; 35090075Sobrien else 35190075Sobrien /* Skip the slash. */ 35290075Sobrien ++filename; 35390075Sobrien 35490075Sobrien dump_maybe_newline (di); 355117395Skan fprintf (di->stream, "srcp: %s:%-6d ", filename, 356169689Skan xloc.line); 35790075Sobrien di->column += 6 + strlen (filename) + 8; 35890075Sobrien } 35990075Sobrien /* And any declaration can be compiler-generated. */ 360169689Skan if (CODE_CONTAINS_STRUCT (TREE_CODE (t), TS_DECL_COMMON) 361169689Skan && DECL_ARTIFICIAL (t)) 362169689Skan dump_string_field (di, "note", "artificial"); 36390075Sobrien if (TREE_CHAIN (t) && !dump_flag (di, TDF_SLIM, NULL)) 36490075Sobrien dump_child ("chan", TREE_CHAIN (t)); 36590075Sobrien } 366169689Skan else if (code_class == tcc_type) 36790075Sobrien { 36890075Sobrien /* All types have qualifiers. */ 369169689Skan int quals = lang_hooks.tree_dump.type_quals (t); 370117395Skan 37190075Sobrien if (quals != TYPE_UNQUALIFIED) 37290075Sobrien { 37390075Sobrien fprintf (di->stream, "qual: %c%c%c ", 37490075Sobrien (quals & TYPE_QUAL_CONST) ? 'c' : ' ', 37590075Sobrien (quals & TYPE_QUAL_VOLATILE) ? 'v' : ' ', 37690075Sobrien (quals & TYPE_QUAL_RESTRICT) ? 'r' : ' '); 37790075Sobrien di->column += 14; 37890075Sobrien } 37990075Sobrien 38090075Sobrien /* All types have associated declarations. */ 38190075Sobrien dump_child ("name", TYPE_NAME (t)); 38290075Sobrien 38390075Sobrien /* All types have a main variant. */ 38490075Sobrien if (TYPE_MAIN_VARIANT (t) != t) 38590075Sobrien dump_child ("unql", TYPE_MAIN_VARIANT (t)); 386117395Skan 38790075Sobrien /* And sizes. */ 38890075Sobrien dump_child ("size", TYPE_SIZE (t)); 38990075Sobrien 39090075Sobrien /* All types have alignments. */ 39190075Sobrien dump_int (di, "algn", TYPE_ALIGN (t)); 39290075Sobrien } 393169689Skan else if (code_class == tcc_constant) 39490075Sobrien /* All constants can have types. */ 39590075Sobrien queue_and_dump_type (di, t); 39690075Sobrien 39790075Sobrien /* Give the language-specific code a chance to print something. If 39890075Sobrien it's completely taken care of things, don't bother printing 39990075Sobrien anything more ourselves. */ 400169689Skan if (lang_hooks.tree_dump.dump_tree (di, t)) 40190075Sobrien goto done; 40290075Sobrien 40390075Sobrien /* Now handle the various kinds of nodes. */ 40490075Sobrien switch (code) 40590075Sobrien { 40690075Sobrien int i; 40790075Sobrien 40890075Sobrien case IDENTIFIER_NODE: 40990075Sobrien dump_string_field (di, "strg", IDENTIFIER_POINTER (t)); 41090075Sobrien dump_int (di, "lngt", IDENTIFIER_LENGTH (t)); 41190075Sobrien break; 41290075Sobrien 41390075Sobrien case TREE_LIST: 41490075Sobrien dump_child ("purp", TREE_PURPOSE (t)); 41590075Sobrien dump_child ("valu", TREE_VALUE (t)); 41690075Sobrien dump_child ("chan", TREE_CHAIN (t)); 41790075Sobrien break; 41890075Sobrien 419169689Skan case STATEMENT_LIST: 420169689Skan { 421169689Skan tree_stmt_iterator it; 422169689Skan for (i = 0, it = tsi_start (t); !tsi_end_p (it); tsi_next (&it), i++) 423169689Skan { 424169689Skan char buffer[32]; 425169689Skan sprintf (buffer, "%u", i); 426169689Skan dump_child (buffer, tsi_stmt (it)); 427169689Skan } 428169689Skan } 429169689Skan break; 430169689Skan 43190075Sobrien case TREE_VEC: 43290075Sobrien dump_int (di, "lngt", TREE_VEC_LENGTH (t)); 43390075Sobrien for (i = 0; i < TREE_VEC_LENGTH (t); ++i) 43490075Sobrien { 43590075Sobrien char buffer[32]; 43690075Sobrien sprintf (buffer, "%u", i); 43790075Sobrien dump_child (buffer, TREE_VEC_ELT (t, i)); 43890075Sobrien } 43990075Sobrien break; 44090075Sobrien 44190075Sobrien case INTEGER_TYPE: 44290075Sobrien case ENUMERAL_TYPE: 44390075Sobrien dump_int (di, "prec", TYPE_PRECISION (t)); 444169689Skan dump_string_field (di, "sign", TYPE_UNSIGNED (t) ? "unsigned": "signed"); 44590075Sobrien dump_child ("min", TYPE_MIN_VALUE (t)); 44690075Sobrien dump_child ("max", TYPE_MAX_VALUE (t)); 44790075Sobrien 44890075Sobrien if (code == ENUMERAL_TYPE) 44990075Sobrien dump_child ("csts", TYPE_VALUES (t)); 45090075Sobrien break; 45190075Sobrien 45290075Sobrien case REAL_TYPE: 45390075Sobrien dump_int (di, "prec", TYPE_PRECISION (t)); 45490075Sobrien break; 45590075Sobrien 45690075Sobrien case POINTER_TYPE: 45790075Sobrien dump_child ("ptd", TREE_TYPE (t)); 45890075Sobrien break; 45990075Sobrien 46090075Sobrien case REFERENCE_TYPE: 46190075Sobrien dump_child ("refd", TREE_TYPE (t)); 46290075Sobrien break; 46390075Sobrien 46490075Sobrien case METHOD_TYPE: 46590075Sobrien dump_child ("clas", TYPE_METHOD_BASETYPE (t)); 46690075Sobrien /* Fall through. */ 46790075Sobrien 46890075Sobrien case FUNCTION_TYPE: 46990075Sobrien dump_child ("retn", TREE_TYPE (t)); 47090075Sobrien dump_child ("prms", TYPE_ARG_TYPES (t)); 47190075Sobrien break; 47290075Sobrien 47390075Sobrien case ARRAY_TYPE: 47490075Sobrien dump_child ("elts", TREE_TYPE (t)); 47590075Sobrien dump_child ("domn", TYPE_DOMAIN (t)); 47690075Sobrien break; 47790075Sobrien 47890075Sobrien case RECORD_TYPE: 47990075Sobrien case UNION_TYPE: 48090075Sobrien if (TREE_CODE (t) == RECORD_TYPE) 481169689Skan dump_string_field (di, "tag", "struct"); 48290075Sobrien else 483169689Skan dump_string_field (di, "tag", "union"); 484117395Skan 48590075Sobrien dump_child ("flds", TYPE_FIELDS (t)); 48690075Sobrien dump_child ("fncs", TYPE_METHODS (t)); 487117395Skan queue_and_dump_index (di, "binf", TYPE_BINFO (t), 48890075Sobrien DUMP_BINFO); 48990075Sobrien break; 49090075Sobrien 49190075Sobrien case CONST_DECL: 49290075Sobrien dump_child ("cnst", DECL_INITIAL (t)); 49390075Sobrien break; 494169689Skan 495169689Skan case SYMBOL_MEMORY_TAG: 496169689Skan case NAME_MEMORY_TAG: 497169689Skan case STRUCT_FIELD_TAG: 498169689Skan break; 49990075Sobrien 50090075Sobrien case VAR_DECL: 50190075Sobrien case PARM_DECL: 50290075Sobrien case FIELD_DECL: 50390075Sobrien case RESULT_DECL: 50490075Sobrien if (TREE_CODE (t) == PARM_DECL) 50590075Sobrien dump_child ("argt", DECL_ARG_TYPE (t)); 50690075Sobrien else 50790075Sobrien dump_child ("init", DECL_INITIAL (t)); 50890075Sobrien dump_child ("size", DECL_SIZE (t)); 50990075Sobrien dump_int (di, "algn", DECL_ALIGN (t)); 51090075Sobrien 51190075Sobrien if (TREE_CODE (t) == FIELD_DECL) 51290075Sobrien { 51390075Sobrien if (DECL_FIELD_OFFSET (t)) 51490075Sobrien dump_child ("bpos", bit_position (t)); 51590075Sobrien } 516117395Skan else if (TREE_CODE (t) == VAR_DECL 51790075Sobrien || TREE_CODE (t) == PARM_DECL) 51890075Sobrien { 51990075Sobrien dump_int (di, "used", TREE_USED (t)); 52090075Sobrien if (DECL_REGISTER (t)) 521169689Skan dump_string_field (di, "spec", "register"); 52290075Sobrien } 52390075Sobrien break; 52490075Sobrien 52590075Sobrien case FUNCTION_DECL: 52690075Sobrien dump_child ("args", DECL_ARGUMENTS (t)); 52790075Sobrien if (DECL_EXTERNAL (t)) 528169689Skan dump_string_field (di, "body", "undefined"); 52990075Sobrien if (TREE_PUBLIC (t)) 530169689Skan dump_string_field (di, "link", "extern"); 53190075Sobrien else 532169689Skan dump_string_field (di, "link", "static"); 53390075Sobrien if (DECL_LANG_SPECIFIC (t) && !dump_flag (di, TDF_SLIM, t)) 53490075Sobrien dump_child ("body", DECL_SAVED_TREE (t)); 53590075Sobrien break; 53690075Sobrien 53790075Sobrien case INTEGER_CST: 53890075Sobrien if (TREE_INT_CST_HIGH (t)) 53990075Sobrien dump_int (di, "high", TREE_INT_CST_HIGH (t)); 54090075Sobrien dump_int (di, "low", TREE_INT_CST_LOW (t)); 54190075Sobrien break; 54290075Sobrien 54390075Sobrien case STRING_CST: 54490075Sobrien fprintf (di->stream, "strg: %-7s ", TREE_STRING_POINTER (t)); 54590075Sobrien dump_int (di, "lngt", TREE_STRING_LENGTH (t)); 54690075Sobrien break; 54790075Sobrien 548169689Skan case REAL_CST: 549169689Skan dump_real (di, "valu", TREE_REAL_CST_PTR (t)); 550169689Skan break; 551169689Skan 55290075Sobrien case TRUTH_NOT_EXPR: 55390075Sobrien case ADDR_EXPR: 55490075Sobrien case INDIRECT_REF: 555169689Skan case ALIGN_INDIRECT_REF: 556169689Skan case MISALIGNED_INDIRECT_REF: 55790075Sobrien case CLEANUP_POINT_EXPR: 55890075Sobrien case SAVE_EXPR: 559169689Skan case REALPART_EXPR: 560169689Skan case IMAGPART_EXPR: 56190075Sobrien /* These nodes are unary, but do not have code class `1'. */ 56290075Sobrien dump_child ("op 0", TREE_OPERAND (t, 0)); 56390075Sobrien break; 56490075Sobrien 56590075Sobrien case TRUTH_ANDIF_EXPR: 56690075Sobrien case TRUTH_ORIF_EXPR: 56790075Sobrien case INIT_EXPR: 56890075Sobrien case MODIFY_EXPR: 56990075Sobrien case COMPOUND_EXPR: 57090075Sobrien case PREDECREMENT_EXPR: 57190075Sobrien case PREINCREMENT_EXPR: 57290075Sobrien case POSTDECREMENT_EXPR: 57390075Sobrien case POSTINCREMENT_EXPR: 57490075Sobrien /* These nodes are binary, but do not have code class `2'. */ 57590075Sobrien dump_child ("op 0", TREE_OPERAND (t, 0)); 57690075Sobrien dump_child ("op 1", TREE_OPERAND (t, 1)); 57790075Sobrien break; 57890075Sobrien 579169689Skan case COMPONENT_REF: 580169689Skan dump_child ("op 0", TREE_OPERAND (t, 0)); 581169689Skan dump_child ("op 1", TREE_OPERAND (t, 1)); 582169689Skan dump_child ("op 2", TREE_OPERAND (t, 2)); 583169689Skan break; 584169689Skan 585169689Skan case ARRAY_REF: 586169689Skan case ARRAY_RANGE_REF: 587169689Skan dump_child ("op 0", TREE_OPERAND (t, 0)); 588169689Skan dump_child ("op 1", TREE_OPERAND (t, 1)); 589169689Skan dump_child ("op 2", TREE_OPERAND (t, 2)); 590169689Skan dump_child ("op 3", TREE_OPERAND (t, 3)); 591169689Skan break; 592169689Skan 59390075Sobrien case COND_EXPR: 59490075Sobrien dump_child ("op 0", TREE_OPERAND (t, 0)); 59590075Sobrien dump_child ("op 1", TREE_OPERAND (t, 1)); 59690075Sobrien dump_child ("op 2", TREE_OPERAND (t, 2)); 59790075Sobrien break; 59890075Sobrien 599169689Skan case TRY_FINALLY_EXPR: 600169689Skan dump_child ("op 0", TREE_OPERAND (t, 0)); 601169689Skan dump_child ("op 1", TREE_OPERAND (t, 1)); 602169689Skan break; 603169689Skan 60490075Sobrien case CALL_EXPR: 60590075Sobrien dump_child ("fn", TREE_OPERAND (t, 0)); 60690075Sobrien dump_child ("args", TREE_OPERAND (t, 1)); 60790075Sobrien break; 60890075Sobrien 60990075Sobrien case CONSTRUCTOR: 610169689Skan { 611169689Skan unsigned HOST_WIDE_INT cnt; 612169689Skan tree index, value; 613169689Skan dump_int (di, "lngt", VEC_length (constructor_elt, 614169689Skan CONSTRUCTOR_ELTS (t))); 615169689Skan FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (t), cnt, index, value) 616169689Skan { 617169689Skan dump_child ("idx", index); 618169689Skan dump_child ("val", value); 619169689Skan } 620169689Skan } 62190075Sobrien break; 62290075Sobrien 62390075Sobrien case BIND_EXPR: 62490075Sobrien dump_child ("vars", TREE_OPERAND (t, 0)); 62590075Sobrien dump_child ("body", TREE_OPERAND (t, 1)); 62690075Sobrien break; 62790075Sobrien 62890075Sobrien case LOOP_EXPR: 62990075Sobrien dump_child ("body", TREE_OPERAND (t, 0)); 63090075Sobrien break; 63190075Sobrien 63290075Sobrien case EXIT_EXPR: 63390075Sobrien dump_child ("cond", TREE_OPERAND (t, 0)); 63490075Sobrien break; 63590075Sobrien 636169689Skan case RETURN_EXPR: 637169689Skan dump_child ("expr", TREE_OPERAND (t, 0)); 638169689Skan break; 639169689Skan 64090075Sobrien case TARGET_EXPR: 64190075Sobrien dump_child ("decl", TREE_OPERAND (t, 0)); 64290075Sobrien dump_child ("init", TREE_OPERAND (t, 1)); 64390075Sobrien dump_child ("clnp", TREE_OPERAND (t, 2)); 64490075Sobrien /* There really are two possible places the initializer can be. 64590075Sobrien After RTL expansion, the second operand is moved to the 64690075Sobrien position of the fourth operand, and the second operand 64790075Sobrien becomes NULL. */ 64890075Sobrien dump_child ("init", TREE_OPERAND (t, 3)); 64990075Sobrien break; 650117395Skan 651169689Skan case CASE_LABEL_EXPR: 652169689Skan dump_child ("name", CASE_LABEL (t)); 653169689Skan if (CASE_LOW (t)) { 654169689Skan dump_child ("low ", CASE_LOW (t)); 655169689Skan if (CASE_HIGH (t)) { 656169689Skan dump_child ("high", CASE_HIGH (t)); 657169689Skan } 658169689Skan } 65990075Sobrien break; 660169689Skan case LABEL_EXPR: 661169689Skan dump_child ("name", TREE_OPERAND (t,0)); 662169689Skan break; 663169689Skan case GOTO_EXPR: 664169689Skan dump_child ("labl", TREE_OPERAND (t, 0)); 665169689Skan break; 666169689Skan case SWITCH_EXPR: 667169689Skan dump_child ("cond", TREE_OPERAND (t, 0)); 668169689Skan dump_child ("body", TREE_OPERAND (t, 1)); 669169689Skan if (TREE_OPERAND (t, 2)) 670169689Skan { 671169689Skan dump_child ("labl", TREE_OPERAND (t,2)); 672169689Skan } 673169689Skan break; 674169689Skan case OMP_CLAUSE: 675169689Skan { 676169689Skan int i; 677169689Skan fprintf (di->stream, "%s\n", omp_clause_code_name[OMP_CLAUSE_CODE (t)]); 678169689Skan for (i = 0; i < omp_clause_num_ops[OMP_CLAUSE_CODE (t)]; i++) 679169689Skan dump_child ("op: ", OMP_CLAUSE_OPERAND (t, i)); 680169689Skan } 681169689Skan break; 68290075Sobrien default: 68390075Sobrien /* There are no additional fields to print. */ 68490075Sobrien break; 68590075Sobrien } 68690075Sobrien 68790075Sobrien done: 68890075Sobrien if (dump_flag (di, TDF_ADDRESS, NULL)) 68990075Sobrien dump_pointer (di, "addr", (void *)t); 690117395Skan 69190075Sobrien /* Terminate the line. */ 69290075Sobrien fprintf (di->stream, "\n"); 69390075Sobrien} 69490075Sobrien 695117395Skan/* Return nonzero if FLAG has been specified for the dump, and NODE 69690075Sobrien is not the root node of the dump. */ 69790075Sobrien 698132718Skanint dump_flag (dump_info_p di, int flag, tree node) 69990075Sobrien{ 70090075Sobrien return (di->flags & flag) && (node != di->node); 70190075Sobrien} 70290075Sobrien 70390075Sobrien/* Dump T, and all its children, on STREAM. */ 70490075Sobrien 70590075Sobrienvoid 706132718Skandump_node (tree t, int flags, FILE *stream) 70790075Sobrien{ 70890075Sobrien struct dump_info di; 70990075Sobrien dump_queue_p dq; 71090075Sobrien dump_queue_p next_dq; 71190075Sobrien 71290075Sobrien /* Initialize the dump-information structure. */ 71390075Sobrien di.stream = stream; 71490075Sobrien di.index = 0; 71590075Sobrien di.column = 0; 71690075Sobrien di.queue = 0; 71790075Sobrien di.queue_end = 0; 71890075Sobrien di.free_list = 0; 71990075Sobrien di.flags = flags; 72090075Sobrien di.node = t; 721117395Skan di.nodes = splay_tree_new (splay_tree_compare_pointers, 0, 72290075Sobrien (splay_tree_delete_value_fn) &free); 72390075Sobrien 72490075Sobrien /* Queue up the first node. */ 72590075Sobrien queue (&di, t, DUMP_NONE); 72690075Sobrien 72790075Sobrien /* Until the queue is empty, keep dumping nodes. */ 72890075Sobrien while (di.queue) 72990075Sobrien dequeue_and_dump (&di); 73090075Sobrien 73190075Sobrien /* Now, clean up. */ 73290075Sobrien for (dq = di.free_list; dq; dq = next_dq) 73390075Sobrien { 73490075Sobrien next_dq = dq->next; 73590075Sobrien free (dq); 73690075Sobrien } 73790075Sobrien splay_tree_delete (di.nodes); 73890075Sobrien} 739169689Skan 74090075Sobrien 74190075Sobrien/* Table of tree dump switches. This must be consistent with the 742169689Skan TREE_DUMP_INDEX enumeration in tree.h. */ 74390075Sobrienstatic struct dump_file_info dump_files[TDI_end] = 74490075Sobrien{ 745169689Skan {NULL, NULL, NULL, 0, 0, 0, 0}, 746169689Skan {".cgraph", "ipa-cgraph", NULL, TDF_IPA, 0, 0, 0}, 747169689Skan {".tu", "translation-unit", NULL, TDF_TREE, 0, 1, 0}, 748169689Skan {".class", "class-hierarchy", NULL, TDF_TREE, 0, 2, 0}, 749169689Skan {".original", "tree-original", NULL, TDF_TREE, 0, 3, 0}, 750169689Skan {".gimple", "tree-gimple", NULL, TDF_TREE, 0, 4, 0}, 751169689Skan {".nested", "tree-nested", NULL, TDF_TREE, 0, 5, 0}, 752169689Skan {".inlined", "tree-inlined", NULL, TDF_TREE, 0, 6, 0}, 753169689Skan {".vcg", "tree-vcg", NULL, TDF_TREE, 0, 7, 0}, 754169689Skan#define FIRST_AUTO_NUMBERED_DUMP 8 755169689Skan 756169689Skan {NULL, "tree-all", NULL, TDF_TREE, 0, 0, 0}, 757169689Skan {NULL, "rtl-all", NULL, TDF_RTL, 0, 0, 0}, 758169689Skan {NULL, "ipa-all", NULL, TDF_IPA, 0, 0, 0}, 75990075Sobrien}; 76090075Sobrien 761169689Skan/* Dynamically registered tree dump files and switches. */ 762169689Skanstatic struct dump_file_info *extra_dump_files; 763169689Skanstatic size_t extra_dump_files_in_use; 764169689Skanstatic size_t extra_dump_files_alloced; 765169689Skan 76690075Sobrien/* Define a name->number mapping for a dump flag value. */ 76790075Sobrienstruct dump_option_value_info 76890075Sobrien{ 76990075Sobrien const char *const name; /* the name of the value */ 77090075Sobrien const int value; /* the value of the name */ 77190075Sobrien}; 77290075Sobrien 77390075Sobrien/* Table of dump options. This must be consistent with the TDF_* flags 77490075Sobrien in tree.h */ 77590075Sobrienstatic const struct dump_option_value_info dump_options[] = 77690075Sobrien{ 77790075Sobrien {"address", TDF_ADDRESS}, 77890075Sobrien {"slim", TDF_SLIM}, 779169689Skan {"raw", TDF_RAW}, 780169689Skan {"details", TDF_DETAILS}, 781169689Skan {"stats", TDF_STATS}, 782169689Skan {"blocks", TDF_BLOCKS}, 783169689Skan {"vops", TDF_VOPS}, 784169689Skan {"lineno", TDF_LINENO}, 785169689Skan {"uid", TDF_UID}, 786169689Skan {"stmtaddr", TDF_STMTADDR}, 787169689Skan {"all", ~(TDF_RAW | TDF_SLIM | TDF_LINENO | TDF_TREE | TDF_RTL | TDF_IPA 788169689Skan | TDF_STMTADDR | TDF_GRAPH)}, 78990075Sobrien {NULL, 0} 79090075Sobrien}; 79190075Sobrien 792169689Skanunsigned int 793169689Skandump_register (const char *suffix, const char *swtch, const char *glob, 794169689Skan int flags, int letter) 795169689Skan{ 796169689Skan static int next_dump = FIRST_AUTO_NUMBERED_DUMP; 797169689Skan int num = next_dump++; 798169689Skan 799169689Skan size_t this = extra_dump_files_in_use++; 800169689Skan 801169689Skan if (this >= extra_dump_files_alloced) 802169689Skan { 803169689Skan if (extra_dump_files_alloced == 0) 804169689Skan extra_dump_files_alloced = 32; 805169689Skan else 806169689Skan extra_dump_files_alloced *= 2; 807169689Skan extra_dump_files = xrealloc (extra_dump_files, 808169689Skan sizeof (struct dump_file_info) 809169689Skan * extra_dump_files_alloced); 810169689Skan } 811169689Skan 812169689Skan memset (&extra_dump_files[this], 0, sizeof (struct dump_file_info)); 813169689Skan extra_dump_files[this].suffix = suffix; 814169689Skan extra_dump_files[this].swtch = swtch; 815169689Skan extra_dump_files[this].glob = glob; 816169689Skan extra_dump_files[this].flags = flags; 817169689Skan extra_dump_files[this].num = num; 818169689Skan extra_dump_files[this].letter = letter; 819169689Skan 820169689Skan return this + TDI_end; 821169689Skan} 822169689Skan 823169689Skan 824169689Skan/* Return the dump_file_info for the given phase. */ 825169689Skan 826169689Skanstruct dump_file_info * 827169689Skanget_dump_file_info (enum tree_dump_index phase) 828169689Skan{ 829169689Skan if (phase < TDI_end) 830169689Skan return &dump_files[phase]; 831169689Skan else if (phase - TDI_end >= extra_dump_files_in_use) 832169689Skan return NULL; 833169689Skan else 834169689Skan return extra_dump_files + (phase - TDI_end); 835169689Skan} 836169689Skan 837169689Skan 838169689Skan/* Return the name of the dump file for the given phase. 839169689Skan If the dump is not enabled, returns NULL. */ 840169689Skan 841169689Skanchar * 842169689Skanget_dump_file_name (enum tree_dump_index phase) 843169689Skan{ 844169689Skan char dump_id[10]; 845169689Skan struct dump_file_info *dfi; 846169689Skan 847169689Skan if (phase == TDI_none) 848169689Skan return NULL; 849169689Skan 850169689Skan dfi = get_dump_file_info (phase); 851169689Skan if (dfi->state == 0) 852169689Skan return NULL; 853169689Skan 854169689Skan if (dfi->num < 0) 855169689Skan dump_id[0] = '\0'; 856169689Skan else 857169689Skan { 858169689Skan char suffix; 859169689Skan if (dfi->flags & TDF_TREE) 860169689Skan suffix = 't'; 861169689Skan else if (dfi->flags & TDF_IPA) 862169689Skan suffix = 'i'; 863169689Skan else 864169689Skan suffix = 'r'; 865169689Skan 866169689Skan if (snprintf (dump_id, sizeof (dump_id), ".%03d%c", dfi->num, suffix) < 0) 867169689Skan dump_id[0] = '\0'; 868169689Skan } 869169689Skan 870169689Skan return concat (dump_base_name, dump_id, dfi->suffix, NULL); 871169689Skan} 872169689Skan 87390075Sobrien/* Begin a tree dump for PHASE. Stores any user supplied flag in 87490075Sobrien *FLAG_PTR and returns a stream to write to. If the dump is not 87590075Sobrien enabled, returns NULL. 87690075Sobrien Multiple calls will reopen and append to the dump file. */ 87790075Sobrien 87890075SobrienFILE * 879132718Skandump_begin (enum tree_dump_index phase, int *flag_ptr) 88090075Sobrien{ 881169689Skan char *name; 882169689Skan struct dump_file_info *dfi; 88390075Sobrien FILE *stream; 884117395Skan 885169689Skan if (phase == TDI_none || !dump_enabled_p (phase)) 88690075Sobrien return NULL; 887117395Skan 888169689Skan name = get_dump_file_name (phase); 889169689Skan dfi = get_dump_file_info (phase); 890169689Skan stream = fopen (name, dfi->state < 0 ? "w" : "a"); 89190075Sobrien if (!stream) 892169689Skan error ("could not open dump file %qs: %s", name, strerror (errno)); 89390075Sobrien else 894169689Skan dfi->state = 1; 89590075Sobrien free (name); 896169689Skan 89790075Sobrien if (flag_ptr) 898169689Skan *flag_ptr = dfi->flags; 899117395Skan 90090075Sobrien return stream; 90190075Sobrien} 90290075Sobrien 903169689Skan/* Returns nonzero if tree dump PHASE is enabled. If PHASE is 904169689Skan TDI_tree_all, return nonzero if any dump is enabled. */ 90590075Sobrien 90690075Sobrienint 907132718Skandump_enabled_p (enum tree_dump_index phase) 90890075Sobrien{ 909169689Skan if (phase == TDI_tree_all) 910169689Skan { 911169689Skan size_t i; 912169689Skan for (i = TDI_none + 1; i < (size_t) TDI_end; i++) 913169689Skan if (dump_files[i].state) 914169689Skan return 1; 915169689Skan for (i = 0; i < extra_dump_files_in_use; i++) 916169689Skan if (extra_dump_files[i].state) 917169689Skan return 1; 918169689Skan return 0; 919169689Skan } 920169689Skan else 921169689Skan { 922169689Skan struct dump_file_info *dfi = get_dump_file_info (phase); 923169689Skan return dfi->state; 924169689Skan } 92590075Sobrien} 92690075Sobrien 927169689Skan/* Returns nonzero if tree dump PHASE has been initialized. */ 928169689Skan 929169689Skanint 930169689Skandump_initialized_p (enum tree_dump_index phase) 931169689Skan{ 932169689Skan struct dump_file_info *dfi = get_dump_file_info (phase); 933169689Skan return dfi->state > 0; 934169689Skan} 935169689Skan 93690075Sobrien/* Returns the switch name of PHASE. */ 93790075Sobrien 93890075Sobrienconst char * 939132718Skandump_flag_name (enum tree_dump_index phase) 94090075Sobrien{ 941169689Skan struct dump_file_info *dfi = get_dump_file_info (phase); 942169689Skan return dfi->swtch; 94390075Sobrien} 94490075Sobrien 94590075Sobrien/* Finish a tree dump for PHASE. STREAM is the stream created by 94690075Sobrien dump_begin. */ 94790075Sobrien 94890075Sobrienvoid 949132718Skandump_end (enum tree_dump_index phase ATTRIBUTE_UNUSED, FILE *stream) 95090075Sobrien{ 95190075Sobrien fclose (stream); 95290075Sobrien} 95390075Sobrien 954169689Skan/* Enable all tree dumps. Return number of enabled tree dumps. */ 955169689Skan 956169689Skanstatic int 957169689Skandump_enable_all (int flags, int letter) 958169689Skan{ 959169689Skan int ir_type = (flags & (TDF_TREE | TDF_RTL | TDF_IPA)); 960169689Skan int n = 0; 961169689Skan size_t i; 962169689Skan 963169689Skan for (i = TDI_none + 1; i < (size_t) TDI_end; i++) 964169689Skan if ((dump_files[i].flags & ir_type) 965169689Skan && (letter == 0 || letter == dump_files[i].letter)) 966169689Skan { 967169689Skan dump_files[i].state = -1; 968169689Skan dump_files[i].flags |= flags; 969169689Skan n++; 970169689Skan } 971169689Skan 972169689Skan for (i = 0; i < extra_dump_files_in_use; i++) 973169689Skan if ((extra_dump_files[i].flags & ir_type) 974169689Skan && (letter == 0 || letter == extra_dump_files[i].letter)) 975169689Skan { 976169689Skan extra_dump_files[i].state = -1; 977169689Skan extra_dump_files[i].flags |= flags; 978169689Skan n++; 979169689Skan } 980169689Skan 981169689Skan return n; 982169689Skan} 983169689Skan 984117395Skan/* Parse ARG as a dump switch. Return nonzero if it is, and store the 98590075Sobrien relevant details in the dump_files array. */ 98690075Sobrien 987169689Skanstatic int 988169689Skandump_switch_p_1 (const char *arg, struct dump_file_info *dfi, bool doglob) 98990075Sobrien{ 99090075Sobrien const char *option_value; 991169689Skan const char *ptr; 992169689Skan int flags; 993169689Skan 994169689Skan if (doglob && !dfi->glob) 995169689Skan return 0; 996117395Skan 997169689Skan option_value = skip_leading_substring (arg, doglob ? dfi->glob : dfi->swtch); 998169689Skan if (!option_value) 999169689Skan return 0; 1000117395Skan 1001169689Skan ptr = option_value; 1002169689Skan flags = 0; 1003117395Skan 1004169689Skan while (*ptr) 1005169689Skan { 1006169689Skan const struct dump_option_value_info *option_ptr; 1007169689Skan const char *end_ptr; 1008169689Skan unsigned length; 1009117395Skan 1010169689Skan while (*ptr == '-') 1011169689Skan ptr++; 1012169689Skan end_ptr = strchr (ptr, '-'); 1013169689Skan if (!end_ptr) 1014169689Skan end_ptr = ptr + strlen (ptr); 1015169689Skan length = end_ptr - ptr; 1016169689Skan 1017169689Skan for (option_ptr = dump_options; option_ptr->name; option_ptr++) 1018169689Skan if (strlen (option_ptr->name) == length 1019169689Skan && !memcmp (option_ptr->name, ptr, length)) 1020169689Skan { 1021169689Skan flags |= option_ptr->value; 1022169689Skan goto found; 102390075Sobrien } 1024169689Skan warning (0, "ignoring unknown option %q.*s in %<-fdump-%s%>", 1025169689Skan length, ptr, dfi->swtch); 1026169689Skan found:; 1027169689Skan ptr = end_ptr; 1028169689Skan } 1029117395Skan 1030169689Skan dfi->state = -1; 1031169689Skan dfi->flags |= flags; 1032117395Skan 1033169689Skan /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the 1034169689Skan known dumps. */ 1035169689Skan if (dfi->suffix == NULL) 1036169689Skan dump_enable_all (dfi->flags, 0); 1037169689Skan 1038169689Skan return 1; 103990075Sobrien} 1040169689Skan 1041169689Skanint 1042169689Skandump_switch_p (const char *arg) 1043169689Skan{ 1044169689Skan size_t i; 1045169689Skan int any = 0; 1046169689Skan 1047169689Skan for (i = TDI_none + 1; i != TDI_end; i++) 1048169689Skan any |= dump_switch_p_1 (arg, &dump_files[i], false); 1049169689Skan 1050169689Skan /* Don't glob if we got a hit already */ 1051169689Skan if (!any) 1052169689Skan for (i = TDI_none + 1; i != TDI_end; i++) 1053169689Skan any |= dump_switch_p_1 (arg, &dump_files[i], true); 1054169689Skan 1055169689Skan for (i = 0; i < extra_dump_files_in_use; i++) 1056169689Skan any |= dump_switch_p_1 (arg, &extra_dump_files[i], false); 1057169689Skan 1058169689Skan if (!any) 1059169689Skan for (i = 0; i < extra_dump_files_in_use; i++) 1060169689Skan any |= dump_switch_p_1 (arg, &extra_dump_files[i], true); 1061169689Skan 1062169689Skan 1063169689Skan return any; 1064169689Skan} 1065169689Skan 1066169689Skan/* Dump FUNCTION_DECL FN as tree dump PHASE. */ 1067169689Skan 1068169689Skanvoid 1069169689Skandump_function (enum tree_dump_index phase, tree fn) 1070169689Skan{ 1071169689Skan FILE *stream; 1072169689Skan int flags; 1073169689Skan 1074169689Skan stream = dump_begin (phase, &flags); 1075169689Skan if (stream) 1076169689Skan { 1077169689Skan dump_function_to_file (fn, stream, flags); 1078169689Skan dump_end (phase, stream); 1079169689Skan } 1080169689Skan} 1081169689Skan 1082169689Skanbool 1083169689Skanenable_rtl_dump_file (int letter) 1084169689Skan{ 1085169689Skan if (letter == 'a') 1086169689Skan letter = 0; 1087169689Skan 1088169689Skan return dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS, letter) > 0; 1089169689Skan} 1090169689Skan 1091169689Skan 1092