Home | History | Annotate | Line # | Download | only in gcc
      1  1.1  mrg /* Code for GIMPLE range trace and debugging related routines.
      2  1.1  mrg    Copyright (C) 2019-2022 Free Software Foundation, Inc.
      3  1.1  mrg    Contributed by Andrew MacLeod <amacleod (at) redhat.com>
      4  1.1  mrg    and Aldy Hernandez <aldyh (at) redhat.com>.
      5  1.1  mrg 
      6  1.1  mrg This file is part of GCC.
      7  1.1  mrg 
      8  1.1  mrg GCC is free software; you can redistribute it and/or modify
      9  1.1  mrg it under the terms of the GNU General Public License as published by
     10  1.1  mrg the Free Software Foundation; either version 3, or (at your option)
     11  1.1  mrg any later version.
     12  1.1  mrg 
     13  1.1  mrg GCC is distributed in the hope that it will be useful,
     14  1.1  mrg but WITHOUT ANY WARRANTY; without even the implied warranty of
     15  1.1  mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16  1.1  mrg GNU General Public License for more details.
     17  1.1  mrg 
     18  1.1  mrg You should have received a copy of the GNU General Public License
     19  1.1  mrg along with GCC; see the file COPYING3.  If not see
     20  1.1  mrg <http://www.gnu.org/licenses/>.  */
     21  1.1  mrg 
     22  1.1  mrg #include "config.h"
     23  1.1  mrg #include "system.h"
     24  1.1  mrg #include "coretypes.h"
     25  1.1  mrg #include "backend.h"
     26  1.1  mrg #include "tree.h"
     27  1.1  mrg #include "gimple.h"
     28  1.1  mrg #include "ssa.h"
     29  1.1  mrg #include "gimple-pretty-print.h"
     30  1.1  mrg #include "gimple-iterator.h"
     31  1.1  mrg #include "tree-cfg.h"
     32  1.1  mrg #include "fold-const.h"
     33  1.1  mrg #include "tree-cfg.h"
     34  1.1  mrg #include "cfgloop.h"
     35  1.1  mrg #include "tree-scalar-evolution.h"
     36  1.1  mrg #include "gimple-range.h"
     37  1.1  mrg 
     38  1.1  mrg 
     39  1.1  mrg // Breakpoint to trap at a specific index.  From GDB, this provides a simple
     40  1.1  mrg // place to put a breakpoint to stop at a given trace line.
     41  1.1  mrg // ie.  b range_tracer::breakpoint if index == 45678
     42  1.1  mrg 
     43  1.1  mrg void
     44  1.1  mrg range_tracer::breakpoint (unsigned index ATTRIBUTE_UNUSED)
     45  1.1  mrg {
     46  1.1  mrg }
     47  1.1  mrg 
     48  1.1  mrg // Construct a range_tracer with component NAME.
     49  1.1  mrg 
     50  1.1  mrg range_tracer::range_tracer (const char *name)
     51  1.1  mrg {
     52  1.1  mrg   gcc_checking_assert (strlen(name) < name_len -1);
     53  1.1  mrg   strcpy (component, name);
     54  1.1  mrg   indent = 0;
     55  1.1  mrg   tracing = false;
     56  1.1  mrg }
     57  1.1  mrg 
     58  1.1  mrg // This routine does the initial line spacing/indenting for a trace.
     59  1.1  mrg // If BLANKS is false, then IDX is printed, otherwise spaces.
     60  1.1  mrg 
     61  1.1  mrg void
     62  1.1  mrg range_tracer::print_prefix (unsigned idx, bool blanks)
     63  1.1  mrg {
     64  1.1  mrg   // Print counter index as well as INDENT spaces.
     65  1.1  mrg   if (!blanks)
     66  1.1  mrg     fprintf (dump_file, "%-7u ", idx);
     67  1.1  mrg   else
     68  1.1  mrg     fprintf (dump_file, "        ");
     69  1.1  mrg   fprintf (dump_file, "%s ", component);
     70  1.1  mrg   unsigned x;
     71  1.1  mrg   for (x = 0; x< indent; x++)
     72  1.1  mrg     fputc (' ', dump_file);
     73  1.1  mrg 
     74  1.1  mrg }
     75  1.1  mrg // If dumping, return the next call index and print the prefix for the next
     76  1.1  mrg // output line.  If not, retrurn 0.
     77  1.1  mrg // Counter is static to monotonically increase across the compilation unit.
     78  1.1  mrg 
     79  1.1  mrg unsigned
     80  1.1  mrg range_tracer::do_header (const char *str)
     81  1.1  mrg {
     82  1.1  mrg   static unsigned trace_count = 0;
     83  1.1  mrg 
     84  1.1  mrg   unsigned idx = ++trace_count;
     85  1.1  mrg   print_prefix (idx, false);
     86  1.1  mrg   fprintf (dump_file, "%s", str);
     87  1.1  mrg   indent += bump;
     88  1.1  mrg   breakpoint (idx);
     89  1.1  mrg   return idx;
     90  1.1  mrg }
     91  1.1  mrg 
     92  1.1  mrg // Print a line without starting or ending a trace.
     93  1.1  mrg 
     94  1.1  mrg void
     95  1.1  mrg range_tracer::print (unsigned counter, const char *str)
     96  1.1  mrg {
     97  1.1  mrg   print_prefix (counter, true);
     98  1.1  mrg   fprintf (dump_file, "%s", str);
     99  1.1  mrg }
    100  1.1  mrg 
    101  1.1  mrg // End a trace and print the CALLER, NAME, and RESULT and range R,
    102  1.1  mrg 
    103  1.1  mrg void
    104  1.1  mrg range_tracer::trailer (unsigned counter, const char *caller, bool result,
    105  1.1  mrg 		      tree name, const irange &r)
    106  1.1  mrg {
    107  1.1  mrg   gcc_checking_assert (tracing && counter != 0);
    108  1.1  mrg 
    109  1.1  mrg   indent -= bump;
    110  1.1  mrg   print_prefix (counter, true);
    111  1.1  mrg   fputs(result ? "TRUE : " : "FALSE : ", dump_file);
    112  1.1  mrg   fprintf (dump_file, "(%u) ", counter);
    113  1.1  mrg   fputs (caller, dump_file);
    114  1.1  mrg   fputs (" (",dump_file);
    115  1.1  mrg   if (name)
    116  1.1  mrg     print_generic_expr (dump_file, name, TDF_SLIM);
    117  1.1  mrg   fputs (") ",dump_file);
    118  1.1  mrg   if (result)
    119  1.1  mrg     {
    120  1.1  mrg       r.dump (dump_file);
    121  1.1  mrg       fputc('\n', dump_file);
    122  1.1  mrg     }
    123  1.1  mrg   else
    124  1.1  mrg     fputc('\n', dump_file);
    125  1.1  mrg }
    126  1.1  mrg 
    127  1.1  mrg // =========================================
    128  1.1  mrg // Debugging helpers.
    129  1.1  mrg // =========================================
    130  1.1  mrg 
    131  1.1  mrg // Query all statements in the IL to precalculate computable ranges in RANGER.
    132  1.1  mrg 
    133  1.1  mrg DEBUG_FUNCTION void
    134  1.1  mrg debug_seed_ranger (gimple_ranger &ranger)
    135  1.1  mrg {
    136  1.1  mrg   // Recalculate SCEV to make sure the dump lists everything.
    137  1.1  mrg   if (scev_initialized_p ())
    138  1.1  mrg     {
    139  1.1  mrg       scev_finalize ();
    140  1.1  mrg       scev_initialize ();
    141  1.1  mrg     }
    142  1.1  mrg 
    143  1.1  mrg   basic_block bb;
    144  1.1  mrg   int_range_max r;
    145  1.1  mrg   gimple_stmt_iterator gsi;
    146  1.1  mrg   FOR_EACH_BB_FN (bb, cfun)
    147  1.1  mrg     for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
    148  1.1  mrg       {
    149  1.1  mrg 	gimple *stmt = gsi_stmt (gsi);
    150  1.1  mrg 
    151  1.1  mrg 	if (is_gimple_debug (stmt))
    152  1.1  mrg 	  continue;
    153  1.1  mrg 
    154  1.1  mrg 	ranger.range_of_stmt (r, stmt);
    155  1.1  mrg       }
    156  1.1  mrg }
    157  1.1  mrg 
    158  1.1  mrg // Change the current dump_file and dump_flags to F and FLAGS while
    159  1.1  mrg // saving them for later restoring.
    160  1.1  mrg 
    161  1.1  mrg push_dump_file::push_dump_file (FILE *f, dump_flags_t flags)
    162  1.1  mrg {
    163  1.1  mrg   old_dump_file = dump_file;
    164  1.1  mrg   old_dump_flags = dump_flags;
    165  1.1  mrg   dump_file = f;
    166  1.1  mrg   dump_flags = flags;
    167  1.1  mrg }
    168  1.1  mrg 
    169  1.1  mrg // Restore saved dump_file and dump_flags.
    170  1.1  mrg 
    171  1.1  mrg push_dump_file::~push_dump_file ()
    172  1.1  mrg {
    173  1.1  mrg   dump_file = old_dump_file;
    174  1.1  mrg   dump_flags = old_dump_flags;
    175  1.1  mrg }
    176  1.1  mrg 
    177  1.1  mrg // Dump all that ranger knows for the current function.
    178  1.1  mrg 
    179  1.1  mrg void
    180  1.1  mrg dump_ranger (FILE *out)
    181  1.1  mrg {
    182  1.1  mrg   push_dump_file save (out, dump_flags);
    183  1.1  mrg   gimple_ranger ranger;
    184  1.1  mrg 
    185  1.1  mrg   fprintf (out, ";; Function ");
    186  1.1  mrg   print_generic_expr (out, current_function_decl);
    187  1.1  mrg   fprintf (out, "\n");
    188  1.1  mrg 
    189  1.1  mrg   debug_seed_ranger (ranger);
    190  1.1  mrg   ranger.dump (out);
    191  1.1  mrg }
    192  1.1  mrg 
    193  1.1  mrg DEBUG_FUNCTION void
    194  1.1  mrg debug_ranger ()
    195  1.1  mrg {
    196  1.1  mrg   dump_ranger (stderr);
    197  1.1  mrg }
    198  1.1  mrg 
    199  1.1  mrg // Dump all that ranger knows on a path of BBs.
    200  1.1  mrg //
    201  1.1  mrg // Note that the blocks are in reverse order, thus the exit block is
    202  1.1  mrg // path[0].
    203  1.1  mrg 
    204  1.1  mrg void
    205  1.1  mrg dump_ranger (FILE *dump_file, const vec<basic_block> &path)
    206  1.1  mrg {
    207  1.1  mrg   if (path.length () == 0)
    208  1.1  mrg     {
    209  1.1  mrg       fprintf (dump_file, "empty\n");
    210  1.1  mrg       return;
    211  1.1  mrg     }
    212  1.1  mrg 
    213  1.1  mrg   gimple_ranger ranger;
    214  1.1  mrg   debug_seed_ranger (ranger);
    215  1.1  mrg 
    216  1.1  mrg   unsigned i = path.length ();
    217  1.1  mrg   do
    218  1.1  mrg     {
    219  1.1  mrg       i--;
    220  1.1  mrg       ranger.dump_bb (dump_file, path[i]);
    221  1.1  mrg     }
    222  1.1  mrg   while (i > 0);
    223  1.1  mrg }
    224  1.1  mrg 
    225  1.1  mrg DEBUG_FUNCTION void
    226  1.1  mrg debug_ranger (const vec<basic_block> &path)
    227  1.1  mrg {
    228  1.1  mrg   dump_ranger (stderr, path);
    229  1.1  mrg }
    230  1.1  mrg 
    231  1.1  mrg #include "gimple-range-tests.cc"
    232