1/* Code for GIMPLE range trace and debugging related routines.
2 Copyright (C) 2019-2023 Free Software Foundation, Inc.
3 Contributed by Andrew MacLeod <amacleod@redhat.com>
4 and Aldy Hernandez <aldyh@redhat.com>.
5
6This file is part of GCC.
7
8GCC is free software; you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation; either version 3, or (at your option)
11any later version.
12
13GCC is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19along 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
43void
44range_tracer::breakpoint (unsigned index ATTRIBUTE_UNUSED)
45{
46}
47
48// Construct a range_tracer with component NAME.
49
50range_tracer::range_tracer (const char *name)
51{
52 gcc_checking_assert (strlen(name) < name_len -1);
53 strcpy (dest: component, src: name);
54 indent = 0;
55 tracing = false;
56}
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
61void
62range_tracer::print_prefix (unsigned idx, bool blanks)
63{
64 // Print counter index as well as INDENT spaces.
65 if (!blanks)
66 fprintf (stream: dump_file, format: "%-7u ", idx);
67 else
68 fprintf (stream: dump_file, format: " ");
69 fprintf (stream: dump_file, format: "%s ", component);
70 unsigned x;
71 for (x = 0; x< indent; x++)
72 fputc (c: ' ', stream: dump_file);
73
74}
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
79unsigned
80range_tracer::do_header (const char *str)
81{
82 static unsigned trace_count = 0;
83
84 unsigned idx = ++trace_count;
85 print_prefix (idx, blanks: false);
86 fprintf (stream: dump_file, format: "%s", str);
87 indent += bump;
88 breakpoint (index: idx);
89 return idx;
90}
91
92// Print a line without starting or ending a trace.
93
94void
95range_tracer::print (unsigned counter, const char *str)
96{
97 print_prefix (idx: counter, blanks: true);
98 fprintf (stream: dump_file, format: "%s", str);
99}
100
101// End a trace and print the CALLER, NAME, and RESULT and range R,
102
103void
104range_tracer::trailer (unsigned counter, const char *caller, bool result,
105 tree name, const vrange &r)
106{
107 gcc_checking_assert (tracing && counter != 0);
108
109 indent -= bump;
110 print_prefix (idx: counter, blanks: true);
111 fputs(s: result ? "TRUE : " : "FALSE : ", stream: dump_file);
112 fprintf (stream: dump_file, format: "(%u) ", counter);
113 fputs (s: caller, stream: dump_file);
114 fputs (s: " (",stream: dump_file);
115 if (name)
116 print_generic_expr (dump_file, name, TDF_SLIM);
117 fputs (s: ") ",stream: dump_file);
118 if (result)
119 {
120 r.dump (dump_file);
121 fputc(c: '\n', stream: dump_file);
122 }
123 else
124 fputc(c: '\n', stream: dump_file);
125}
126
127// =========================================
128// Debugging helpers.
129// =========================================
130
131// Query all statements in the IL to precalculate computable ranges in RANGER.
132
133DEBUG_FUNCTION void
134debug_seed_ranger (gimple_ranger &ranger)
135{
136 // Recalculate SCEV to make sure the dump lists everything.
137 if (scev_initialized_p ())
138 {
139 scev_finalize ();
140 scev_initialize ();
141 }
142
143 basic_block bb;
144 gimple_stmt_iterator gsi;
145 FOR_EACH_BB_FN (bb, cfun)
146 for (gsi = gsi_start_bb (bb); !gsi_end_p (i: gsi); gsi_next (i: &gsi))
147 {
148 gimple *stmt = gsi_stmt (i: gsi);
149
150 if (is_gimple_debug (gs: stmt))
151 continue;
152
153 if (tree type = gimple_range_type (s: stmt))
154 {
155 Value_Range r (type);
156 ranger.range_of_stmt (r, stmt);
157 }
158 }
159}
160
161// Change the current dump_file and dump_flags to F and FLAGS while
162// saving them for later restoring.
163
164push_dump_file::push_dump_file (FILE *f, dump_flags_t flags)
165{
166 old_dump_file = dump_file;
167 old_dump_flags = dump_flags;
168 dump_file = f;
169 dump_flags = flags;
170}
171
172// Restore saved dump_file and dump_flags.
173
174push_dump_file::~push_dump_file ()
175{
176 dump_file = old_dump_file;
177 dump_flags = old_dump_flags;
178}
179
180// Dump all that ranger knows for the current function.
181
182void
183dump_ranger (FILE *out)
184{
185 push_dump_file save (out, dump_flags);
186 gimple_ranger ranger;
187
188 fprintf (stream: out, format: ";; Function ");
189 print_generic_expr (out, current_function_decl);
190 fprintf (stream: out, format: "\n");
191
192 debug_seed_ranger (ranger);
193 ranger.dump (f: out);
194}
195
196DEBUG_FUNCTION void
197debug_ranger ()
198{
199 dump_ranger (stderr);
200}
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
207void
208dump_ranger (FILE *dump_file, const vec<basic_block> &path)
209{
210 if (path.length () == 0)
211 {
212 fprintf (stream: dump_file, format: "empty\n");
213 return;
214 }
215
216 gimple_ranger ranger;
217 debug_seed_ranger (ranger);
218
219 unsigned i = path.length ();
220 do
221 {
222 i--;
223 ranger.dump_bb (f: dump_file, bb: path[i]);
224 }
225 while (i > 0);
226}
227
228DEBUG_FUNCTION void
229debug_ranger (const vec<basic_block> &path)
230{
231 dump_ranger (stderr, path);
232}
233
234#include "gimple-range-tests.cc"
235

source code of gcc/gimple-range-trace.cc