Line data Source code
1 : /* Code for GIMPLE range trace and debugging related routines.
2 : Copyright (C) 2019-2026 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 "cfgloop.h"
34 : #include "tree-scalar-evolution.h"
35 : #include "gimple-range.h"
36 :
37 :
38 : // Breakpoint to trap at a specific index. From GDB, this provides a simple
39 : // place to put a breakpoint to stop at a given trace line.
40 : // ie. b range_tracer::breakpoint if index == 45678
41 :
42 : void
43 0 : range_tracer::breakpoint (unsigned index ATTRIBUTE_UNUSED)
44 : {
45 0 : }
46 :
47 : // Construct a range_tracer with component NAME.
48 :
49 59786473 : range_tracer::range_tracer (const char *name)
50 : {
51 59786473 : gcc_checking_assert (strlen(name) < name_len -1);
52 59786473 : strcpy (component, name);
53 59786473 : indent = 0;
54 59786473 : tracing = false;
55 59786473 : }
56 :
57 : // This routine does the initial line spacing/indenting for a trace.
58 : // If BLANKS is false, then IDX is printed, otherwise spaces.
59 :
60 : void
61 0 : range_tracer::print_prefix (unsigned idx, bool blanks)
62 : {
63 : // Print counter index as well as INDENT spaces.
64 0 : if (!blanks)
65 0 : fprintf (dump_file, "%-7u ", idx);
66 : else
67 0 : fprintf (dump_file, " ");
68 0 : fprintf (dump_file, "%s ", component);
69 0 : unsigned x;
70 0 : for (x = 0; x< indent; x++)
71 0 : fputc (' ', dump_file);
72 :
73 0 : }
74 : // If dumping, return the next call index and print the prefix for the next
75 : // output line. If not, return 0.
76 : // Counter is static to monotonically increase across the compilation unit.
77 :
78 : unsigned
79 0 : range_tracer::do_header (const char *str)
80 : {
81 0 : static unsigned trace_count = 0;
82 :
83 0 : unsigned idx = ++trace_count;
84 0 : print_prefix (idx, false);
85 0 : fprintf (dump_file, "%s", str);
86 0 : indent += bump;
87 0 : breakpoint (idx);
88 0 : return idx;
89 : }
90 :
91 : // Print a line without starting or ending a trace.
92 :
93 : void
94 0 : range_tracer::print (unsigned counter, const char *str)
95 : {
96 0 : print_prefix (counter, true);
97 0 : fprintf (dump_file, "%s", str);
98 0 : }
99 :
100 : // End a trace and print the CALLER, NAME, and RESULT and range R,
101 :
102 : void
103 0 : range_tracer::trailer (unsigned counter, const char *caller, bool result,
104 : tree name, const vrange &r)
105 : {
106 0 : gcc_checking_assert (tracing && counter != 0);
107 :
108 0 : indent -= bump;
109 0 : print_prefix (counter, true);
110 0 : fputs(result ? "TRUE : " : "FALSE : ", dump_file);
111 0 : fprintf (dump_file, "(%u) ", counter);
112 0 : fputs (caller, dump_file);
113 0 : fputs (" (",dump_file);
114 0 : if (name)
115 0 : print_generic_expr (dump_file, name, TDF_SLIM);
116 0 : fputs (") ",dump_file);
117 0 : if (result)
118 : {
119 0 : r.dump (dump_file);
120 0 : fputc('\n', dump_file);
121 : }
122 : else
123 0 : fputc('\n', dump_file);
124 0 : }
125 :
126 : // =========================================
127 : // Debugging helpers.
128 : // =========================================
129 :
130 : // Query all statements in the IL to precalculate computable ranges in RANGER.
131 :
132 : DEBUG_FUNCTION void
133 0 : debug_seed_ranger (gimple_ranger &ranger)
134 : {
135 : // Recalculate SCEV to make sure the dump lists everything.
136 0 : if (scev_initialized_p ())
137 : {
138 0 : scev_finalize ();
139 0 : scev_initialize ();
140 : }
141 :
142 0 : basic_block bb;
143 0 : gimple_stmt_iterator gsi;
144 0 : FOR_EACH_BB_FN (bb, cfun)
145 0 : for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
146 : {
147 0 : gimple *stmt = gsi_stmt (gsi);
148 :
149 0 : if (is_gimple_debug (stmt))
150 0 : continue;
151 :
152 0 : if (tree type = gimple_range_type (stmt))
153 : {
154 0 : value_range r (type);
155 0 : ranger.range_of_stmt (r, stmt);
156 0 : }
157 : }
158 0 : }
159 :
160 : // Change the current dump_file and dump_flags to F and FLAGS while
161 : // saving them for later restoring.
162 :
163 0 : push_dump_file::push_dump_file (FILE *f, dump_flags_t flags)
164 : {
165 0 : old_dump_file = dump_file;
166 0 : old_dump_flags = dump_flags;
167 0 : dump_file = f;
168 0 : dump_flags = flags;
169 0 : }
170 :
171 : // Restore saved dump_file and dump_flags.
172 :
173 0 : push_dump_file::~push_dump_file ()
174 : {
175 0 : dump_file = old_dump_file;
176 0 : dump_flags = old_dump_flags;
177 0 : }
178 :
179 : // Dump all that ranger knows for the current function.
180 :
181 : void
182 0 : dump_ranger (FILE *out)
183 : {
184 0 : push_dump_file save (out, dump_flags);
185 0 : gimple_ranger ranger;
186 :
187 0 : fprintf (out, ";; Function ");
188 0 : print_generic_expr (out, current_function_decl);
189 0 : fprintf (out, "\n");
190 :
191 0 : debug_seed_ranger (ranger);
192 0 : ranger.dump (out);
193 0 : }
194 :
195 : DEBUG_FUNCTION void
196 0 : debug_ranger ()
197 : {
198 0 : dump_ranger (stderr);
199 0 : }
200 :
201 : // Dump all that ranger knows on a path of BBs.
202 : //
203 : // Note that the blocks are in reverse order, thus the exit block is
204 : // path[0].
205 :
206 : void
207 0 : dump_ranger (FILE *dump_file, const vec<basic_block> &path)
208 : {
209 0 : if (path.length () == 0)
210 : {
211 0 : fprintf (dump_file, "empty\n");
212 0 : return;
213 : }
214 :
215 0 : gimple_ranger ranger;
216 0 : debug_seed_ranger (ranger);
217 :
218 0 : unsigned i = path.length ();
219 0 : do
220 : {
221 0 : i--;
222 0 : ranger.dump_bb (dump_file, path[i]);
223 : }
224 0 : while (i > 0);
225 0 : }
226 :
227 : DEBUG_FUNCTION void
228 0 : debug_ranger (const vec<basic_block> &path)
229 : {
230 0 : dump_ranger (stderr, path);
231 0 : }
232 :
233 : #include "gimple-range-tests.cc"
|