1*e4b17023SJohn Marino /* Tree-dumping functionality for intermediate representation. 2*e4b17023SJohn Marino Copyright (C) 1999, 2000, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 3*e4b17023SJohn Marino 2010, 2011 Free Software Foundation, Inc. 4*e4b17023SJohn Marino Written by Mark Mitchell <mark@codesourcery.com> 5*e4b17023SJohn Marino 6*e4b17023SJohn Marino This file is part of GCC. 7*e4b17023SJohn Marino 8*e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify it under 9*e4b17023SJohn Marino the terms of the GNU General Public License as published by the Free 10*e4b17023SJohn Marino Software Foundation; either version 3, or (at your option) any later 11*e4b17023SJohn Marino version. 12*e4b17023SJohn Marino 13*e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, but WITHOUT ANY 14*e4b17023SJohn Marino WARRANTY; without even the implied warranty of MERCHANTABILITY or 15*e4b17023SJohn Marino FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16*e4b17023SJohn Marino for more details. 17*e4b17023SJohn Marino 18*e4b17023SJohn Marino You should have received a copy of the GNU General Public License 19*e4b17023SJohn Marino along with GCC; see the file COPYING3. If not see 20*e4b17023SJohn Marino <http://www.gnu.org/licenses/>. */ 21*e4b17023SJohn Marino 22*e4b17023SJohn Marino #include "config.h" 23*e4b17023SJohn Marino #include "system.h" 24*e4b17023SJohn Marino #include "coretypes.h" 25*e4b17023SJohn Marino #include "tm.h" 26*e4b17023SJohn Marino #include "tree.h" 27*e4b17023SJohn Marino #include "splay-tree.h" 28*e4b17023SJohn Marino #include "filenames.h" 29*e4b17023SJohn Marino #include "diagnostic-core.h" 30*e4b17023SJohn Marino #include "toplev.h" 31*e4b17023SJohn Marino #include "tree-dump.h" 32*e4b17023SJohn Marino #include "tree-pass.h" 33*e4b17023SJohn Marino #include "langhooks.h" 34*e4b17023SJohn Marino #include "tree-iterator.h" 35*e4b17023SJohn Marino 36*e4b17023SJohn Marino /* If non-NULL, return one past-the-end of the matching SUBPART of 37*e4b17023SJohn Marino the WHOLE string. */ 38*e4b17023SJohn Marino #define skip_leading_substring(whole, part) \ 39*e4b17023SJohn Marino (strncmp (whole, part, strlen (part)) ? NULL : whole + strlen (part)) 40*e4b17023SJohn Marino 41*e4b17023SJohn Marino static unsigned int queue (dump_info_p, const_tree, int); 42*e4b17023SJohn Marino static void dump_index (dump_info_p, unsigned int); 43*e4b17023SJohn Marino static void dequeue_and_dump (dump_info_p); 44*e4b17023SJohn Marino static void dump_new_line (dump_info_p); 45*e4b17023SJohn Marino static void dump_maybe_newline (dump_info_p); 46*e4b17023SJohn Marino 47*e4b17023SJohn Marino /* Add T to the end of the queue of nodes to dump. Returns the index 48*e4b17023SJohn Marino assigned to T. */ 49*e4b17023SJohn Marino 50*e4b17023SJohn Marino static unsigned int 51*e4b17023SJohn Marino queue (dump_info_p di, const_tree t, int flags) 52*e4b17023SJohn Marino { 53*e4b17023SJohn Marino dump_queue_p dq; 54*e4b17023SJohn Marino dump_node_info_p dni; 55*e4b17023SJohn Marino unsigned int index; 56*e4b17023SJohn Marino 57*e4b17023SJohn Marino /* Assign the next available index to T. */ 58*e4b17023SJohn Marino index = ++di->index; 59*e4b17023SJohn Marino 60*e4b17023SJohn Marino /* Obtain a new queue node. */ 61*e4b17023SJohn Marino if (di->free_list) 62*e4b17023SJohn Marino { 63*e4b17023SJohn Marino dq = di->free_list; 64*e4b17023SJohn Marino di->free_list = dq->next; 65*e4b17023SJohn Marino } 66*e4b17023SJohn Marino else 67*e4b17023SJohn Marino dq = XNEW (struct dump_queue); 68*e4b17023SJohn Marino 69*e4b17023SJohn Marino /* Create a new entry in the splay-tree. */ 70*e4b17023SJohn Marino dni = XNEW (struct dump_node_info); 71*e4b17023SJohn Marino dni->index = index; 72*e4b17023SJohn Marino dni->binfo_p = ((flags & DUMP_BINFO) != 0); 73*e4b17023SJohn Marino dq->node = splay_tree_insert (di->nodes, (splay_tree_key) t, 74*e4b17023SJohn Marino (splay_tree_value) dni); 75*e4b17023SJohn Marino 76*e4b17023SJohn Marino /* Add it to the end of the queue. */ 77*e4b17023SJohn Marino dq->next = 0; 78*e4b17023SJohn Marino if (!di->queue_end) 79*e4b17023SJohn Marino di->queue = dq; 80*e4b17023SJohn Marino else 81*e4b17023SJohn Marino di->queue_end->next = dq; 82*e4b17023SJohn Marino di->queue_end = dq; 83*e4b17023SJohn Marino 84*e4b17023SJohn Marino /* Return the index. */ 85*e4b17023SJohn Marino return index; 86*e4b17023SJohn Marino } 87*e4b17023SJohn Marino 88*e4b17023SJohn Marino static void 89*e4b17023SJohn Marino dump_index (dump_info_p di, unsigned int index) 90*e4b17023SJohn Marino { 91*e4b17023SJohn Marino fprintf (di->stream, "@%-6u ", index); 92*e4b17023SJohn Marino di->column += 8; 93*e4b17023SJohn Marino } 94*e4b17023SJohn Marino 95*e4b17023SJohn Marino /* If T has not already been output, queue it for subsequent output. 96*e4b17023SJohn Marino FIELD is a string to print before printing the index. Then, the 97*e4b17023SJohn Marino index of T is printed. */ 98*e4b17023SJohn Marino 99*e4b17023SJohn Marino void 100*e4b17023SJohn Marino queue_and_dump_index (dump_info_p di, const char *field, const_tree t, int flags) 101*e4b17023SJohn Marino { 102*e4b17023SJohn Marino unsigned int index; 103*e4b17023SJohn Marino splay_tree_node n; 104*e4b17023SJohn Marino 105*e4b17023SJohn Marino /* If there's no node, just return. This makes for fewer checks in 106*e4b17023SJohn Marino our callers. */ 107*e4b17023SJohn Marino if (!t) 108*e4b17023SJohn Marino return; 109*e4b17023SJohn Marino 110*e4b17023SJohn Marino /* See if we've already queued or dumped this node. */ 111*e4b17023SJohn Marino n = splay_tree_lookup (di->nodes, (splay_tree_key) t); 112*e4b17023SJohn Marino if (n) 113*e4b17023SJohn Marino index = ((dump_node_info_p) n->value)->index; 114*e4b17023SJohn Marino else 115*e4b17023SJohn Marino /* If we haven't, add it to the queue. */ 116*e4b17023SJohn Marino index = queue (di, t, flags); 117*e4b17023SJohn Marino 118*e4b17023SJohn Marino /* Print the index of the node. */ 119*e4b17023SJohn Marino dump_maybe_newline (di); 120*e4b17023SJohn Marino fprintf (di->stream, "%-4s: ", field); 121*e4b17023SJohn Marino di->column += 6; 122*e4b17023SJohn Marino dump_index (di, index); 123*e4b17023SJohn Marino } 124*e4b17023SJohn Marino 125*e4b17023SJohn Marino /* Dump the type of T. */ 126*e4b17023SJohn Marino 127*e4b17023SJohn Marino void 128*e4b17023SJohn Marino queue_and_dump_type (dump_info_p di, const_tree t) 129*e4b17023SJohn Marino { 130*e4b17023SJohn Marino queue_and_dump_index (di, "type", TREE_TYPE (t), DUMP_NONE); 131*e4b17023SJohn Marino } 132*e4b17023SJohn Marino 133*e4b17023SJohn Marino /* Dump column control */ 134*e4b17023SJohn Marino #define SOL_COLUMN 25 /* Start of line column. */ 135*e4b17023SJohn Marino #define EOL_COLUMN 55 /* End of line column. */ 136*e4b17023SJohn Marino #define COLUMN_ALIGNMENT 15 /* Alignment. */ 137*e4b17023SJohn Marino 138*e4b17023SJohn Marino /* Insert a new line in the dump output, and indent to an appropriate 139*e4b17023SJohn Marino place to start printing more fields. */ 140*e4b17023SJohn Marino 141*e4b17023SJohn Marino static void 142*e4b17023SJohn Marino dump_new_line (dump_info_p di) 143*e4b17023SJohn Marino { 144*e4b17023SJohn Marino fprintf (di->stream, "\n%*s", SOL_COLUMN, ""); 145*e4b17023SJohn Marino di->column = SOL_COLUMN; 146*e4b17023SJohn Marino } 147*e4b17023SJohn Marino 148*e4b17023SJohn Marino /* If necessary, insert a new line. */ 149*e4b17023SJohn Marino 150*e4b17023SJohn Marino static void 151*e4b17023SJohn Marino dump_maybe_newline (dump_info_p di) 152*e4b17023SJohn Marino { 153*e4b17023SJohn Marino int extra; 154*e4b17023SJohn Marino 155*e4b17023SJohn Marino /* See if we need a new line. */ 156*e4b17023SJohn Marino if (di->column > EOL_COLUMN) 157*e4b17023SJohn Marino dump_new_line (di); 158*e4b17023SJohn Marino /* See if we need any padding. */ 159*e4b17023SJohn Marino else if ((extra = (di->column - SOL_COLUMN) % COLUMN_ALIGNMENT) != 0) 160*e4b17023SJohn Marino { 161*e4b17023SJohn Marino fprintf (di->stream, "%*s", COLUMN_ALIGNMENT - extra, ""); 162*e4b17023SJohn Marino di->column += COLUMN_ALIGNMENT - extra; 163*e4b17023SJohn Marino } 164*e4b17023SJohn Marino } 165*e4b17023SJohn Marino 166*e4b17023SJohn Marino /* Dump pointer PTR using FIELD to identify it. */ 167*e4b17023SJohn Marino 168*e4b17023SJohn Marino void 169*e4b17023SJohn Marino dump_pointer (dump_info_p di, const char *field, void *ptr) 170*e4b17023SJohn Marino { 171*e4b17023SJohn Marino dump_maybe_newline (di); 172*e4b17023SJohn Marino fprintf (di->stream, "%-4s: %-8lx ", field, (unsigned long) ptr); 173*e4b17023SJohn Marino di->column += 15; 174*e4b17023SJohn Marino } 175*e4b17023SJohn Marino 176*e4b17023SJohn Marino /* Dump integer I using FIELD to identify it. */ 177*e4b17023SJohn Marino 178*e4b17023SJohn Marino void 179*e4b17023SJohn Marino dump_int (dump_info_p di, const char *field, int i) 180*e4b17023SJohn Marino { 181*e4b17023SJohn Marino dump_maybe_newline (di); 182*e4b17023SJohn Marino fprintf (di->stream, "%-4s: %-7d ", field, i); 183*e4b17023SJohn Marino di->column += 14; 184*e4b17023SJohn Marino } 185*e4b17023SJohn Marino 186*e4b17023SJohn Marino /* Dump the floating point value R, using FIELD to identify it. */ 187*e4b17023SJohn Marino 188*e4b17023SJohn Marino static void 189*e4b17023SJohn Marino dump_real (dump_info_p di, const char *field, const REAL_VALUE_TYPE *r) 190*e4b17023SJohn Marino { 191*e4b17023SJohn Marino char buf[32]; 192*e4b17023SJohn Marino real_to_decimal (buf, r, sizeof (buf), 0, true); 193*e4b17023SJohn Marino dump_maybe_newline (di); 194*e4b17023SJohn Marino fprintf (di->stream, "%-4s: %s ", field, buf); 195*e4b17023SJohn Marino di->column += strlen (buf) + 7; 196*e4b17023SJohn Marino } 197*e4b17023SJohn Marino 198*e4b17023SJohn Marino /* Dump the fixed-point value F, using FIELD to identify it. */ 199*e4b17023SJohn Marino 200*e4b17023SJohn Marino static void 201*e4b17023SJohn Marino dump_fixed (dump_info_p di, const char *field, const FIXED_VALUE_TYPE *f) 202*e4b17023SJohn Marino { 203*e4b17023SJohn Marino char buf[32]; 204*e4b17023SJohn Marino fixed_to_decimal (buf, f, sizeof (buf)); 205*e4b17023SJohn Marino dump_maybe_newline (di); 206*e4b17023SJohn Marino fprintf (di->stream, "%-4s: %s ", field, buf); 207*e4b17023SJohn Marino di->column += strlen (buf) + 7; 208*e4b17023SJohn Marino } 209*e4b17023SJohn Marino 210*e4b17023SJohn Marino 211*e4b17023SJohn Marino /* Dump the string S. */ 212*e4b17023SJohn Marino 213*e4b17023SJohn Marino void 214*e4b17023SJohn Marino dump_string (dump_info_p di, const char *string) 215*e4b17023SJohn Marino { 216*e4b17023SJohn Marino dump_maybe_newline (di); 217*e4b17023SJohn Marino fprintf (di->stream, "%-13s ", string); 218*e4b17023SJohn Marino if (strlen (string) > 13) 219*e4b17023SJohn Marino di->column += strlen (string) + 1; 220*e4b17023SJohn Marino else 221*e4b17023SJohn Marino di->column += 14; 222*e4b17023SJohn Marino } 223*e4b17023SJohn Marino 224*e4b17023SJohn Marino /* Dump the string field S. */ 225*e4b17023SJohn Marino 226*e4b17023SJohn Marino void 227*e4b17023SJohn Marino dump_string_field (dump_info_p di, const char *field, const char *string) 228*e4b17023SJohn Marino { 229*e4b17023SJohn Marino dump_maybe_newline (di); 230*e4b17023SJohn Marino fprintf (di->stream, "%-4s: %-7s ", field, string); 231*e4b17023SJohn Marino if (strlen (string) > 7) 232*e4b17023SJohn Marino di->column += 6 + strlen (string) + 1; 233*e4b17023SJohn Marino else 234*e4b17023SJohn Marino di->column += 14; 235*e4b17023SJohn Marino } 236*e4b17023SJohn Marino 237*e4b17023SJohn Marino /* Dump the next node in the queue. */ 238*e4b17023SJohn Marino 239*e4b17023SJohn Marino static void 240*e4b17023SJohn Marino dequeue_and_dump (dump_info_p di) 241*e4b17023SJohn Marino { 242*e4b17023SJohn Marino dump_queue_p dq; 243*e4b17023SJohn Marino splay_tree_node stn; 244*e4b17023SJohn Marino dump_node_info_p dni; 245*e4b17023SJohn Marino tree t; 246*e4b17023SJohn Marino unsigned int index; 247*e4b17023SJohn Marino enum tree_code code; 248*e4b17023SJohn Marino enum tree_code_class code_class; 249*e4b17023SJohn Marino const char* code_name; 250*e4b17023SJohn Marino 251*e4b17023SJohn Marino /* Get the next node from the queue. */ 252*e4b17023SJohn Marino dq = di->queue; 253*e4b17023SJohn Marino stn = dq->node; 254*e4b17023SJohn Marino t = (tree) stn->key; 255*e4b17023SJohn Marino dni = (dump_node_info_p) stn->value; 256*e4b17023SJohn Marino index = dni->index; 257*e4b17023SJohn Marino 258*e4b17023SJohn Marino /* Remove the node from the queue, and put it on the free list. */ 259*e4b17023SJohn Marino di->queue = dq->next; 260*e4b17023SJohn Marino if (!di->queue) 261*e4b17023SJohn Marino di->queue_end = 0; 262*e4b17023SJohn Marino dq->next = di->free_list; 263*e4b17023SJohn Marino di->free_list = dq; 264*e4b17023SJohn Marino 265*e4b17023SJohn Marino /* Print the node index. */ 266*e4b17023SJohn Marino dump_index (di, index); 267*e4b17023SJohn Marino /* And the type of node this is. */ 268*e4b17023SJohn Marino if (dni->binfo_p) 269*e4b17023SJohn Marino code_name = "binfo"; 270*e4b17023SJohn Marino else 271*e4b17023SJohn Marino code_name = tree_code_name[(int) TREE_CODE (t)]; 272*e4b17023SJohn Marino fprintf (di->stream, "%-16s ", code_name); 273*e4b17023SJohn Marino di->column = 25; 274*e4b17023SJohn Marino 275*e4b17023SJohn Marino /* Figure out what kind of node this is. */ 276*e4b17023SJohn Marino code = TREE_CODE (t); 277*e4b17023SJohn Marino code_class = TREE_CODE_CLASS (code); 278*e4b17023SJohn Marino 279*e4b17023SJohn Marino /* Although BINFOs are TREE_VECs, we dump them specially so as to be 280*e4b17023SJohn Marino more informative. */ 281*e4b17023SJohn Marino if (dni->binfo_p) 282*e4b17023SJohn Marino { 283*e4b17023SJohn Marino unsigned ix; 284*e4b17023SJohn Marino tree base; 285*e4b17023SJohn Marino VEC(tree,gc) *accesses = BINFO_BASE_ACCESSES (t); 286*e4b17023SJohn Marino 287*e4b17023SJohn Marino dump_child ("type", BINFO_TYPE (t)); 288*e4b17023SJohn Marino 289*e4b17023SJohn Marino if (BINFO_VIRTUAL_P (t)) 290*e4b17023SJohn Marino dump_string_field (di, "spec", "virt"); 291*e4b17023SJohn Marino 292*e4b17023SJohn Marino dump_int (di, "bases", BINFO_N_BASE_BINFOS (t)); 293*e4b17023SJohn Marino for (ix = 0; BINFO_BASE_ITERATE (t, ix, base); ix++) 294*e4b17023SJohn Marino { 295*e4b17023SJohn Marino tree access = (accesses ? VEC_index (tree, accesses, ix) 296*e4b17023SJohn Marino : access_public_node); 297*e4b17023SJohn Marino const char *string = NULL; 298*e4b17023SJohn Marino 299*e4b17023SJohn Marino if (access == access_public_node) 300*e4b17023SJohn Marino string = "pub"; 301*e4b17023SJohn Marino else if (access == access_protected_node) 302*e4b17023SJohn Marino string = "prot"; 303*e4b17023SJohn Marino else if (access == access_private_node) 304*e4b17023SJohn Marino string = "priv"; 305*e4b17023SJohn Marino else 306*e4b17023SJohn Marino gcc_unreachable (); 307*e4b17023SJohn Marino 308*e4b17023SJohn Marino dump_string_field (di, "accs", string); 309*e4b17023SJohn Marino queue_and_dump_index (di, "binf", base, DUMP_BINFO); 310*e4b17023SJohn Marino } 311*e4b17023SJohn Marino 312*e4b17023SJohn Marino goto done; 313*e4b17023SJohn Marino } 314*e4b17023SJohn Marino 315*e4b17023SJohn Marino /* We can knock off a bunch of expression nodes in exactly the same 316*e4b17023SJohn Marino way. */ 317*e4b17023SJohn Marino if (IS_EXPR_CODE_CLASS (code_class)) 318*e4b17023SJohn Marino { 319*e4b17023SJohn Marino /* If we're dumping children, dump them now. */ 320*e4b17023SJohn Marino queue_and_dump_type (di, t); 321*e4b17023SJohn Marino 322*e4b17023SJohn Marino switch (code_class) 323*e4b17023SJohn Marino { 324*e4b17023SJohn Marino case tcc_unary: 325*e4b17023SJohn Marino dump_child ("op 0", TREE_OPERAND (t, 0)); 326*e4b17023SJohn Marino break; 327*e4b17023SJohn Marino 328*e4b17023SJohn Marino case tcc_binary: 329*e4b17023SJohn Marino case tcc_comparison: 330*e4b17023SJohn Marino dump_child ("op 0", TREE_OPERAND (t, 0)); 331*e4b17023SJohn Marino dump_child ("op 1", TREE_OPERAND (t, 1)); 332*e4b17023SJohn Marino break; 333*e4b17023SJohn Marino 334*e4b17023SJohn Marino case tcc_expression: 335*e4b17023SJohn Marino case tcc_reference: 336*e4b17023SJohn Marino case tcc_statement: 337*e4b17023SJohn Marino case tcc_vl_exp: 338*e4b17023SJohn Marino /* These nodes are handled explicitly below. */ 339*e4b17023SJohn Marino break; 340*e4b17023SJohn Marino 341*e4b17023SJohn Marino default: 342*e4b17023SJohn Marino gcc_unreachable (); 343*e4b17023SJohn Marino } 344*e4b17023SJohn Marino } 345*e4b17023SJohn Marino else if (DECL_P (t)) 346*e4b17023SJohn Marino { 347*e4b17023SJohn Marino expanded_location xloc; 348*e4b17023SJohn Marino /* All declarations have names. */ 349*e4b17023SJohn Marino if (DECL_NAME (t)) 350*e4b17023SJohn Marino dump_child ("name", DECL_NAME (t)); 351*e4b17023SJohn Marino if (DECL_ASSEMBLER_NAME_SET_P (t) 352*e4b17023SJohn Marino && DECL_ASSEMBLER_NAME (t) != DECL_NAME (t)) 353*e4b17023SJohn Marino dump_child ("mngl", DECL_ASSEMBLER_NAME (t)); 354*e4b17023SJohn Marino if (DECL_ABSTRACT_ORIGIN (t)) 355*e4b17023SJohn Marino dump_child ("orig", DECL_ABSTRACT_ORIGIN (t)); 356*e4b17023SJohn Marino /* And types. */ 357*e4b17023SJohn Marino queue_and_dump_type (di, t); 358*e4b17023SJohn Marino dump_child ("scpe", DECL_CONTEXT (t)); 359*e4b17023SJohn Marino /* And a source position. */ 360*e4b17023SJohn Marino xloc = expand_location (DECL_SOURCE_LOCATION (t)); 361*e4b17023SJohn Marino if (xloc.file) 362*e4b17023SJohn Marino { 363*e4b17023SJohn Marino const char *filename = lbasename (xloc.file); 364*e4b17023SJohn Marino 365*e4b17023SJohn Marino dump_maybe_newline (di); 366*e4b17023SJohn Marino fprintf (di->stream, "srcp: %s:%-6d ", filename, 367*e4b17023SJohn Marino xloc.line); 368*e4b17023SJohn Marino di->column += 6 + strlen (filename) + 8; 369*e4b17023SJohn Marino } 370*e4b17023SJohn Marino /* And any declaration can be compiler-generated. */ 371*e4b17023SJohn Marino if (CODE_CONTAINS_STRUCT (TREE_CODE (t), TS_DECL_COMMON) 372*e4b17023SJohn Marino && DECL_ARTIFICIAL (t)) 373*e4b17023SJohn Marino dump_string_field (di, "note", "artificial"); 374*e4b17023SJohn Marino if (DECL_CHAIN (t) && !dump_flag (di, TDF_SLIM, NULL)) 375*e4b17023SJohn Marino dump_child ("chain", DECL_CHAIN (t)); 376*e4b17023SJohn Marino } 377*e4b17023SJohn Marino else if (code_class == tcc_type) 378*e4b17023SJohn Marino { 379*e4b17023SJohn Marino /* All types have qualifiers. */ 380*e4b17023SJohn Marino int quals = lang_hooks.tree_dump.type_quals (t); 381*e4b17023SJohn Marino 382*e4b17023SJohn Marino if (quals != TYPE_UNQUALIFIED) 383*e4b17023SJohn Marino { 384*e4b17023SJohn Marino fprintf (di->stream, "qual: %c%c%c ", 385*e4b17023SJohn Marino (quals & TYPE_QUAL_CONST) ? 'c' : ' ', 386*e4b17023SJohn Marino (quals & TYPE_QUAL_VOLATILE) ? 'v' : ' ', 387*e4b17023SJohn Marino (quals & TYPE_QUAL_RESTRICT) ? 'r' : ' '); 388*e4b17023SJohn Marino di->column += 14; 389*e4b17023SJohn Marino } 390*e4b17023SJohn Marino 391*e4b17023SJohn Marino /* All types have associated declarations. */ 392*e4b17023SJohn Marino dump_child ("name", TYPE_NAME (t)); 393*e4b17023SJohn Marino 394*e4b17023SJohn Marino /* All types have a main variant. */ 395*e4b17023SJohn Marino if (TYPE_MAIN_VARIANT (t) != t) 396*e4b17023SJohn Marino dump_child ("unql", TYPE_MAIN_VARIANT (t)); 397*e4b17023SJohn Marino 398*e4b17023SJohn Marino /* And sizes. */ 399*e4b17023SJohn Marino dump_child ("size", TYPE_SIZE (t)); 400*e4b17023SJohn Marino 401*e4b17023SJohn Marino /* All types have alignments. */ 402*e4b17023SJohn Marino dump_int (di, "algn", TYPE_ALIGN (t)); 403*e4b17023SJohn Marino } 404*e4b17023SJohn Marino else if (code_class == tcc_constant) 405*e4b17023SJohn Marino /* All constants can have types. */ 406*e4b17023SJohn Marino queue_and_dump_type (di, t); 407*e4b17023SJohn Marino 408*e4b17023SJohn Marino /* Give the language-specific code a chance to print something. If 409*e4b17023SJohn Marino it's completely taken care of things, don't bother printing 410*e4b17023SJohn Marino anything more ourselves. */ 411*e4b17023SJohn Marino if (lang_hooks.tree_dump.dump_tree (di, t)) 412*e4b17023SJohn Marino goto done; 413*e4b17023SJohn Marino 414*e4b17023SJohn Marino /* Now handle the various kinds of nodes. */ 415*e4b17023SJohn Marino switch (code) 416*e4b17023SJohn Marino { 417*e4b17023SJohn Marino int i; 418*e4b17023SJohn Marino 419*e4b17023SJohn Marino case IDENTIFIER_NODE: 420*e4b17023SJohn Marino dump_string_field (di, "strg", IDENTIFIER_POINTER (t)); 421*e4b17023SJohn Marino dump_int (di, "lngt", IDENTIFIER_LENGTH (t)); 422*e4b17023SJohn Marino break; 423*e4b17023SJohn Marino 424*e4b17023SJohn Marino case TREE_LIST: 425*e4b17023SJohn Marino dump_child ("purp", TREE_PURPOSE (t)); 426*e4b17023SJohn Marino dump_child ("valu", TREE_VALUE (t)); 427*e4b17023SJohn Marino dump_child ("chan", TREE_CHAIN (t)); 428*e4b17023SJohn Marino break; 429*e4b17023SJohn Marino 430*e4b17023SJohn Marino case STATEMENT_LIST: 431*e4b17023SJohn Marino { 432*e4b17023SJohn Marino tree_stmt_iterator it; 433*e4b17023SJohn Marino for (i = 0, it = tsi_start (t); !tsi_end_p (it); tsi_next (&it), i++) 434*e4b17023SJohn Marino { 435*e4b17023SJohn Marino char buffer[32]; 436*e4b17023SJohn Marino sprintf (buffer, "%u", i); 437*e4b17023SJohn Marino dump_child (buffer, tsi_stmt (it)); 438*e4b17023SJohn Marino } 439*e4b17023SJohn Marino } 440*e4b17023SJohn Marino break; 441*e4b17023SJohn Marino 442*e4b17023SJohn Marino case TREE_VEC: 443*e4b17023SJohn Marino dump_int (di, "lngt", TREE_VEC_LENGTH (t)); 444*e4b17023SJohn Marino for (i = 0; i < TREE_VEC_LENGTH (t); ++i) 445*e4b17023SJohn Marino { 446*e4b17023SJohn Marino char buffer[32]; 447*e4b17023SJohn Marino sprintf (buffer, "%u", i); 448*e4b17023SJohn Marino dump_child (buffer, TREE_VEC_ELT (t, i)); 449*e4b17023SJohn Marino } 450*e4b17023SJohn Marino break; 451*e4b17023SJohn Marino 452*e4b17023SJohn Marino case INTEGER_TYPE: 453*e4b17023SJohn Marino case ENUMERAL_TYPE: 454*e4b17023SJohn Marino dump_int (di, "prec", TYPE_PRECISION (t)); 455*e4b17023SJohn Marino dump_string_field (di, "sign", TYPE_UNSIGNED (t) ? "unsigned": "signed"); 456*e4b17023SJohn Marino dump_child ("min", TYPE_MIN_VALUE (t)); 457*e4b17023SJohn Marino dump_child ("max", TYPE_MAX_VALUE (t)); 458*e4b17023SJohn Marino 459*e4b17023SJohn Marino if (code == ENUMERAL_TYPE) 460*e4b17023SJohn Marino dump_child ("csts", TYPE_VALUES (t)); 461*e4b17023SJohn Marino break; 462*e4b17023SJohn Marino 463*e4b17023SJohn Marino case REAL_TYPE: 464*e4b17023SJohn Marino dump_int (di, "prec", TYPE_PRECISION (t)); 465*e4b17023SJohn Marino break; 466*e4b17023SJohn Marino 467*e4b17023SJohn Marino case FIXED_POINT_TYPE: 468*e4b17023SJohn Marino dump_int (di, "prec", TYPE_PRECISION (t)); 469*e4b17023SJohn Marino dump_string_field (di, "sign", TYPE_UNSIGNED (t) ? "unsigned": "signed"); 470*e4b17023SJohn Marino dump_string_field (di, "saturating", 471*e4b17023SJohn Marino TYPE_SATURATING (t) ? "saturating": "non-saturating"); 472*e4b17023SJohn Marino break; 473*e4b17023SJohn Marino 474*e4b17023SJohn Marino case POINTER_TYPE: 475*e4b17023SJohn Marino dump_child ("ptd", TREE_TYPE (t)); 476*e4b17023SJohn Marino break; 477*e4b17023SJohn Marino 478*e4b17023SJohn Marino case REFERENCE_TYPE: 479*e4b17023SJohn Marino dump_child ("refd", TREE_TYPE (t)); 480*e4b17023SJohn Marino break; 481*e4b17023SJohn Marino 482*e4b17023SJohn Marino case METHOD_TYPE: 483*e4b17023SJohn Marino dump_child ("clas", TYPE_METHOD_BASETYPE (t)); 484*e4b17023SJohn Marino /* Fall through. */ 485*e4b17023SJohn Marino 486*e4b17023SJohn Marino case FUNCTION_TYPE: 487*e4b17023SJohn Marino dump_child ("retn", TREE_TYPE (t)); 488*e4b17023SJohn Marino dump_child ("prms", TYPE_ARG_TYPES (t)); 489*e4b17023SJohn Marino break; 490*e4b17023SJohn Marino 491*e4b17023SJohn Marino case ARRAY_TYPE: 492*e4b17023SJohn Marino dump_child ("elts", TREE_TYPE (t)); 493*e4b17023SJohn Marino dump_child ("domn", TYPE_DOMAIN (t)); 494*e4b17023SJohn Marino break; 495*e4b17023SJohn Marino 496*e4b17023SJohn Marino case RECORD_TYPE: 497*e4b17023SJohn Marino case UNION_TYPE: 498*e4b17023SJohn Marino if (TREE_CODE (t) == RECORD_TYPE) 499*e4b17023SJohn Marino dump_string_field (di, "tag", "struct"); 500*e4b17023SJohn Marino else 501*e4b17023SJohn Marino dump_string_field (di, "tag", "union"); 502*e4b17023SJohn Marino 503*e4b17023SJohn Marino dump_child ("flds", TYPE_FIELDS (t)); 504*e4b17023SJohn Marino dump_child ("fncs", TYPE_METHODS (t)); 505*e4b17023SJohn Marino queue_and_dump_index (di, "binf", TYPE_BINFO (t), 506*e4b17023SJohn Marino DUMP_BINFO); 507*e4b17023SJohn Marino break; 508*e4b17023SJohn Marino 509*e4b17023SJohn Marino case CONST_DECL: 510*e4b17023SJohn Marino dump_child ("cnst", DECL_INITIAL (t)); 511*e4b17023SJohn Marino break; 512*e4b17023SJohn Marino 513*e4b17023SJohn Marino case DEBUG_EXPR_DECL: 514*e4b17023SJohn Marino dump_int (di, "-uid", DEBUG_TEMP_UID (t)); 515*e4b17023SJohn Marino /* Fall through. */ 516*e4b17023SJohn Marino 517*e4b17023SJohn Marino case VAR_DECL: 518*e4b17023SJohn Marino case PARM_DECL: 519*e4b17023SJohn Marino case FIELD_DECL: 520*e4b17023SJohn Marino case RESULT_DECL: 521*e4b17023SJohn Marino if (TREE_CODE (t) == PARM_DECL) 522*e4b17023SJohn Marino dump_child ("argt", DECL_ARG_TYPE (t)); 523*e4b17023SJohn Marino else 524*e4b17023SJohn Marino dump_child ("init", DECL_INITIAL (t)); 525*e4b17023SJohn Marino dump_child ("size", DECL_SIZE (t)); 526*e4b17023SJohn Marino dump_int (di, "algn", DECL_ALIGN (t)); 527*e4b17023SJohn Marino 528*e4b17023SJohn Marino if (TREE_CODE (t) == FIELD_DECL) 529*e4b17023SJohn Marino { 530*e4b17023SJohn Marino if (DECL_FIELD_OFFSET (t)) 531*e4b17023SJohn Marino dump_child ("bpos", bit_position (t)); 532*e4b17023SJohn Marino } 533*e4b17023SJohn Marino else if (TREE_CODE (t) == VAR_DECL 534*e4b17023SJohn Marino || TREE_CODE (t) == PARM_DECL) 535*e4b17023SJohn Marino { 536*e4b17023SJohn Marino dump_int (di, "used", TREE_USED (t)); 537*e4b17023SJohn Marino if (DECL_REGISTER (t)) 538*e4b17023SJohn Marino dump_string_field (di, "spec", "register"); 539*e4b17023SJohn Marino } 540*e4b17023SJohn Marino break; 541*e4b17023SJohn Marino 542*e4b17023SJohn Marino case FUNCTION_DECL: 543*e4b17023SJohn Marino dump_child ("args", DECL_ARGUMENTS (t)); 544*e4b17023SJohn Marino if (DECL_EXTERNAL (t)) 545*e4b17023SJohn Marino dump_string_field (di, "body", "undefined"); 546*e4b17023SJohn Marino if (TREE_PUBLIC (t)) 547*e4b17023SJohn Marino dump_string_field (di, "link", "extern"); 548*e4b17023SJohn Marino else 549*e4b17023SJohn Marino dump_string_field (di, "link", "static"); 550*e4b17023SJohn Marino if (DECL_SAVED_TREE (t) && !dump_flag (di, TDF_SLIM, t)) 551*e4b17023SJohn Marino dump_child ("body", DECL_SAVED_TREE (t)); 552*e4b17023SJohn Marino break; 553*e4b17023SJohn Marino 554*e4b17023SJohn Marino case INTEGER_CST: 555*e4b17023SJohn Marino if (TREE_INT_CST_HIGH (t)) 556*e4b17023SJohn Marino dump_int (di, "high", TREE_INT_CST_HIGH (t)); 557*e4b17023SJohn Marino dump_int (di, "low", TREE_INT_CST_LOW (t)); 558*e4b17023SJohn Marino break; 559*e4b17023SJohn Marino 560*e4b17023SJohn Marino case STRING_CST: 561*e4b17023SJohn Marino fprintf (di->stream, "strg: %-7s ", TREE_STRING_POINTER (t)); 562*e4b17023SJohn Marino dump_int (di, "lngt", TREE_STRING_LENGTH (t)); 563*e4b17023SJohn Marino break; 564*e4b17023SJohn Marino 565*e4b17023SJohn Marino case REAL_CST: 566*e4b17023SJohn Marino dump_real (di, "valu", TREE_REAL_CST_PTR (t)); 567*e4b17023SJohn Marino break; 568*e4b17023SJohn Marino 569*e4b17023SJohn Marino case FIXED_CST: 570*e4b17023SJohn Marino dump_fixed (di, "valu", TREE_FIXED_CST_PTR (t)); 571*e4b17023SJohn Marino break; 572*e4b17023SJohn Marino 573*e4b17023SJohn Marino case TRUTH_NOT_EXPR: 574*e4b17023SJohn Marino case ADDR_EXPR: 575*e4b17023SJohn Marino case INDIRECT_REF: 576*e4b17023SJohn Marino case CLEANUP_POINT_EXPR: 577*e4b17023SJohn Marino case SAVE_EXPR: 578*e4b17023SJohn Marino case REALPART_EXPR: 579*e4b17023SJohn Marino case IMAGPART_EXPR: 580*e4b17023SJohn Marino /* These nodes are unary, but do not have code class `1'. */ 581*e4b17023SJohn Marino dump_child ("op 0", TREE_OPERAND (t, 0)); 582*e4b17023SJohn Marino break; 583*e4b17023SJohn Marino 584*e4b17023SJohn Marino case TRUTH_ANDIF_EXPR: 585*e4b17023SJohn Marino case TRUTH_ORIF_EXPR: 586*e4b17023SJohn Marino case INIT_EXPR: 587*e4b17023SJohn Marino case MODIFY_EXPR: 588*e4b17023SJohn Marino case COMPOUND_EXPR: 589*e4b17023SJohn Marino case PREDECREMENT_EXPR: 590*e4b17023SJohn Marino case PREINCREMENT_EXPR: 591*e4b17023SJohn Marino case POSTDECREMENT_EXPR: 592*e4b17023SJohn Marino case POSTINCREMENT_EXPR: 593*e4b17023SJohn Marino /* These nodes are binary, but do not have code class `2'. */ 594*e4b17023SJohn Marino dump_child ("op 0", TREE_OPERAND (t, 0)); 595*e4b17023SJohn Marino dump_child ("op 1", TREE_OPERAND (t, 1)); 596*e4b17023SJohn Marino break; 597*e4b17023SJohn Marino 598*e4b17023SJohn Marino case COMPONENT_REF: 599*e4b17023SJohn Marino dump_child ("op 0", TREE_OPERAND (t, 0)); 600*e4b17023SJohn Marino dump_child ("op 1", TREE_OPERAND (t, 1)); 601*e4b17023SJohn Marino dump_child ("op 2", TREE_OPERAND (t, 2)); 602*e4b17023SJohn Marino break; 603*e4b17023SJohn Marino 604*e4b17023SJohn Marino case ARRAY_REF: 605*e4b17023SJohn Marino case ARRAY_RANGE_REF: 606*e4b17023SJohn Marino dump_child ("op 0", TREE_OPERAND (t, 0)); 607*e4b17023SJohn Marino dump_child ("op 1", TREE_OPERAND (t, 1)); 608*e4b17023SJohn Marino dump_child ("op 2", TREE_OPERAND (t, 2)); 609*e4b17023SJohn Marino dump_child ("op 3", TREE_OPERAND (t, 3)); 610*e4b17023SJohn Marino break; 611*e4b17023SJohn Marino 612*e4b17023SJohn Marino case COND_EXPR: 613*e4b17023SJohn Marino dump_child ("op 0", TREE_OPERAND (t, 0)); 614*e4b17023SJohn Marino dump_child ("op 1", TREE_OPERAND (t, 1)); 615*e4b17023SJohn Marino dump_child ("op 2", TREE_OPERAND (t, 2)); 616*e4b17023SJohn Marino break; 617*e4b17023SJohn Marino 618*e4b17023SJohn Marino case TRY_FINALLY_EXPR: 619*e4b17023SJohn Marino dump_child ("op 0", TREE_OPERAND (t, 0)); 620*e4b17023SJohn Marino dump_child ("op 1", TREE_OPERAND (t, 1)); 621*e4b17023SJohn Marino break; 622*e4b17023SJohn Marino 623*e4b17023SJohn Marino case CALL_EXPR: 624*e4b17023SJohn Marino { 625*e4b17023SJohn Marino int i = 0; 626*e4b17023SJohn Marino tree arg; 627*e4b17023SJohn Marino call_expr_arg_iterator iter; 628*e4b17023SJohn Marino dump_child ("fn", CALL_EXPR_FN (t)); 629*e4b17023SJohn Marino FOR_EACH_CALL_EXPR_ARG (arg, iter, t) 630*e4b17023SJohn Marino { 631*e4b17023SJohn Marino char buffer[32]; 632*e4b17023SJohn Marino sprintf (buffer, "%u", i); 633*e4b17023SJohn Marino dump_child (buffer, arg); 634*e4b17023SJohn Marino i++; 635*e4b17023SJohn Marino } 636*e4b17023SJohn Marino } 637*e4b17023SJohn Marino break; 638*e4b17023SJohn Marino 639*e4b17023SJohn Marino case CONSTRUCTOR: 640*e4b17023SJohn Marino { 641*e4b17023SJohn Marino unsigned HOST_WIDE_INT cnt; 642*e4b17023SJohn Marino tree index, value; 643*e4b17023SJohn Marino dump_int (di, "lngt", VEC_length (constructor_elt, 644*e4b17023SJohn Marino CONSTRUCTOR_ELTS (t))); 645*e4b17023SJohn Marino FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (t), cnt, index, value) 646*e4b17023SJohn Marino { 647*e4b17023SJohn Marino dump_child ("idx", index); 648*e4b17023SJohn Marino dump_child ("val", value); 649*e4b17023SJohn Marino } 650*e4b17023SJohn Marino } 651*e4b17023SJohn Marino break; 652*e4b17023SJohn Marino 653*e4b17023SJohn Marino case BIND_EXPR: 654*e4b17023SJohn Marino dump_child ("vars", TREE_OPERAND (t, 0)); 655*e4b17023SJohn Marino dump_child ("body", TREE_OPERAND (t, 1)); 656*e4b17023SJohn Marino break; 657*e4b17023SJohn Marino 658*e4b17023SJohn Marino case LOOP_EXPR: 659*e4b17023SJohn Marino dump_child ("body", TREE_OPERAND (t, 0)); 660*e4b17023SJohn Marino break; 661*e4b17023SJohn Marino 662*e4b17023SJohn Marino case EXIT_EXPR: 663*e4b17023SJohn Marino dump_child ("cond", TREE_OPERAND (t, 0)); 664*e4b17023SJohn Marino break; 665*e4b17023SJohn Marino 666*e4b17023SJohn Marino case RETURN_EXPR: 667*e4b17023SJohn Marino dump_child ("expr", TREE_OPERAND (t, 0)); 668*e4b17023SJohn Marino break; 669*e4b17023SJohn Marino 670*e4b17023SJohn Marino case TARGET_EXPR: 671*e4b17023SJohn Marino dump_child ("decl", TREE_OPERAND (t, 0)); 672*e4b17023SJohn Marino dump_child ("init", TREE_OPERAND (t, 1)); 673*e4b17023SJohn Marino dump_child ("clnp", TREE_OPERAND (t, 2)); 674*e4b17023SJohn Marino /* There really are two possible places the initializer can be. 675*e4b17023SJohn Marino After RTL expansion, the second operand is moved to the 676*e4b17023SJohn Marino position of the fourth operand, and the second operand 677*e4b17023SJohn Marino becomes NULL. */ 678*e4b17023SJohn Marino dump_child ("init", TREE_OPERAND (t, 3)); 679*e4b17023SJohn Marino break; 680*e4b17023SJohn Marino 681*e4b17023SJohn Marino case CASE_LABEL_EXPR: 682*e4b17023SJohn Marino dump_child ("name", CASE_LABEL (t)); 683*e4b17023SJohn Marino if (CASE_LOW (t)) 684*e4b17023SJohn Marino { 685*e4b17023SJohn Marino dump_child ("low ", CASE_LOW (t)); 686*e4b17023SJohn Marino if (CASE_HIGH (t)) 687*e4b17023SJohn Marino dump_child ("high", CASE_HIGH (t)); 688*e4b17023SJohn Marino } 689*e4b17023SJohn Marino break; 690*e4b17023SJohn Marino case LABEL_EXPR: 691*e4b17023SJohn Marino dump_child ("name", TREE_OPERAND (t,0)); 692*e4b17023SJohn Marino break; 693*e4b17023SJohn Marino case GOTO_EXPR: 694*e4b17023SJohn Marino dump_child ("labl", TREE_OPERAND (t, 0)); 695*e4b17023SJohn Marino break; 696*e4b17023SJohn Marino case SWITCH_EXPR: 697*e4b17023SJohn Marino dump_child ("cond", TREE_OPERAND (t, 0)); 698*e4b17023SJohn Marino dump_child ("body", TREE_OPERAND (t, 1)); 699*e4b17023SJohn Marino if (TREE_OPERAND (t, 2)) 700*e4b17023SJohn Marino { 701*e4b17023SJohn Marino dump_child ("labl", TREE_OPERAND (t,2)); 702*e4b17023SJohn Marino } 703*e4b17023SJohn Marino break; 704*e4b17023SJohn Marino case OMP_CLAUSE: 705*e4b17023SJohn Marino { 706*e4b17023SJohn Marino int i; 707*e4b17023SJohn Marino fprintf (di->stream, "%s\n", omp_clause_code_name[OMP_CLAUSE_CODE (t)]); 708*e4b17023SJohn Marino for (i = 0; i < omp_clause_num_ops[OMP_CLAUSE_CODE (t)]; i++) 709*e4b17023SJohn Marino dump_child ("op: ", OMP_CLAUSE_OPERAND (t, i)); 710*e4b17023SJohn Marino } 711*e4b17023SJohn Marino break; 712*e4b17023SJohn Marino default: 713*e4b17023SJohn Marino /* There are no additional fields to print. */ 714*e4b17023SJohn Marino break; 715*e4b17023SJohn Marino } 716*e4b17023SJohn Marino 717*e4b17023SJohn Marino done: 718*e4b17023SJohn Marino if (dump_flag (di, TDF_ADDRESS, NULL)) 719*e4b17023SJohn Marino dump_pointer (di, "addr", (void *)t); 720*e4b17023SJohn Marino 721*e4b17023SJohn Marino /* Terminate the line. */ 722*e4b17023SJohn Marino fprintf (di->stream, "\n"); 723*e4b17023SJohn Marino } 724*e4b17023SJohn Marino 725*e4b17023SJohn Marino /* Return nonzero if FLAG has been specified for the dump, and NODE 726*e4b17023SJohn Marino is not the root node of the dump. */ 727*e4b17023SJohn Marino 728*e4b17023SJohn Marino int dump_flag (dump_info_p di, int flag, const_tree node) 729*e4b17023SJohn Marino { 730*e4b17023SJohn Marino return (di->flags & flag) && (node != di->node); 731*e4b17023SJohn Marino } 732*e4b17023SJohn Marino 733*e4b17023SJohn Marino /* Dump T, and all its children, on STREAM. */ 734*e4b17023SJohn Marino 735*e4b17023SJohn Marino void 736*e4b17023SJohn Marino dump_node (const_tree t, int flags, FILE *stream) 737*e4b17023SJohn Marino { 738*e4b17023SJohn Marino struct dump_info di; 739*e4b17023SJohn Marino dump_queue_p dq; 740*e4b17023SJohn Marino dump_queue_p next_dq; 741*e4b17023SJohn Marino 742*e4b17023SJohn Marino /* Initialize the dump-information structure. */ 743*e4b17023SJohn Marino di.stream = stream; 744*e4b17023SJohn Marino di.index = 0; 745*e4b17023SJohn Marino di.column = 0; 746*e4b17023SJohn Marino di.queue = 0; 747*e4b17023SJohn Marino di.queue_end = 0; 748*e4b17023SJohn Marino di.free_list = 0; 749*e4b17023SJohn Marino di.flags = flags; 750*e4b17023SJohn Marino di.node = t; 751*e4b17023SJohn Marino di.nodes = splay_tree_new (splay_tree_compare_pointers, 0, 752*e4b17023SJohn Marino (splay_tree_delete_value_fn) &free); 753*e4b17023SJohn Marino 754*e4b17023SJohn Marino /* Queue up the first node. */ 755*e4b17023SJohn Marino queue (&di, t, DUMP_NONE); 756*e4b17023SJohn Marino 757*e4b17023SJohn Marino /* Until the queue is empty, keep dumping nodes. */ 758*e4b17023SJohn Marino while (di.queue) 759*e4b17023SJohn Marino dequeue_and_dump (&di); 760*e4b17023SJohn Marino 761*e4b17023SJohn Marino /* Now, clean up. */ 762*e4b17023SJohn Marino for (dq = di.free_list; dq; dq = next_dq) 763*e4b17023SJohn Marino { 764*e4b17023SJohn Marino next_dq = dq->next; 765*e4b17023SJohn Marino free (dq); 766*e4b17023SJohn Marino } 767*e4b17023SJohn Marino splay_tree_delete (di.nodes); 768*e4b17023SJohn Marino } 769*e4b17023SJohn Marino 770*e4b17023SJohn Marino 771*e4b17023SJohn Marino /* Table of tree dump switches. This must be consistent with the 772*e4b17023SJohn Marino tree_dump_index enumeration in tree-pass.h. */ 773*e4b17023SJohn Marino static struct dump_file_info dump_files[TDI_end] = 774*e4b17023SJohn Marino { 775*e4b17023SJohn Marino {NULL, NULL, NULL, 0, 0, 0}, 776*e4b17023SJohn Marino {".cgraph", "ipa-cgraph", NULL, TDF_IPA, 0, 0}, 777*e4b17023SJohn Marino {".tu", "translation-unit", NULL, TDF_TREE, 0, 1}, 778*e4b17023SJohn Marino {".class", "class-hierarchy", NULL, TDF_TREE, 0, 2}, 779*e4b17023SJohn Marino {".original", "tree-original", NULL, TDF_TREE, 0, 3}, 780*e4b17023SJohn Marino {".gimple", "tree-gimple", NULL, TDF_TREE, 0, 4}, 781*e4b17023SJohn Marino {".nested", "tree-nested", NULL, TDF_TREE, 0, 5}, 782*e4b17023SJohn Marino {".vcg", "tree-vcg", NULL, TDF_TREE, 0, 6}, 783*e4b17023SJohn Marino {".ads", "ada-spec", NULL, 0, 0, 7}, 784*e4b17023SJohn Marino #define FIRST_AUTO_NUMBERED_DUMP 8 785*e4b17023SJohn Marino 786*e4b17023SJohn Marino {NULL, "tree-all", NULL, TDF_TREE, 0, 0}, 787*e4b17023SJohn Marino {NULL, "rtl-all", NULL, TDF_RTL, 0, 0}, 788*e4b17023SJohn Marino {NULL, "ipa-all", NULL, TDF_IPA, 0, 0}, 789*e4b17023SJohn Marino }; 790*e4b17023SJohn Marino 791*e4b17023SJohn Marino /* Dynamically registered tree dump files and switches. */ 792*e4b17023SJohn Marino static struct dump_file_info *extra_dump_files; 793*e4b17023SJohn Marino static size_t extra_dump_files_in_use; 794*e4b17023SJohn Marino static size_t extra_dump_files_alloced; 795*e4b17023SJohn Marino 796*e4b17023SJohn Marino /* Define a name->number mapping for a dump flag value. */ 797*e4b17023SJohn Marino struct dump_option_value_info 798*e4b17023SJohn Marino { 799*e4b17023SJohn Marino const char *const name; /* the name of the value */ 800*e4b17023SJohn Marino const int value; /* the value of the name */ 801*e4b17023SJohn Marino }; 802*e4b17023SJohn Marino 803*e4b17023SJohn Marino /* Table of dump options. This must be consistent with the TDF_* flags 804*e4b17023SJohn Marino in tree.h */ 805*e4b17023SJohn Marino static const struct dump_option_value_info dump_options[] = 806*e4b17023SJohn Marino { 807*e4b17023SJohn Marino {"address", TDF_ADDRESS}, 808*e4b17023SJohn Marino {"asmname", TDF_ASMNAME}, 809*e4b17023SJohn Marino {"slim", TDF_SLIM}, 810*e4b17023SJohn Marino {"raw", TDF_RAW}, 811*e4b17023SJohn Marino {"graph", TDF_GRAPH}, 812*e4b17023SJohn Marino {"details", TDF_DETAILS}, 813*e4b17023SJohn Marino {"cselib", TDF_CSELIB}, 814*e4b17023SJohn Marino {"stats", TDF_STATS}, 815*e4b17023SJohn Marino {"blocks", TDF_BLOCKS}, 816*e4b17023SJohn Marino {"vops", TDF_VOPS}, 817*e4b17023SJohn Marino {"lineno", TDF_LINENO}, 818*e4b17023SJohn Marino {"uid", TDF_UID}, 819*e4b17023SJohn Marino {"stmtaddr", TDF_STMTADDR}, 820*e4b17023SJohn Marino {"memsyms", TDF_MEMSYMS}, 821*e4b17023SJohn Marino {"verbose", TDF_VERBOSE}, 822*e4b17023SJohn Marino {"eh", TDF_EH}, 823*e4b17023SJohn Marino {"alias", TDF_ALIAS}, 824*e4b17023SJohn Marino {"nouid", TDF_NOUID}, 825*e4b17023SJohn Marino {"enumerate_locals", TDF_ENUMERATE_LOCALS}, 826*e4b17023SJohn Marino {"scev", TDF_SCEV}, 827*e4b17023SJohn Marino {"all", ~(TDF_RAW | TDF_SLIM | TDF_LINENO | TDF_TREE | TDF_RTL | TDF_IPA 828*e4b17023SJohn Marino | TDF_STMTADDR | TDF_GRAPH | TDF_DIAGNOSTIC | TDF_VERBOSE 829*e4b17023SJohn Marino | TDF_RHS_ONLY | TDF_NOUID | TDF_ENUMERATE_LOCALS | TDF_SCEV)}, 830*e4b17023SJohn Marino {NULL, 0} 831*e4b17023SJohn Marino }; 832*e4b17023SJohn Marino 833*e4b17023SJohn Marino unsigned int 834*e4b17023SJohn Marino dump_register (const char *suffix, const char *swtch, const char *glob, 835*e4b17023SJohn Marino int flags) 836*e4b17023SJohn Marino { 837*e4b17023SJohn Marino static int next_dump = FIRST_AUTO_NUMBERED_DUMP; 838*e4b17023SJohn Marino int num = next_dump++; 839*e4b17023SJohn Marino 840*e4b17023SJohn Marino size_t count = extra_dump_files_in_use++; 841*e4b17023SJohn Marino 842*e4b17023SJohn Marino if (count >= extra_dump_files_alloced) 843*e4b17023SJohn Marino { 844*e4b17023SJohn Marino if (extra_dump_files_alloced == 0) 845*e4b17023SJohn Marino extra_dump_files_alloced = 32; 846*e4b17023SJohn Marino else 847*e4b17023SJohn Marino extra_dump_files_alloced *= 2; 848*e4b17023SJohn Marino extra_dump_files = XRESIZEVEC (struct dump_file_info, 849*e4b17023SJohn Marino extra_dump_files, 850*e4b17023SJohn Marino extra_dump_files_alloced); 851*e4b17023SJohn Marino } 852*e4b17023SJohn Marino 853*e4b17023SJohn Marino memset (&extra_dump_files[count], 0, sizeof (struct dump_file_info)); 854*e4b17023SJohn Marino extra_dump_files[count].suffix = suffix; 855*e4b17023SJohn Marino extra_dump_files[count].swtch = swtch; 856*e4b17023SJohn Marino extra_dump_files[count].glob = glob; 857*e4b17023SJohn Marino extra_dump_files[count].flags = flags; 858*e4b17023SJohn Marino extra_dump_files[count].num = num; 859*e4b17023SJohn Marino 860*e4b17023SJohn Marino return count + TDI_end; 861*e4b17023SJohn Marino } 862*e4b17023SJohn Marino 863*e4b17023SJohn Marino 864*e4b17023SJohn Marino /* Return the dump_file_info for the given phase. */ 865*e4b17023SJohn Marino 866*e4b17023SJohn Marino struct dump_file_info * 867*e4b17023SJohn Marino get_dump_file_info (int phase) 868*e4b17023SJohn Marino { 869*e4b17023SJohn Marino if (phase < TDI_end) 870*e4b17023SJohn Marino return &dump_files[phase]; 871*e4b17023SJohn Marino else if ((size_t) (phase - TDI_end) >= extra_dump_files_in_use) 872*e4b17023SJohn Marino return NULL; 873*e4b17023SJohn Marino else 874*e4b17023SJohn Marino return extra_dump_files + (phase - TDI_end); 875*e4b17023SJohn Marino } 876*e4b17023SJohn Marino 877*e4b17023SJohn Marino 878*e4b17023SJohn Marino /* Return the name of the dump file for the given phase. 879*e4b17023SJohn Marino If the dump is not enabled, returns NULL. */ 880*e4b17023SJohn Marino 881*e4b17023SJohn Marino char * 882*e4b17023SJohn Marino get_dump_file_name (int phase) 883*e4b17023SJohn Marino { 884*e4b17023SJohn Marino char dump_id[10]; 885*e4b17023SJohn Marino struct dump_file_info *dfi; 886*e4b17023SJohn Marino 887*e4b17023SJohn Marino if (phase == TDI_none) 888*e4b17023SJohn Marino return NULL; 889*e4b17023SJohn Marino 890*e4b17023SJohn Marino dfi = get_dump_file_info (phase); 891*e4b17023SJohn Marino if (dfi->state == 0) 892*e4b17023SJohn Marino return NULL; 893*e4b17023SJohn Marino 894*e4b17023SJohn Marino if (dfi->num < 0) 895*e4b17023SJohn Marino dump_id[0] = '\0'; 896*e4b17023SJohn Marino else 897*e4b17023SJohn Marino { 898*e4b17023SJohn Marino char suffix; 899*e4b17023SJohn Marino if (dfi->flags & TDF_TREE) 900*e4b17023SJohn Marino suffix = 't'; 901*e4b17023SJohn Marino else if (dfi->flags & TDF_IPA) 902*e4b17023SJohn Marino suffix = 'i'; 903*e4b17023SJohn Marino else 904*e4b17023SJohn Marino suffix = 'r'; 905*e4b17023SJohn Marino 906*e4b17023SJohn Marino if (snprintf (dump_id, sizeof (dump_id), ".%03d%c", dfi->num, suffix) < 0) 907*e4b17023SJohn Marino dump_id[0] = '\0'; 908*e4b17023SJohn Marino } 909*e4b17023SJohn Marino 910*e4b17023SJohn Marino return concat (dump_base_name, dump_id, dfi->suffix, NULL); 911*e4b17023SJohn Marino } 912*e4b17023SJohn Marino 913*e4b17023SJohn Marino /* Begin a tree dump for PHASE. Stores any user supplied flag in 914*e4b17023SJohn Marino *FLAG_PTR and returns a stream to write to. If the dump is not 915*e4b17023SJohn Marino enabled, returns NULL. 916*e4b17023SJohn Marino Multiple calls will reopen and append to the dump file. */ 917*e4b17023SJohn Marino 918*e4b17023SJohn Marino FILE * 919*e4b17023SJohn Marino dump_begin (int phase, int *flag_ptr) 920*e4b17023SJohn Marino { 921*e4b17023SJohn Marino char *name; 922*e4b17023SJohn Marino struct dump_file_info *dfi; 923*e4b17023SJohn Marino FILE *stream; 924*e4b17023SJohn Marino 925*e4b17023SJohn Marino if (phase == TDI_none || !dump_enabled_p (phase)) 926*e4b17023SJohn Marino return NULL; 927*e4b17023SJohn Marino 928*e4b17023SJohn Marino name = get_dump_file_name (phase); 929*e4b17023SJohn Marino dfi = get_dump_file_info (phase); 930*e4b17023SJohn Marino stream = fopen (name, dfi->state < 0 ? "w" : "a"); 931*e4b17023SJohn Marino if (!stream) 932*e4b17023SJohn Marino error ("could not open dump file %qs: %m", name); 933*e4b17023SJohn Marino else 934*e4b17023SJohn Marino dfi->state = 1; 935*e4b17023SJohn Marino free (name); 936*e4b17023SJohn Marino 937*e4b17023SJohn Marino if (flag_ptr) 938*e4b17023SJohn Marino *flag_ptr = dfi->flags; 939*e4b17023SJohn Marino 940*e4b17023SJohn Marino return stream; 941*e4b17023SJohn Marino } 942*e4b17023SJohn Marino 943*e4b17023SJohn Marino /* Returns nonzero if tree dump PHASE is enabled. If PHASE is 944*e4b17023SJohn Marino TDI_tree_all, return nonzero if any dump is enabled. */ 945*e4b17023SJohn Marino 946*e4b17023SJohn Marino int 947*e4b17023SJohn Marino dump_enabled_p (int phase) 948*e4b17023SJohn Marino { 949*e4b17023SJohn Marino if (phase == TDI_tree_all) 950*e4b17023SJohn Marino { 951*e4b17023SJohn Marino size_t i; 952*e4b17023SJohn Marino for (i = TDI_none + 1; i < (size_t) TDI_end; i++) 953*e4b17023SJohn Marino if (dump_files[i].state) 954*e4b17023SJohn Marino return 1; 955*e4b17023SJohn Marino for (i = 0; i < extra_dump_files_in_use; i++) 956*e4b17023SJohn Marino if (extra_dump_files[i].state) 957*e4b17023SJohn Marino return 1; 958*e4b17023SJohn Marino return 0; 959*e4b17023SJohn Marino } 960*e4b17023SJohn Marino else 961*e4b17023SJohn Marino { 962*e4b17023SJohn Marino struct dump_file_info *dfi = get_dump_file_info (phase); 963*e4b17023SJohn Marino return dfi->state; 964*e4b17023SJohn Marino } 965*e4b17023SJohn Marino } 966*e4b17023SJohn Marino 967*e4b17023SJohn Marino /* Returns nonzero if tree dump PHASE has been initialized. */ 968*e4b17023SJohn Marino 969*e4b17023SJohn Marino int 970*e4b17023SJohn Marino dump_initialized_p (int phase) 971*e4b17023SJohn Marino { 972*e4b17023SJohn Marino struct dump_file_info *dfi = get_dump_file_info (phase); 973*e4b17023SJohn Marino return dfi->state > 0; 974*e4b17023SJohn Marino } 975*e4b17023SJohn Marino 976*e4b17023SJohn Marino /* Returns the switch name of PHASE. */ 977*e4b17023SJohn Marino 978*e4b17023SJohn Marino const char * 979*e4b17023SJohn Marino dump_flag_name (int phase) 980*e4b17023SJohn Marino { 981*e4b17023SJohn Marino struct dump_file_info *dfi = get_dump_file_info (phase); 982*e4b17023SJohn Marino return dfi->swtch; 983*e4b17023SJohn Marino } 984*e4b17023SJohn Marino 985*e4b17023SJohn Marino /* Finish a tree dump for PHASE. STREAM is the stream created by 986*e4b17023SJohn Marino dump_begin. */ 987*e4b17023SJohn Marino 988*e4b17023SJohn Marino void 989*e4b17023SJohn Marino dump_end (int phase ATTRIBUTE_UNUSED, FILE *stream) 990*e4b17023SJohn Marino { 991*e4b17023SJohn Marino fclose (stream); 992*e4b17023SJohn Marino } 993*e4b17023SJohn Marino 994*e4b17023SJohn Marino /* Enable all tree dumps. Return number of enabled tree dumps. */ 995*e4b17023SJohn Marino 996*e4b17023SJohn Marino static int 997*e4b17023SJohn Marino dump_enable_all (int flags) 998*e4b17023SJohn Marino { 999*e4b17023SJohn Marino int ir_dump_type = (flags & (TDF_TREE | TDF_RTL | TDF_IPA)); 1000*e4b17023SJohn Marino int n = 0; 1001*e4b17023SJohn Marino size_t i; 1002*e4b17023SJohn Marino 1003*e4b17023SJohn Marino for (i = TDI_none + 1; i < (size_t) TDI_end; i++) 1004*e4b17023SJohn Marino if ((dump_files[i].flags & ir_dump_type)) 1005*e4b17023SJohn Marino { 1006*e4b17023SJohn Marino dump_files[i].state = -1; 1007*e4b17023SJohn Marino dump_files[i].flags |= flags; 1008*e4b17023SJohn Marino n++; 1009*e4b17023SJohn Marino } 1010*e4b17023SJohn Marino 1011*e4b17023SJohn Marino for (i = 0; i < extra_dump_files_in_use; i++) 1012*e4b17023SJohn Marino if ((extra_dump_files[i].flags & ir_dump_type)) 1013*e4b17023SJohn Marino { 1014*e4b17023SJohn Marino extra_dump_files[i].state = -1; 1015*e4b17023SJohn Marino extra_dump_files[i].flags |= flags; 1016*e4b17023SJohn Marino n++; 1017*e4b17023SJohn Marino } 1018*e4b17023SJohn Marino 1019*e4b17023SJohn Marino return n; 1020*e4b17023SJohn Marino } 1021*e4b17023SJohn Marino 1022*e4b17023SJohn Marino /* Parse ARG as a dump switch. Return nonzero if it is, and store the 1023*e4b17023SJohn Marino relevant details in the dump_files array. */ 1024*e4b17023SJohn Marino 1025*e4b17023SJohn Marino static int 1026*e4b17023SJohn Marino dump_switch_p_1 (const char *arg, struct dump_file_info *dfi, bool doglob) 1027*e4b17023SJohn Marino { 1028*e4b17023SJohn Marino const char *option_value; 1029*e4b17023SJohn Marino const char *ptr; 1030*e4b17023SJohn Marino int flags; 1031*e4b17023SJohn Marino 1032*e4b17023SJohn Marino if (doglob && !dfi->glob) 1033*e4b17023SJohn Marino return 0; 1034*e4b17023SJohn Marino 1035*e4b17023SJohn Marino option_value = skip_leading_substring (arg, doglob ? dfi->glob : dfi->swtch); 1036*e4b17023SJohn Marino if (!option_value) 1037*e4b17023SJohn Marino return 0; 1038*e4b17023SJohn Marino 1039*e4b17023SJohn Marino if (*option_value && *option_value != '-') 1040*e4b17023SJohn Marino return 0; 1041*e4b17023SJohn Marino 1042*e4b17023SJohn Marino ptr = option_value; 1043*e4b17023SJohn Marino flags = 0; 1044*e4b17023SJohn Marino 1045*e4b17023SJohn Marino while (*ptr) 1046*e4b17023SJohn Marino { 1047*e4b17023SJohn Marino const struct dump_option_value_info *option_ptr; 1048*e4b17023SJohn Marino const char *end_ptr; 1049*e4b17023SJohn Marino unsigned length; 1050*e4b17023SJohn Marino 1051*e4b17023SJohn Marino while (*ptr == '-') 1052*e4b17023SJohn Marino ptr++; 1053*e4b17023SJohn Marino end_ptr = strchr (ptr, '-'); 1054*e4b17023SJohn Marino if (!end_ptr) 1055*e4b17023SJohn Marino end_ptr = ptr + strlen (ptr); 1056*e4b17023SJohn Marino length = end_ptr - ptr; 1057*e4b17023SJohn Marino 1058*e4b17023SJohn Marino for (option_ptr = dump_options; option_ptr->name; option_ptr++) 1059*e4b17023SJohn Marino if (strlen (option_ptr->name) == length 1060*e4b17023SJohn Marino && !memcmp (option_ptr->name, ptr, length)) 1061*e4b17023SJohn Marino { 1062*e4b17023SJohn Marino flags |= option_ptr->value; 1063*e4b17023SJohn Marino goto found; 1064*e4b17023SJohn Marino } 1065*e4b17023SJohn Marino warning (0, "ignoring unknown option %q.*s in %<-fdump-%s%>", 1066*e4b17023SJohn Marino length, ptr, dfi->swtch); 1067*e4b17023SJohn Marino found:; 1068*e4b17023SJohn Marino ptr = end_ptr; 1069*e4b17023SJohn Marino } 1070*e4b17023SJohn Marino 1071*e4b17023SJohn Marino dfi->state = -1; 1072*e4b17023SJohn Marino dfi->flags |= flags; 1073*e4b17023SJohn Marino 1074*e4b17023SJohn Marino /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the 1075*e4b17023SJohn Marino known dumps. */ 1076*e4b17023SJohn Marino if (dfi->suffix == NULL) 1077*e4b17023SJohn Marino dump_enable_all (dfi->flags); 1078*e4b17023SJohn Marino 1079*e4b17023SJohn Marino return 1; 1080*e4b17023SJohn Marino } 1081*e4b17023SJohn Marino 1082*e4b17023SJohn Marino int 1083*e4b17023SJohn Marino dump_switch_p (const char *arg) 1084*e4b17023SJohn Marino { 1085*e4b17023SJohn Marino size_t i; 1086*e4b17023SJohn Marino int any = 0; 1087*e4b17023SJohn Marino 1088*e4b17023SJohn Marino for (i = TDI_none + 1; i != TDI_end; i++) 1089*e4b17023SJohn Marino any |= dump_switch_p_1 (arg, &dump_files[i], false); 1090*e4b17023SJohn Marino 1091*e4b17023SJohn Marino /* Don't glob if we got a hit already */ 1092*e4b17023SJohn Marino if (!any) 1093*e4b17023SJohn Marino for (i = TDI_none + 1; i != TDI_end; i++) 1094*e4b17023SJohn Marino any |= dump_switch_p_1 (arg, &dump_files[i], true); 1095*e4b17023SJohn Marino 1096*e4b17023SJohn Marino for (i = 0; i < extra_dump_files_in_use; i++) 1097*e4b17023SJohn Marino any |= dump_switch_p_1 (arg, &extra_dump_files[i], false); 1098*e4b17023SJohn Marino 1099*e4b17023SJohn Marino if (!any) 1100*e4b17023SJohn Marino for (i = 0; i < extra_dump_files_in_use; i++) 1101*e4b17023SJohn Marino any |= dump_switch_p_1 (arg, &extra_dump_files[i], true); 1102*e4b17023SJohn Marino 1103*e4b17023SJohn Marino 1104*e4b17023SJohn Marino return any; 1105*e4b17023SJohn Marino } 1106*e4b17023SJohn Marino 1107*e4b17023SJohn Marino /* Dump FUNCTION_DECL FN as tree dump PHASE. */ 1108*e4b17023SJohn Marino 1109*e4b17023SJohn Marino void 1110*e4b17023SJohn Marino dump_function (int phase, tree fn) 1111*e4b17023SJohn Marino { 1112*e4b17023SJohn Marino FILE *stream; 1113*e4b17023SJohn Marino int flags; 1114*e4b17023SJohn Marino 1115*e4b17023SJohn Marino stream = dump_begin (phase, &flags); 1116*e4b17023SJohn Marino if (stream) 1117*e4b17023SJohn Marino { 1118*e4b17023SJohn Marino dump_function_to_file (fn, stream, flags); 1119*e4b17023SJohn Marino dump_end (phase, stream); 1120*e4b17023SJohn Marino } 1121*e4b17023SJohn Marino } 1122*e4b17023SJohn Marino 1123*e4b17023SJohn Marino bool 1124*e4b17023SJohn Marino enable_rtl_dump_file (void) 1125*e4b17023SJohn Marino { 1126*e4b17023SJohn Marino return dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS) > 0; 1127*e4b17023SJohn Marino } 1128