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