annotate gcc/analyzer/engine.cc @ 158:494b0b89df80 default tip

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 May 2020 18:13:55 +0900
parents 1830386684a0
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
145
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1 /* The analysis "engine".
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2 Copyright (C) 2019-2020 Free Software Foundation, Inc.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3 Contributed by David Malcolm <dmalcolm@redhat.com>.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
4
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
5 This file is part of GCC.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
6
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
7 GCC is free software; you can redistribute it and/or modify it
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
8 under the terms of the GNU General Public License as published by
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
9 the Free Software Foundation; either version 3, or (at your option)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
10 any later version.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
11
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
12 GCC is distributed in the hope that it will be useful, but
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
13 WITHOUT ANY WARRANTY; without even the implied warranty of
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
15 General Public License for more details.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
16
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
17 You should have received a copy of the GNU General Public License
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
18 along with GCC; see the file COPYING3. If not see
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
19 <http://www.gnu.org/licenses/>. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
20
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
21 #include "config.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
22 #include "system.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
23 #include "coretypes.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
24 #include "tree.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
25 #include "fold-const.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
26 #include "gcc-rich-location.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
27 #include "alloc-pool.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
28 #include "fibonacci_heap.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
29 #include "shortest-paths.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
30 #include "diagnostic-core.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
31 #include "diagnostic-event-id.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
32 #include "diagnostic-path.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
33 #include "function.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
34 #include "pretty-print.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
35 #include "sbitmap.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
36 #include "tristate.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
37 #include "ordered-hash-map.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
38 #include "selftest.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
39 #include "analyzer/analyzer.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
40 #include "analyzer/analyzer-logging.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
41 #include "analyzer/region-model.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
42 #include "analyzer/constraint-manager.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
43 #include "analyzer/sm.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
44 #include "analyzer/pending-diagnostic.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
45 #include "analyzer/diagnostic-manager.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
46 #include "cfg.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
47 #include "basic-block.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
48 #include "gimple.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
49 #include "gimple-iterator.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
50 #include "cgraph.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
51 #include "digraph.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
52 #include "analyzer/supergraph.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
53 #include "analyzer/call-string.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
54 #include "analyzer/program-point.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
55 #include "analyzer/program-state.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
56 #include "analyzer/exploded-graph.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
57 #include "analyzer/analysis-plan.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
58 #include "analyzer/checker-path.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
59 #include "analyzer/state-purge.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
60
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
61 /* For an overview, see gcc/doc/analyzer.texi. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
62
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
63 #if ENABLE_ANALYZER
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
64
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
65 namespace ana {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
66
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
67 static int readability_comparator (const void *p1, const void *p2);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
68
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
69 /* class impl_region_model_context : public region_model_context. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
70
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
71 impl_region_model_context::
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
72 impl_region_model_context (exploded_graph &eg,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
73 const exploded_node *enode_for_diag,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
74 const program_state *old_state,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
75 program_state *new_state,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
76 state_change *change,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
77 const gimple *stmt,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
78 stmt_finder *stmt_finder)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
79 : m_eg (&eg), m_logger (eg.get_logger ()),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
80 m_enode_for_diag (enode_for_diag),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
81 m_old_state (old_state),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
82 m_new_state (new_state),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
83 m_change (change),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
84 m_stmt (stmt),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
85 m_stmt_finder (stmt_finder),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
86 m_ext_state (eg.get_ext_state ())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
87 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
88 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
89
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
90 impl_region_model_context::
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
91 impl_region_model_context (program_state *state,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
92 state_change *change,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
93 const extrinsic_state &ext_state)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
94 : m_eg (NULL), m_logger (NULL), m_enode_for_diag (NULL),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
95 m_old_state (NULL),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
96 m_new_state (state),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
97 m_change (change),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
98 m_stmt (NULL),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
99 m_stmt_finder (NULL),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
100 m_ext_state (ext_state)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
101 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
102 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
103
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
104 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
105 impl_region_model_context::warn (pending_diagnostic *d)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
106 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
107 LOG_FUNC (get_logger ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
108 if (m_eg)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
109 m_eg->get_diagnostic_manager ().add_diagnostic
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
110 (m_enode_for_diag, m_enode_for_diag->get_supernode (),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
111 m_stmt, m_stmt_finder, d);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
112 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
113
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
114 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
115 impl_region_model_context::remap_svalue_ids (const svalue_id_map &map)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
116 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
117 m_new_state->remap_svalue_ids (map);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
118 if (m_change)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
119 m_change->remap_svalue_ids (map);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
120 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
121
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
122 int
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
123 impl_region_model_context::on_svalue_purge (svalue_id first_unused_sid,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
124 const svalue_id_map &map)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
125 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
126 int total = 0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
127 int sm_idx;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
128 sm_state_map *smap;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
129 FOR_EACH_VEC_ELT (m_new_state->m_checker_states, sm_idx, smap)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
130 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
131 const state_machine &sm = m_ext_state.get_sm (sm_idx);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
132 total += smap->on_svalue_purge (sm, sm_idx, first_unused_sid,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
133 map, this);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
134 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
135 if (m_change)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
136 total += m_change->on_svalue_purge (first_unused_sid);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
137 return total;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
138 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
139
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
140 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
141 impl_region_model_context::on_unknown_change (svalue_id sid)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
142 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
143 int sm_idx;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
144 sm_state_map *smap;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
145 FOR_EACH_VEC_ELT (m_new_state->m_checker_states, sm_idx, smap)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
146 smap->on_unknown_change (sid);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
147 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
148
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
149 /* class setjmp_svalue : public svalue. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
150
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
151 /* Compare the fields of this setjmp_svalue with OTHER, returning true
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
152 if they are equal.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
153 For use by svalue::operator==. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
154
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
155 bool
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
156 setjmp_svalue::compare_fields (const setjmp_svalue &other) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
157 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
158 return m_setjmp_record == other.m_setjmp_record;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
159 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
160
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
161 /* Implementation of svalue::add_to_hash vfunc for setjmp_svalue. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
162
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
163 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
164 setjmp_svalue::add_to_hash (inchash::hash &hstate) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
165 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
166 hstate.add_int (m_setjmp_record.m_enode->m_index);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
167 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
168
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
169 /* Get the index of the stored exploded_node. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
170
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
171 int
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
172 setjmp_svalue::get_enode_index () const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
173 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
174 return m_setjmp_record.m_enode->m_index;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
175 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
176
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
177 /* Implementation of svalue::print_details vfunc for setjmp_svalue. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
178
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
179 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
180 setjmp_svalue::print_details (const region_model &model ATTRIBUTE_UNUSED,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
181 svalue_id this_sid ATTRIBUTE_UNUSED,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
182 pretty_printer *pp) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
183 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
184 pp_printf (pp, "setjmp: EN: %i", get_enode_index ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
185 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
186
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
187 /* Concrete implementation of sm_context, wiring it up to the rest of this
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
188 file. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
189
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
190 class impl_sm_context : public sm_context
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
191 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
192 public:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
193 impl_sm_context (exploded_graph &eg,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
194 int sm_idx,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
195 const state_machine &sm,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
196 const exploded_node *enode_for_diag,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
197 const program_state *old_state,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
198 program_state *new_state,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
199 state_change *change,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
200 const sm_state_map *old_smap,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
201 sm_state_map *new_smap,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
202 stmt_finder *stmt_finder = NULL)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
203 : sm_context (sm_idx, sm),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
204 m_logger (eg.get_logger ()),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
205 m_eg (eg), m_enode_for_diag (enode_for_diag),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
206 m_old_state (old_state), m_new_state (new_state),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
207 m_change (change),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
208 m_old_smap (old_smap), m_new_smap (new_smap),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
209 m_stmt_finder (stmt_finder)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
210 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
211 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
212
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
213 logger *get_logger () const { return m_logger.get_logger (); }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
214
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
215 tree get_fndecl_for_call (const gcall *call) FINAL OVERRIDE
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
216 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
217 impl_region_model_context old_ctxt
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
218 (m_eg, m_enode_for_diag, NULL, NULL/*m_enode->get_state ()*/,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
219 m_change, call);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
220 region_model *model = m_new_state->m_region_model;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
221 return model->get_fndecl_for_call (call, &old_ctxt);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
222 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
223
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
224 void on_transition (const supernode *node ATTRIBUTE_UNUSED,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
225 const gimple *stmt ATTRIBUTE_UNUSED,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
226 tree var,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
227 state_machine::state_t from,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
228 state_machine::state_t to,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
229 tree origin) FINAL OVERRIDE
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
230 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
231 logger * const logger = get_logger ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
232 LOG_FUNC (logger);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
233 impl_region_model_context old_ctxt
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
234 (m_eg, m_enode_for_diag, NULL, NULL/*m_enode->get_state ()*/,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
235 m_change, stmt);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
236 svalue_id var_old_sid
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
237 = m_old_state->m_region_model->get_rvalue (var, &old_ctxt);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
238
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
239 impl_region_model_context new_ctxt (m_eg, m_enode_for_diag,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
240 m_old_state, m_new_state,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
241 m_change, NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
242 svalue_id var_new_sid
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
243 = m_new_state->m_region_model->get_rvalue (var, &new_ctxt);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
244 svalue_id origin_new_sid
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
245 = m_new_state->m_region_model->get_rvalue (origin, &new_ctxt);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
246
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
247 state_machine::state_t current = m_old_smap->get_state (var_old_sid);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
248 if (current == from)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
249 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
250 if (logger)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
251 logger->log ("%s: state transition of %qE: %s -> %s",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
252 m_sm.get_name (),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
253 var,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
254 m_sm.get_state_name (from),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
255 m_sm.get_state_name (to));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
256 m_new_smap->set_state (m_new_state->m_region_model, var_new_sid,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
257 to, origin_new_sid);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
258 if (m_change)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
259 m_change->add_sm_change (m_sm_idx, var_new_sid, from, to);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
260 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
261 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
262
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
263 void warn_for_state (const supernode *snode, const gimple *stmt,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
264 tree var, state_machine::state_t state,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
265 pending_diagnostic *d) FINAL OVERRIDE
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
266 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
267 LOG_FUNC (get_logger ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
268 gcc_assert (d); // take ownership
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
269
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
270 impl_region_model_context old_ctxt
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
271 (m_eg, m_enode_for_diag, m_old_state, m_new_state, m_change, NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
272 state_machine::state_t current;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
273 if (var)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
274 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
275 svalue_id var_old_sid
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
276 = m_old_state->m_region_model->get_rvalue (var, &old_ctxt);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
277 current = m_old_smap->get_state (var_old_sid);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
278 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
279 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
280 current = m_old_smap->get_global_state ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
281
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
282 if (state == current)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
283 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
284 m_eg.get_diagnostic_manager ().add_diagnostic
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
285 (&m_sm, m_enode_for_diag, snode, stmt, m_stmt_finder,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
286 var, state, d);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
287 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
288 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
289 delete d;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
290 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
291
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
292 /* Hook for picking more readable trees for SSA names of temporaries,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
293 so that rather than e.g.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
294 "double-free of '<unknown>'"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
295 we can print:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
296 "double-free of 'inbuf.data'". */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
297
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
298 tree get_readable_tree (tree expr) FINAL OVERRIDE
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
299 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
300 /* Only for SSA_NAMEs of temporaries; otherwise, return EXPR, as it's
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
301 likely to be the least surprising tree to report. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
302 if (TREE_CODE (expr) != SSA_NAME)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
303 return expr;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
304 if (SSA_NAME_VAR (expr) != NULL)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
305 return expr;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
306
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
307 gcc_assert (m_new_state);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
308 svalue_id sid = m_new_state->m_region_model->get_rvalue (expr, NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
309 /* Find trees for all regions storing the value. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
310 auto_vec<path_var> pvs;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
311 m_new_state->m_region_model->get_path_vars_for_svalue (sid, &pvs);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
312 if (pvs.length () < 1)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
313 return expr;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
314 /* Pick the "best" such tree. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
315 // TODO: should we also consider (and consolidate) equiv classes?
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
316 pvs.qsort (readability_comparator);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
317 return pvs[0].m_tree;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
318 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
319
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
320 state_machine::state_t get_global_state () const FINAL OVERRIDE
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
321 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
322 return m_old_state->m_checker_states[m_sm_idx]->get_global_state ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
323 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
324
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
325 void set_global_state (state_machine::state_t state) FINAL OVERRIDE
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
326 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
327 m_new_state->m_checker_states[m_sm_idx]->set_global_state (state);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
328 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
329
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
330 void on_custom_transition (custom_transition *transition) FINAL OVERRIDE
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
331 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
332 transition->impl_transition (&m_eg,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
333 const_cast<exploded_node *> (m_enode_for_diag),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
334 m_sm_idx);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
335 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
336
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
337 log_user m_logger;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
338 exploded_graph &m_eg;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
339 const exploded_node *m_enode_for_diag;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
340 const program_state *m_old_state;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
341 program_state *m_new_state;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
342 state_change *m_change;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
343 const sm_state_map *m_old_smap;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
344 sm_state_map *m_new_smap;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
345 stmt_finder *m_stmt_finder;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
346 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
347
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
348 /* Subclass of stmt_finder for finding the best stmt to report the leak at,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
349 given the emission path. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
350
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
351 class leak_stmt_finder : public stmt_finder
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
352 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
353 public:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
354 leak_stmt_finder (const exploded_graph &eg, tree var)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
355 : m_eg (eg), m_var (var) {}
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
356
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
357 stmt_finder *clone () const FINAL OVERRIDE
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
358 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
359 return new leak_stmt_finder (m_eg, m_var);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
360 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
361
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
362 const gimple *find_stmt (const exploded_path &epath)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
363 FINAL OVERRIDE
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
364 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
365 logger * const logger = m_eg.get_logger ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
366 LOG_FUNC (logger);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
367
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
368 if (TREE_CODE (m_var) == SSA_NAME)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
369 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
370 /* Locate the final write to this SSA name in the path. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
371 const gimple *def_stmt = SSA_NAME_DEF_STMT (m_var);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
372
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
373 int idx_of_def_stmt;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
374 bool found = epath.find_stmt_backwards (def_stmt, &idx_of_def_stmt);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
375 if (!found)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
376 goto not_found;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
377
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
378 /* What was the next write to the underlying var
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
379 after the SSA name was set? (if any). */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
380
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
381 for (unsigned idx = idx_of_def_stmt + 1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
382 idx < epath.m_edges.length ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
383 ++idx)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
384 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
385 const exploded_edge *eedge = epath.m_edges[idx];
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
386 if (logger)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
387 logger->log ("eedge[%i]: EN %i -> EN %i",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
388 idx,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
389 eedge->m_src->m_index,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
390 eedge->m_dest->m_index);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
391 const exploded_node *dst_node = eedge->m_dest;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
392 const program_point &dst_point = dst_node->get_point ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
393 const gimple *stmt = dst_point.get_stmt ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
394 if (!stmt)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
395 continue;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
396 if (const gassign *assign = dyn_cast <const gassign *> (stmt))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
397 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
398 tree lhs = gimple_assign_lhs (assign);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
399 if (TREE_CODE (lhs) == SSA_NAME
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
400 && SSA_NAME_VAR (lhs) == SSA_NAME_VAR (m_var))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
401 return assign;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
402 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
403 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
404 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
405
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
406 not_found:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
407
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
408 /* Look backwards for the first statement with a location. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
409 int i;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
410 const exploded_edge *eedge;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
411 FOR_EACH_VEC_ELT_REVERSE (epath.m_edges, i, eedge)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
412 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
413 if (logger)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
414 logger->log ("eedge[%i]: EN %i -> EN %i",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
415 i,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
416 eedge->m_src->m_index,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
417 eedge->m_dest->m_index);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
418 const exploded_node *dst_node = eedge->m_dest;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
419 const program_point &dst_point = dst_node->get_point ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
420 const gimple *stmt = dst_point.get_stmt ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
421 if (stmt)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
422 if (get_pure_location (stmt->location) != UNKNOWN_LOCATION)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
423 return stmt;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
424 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
425
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
426 gcc_unreachable ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
427 return NULL;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
428 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
429
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
430 private:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
431 const exploded_graph &m_eg;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
432 tree m_var;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
433 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
434
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
435 /* A measurement of how good EXPR is for presenting to the user, so
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
436 that e.g. we can say prefer printing
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
437 "leak of 'tmp.m_ptr'"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
438 over:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
439 "leak of '<unknown>'". */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
440
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
441 static int
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
442 readability (const_tree expr)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
443 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
444 gcc_assert (expr);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
445 switch (TREE_CODE (expr))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
446 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
447 case COMPONENT_REF:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
448 case MEM_REF:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
449 /* Impose a slight readability penalty relative to that of
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
450 operand 0. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
451 return readability (TREE_OPERAND (expr, 0)) - 1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
452
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
453 case SSA_NAME:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
454 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
455 if (tree var = SSA_NAME_VAR (expr))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
456 return readability (var);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
457 /* Avoid printing '<unknown>' for SSA names for temporaries. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
458 return -1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
459 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
460 break;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
461
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
462 case VAR_DECL:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
463 /* Arbitrarily-chosen "high readability" value. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
464 return 256;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
465
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
466 default:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
467 return 0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
468 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
469
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
470 return 0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
471 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
472
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
473 /* A qsort comparator for trees to sort them into most user-readable to
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
474 least user-readable. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
475
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
476 static int
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
477 readability_comparator (const void *p1, const void *p2)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
478 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
479 path_var pv1 = *(path_var const *)p1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
480 path_var pv2 = *(path_var const *)p2;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
481
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
482 /* TODO: should we consider stack depths? */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
483 int r1 = readability (pv1.m_tree);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
484 int r2 = readability (pv2.m_tree);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
485
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
486 return r2 - r1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
487 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
488
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
489 /* Create an sm_context and use it to call SM's on_leak vfunc, so that
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
490 it can potentially complain about a leak of DST_SID (in a new region_model)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
491 in the given STATE, where MAP can be used to map SID back to an "old"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
492 region_model. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
493
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
494 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
495 impl_region_model_context::on_state_leak (const state_machine &sm,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
496 int sm_idx,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
497 svalue_id dst_sid,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
498 svalue_id first_unused_sid,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
499 const svalue_id_map &map,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
500 state_machine::state_t state)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
501 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
502 logger * const logger = get_logger ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
503 LOG_SCOPE (logger);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
504 if (logger)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
505 logger->log ("considering leak of sv%i", dst_sid.as_int ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
506
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
507 if (!m_eg)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
508 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
509
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
510 /* m_old_state also needs to be non-NULL so that the sm_ctxt can look
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
511 up the old state of the sid. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
512 gcc_assert (m_old_state);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
513
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
514 /* Don't report on sid leaking if it's equal to one of the used sids.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
515 For example, given:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
516 some_non_trivial_expression = malloc (sizeof (struct foo));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
517 we have:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
518 _1 = malloc; (void *)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
519 some_non_trivial_expression = _1; (struct foo *)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
520 and at leak-detection time we may have:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
521 sv5: {type: 'struct foo *', &r3} (used)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
522 sv6: {type: 'void *', &r3} (unused)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
523 where both point to the same region. We don't want to report a
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
524 leak of sv6, so we reject the report due to its equality with sv5. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
525 gcc_assert (m_new_state);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
526 gcc_assert (!first_unused_sid.null_p ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
527 for (int i = 0; i < first_unused_sid.as_int (); i++)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
528 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
529 svalue_id used_sid = svalue_id::from_int (i);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
530
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
531 /* Use the "_without_cm" form of eval_condition, since
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
532 we're half-way through purging - we don't want to introduce new
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
533 equivalence classes into the constraint_manager for "sid" and
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
534 for each of the used_sids. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
535 const region_model &rm = *m_new_state->m_region_model;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
536 tristate eq = rm.eval_condition_without_cm (dst_sid, EQ_EXPR, used_sid);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
537 if (eq.is_true ())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
538 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
539 if (logger)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
540 logger->log ("rejecting leak of sv%i due to equality with sv%i",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
541 dst_sid.as_int (), used_sid.as_int ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
542 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
543 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
544 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
545
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
546 /* SID has leaked within the new state: no regions use it.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
547 We need to convert it back to a tree, but since no regions use it, we
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
548 have to use MAP to convert it back to an svalue_id within the old state.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
549 We can then look that svalue_id up to locate regions and thus tree(s)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
550 that use it. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
551
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
552 svalue_id old_sid = map.get_src_for_dst (dst_sid);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
553
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
554 auto_vec<path_var> leaked_pvs;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
555 m_old_state->m_region_model->get_path_vars_for_svalue (old_sid, &leaked_pvs);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
556
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
557 if (leaked_pvs.length () < 1)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
558 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
559
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
560 /* Find "best" leaked tree.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
561 Sort the leaks into most human-readable first, through
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
562 to least user-readable. Given that we only emit one
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
563 leak per EC, this ought to ensure that we pick the most
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
564 user-readable description of each leaking EC.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
565 This assumes that all vars in the EC have the same state. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
566 leaked_pvs.qsort (readability_comparator);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
567
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
568 tree leaked_tree = leaked_pvs[0].m_tree;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
569 if (logger)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
570 logger->log ("best leaked_tree: %qE", leaked_tree);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
571
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
572 leak_stmt_finder stmt_finder (*m_eg, leaked_tree);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
573 impl_sm_context sm_ctxt (*m_eg, sm_idx, sm, m_enode_for_diag,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
574 m_old_state, m_new_state,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
575 m_change,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
576 m_old_state->m_checker_states[sm_idx],
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
577 m_new_state->m_checker_states[sm_idx],
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
578 &stmt_finder);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
579 gcc_assert (m_enode_for_diag);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
580
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
581 /* Don't complain about leaks when returning from "main". */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
582 if (m_enode_for_diag->get_supernode ()
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
583 && m_enode_for_diag->get_supernode ()->return_p ())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
584 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
585 tree fndecl = m_enode_for_diag->get_function ()->decl;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
586 if (0 == strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), "main"))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
587 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
588 if (logger)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
589 logger->log ("not reporting leak from main");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
590 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
591 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
592 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
593
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
594 pending_diagnostic *pd = sm.on_leak (leaked_tree);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
595 if (pd)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
596 m_eg->get_diagnostic_manager ().add_diagnostic
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
597 (&sm, m_enode_for_diag, m_enode_for_diag->get_supernode (),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
598 m_stmt, &stmt_finder,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
599 leaked_tree, state, pd);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
600 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
601
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
602 /* Implementation of region_model_context::on_inherited_svalue vfunc
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
603 for impl_region_model_context.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
604 Notify all checkers that CHILD_SID has been created from PARENT_SID,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
605 so that those state machines that inherit state can propagate the state
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
606 from parent to child. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
607
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
608 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
609 impl_region_model_context::on_inherited_svalue (svalue_id parent_sid,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
610 svalue_id child_sid)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
611 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
612 if (!m_new_state)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
613 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
614
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
615 int sm_idx;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
616 sm_state_map *smap;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
617 FOR_EACH_VEC_ELT (m_new_state->m_checker_states, sm_idx, smap)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
618 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
619 const state_machine &sm = m_ext_state.get_sm (sm_idx);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
620 if (sm.inherited_state_p ())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
621 smap->on_inherited_svalue (parent_sid, child_sid);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
622 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
623 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
624
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
625 /* Implementation of region_model_context::on_cast vfunc
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
626 for impl_region_model_context.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
627 Notify all checkers that DST_SID is a cast of SRC_SID, so that sm-state
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
628 can be propagated from src to dst. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
629
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
630 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
631 impl_region_model_context::on_cast (svalue_id src_sid,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
632 svalue_id dst_sid)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
633 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
634 if (!m_new_state)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
635 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
636
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
637 int sm_idx;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
638 sm_state_map *smap;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
639 FOR_EACH_VEC_ELT (m_new_state->m_checker_states, sm_idx, smap)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
640 smap->on_cast (src_sid, dst_sid);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
641 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
642
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
643 /* Implementation of region_model_context::on_condition vfunc.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
644 Notify all state machines about the condition, which could lead to
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
645 state transitions. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
646
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
647 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
648 impl_region_model_context::on_condition (tree lhs, enum tree_code op, tree rhs)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
649 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
650 int sm_idx;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
651 sm_state_map *smap;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
652 FOR_EACH_VEC_ELT (m_new_state->m_checker_states, sm_idx, smap)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
653 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
654 const state_machine &sm = m_ext_state.get_sm (sm_idx);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
655 impl_sm_context sm_ctxt (*m_eg, sm_idx, sm, m_enode_for_diag,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
656 m_old_state, m_new_state,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
657 m_change,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
658 m_old_state->m_checker_states[sm_idx],
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
659 m_new_state->m_checker_states[sm_idx]);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
660 sm.on_condition (&sm_ctxt,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
661 m_enode_for_diag->get_supernode (), m_stmt,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
662 lhs, op, rhs);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
663 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
664 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
665
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
666 /* Implementation of region_model_context::on_phi vfunc.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
667 Notify all state machines about the phi, which could lead to
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
668 state transitions. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
669
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
670 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
671 impl_region_model_context::on_phi (const gphi *phi, tree rhs)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
672 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
673 int sm_idx;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
674 sm_state_map *smap;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
675 FOR_EACH_VEC_ELT (m_new_state->m_checker_states, sm_idx, smap)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
676 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
677 const state_machine &sm = m_ext_state.get_sm (sm_idx);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
678 impl_sm_context sm_ctxt (*m_eg, sm_idx, sm, m_enode_for_diag,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
679 m_old_state, m_new_state,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
680 m_change,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
681 m_old_state->m_checker_states[sm_idx],
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
682 m_new_state->m_checker_states[sm_idx]);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
683 sm.on_phi (&sm_ctxt, m_enode_for_diag->get_supernode (), phi, rhs);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
684 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
685 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
686
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
687 /* struct point_and_state. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
688
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
689 /* Assert that this object is sane. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
690
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
691 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
692 point_and_state::validate (const extrinsic_state &ext_state) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
693 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
694 /* Skip this in a release build. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
695 #if !CHECKING_P
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
696 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
697 #endif
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
698
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
699 m_point.validate ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
700
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
701 m_state.validate (ext_state);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
702
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
703 /* Verify that the callstring's model of the stack corresponds to that
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
704 of the region_model. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
705 /* They should have the same depth. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
706 gcc_assert (m_point.get_stack_depth ()
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
707 == m_state.m_region_model->get_stack_depth ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
708 /* Check the functions in the callstring vs those in the frames
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
709 at each depth. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
710 for (int depth = 0; depth < m_point.get_stack_depth (); ++depth)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
711 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
712 gcc_assert (m_point.get_function_at_depth (depth)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
713 == m_state.m_region_model->get_function_at_depth (depth));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
714 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
715 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
716
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
717 /* Subroutine of print_enode_indices: print a run of indices from START_IDX
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
718 to END_IDX to PP, using and updating *FIRST_RUN. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
719
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
720 static void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
721 print_run (pretty_printer *pp, int start_idx, int end_idx,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
722 bool *first_run)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
723 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
724 if (!(*first_run))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
725 pp_string (pp, ", ");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
726 *first_run = false;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
727 if (start_idx == end_idx)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
728 pp_printf (pp, "EN: %i", start_idx);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
729 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
730 pp_printf (pp, "EN: %i-%i", start_idx, end_idx);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
731 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
732
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
733 /* Print the indices within ENODES to PP, collecting them as
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
734 runs/singletons e.g. "EN: 4-7, EN: 20-23, EN: 42". */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
735
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
736 static void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
737 print_enode_indices (pretty_printer *pp,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
738 const auto_vec<exploded_node *> &enodes)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
739 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
740 int cur_start_idx = -1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
741 int cur_finish_idx = -1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
742 bool first_run = true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
743 unsigned i;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
744 exploded_node *enode;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
745 FOR_EACH_VEC_ELT (enodes, i, enode)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
746 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
747 if (cur_start_idx == -1)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
748 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
749 gcc_assert (cur_finish_idx == -1);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
750 cur_start_idx = cur_finish_idx = enode->m_index;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
751 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
752 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
753 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
754 if (enode->m_index == cur_finish_idx + 1)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
755 /* Continuation of a run. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
756 cur_finish_idx = enode->m_index;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
757 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
758 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
759 /* Finish existing run, start a new one. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
760 gcc_assert (cur_start_idx >= 0);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
761 gcc_assert (cur_finish_idx >= 0);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
762 print_run (pp, cur_start_idx, cur_finish_idx,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
763 &first_run);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
764 cur_start_idx = cur_finish_idx = enode->m_index;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
765 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
766 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
767 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
768 /* Finish any existing run. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
769 if (cur_start_idx >= 0)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
770 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
771 gcc_assert (cur_finish_idx >= 0);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
772 print_run (pp, cur_start_idx, cur_finish_idx,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
773 &first_run);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
774 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
775 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
776
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
777 /* For use by dump_dot, get a value for the .dot "fillcolor" attribute.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
778 Colorize by sm-state, to make it easier to see how sm-state propagates
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
779 through the exploded_graph. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
780
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
781 const char *
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
782 exploded_node::get_dot_fillcolor () const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
783 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
784 const program_state &state = get_state ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
785
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
786 /* We want to be able to easily distinguish the no-sm-state case,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
787 and to be able to distinguish cases where there's a single state
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
788 from each other.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
789
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
790 Sum the sm_states, and use the result to choose from a table,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
791 modulo table-size, special-casing the "no sm-state" case. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
792 int total_sm_state = 0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
793 int i;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
794 sm_state_map *smap;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
795 FOR_EACH_VEC_ELT (state.m_checker_states, i, smap)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
796 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
797 for (sm_state_map::iterator_t iter = smap->begin ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
798 iter != smap->end ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
799 ++iter)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
800 total_sm_state += (*iter).second.m_state;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
801 total_sm_state += smap->get_global_state ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
802 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
803
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
804 if (total_sm_state > 0)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
805 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
806 /* An arbitrarily-picked collection of light colors. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
807 const char * const colors[]
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
808 = {"azure", "coral", "cornsilk", "lightblue", "yellow"};
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
809 const int num_colors = sizeof (colors) / sizeof (colors[0]);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
810 return colors[total_sm_state % num_colors];
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
811 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
812 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
813 /* No sm-state. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
814 return "lightgrey";
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
815 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
816
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
817 /* Implementation of dnode::dump_dot vfunc for exploded_node. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
818
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
819 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
820 exploded_node::dump_dot (graphviz_out *gv, const dump_args_t &args) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
821 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
822 pretty_printer *pp = gv->get_pp ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
823
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
824 dump_dot_id (pp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
825 pp_printf (pp, " [shape=none,margin=0,style=filled,fillcolor=%s,label=\"",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
826 get_dot_fillcolor ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
827 pp_write_text_to_stream (pp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
828
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
829 pp_printf (pp, "EN: %i", m_index);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
830 if (m_status == STATUS_MERGER)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
831 pp_string (pp, " (merger)");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
832 pp_newline (pp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
833
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
834 format f (true);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
835 m_ps.get_point ().print (pp, f);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
836 pp_newline (pp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
837
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
838 const extrinsic_state &ext_state = args.m_eg.get_ext_state ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
839 const program_state &state = m_ps.get_state ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
840 state.dump_to_pp (ext_state, true, pp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
841 pp_newline (pp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
842
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
843 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
844 int i;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
845 sm_state_map *smap;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
846 FOR_EACH_VEC_ELT (state.m_checker_states, i, smap)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
847 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
848 if (!smap->is_empty_p ())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
849 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
850 pp_printf (pp, "%s: ", ext_state.get_name (i));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
851 smap->print (ext_state.get_sm (i), pp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
852 pp_newline (pp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
853 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
854 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
855 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
856
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
857 pp_write_text_as_dot_label_to_stream (pp, /*for_record=*/true);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
858
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
859 pp_string (pp, "\"];\n\n");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
860 pp_flush (pp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
861 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
862
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
863 /* Dump this to PP in a form suitable for use as an id in .dot output. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
864
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
865 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
866 exploded_node::dump_dot_id (pretty_printer *pp) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
867 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
868 pp_printf (pp, "exploded_node_%i", m_index);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
869 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
870
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
871 /* Dump a multiline representation of this node to PP. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
872
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
873 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
874 exploded_node::dump_to_pp (pretty_printer *pp,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
875 const extrinsic_state &ext_state) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
876 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
877 pp_printf (pp, "EN: %i", m_index);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
878 pp_newline (pp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
879
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
880 format f (true);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
881 m_ps.get_point ().print (pp, f);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
882 pp_newline (pp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
883
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
884 m_ps.get_state ().dump_to_pp (ext_state, false, pp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
885 pp_newline (pp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
886 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
887
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
888 /* Dump a multiline representation of this node to FILE. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
889
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
890 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
891 exploded_node::dump (FILE *fp,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
892 const extrinsic_state &ext_state) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
893 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
894 pretty_printer pp;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
895 pp_format_decoder (&pp) = default_tree_printer;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
896 pp_show_color (&pp) = pp_show_color (global_dc->printer);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
897 pp.buffer->stream = fp;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
898 dump_to_pp (&pp, ext_state);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
899 pp_flush (&pp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
900 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
901
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
902 /* Dump a multiline representation of this node to stderr. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
903
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
904 DEBUG_FUNCTION void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
905 exploded_node::dump (const extrinsic_state &ext_state) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
906 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
907 dump (stderr, ext_state);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
908 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
909
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
910 } // namespace ana
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
911
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
912 /* Return true if FNDECL has a gimple body. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
913 // TODO: is there a pre-canned way to do this?
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
914
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
915 bool
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
916 fndecl_has_gimple_body_p (tree fndecl)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
917 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
918 if (fndecl == NULL_TREE)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
919 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
920
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
921 cgraph_node *n = cgraph_node::get (fndecl);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
922 if (!n)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
923 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
924
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
925 return n->has_gimple_body_p ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
926 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
927
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
928 namespace ana {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
929
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
930 /* A pending_diagnostic subclass for implementing "__analyzer_dump_path". */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
931
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
932 class dump_path_diagnostic
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
933 : public pending_diagnostic_subclass<dump_path_diagnostic>
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
934 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
935 public:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
936 bool emit (rich_location *richloc) FINAL OVERRIDE
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
937 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
938 inform (richloc, "path");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
939 return true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
940 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
941
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
942 const char *get_kind () const FINAL OVERRIDE { return "dump_path_diagnostic"; }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
943
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
944 bool operator== (const dump_path_diagnostic &) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
945 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
946 return true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
947 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
948 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
949
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
950 /* Modify STATE in place, applying the effects of the stmt at this node's
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
951 point. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
952
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
953 exploded_node::on_stmt_flags
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
954 exploded_node::on_stmt (exploded_graph &eg,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
955 const supernode *snode,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
956 const gimple *stmt,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
957 program_state *state,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
958 state_change *change) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
959 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
960 /* Preserve the old state. It is used here for looking
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
961 up old checker states, for determining state transitions, and
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
962 also within impl_region_model_context and impl_sm_context for
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
963 going from tree to svalue_id. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
964 const program_state old_state (*state);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
965
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
966 impl_region_model_context ctxt (eg, this,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
967 &old_state, state, change,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
968 stmt);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
969
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
970 if (const gassign *assign = dyn_cast <const gassign *> (stmt))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
971 state->m_region_model->on_assignment (assign, &ctxt);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
972
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
973 if (const greturn *return_ = dyn_cast <const greturn *> (stmt))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
974 state->m_region_model->on_return (return_, &ctxt);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
975
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
976 /* Track whether we have a gcall to a function that's not recognized by
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
977 anything, for which we don't have a function body, or for which we
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
978 don't know the fndecl. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
979 bool unknown_side_effects = false;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
980 if (const gcall *call = dyn_cast <const gcall *> (stmt))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
981 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
982 /* Debugging/test support. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
983 if (is_special_named_call_p (call, "__analyzer_dump", 0))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
984 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
985 /* Handle the builtin "__analyzer_dump" by dumping state
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
986 to stderr. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
987 dump (eg.get_ext_state ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
988 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
989 else if (is_special_named_call_p (call, "__analyzer_dump_path", 0))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
990 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
991 /* Handle the builtin "__analyzer_dump_path" by queuing a
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
992 diagnostic at this exploded_node. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
993 ctxt.warn (new dump_path_diagnostic ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
994 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
995 else if (is_special_named_call_p (call, "__analyzer_dump_region_model", 0))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
996 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
997 /* Handle the builtin "__analyzer_dump_region_model" by dumping
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
998 the region model's state to stderr. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
999 state->m_region_model->dump (false);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1000 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1001 else if (is_special_named_call_p (call, "__analyzer_eval", 1))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1002 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1003 /* Handle the builtin "__analyzer_eval" by evaluating the input
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1004 and dumping as a dummy warning, so that test cases can use
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1005 dg-warning to validate the result (and so unexpected warnings will
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1006 lead to DejaGnu failures). */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1007 tree t_arg = gimple_call_arg (call, 0);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1008 tristate t
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1009 = state->m_region_model->eval_condition (t_arg,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1010 NE_EXPR,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1011 integer_zero_node,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1012 &ctxt);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1013 warning_at (call->location, 0, "%s", t.as_string ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1014 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1015 else if (is_special_named_call_p (call, "__analyzer_break", 0))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1016 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1017 /* Handle the builtin "__analyzer_break" by triggering a
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1018 breakpoint. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1019 /* TODO: is there a good cross-platform way to do this? */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1020 raise (SIGINT);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1021 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1022 else if (is_special_named_call_p (call, "__analyzer_dump_exploded_nodes",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1023 1))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1024 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1025 /* This is handled elsewhere. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1026 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1027 else if (is_setjmp_call_p (call))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1028 state->m_region_model->on_setjmp (call, this, &ctxt);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1029 else if (is_longjmp_call_p (call))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1030 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1031 on_longjmp (eg, call, state, &ctxt);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1032 return on_stmt_flags::terminate_path ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1033 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1034 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1035 unknown_side_effects = state->m_region_model->on_call_pre (call, &ctxt);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1036 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1037
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1038 bool any_sm_changes = false;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1039 int sm_idx;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1040 sm_state_map *smap;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1041 FOR_EACH_VEC_ELT (old_state.m_checker_states, sm_idx, smap)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1042 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1043 const state_machine &sm = eg.get_ext_state ().get_sm (sm_idx);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1044 const sm_state_map *old_smap
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1045 = old_state.m_checker_states[sm_idx];
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1046 sm_state_map *new_smap = state->m_checker_states[sm_idx];
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1047 impl_sm_context sm_ctxt (eg, sm_idx, sm, this, &old_state, state,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1048 change,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1049 old_smap, new_smap);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1050 /* Allow the state_machine to handle the stmt. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1051 if (sm.on_stmt (&sm_ctxt, snode, stmt))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1052 unknown_side_effects = false;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1053 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1054 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1055 /* For those stmts that were not handled by the state machine. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1056 if (const gcall *call = dyn_cast <const gcall *> (stmt))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1057 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1058 tree callee_fndecl
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1059 = state->m_region_model->get_fndecl_for_call (call, &ctxt);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1060
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1061 if (!fndecl_has_gimple_body_p (callee_fndecl))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1062 new_smap->purge_for_unknown_fncall (eg, sm, call, callee_fndecl,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1063 state->m_region_model);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1064 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1065 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1066 if (*old_smap != *new_smap)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1067 any_sm_changes = true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1068 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1069
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1070 if (const gcall *call = dyn_cast <const gcall *> (stmt))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1071 state->m_region_model->on_call_post (call, unknown_side_effects, &ctxt);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1072
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1073 return on_stmt_flags (any_sm_changes);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1074 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1075
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1076 /* Consider the effect of following superedge SUCC from this node.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1077
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1078 Return true if it's feasible to follow the edge, or false
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1079 if it's infeasible.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1080
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1081 Examples: if it's the "true" branch within
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1082 a CFG and we know the conditional is false, we know it's infeasible.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1083 If it's one of multiple interprocedual "return" edges, then only
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1084 the edge back to the most recent callsite is feasible.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1085
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1086 Update NEXT_STATE accordingly (e.g. to record that a condition was
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1087 true or false, or that the NULL-ness of a pointer has been checked,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1088 pushing/popping stack frames, etc).
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1089
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1090 Update NEXT_POINT accordingly (updating the call string). */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1091
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1092 bool
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1093 exploded_node::on_edge (exploded_graph &eg,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1094 const superedge *succ,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1095 program_point *next_point,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1096 program_state *next_state,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1097 state_change *change) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1098 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1099 LOG_FUNC (eg.get_logger ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1100
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1101 if (!next_point->on_edge (eg, succ))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1102 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1103
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1104 if (!next_state->on_edge (eg, *this, succ, change))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1105 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1106
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1107 return true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1108 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1109
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1110 /* Verify that the stack at LONGJMP_POINT is still valid, given a call
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1111 to "setjmp" at SETJMP_POINT - the stack frame that "setjmp" was
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1112 called in must still be valid.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1113
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1114 Caveat: this merely checks the call_strings in the points; it doesn't
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1115 detect the case where a frame returns and is then called again. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1116
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1117 static bool
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1118 valid_longjmp_stack_p (const program_point &longjmp_point,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1119 const program_point &setjmp_point)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1120 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1121 const call_string &cs_at_longjmp = longjmp_point.get_call_string ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1122 const call_string &cs_at_setjmp = setjmp_point.get_call_string ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1123
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1124 if (cs_at_longjmp.length () < cs_at_setjmp.length ())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1125 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1126
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1127 /* Check that the call strings match, up to the depth of the
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1128 setjmp point. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1129 for (unsigned depth = 0; depth < cs_at_setjmp.length (); depth++)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1130 if (cs_at_longjmp[depth] != cs_at_setjmp[depth])
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1131 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1132
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1133 return true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1134 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1135
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1136 /* A pending_diagnostic subclass for complaining about bad longjmps,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1137 where the enclosing function of the "setjmp" has returned (and thus
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1138 the stack frame no longer exists). */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1139
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1140 class stale_jmp_buf : public pending_diagnostic_subclass<dump_path_diagnostic>
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1141 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1142 public:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1143 stale_jmp_buf (const gcall *setjmp_call, const gcall *longjmp_call)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1144 : m_setjmp_call (setjmp_call), m_longjmp_call (longjmp_call)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1145 {}
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1146
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1147 bool emit (rich_location *richloc) FINAL OVERRIDE
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1148 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1149 return warning_at
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1150 (richloc, OPT_Wanalyzer_stale_setjmp_buffer,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1151 "%qs called after enclosing function of %qs has returned",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1152 get_user_facing_name (m_longjmp_call),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1153 get_user_facing_name (m_setjmp_call));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1154 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1155
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1156 const char *get_kind () const FINAL OVERRIDE
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1157 { return "stale_jmp_buf"; }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1158
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1159 bool operator== (const stale_jmp_buf &other) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1160 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1161 return (m_setjmp_call == other.m_setjmp_call
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1162 && m_longjmp_call == other.m_longjmp_call);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1163 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1164
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1165 private:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1166 const gcall *m_setjmp_call;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1167 const gcall *m_longjmp_call;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1168 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1169
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1170 /* Handle LONGJMP_CALL, a call to longjmp or siglongjmp.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1171
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1172 Attempt to locate where setjmp/sigsetjmp was called on the jmp_buf and build
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1173 an exploded_node and exploded_edge to it representing a rewind to that frame,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1174 handling the various kinds of failure that can occur. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1175
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1176 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1177 exploded_node::on_longjmp (exploded_graph &eg,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1178 const gcall *longjmp_call,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1179 program_state *new_state,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1180 region_model_context *ctxt) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1181 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1182 tree buf_ptr = gimple_call_arg (longjmp_call, 0);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1183
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1184 region_model *new_region_model = new_state->m_region_model;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1185 region_id buf_rid = new_region_model->deref_rvalue (buf_ptr, ctxt);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1186 region *buf = new_region_model->get_region (buf_rid);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1187 if (!buf)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1188 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1189
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1190 svalue_id buf_content_sid
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1191 = buf->get_value (*new_region_model, false, ctxt);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1192 svalue *buf_content_sval = new_region_model->get_svalue (buf_content_sid);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1193 if (!buf_content_sval)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1194 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1195 setjmp_svalue *setjmp_sval = buf_content_sval->dyn_cast_setjmp_svalue ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1196 if (!setjmp_sval)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1197 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1198
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1199 const setjmp_record tmp_setjmp_record = setjmp_sval->get_setjmp_record ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1200
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1201 /* Build a custom enode and eedge for rewinding from the longjmp/siglongjmp
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1202 call back to the setjmp/sigsetjmp. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1203 rewind_info_t rewind_info (tmp_setjmp_record, longjmp_call);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1204
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1205 const gcall *setjmp_call = rewind_info.get_setjmp_call ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1206 const program_point &setjmp_point = rewind_info.get_setjmp_point ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1207
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1208 const program_point &longjmp_point = get_point ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1209
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1210 /* Verify that the setjmp's call_stack hasn't been popped. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1211 if (!valid_longjmp_stack_p (longjmp_point, setjmp_point))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1212 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1213 ctxt->warn (new stale_jmp_buf (setjmp_call, longjmp_call));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1214 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1215 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1216
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1217 gcc_assert (longjmp_point.get_stack_depth ()
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1218 >= setjmp_point.get_stack_depth ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1219
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1220 /* Update the state for use by the destination node. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1221
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1222 /* Stash the current number of diagnostics so that we can update
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1223 any that this adds to show where the longjmp is rewinding to. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1224
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1225 diagnostic_manager *dm = &eg.get_diagnostic_manager ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1226 unsigned prev_num_diagnostics = dm->get_num_diagnostics ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1227
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1228 new_region_model->on_longjmp (longjmp_call, setjmp_call,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1229 setjmp_point.get_stack_depth (), ctxt);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1230
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1231 program_point next_point
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1232 = program_point::after_supernode (setjmp_point.get_supernode (),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1233 setjmp_point.get_call_string ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1234
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1235 state_change change;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1236 exploded_node *next = eg.get_or_create_node (next_point, *new_state, &change);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1237
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1238 /* Create custom exploded_edge for a longjmp. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1239 if (next)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1240 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1241 exploded_edge *eedge
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1242 = eg.add_edge (const_cast<exploded_node *> (this), next, NULL,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1243 change,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1244 new rewind_info_t (tmp_setjmp_record, longjmp_call));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1245
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1246 /* For any diagnostics that were queued here (such as leaks) we want
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1247 the checker_path to show the rewinding events after the "final event"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1248 so that the user sees where the longjmp is rewinding to (otherwise the
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1249 path is meaningless).
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1250
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1251 For example, we want to emit something like:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1252 | NN | {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1253 | NN | longjmp (env, 1);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1254 | | ~~~~~~~~~~~~~~~~
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1255 | | |
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1256 | | (10) 'ptr' leaks here; was allocated at (7)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1257 | | (11) rewinding from 'longjmp' in 'inner'...
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1258 |
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1259 <-------------+
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1260 |
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1261 'outer': event 12
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1262 |
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1263 | NN | i = setjmp(env);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1264 | | ^~~~~~
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1265 | | |
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1266 | | (12) ...to 'setjmp' in 'outer' (saved at (2))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1267
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1268 where the "final" event above is event (10), but we want to append
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1269 events (11) and (12) afterwards.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1270
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1271 Do this by setting m_trailing_eedge on any diagnostics that were
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1272 just saved. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1273 unsigned num_diagnostics = dm->get_num_diagnostics ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1274 for (unsigned i = prev_num_diagnostics; i < num_diagnostics; i++)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1275 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1276 saved_diagnostic *sd = dm->get_saved_diagnostic (i);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1277 sd->m_trailing_eedge = eedge;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1278 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1279 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1280 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1281
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1282 /* Subroutine of exploded_graph::process_node for finding the successors
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1283 of the supernode for a function exit basic block.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1284
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1285 Ensure that pop_frame is called, potentially queuing diagnostics about
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1286 leaks. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1287
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1288 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1289 exploded_node::detect_leaks (exploded_graph &eg) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1290 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1291 LOG_FUNC_1 (eg.get_logger (), "EN: %i", m_index);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1292
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1293 gcc_assert (get_point ().get_supernode ()->return_p ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1294
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1295 /* If we're not a "top-level" function, do nothing; pop_frame
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1296 will be called when handling the return superedge. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1297 if (get_point ().get_stack_depth () > 1)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1298 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1299
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1300 /* We have a "top-level" function. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1301 gcc_assert (get_point ().get_stack_depth () == 1);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1302
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1303 const program_state &old_state = get_state ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1304
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1305 /* Work with a temporary copy of the state: pop the frame, and see
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1306 what leaks (via purge_unused_svalues). */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1307 program_state new_state (old_state);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1308
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1309 gcc_assert (new_state.m_region_model);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1310
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1311 purge_stats stats;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1312 impl_region_model_context ctxt (eg, this,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1313 &old_state, &new_state,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1314 NULL,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1315 get_stmt ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1316 new_state.m_region_model->pop_frame (true, &stats, &ctxt);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1317 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1318
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1319 /* Dump the successors and predecessors of this enode to OUTF. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1320
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1321 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1322 exploded_node::dump_succs_and_preds (FILE *outf) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1323 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1324 unsigned i;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1325 exploded_edge *e;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1326 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1327 auto_vec<exploded_node *> preds (m_preds.length ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1328 FOR_EACH_VEC_ELT (m_preds, i, e)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1329 preds.quick_push (e->m_src);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1330 pretty_printer pp;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1331 print_enode_indices (&pp, preds);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1332 fprintf (outf, "preds: %s\n",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1333 pp_formatted_text (&pp));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1334 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1335 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1336 auto_vec<exploded_node *> succs (m_succs.length ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1337 FOR_EACH_VEC_ELT (m_succs, i, e)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1338 succs.quick_push (e->m_dest);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1339 pretty_printer pp;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1340 print_enode_indices (&pp, succs);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1341 fprintf (outf, "succs: %s\n",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1342 pp_formatted_text (&pp));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1343 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1344 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1345
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1346 /* class rewind_info_t : public exploded_edge::custom_info_t. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1347
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1348 /* Implementation of exploded_edge::custom_info_t::update_model vfunc
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1349 for rewind_info_t.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1350
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1351 Update state for the special-case of a rewind of a longjmp
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1352 to a setjmp (which doesn't have a superedge, but does affect
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1353 state). */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1354
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1355 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1356 rewind_info_t::update_model (region_model *model,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1357 const exploded_edge &eedge)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1358 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1359 const program_point &longjmp_point = eedge.m_src->get_point ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1360 const program_point &setjmp_point = eedge.m_dest->get_point ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1361
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1362 gcc_assert (longjmp_point.get_stack_depth ()
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1363 >= setjmp_point.get_stack_depth ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1364
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1365 model->on_longjmp (get_longjmp_call (),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1366 get_setjmp_call (),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1367 setjmp_point.get_stack_depth (), NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1368 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1369
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1370 /* Implementation of exploded_edge::custom_info_t::add_events_to_path vfunc
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1371 for rewind_info_t. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1372
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1373 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1374 rewind_info_t::add_events_to_path (checker_path *emission_path,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1375 const exploded_edge &eedge)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1376 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1377 const exploded_node *src_node = eedge.m_src;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1378 const program_point &src_point = src_node->get_point ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1379 const int src_stack_depth = src_point.get_stack_depth ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1380 const exploded_node *dst_node = eedge.m_dest;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1381 const program_point &dst_point = dst_node->get_point ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1382 const int dst_stack_depth = dst_point.get_stack_depth ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1383
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1384 emission_path->add_event
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1385 (new rewind_from_longjmp_event
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1386 (&eedge, get_longjmp_call ()->location,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1387 src_point.get_fndecl (),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1388 src_stack_depth, this));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1389 emission_path->add_event
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1390 (new rewind_to_setjmp_event
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1391 (&eedge, get_setjmp_call ()->location,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1392 dst_point.get_fndecl (),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1393 dst_stack_depth, this));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1394 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1395
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1396 /* class exploded_edge : public dedge<eg_traits>. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1397
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1398 /* exploded_edge's ctor. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1399
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1400 exploded_edge::exploded_edge (exploded_node *src, exploded_node *dest,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1401 const extrinsic_state &ext_state,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1402 const superedge *sedge,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1403 const state_change &change,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1404 custom_info_t *custom_info)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1405 : dedge<eg_traits> (src, dest), m_sedge (sedge), m_change (change),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1406 m_custom_info (custom_info)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1407 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1408 change.validate (dest->get_state (), ext_state);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1409 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1410
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1411 /* exploded_edge's dtor. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1412
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1413 exploded_edge::~exploded_edge ()
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1414 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1415 delete m_custom_info;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1416 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1417
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1418 /* Implementation of dedge::dump_dot vfunc for exploded_edge.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1419 Use the label of the underlying superedge, if any. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1420
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1421 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1422 exploded_edge::dump_dot (graphviz_out *gv, const dump_args_t &args) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1423 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1424 pretty_printer *pp = gv->get_pp ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1425
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1426 const char *style = "\"solid,bold\"";
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1427 const char *color = "black";
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1428 int weight = 10;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1429 const char *constraint = "true";
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1430
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1431 if (m_sedge)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1432 switch (m_sedge->m_kind)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1433 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1434 default:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1435 gcc_unreachable ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1436 case SUPEREDGE_CFG_EDGE:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1437 break;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1438 case SUPEREDGE_CALL:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1439 color = "red";
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1440 //constraint = "false";
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1441 break;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1442 case SUPEREDGE_RETURN:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1443 color = "green";
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1444 //constraint = "false";
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1445 break;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1446 case SUPEREDGE_INTRAPROCEDURAL_CALL:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1447 style = "\"dotted\"";
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1448 break;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1449 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1450 if (m_custom_info)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1451 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1452 color = "red";
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1453 style = "\"dotted\"";
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1454 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1455
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1456 m_src->dump_dot_id (pp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1457 pp_string (pp, " -> ");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1458 m_dest->dump_dot_id (pp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1459 pp_printf (pp,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1460 (" [style=%s, color=%s, weight=%d, constraint=%s,"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1461 " headlabel=\""),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1462 style, color, weight, constraint);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1463
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1464 if (m_sedge)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1465 m_sedge->dump_label_to_pp (pp, false);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1466 else if (m_custom_info)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1467 m_custom_info->print (pp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1468
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1469 m_change.dump (pp, args.m_eg.get_ext_state ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1470 //pp_write_text_as_dot_label_to_stream (pp, /*for_record=*/false);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1471
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1472 pp_printf (pp, "\"];\n");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1473 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1474
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1475 /* struct stats. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1476
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1477 /* stats' ctor. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1478
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1479 stats::stats (int num_supernodes)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1480 : m_node_reuse_count (0),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1481 m_node_reuse_after_merge_count (0),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1482 m_num_supernodes (num_supernodes)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1483 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1484 for (int i = 0; i < NUM_POINT_KINDS; i++)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1485 m_num_nodes[i] = 0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1486 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1487
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1488 /* Log these stats in multiline form to LOGGER. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1489
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1490 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1491 stats::log (logger *logger) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1492 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1493 gcc_assert (logger);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1494 for (int i = 0; i < NUM_POINT_KINDS; i++)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1495 logger->log ("m_num_nodes[%s]: %i",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1496 point_kind_to_string (static_cast <enum point_kind> (i)),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1497 m_num_nodes[i]);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1498 logger->log ("m_node_reuse_count: %i", m_node_reuse_count);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1499 logger->log ("m_node_reuse_after_merge_count: %i",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1500 m_node_reuse_after_merge_count);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1501 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1502
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1503 /* Dump these stats in multiline form to OUT. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1504
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1505 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1506 stats::dump (FILE *out) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1507 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1508 for (int i = 0; i < NUM_POINT_KINDS; i++)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1509 fprintf (out, "m_num_nodes[%s]: %i\n",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1510 point_kind_to_string (static_cast <enum point_kind> (i)),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1511 m_num_nodes[i]);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1512 fprintf (out, "m_node_reuse_count: %i\n", m_node_reuse_count);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1513 fprintf (out, "m_node_reuse_after_merge_count: %i\n",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1514 m_node_reuse_after_merge_count);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1515
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1516 if (m_num_supernodes > 0)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1517 fprintf (out, "PK_AFTER_SUPERNODE nodes per supernode: %.2f\n",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1518 (float)m_num_nodes[PK_AFTER_SUPERNODE] / (float)m_num_supernodes);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1519 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1520
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1521 /* strongly_connected_components's ctor. Tarjan's SCC algorithm. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1522
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1523 strongly_connected_components::
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1524 strongly_connected_components (const supergraph &sg, logger *logger)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1525 : m_sg (sg), m_per_node (m_sg.num_nodes ())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1526 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1527 LOG_SCOPE (logger);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1528 auto_timevar tv (TV_ANALYZER_SCC);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1529
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1530 for (int i = 0; i < m_sg.num_nodes (); i++)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1531 m_per_node.quick_push (per_node_data ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1532
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1533 for (int i = 0; i < m_sg.num_nodes (); i++)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1534 if (m_per_node[i].m_index == -1)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1535 strong_connect (i);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1536
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1537 if (0)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1538 dump ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1539 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1540
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1541 /* Dump this object to stderr. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1542
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1543 DEBUG_FUNCTION void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1544 strongly_connected_components::dump () const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1545 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1546 for (int i = 0; i < m_sg.num_nodes (); i++)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1547 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1548 const per_node_data &v = m_per_node[i];
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1549 fprintf (stderr, "SN %i: index: %i lowlink: %i on_stack: %i\n",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1550 i, v.m_index, v.m_lowlink, v.m_on_stack);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1551 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1552 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1553
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1554 /* Subroutine of strongly_connected_components's ctor, part of Tarjan's
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1555 SCC algorithm. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1556
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1557 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1558 strongly_connected_components::strong_connect (unsigned index)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1559 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1560 supernode *v_snode = m_sg.get_node_by_index (index);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1561
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1562 /* Set the depth index for v to the smallest unused index. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1563 per_node_data *v = &m_per_node[index];
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1564 v->m_index = index;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1565 v->m_lowlink = index;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1566 m_stack.safe_push (index);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1567 v->m_on_stack = true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1568 index++;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1569
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1570 /* Consider successors of v. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1571 unsigned i;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1572 superedge *sedge;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1573 FOR_EACH_VEC_ELT (v_snode->m_succs, i, sedge)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1574 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1575 supernode *w_snode = sedge->m_dest;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1576 per_node_data *w = &m_per_node[w_snode->m_index];
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1577 if (w->m_index == -1)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1578 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1579 /* Successor w has not yet been visited; recurse on it. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1580 strong_connect (w_snode->m_index);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1581 v->m_lowlink = MIN (v->m_lowlink, w->m_lowlink);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1582 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1583 else if (w->m_on_stack)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1584 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1585 /* Successor w is in stack S and hence in the current SCC
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1586 If w is not on stack, then (v, w) is a cross-edge in the DFS
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1587 tree and must be ignored. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1588 v->m_lowlink = MIN (v->m_lowlink, w->m_index);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1589 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1590 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1591
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1592 /* If v is a root node, pop the stack and generate an SCC. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1593
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1594 if (v->m_lowlink == v->m_index)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1595 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1596 per_node_data *w;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1597 do {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1598 int idx = m_stack.pop ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1599 w = &m_per_node[idx];
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1600 w->m_on_stack = false;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1601 } while (w != v);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1602 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1603 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1604
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1605 /* worklist's ctor. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1606
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1607 worklist::worklist (const exploded_graph &eg, const analysis_plan &plan)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1608 : m_eg (eg),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1609 m_scc (eg.get_supergraph (), eg.get_logger ()),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1610 m_plan (plan),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1611 m_queue (key_t (*this, NULL))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1612 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1613 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1614
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1615 /* Return the number of nodes in the worklist. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1616
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1617 unsigned
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1618 worklist::length () const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1619 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1620 return m_queue.nodes ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1621 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1622
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1623 /* Return the next node in the worklist, removing it. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1624
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1625 exploded_node *
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1626 worklist::take_next ()
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1627 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1628 return m_queue.extract_min ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1629 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1630
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1631 /* Return the next node in the worklist without removing it. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1632
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1633 exploded_node *
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1634 worklist::peek_next ()
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1635 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1636 return m_queue.min ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1637 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1638
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1639 /* Add ENODE to the worklist. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1640
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1641 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1642 worklist::add_node (exploded_node *enode)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1643 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1644 gcc_assert (enode->get_status () == exploded_node::STATUS_WORKLIST);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1645 m_queue.insert (key_t (*this, enode), enode);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1646 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1647
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1648 /* Comparator for implementing worklist::key_t comparison operators.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1649 Return negative if KA is before KB
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1650 Return positive if KA is after KB
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1651 Return 0 if they are equal. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1652
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1653 int
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1654 worklist::key_t::cmp (const worklist::key_t &ka, const worklist::key_t &kb)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1655 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1656 const program_point &point_a = ka.m_enode->get_point ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1657 const program_point &point_b = kb.m_enode->get_point ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1658 const call_string &call_string_a = point_a.get_call_string ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1659 const call_string &call_string_b = point_b.get_call_string ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1660
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1661 /* Order empty-callstring points with different functions based on the
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1662 analysis_plan, so that we generate summaries before they are used. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1663 if (flag_analyzer_call_summaries
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1664 && call_string_a.empty_p ()
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1665 && call_string_b.empty_p ()
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1666 && point_a.get_function () != NULL
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1667 && point_b.get_function () != NULL
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1668 && point_a.get_function () != point_b.get_function ())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1669 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1670 return ka.m_worklist.m_plan.cmp_function (point_a.get_function (),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1671 point_b.get_function ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1672 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1673
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1674 /* First, order by SCC. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1675 int scc_id_a = ka.get_scc_id (ka.m_enode);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1676 int scc_id_b = kb.get_scc_id (kb.m_enode);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1677 if (scc_id_a != scc_id_b)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1678 return scc_id_a - scc_id_b;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1679
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1680 /* If in same SCC, order by supernode index (an arbitrary but stable
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1681 ordering). */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1682 const supernode *snode_a = ka.m_enode->get_supernode ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1683 const supernode *snode_b = kb.m_enode->get_supernode ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1684 if (snode_a == NULL)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1685 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1686 if (snode_b != NULL)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1687 /* One is NULL. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1688 return -1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1689 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1690 /* Both are NULL. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1691 return 0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1692 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1693 if (snode_b == NULL)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1694 /* One is NULL. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1695 return 1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1696 /* Neither are NULL. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1697 gcc_assert (snode_a && snode_b);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1698 if (snode_a->m_index != snode_b->m_index)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1699 return snode_a->m_index - snode_b->m_index;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1700
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1701 gcc_assert (snode_a == snode_b);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1702
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1703 /* Order within supernode via program point. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1704 int within_snode_cmp
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1705 = function_point::cmp_within_supernode (point_a.get_function_point (),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1706 point_b.get_function_point ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1707 if (within_snode_cmp)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1708 return within_snode_cmp;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1709
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1710 /* The points might vary by callstring; try sorting by callstring. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1711 int cs_cmp = call_string::cmp (call_string_a, call_string_b);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1712 if (cs_cmp)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1713 return cs_cmp;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1714
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1715 /* Otherwise, we ought to have the same program_point. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1716 gcc_assert (point_a == point_b);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1717
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1718 const program_state &state_a = ka.m_enode->get_state ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1719 const program_state &state_b = kb.m_enode->get_state ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1720
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1721 /* Sort by sm-state, so that identical sm-states are grouped
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1722 together in the worklist.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1723 For now, sort by the hash value (might not be deterministic). */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1724 for (unsigned sm_idx = 0; sm_idx < state_a.m_checker_states.length ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1725 ++sm_idx)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1726 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1727 sm_state_map *smap_a = state_a.m_checker_states[sm_idx];
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1728 sm_state_map *smap_b = state_b.m_checker_states[sm_idx];
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1729
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1730 hashval_t hash_a = smap_a->hash ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1731 hashval_t hash_b = smap_b->hash ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1732 if (hash_a < hash_b)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1733 return -1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1734 else if (hash_a > hash_b)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1735 return 1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1736 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1737
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1738 /* Otherwise, we have two enodes at the same program point but with
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1739 different states. We don't have a good total ordering on states,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1740 so order them by enode index, so that we have at least have a
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1741 stable sort. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1742 return ka.m_enode->m_index - kb.m_enode->m_index;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1743 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1744
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1745 /* exploded_graph's ctor. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1746
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1747 exploded_graph::exploded_graph (const supergraph &sg, logger *logger,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1748 const extrinsic_state &ext_state,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1749 const state_purge_map *purge_map,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1750 const analysis_plan &plan,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1751 int verbosity)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1752 : m_sg (sg), m_logger (logger),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1753 m_worklist (*this, plan),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1754 m_ext_state (ext_state),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1755 m_purge_map (purge_map),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1756 m_plan (plan),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1757 m_diagnostic_manager (logger, verbosity),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1758 m_global_stats (m_sg.num_nodes ()),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1759 m_functionless_stats (m_sg.num_nodes ()),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1760 m_PK_AFTER_SUPERNODE_per_snode (m_sg.num_nodes ())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1761 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1762 m_origin = get_or_create_node (program_point (function_point (NULL, NULL,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1763 0, PK_ORIGIN),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1764 call_string ()),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1765 program_state (ext_state), NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1766 for (int i = 0; i < m_sg.num_nodes (); i++)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1767 m_PK_AFTER_SUPERNODE_per_snode.quick_push (i);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1768 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1769
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1770 /* exploded_graph's dtor. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1771
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1772 exploded_graph::~exploded_graph ()
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1773 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1774 for (function_stat_map_t::iterator iter = m_per_function_stats.begin ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1775 iter != m_per_function_stats.end ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1776 ++iter)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1777 delete (*iter).second;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1778
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1779 for (point_map_t::iterator iter = m_per_point_data.begin ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1780 iter != m_per_point_data.end ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1781 ++iter)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1782 delete (*iter).second;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1783 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1784
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1785 /* Ensure that there is an exploded_node representing an external call to
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1786 FUN, adding it to the worklist if creating it.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1787
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1788 Add an edge from the origin exploded_node to the function entrypoint
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1789 exploded_node.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1790
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1791 Return the exploded_node for the entrypoint to the function. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1792
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1793 exploded_node *
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1794 exploded_graph::add_function_entry (function *fun)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1795 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1796 program_point point = program_point::from_function_entry (m_sg, fun);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1797 program_state state (m_ext_state);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1798 state.m_region_model->push_frame (fun, NULL, NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1799
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1800 exploded_node *enode = get_or_create_node (point, state, NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1801 /* We should never fail to add such a node. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1802 gcc_assert (enode);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1803 state_change change;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1804 add_edge (m_origin, enode, NULL, change);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1805 return enode;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1806 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1807
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1808 /* Get or create an exploded_node for (POINT, STATE).
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1809 If a new node is created, it is added to the worklist.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1810 If CHANGE is non-NULL, use it to suppress some purging of state,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1811 to make generation of state_change_event instances easier. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1812
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1813 exploded_node *
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1814 exploded_graph::get_or_create_node (const program_point &point,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1815 const program_state &state,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1816 state_change *change)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1817 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1818 logger * const logger = get_logger ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1819 LOG_FUNC (logger);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1820 if (logger)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1821 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1822 format f (false);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1823 pretty_printer *pp = logger->get_printer ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1824 logger->start_log_line ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1825 pp_string (pp, "point: ");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1826 point.print (pp, f);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1827 logger->end_log_line ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1828 logger->start_log_line ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1829 pp_string (pp, "state: ");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1830 state.dump (m_ext_state, true);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1831 logger->end_log_line ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1832 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1833
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1834 auto_cfun sentinel (point.get_function ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1835
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1836 state.validate (get_ext_state ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1837
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1838 //state.dump (get_ext_state ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1839
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1840 /* Prune state to try to improve the chances of a cache hit,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1841 avoiding generating redundant nodes. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1842 program_state pruned_state = state.prune_for_point (*this, point, change);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1843
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1844 pruned_state.validate (get_ext_state ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1845
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1846 //pruned_state.dump (get_ext_state ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1847
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1848 if (logger)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1849 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1850 pretty_printer *pp = logger->get_printer ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1851 logger->start_log_line ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1852 pp_string (pp, "pruned_state: ");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1853 pruned_state.dump_to_pp (m_ext_state, true, pp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1854 logger->end_log_line ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1855 pruned_state.m_region_model->dump_to_pp (logger->get_printer (), true);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1856 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1857
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1858 stats *per_fn_stats = get_or_create_function_stats (point.get_function ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1859
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1860 stats *per_cs_stats
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1861 = &get_or_create_per_call_string_data (point.get_call_string ())->m_stats;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1862
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1863 point_and_state ps (point, pruned_state);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1864 ps.validate (m_ext_state);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1865 if (exploded_node **slot = m_point_and_state_to_node.get (&ps))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1866 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1867 /* An exploded_node for PS already exists. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1868 if (logger)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1869 logger->log ("reused EN: %i", (*slot)->m_index);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1870 m_global_stats.m_node_reuse_count++;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1871 per_fn_stats->m_node_reuse_count++;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1872 per_cs_stats->m_node_reuse_count++;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1873 return *slot;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1874 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1875
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1876 per_program_point_data *per_point_data
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1877 = get_or_create_per_program_point_data (point);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1878
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1879 /* Consider merging state with another enode at this program_point. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1880 if (flag_analyzer_state_merge)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1881 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1882 exploded_node *existing_enode;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1883 unsigned i;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1884 FOR_EACH_VEC_ELT (per_point_data->m_enodes, i, existing_enode)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1885 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1886 if (logger)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1887 logger->log ("considering merging with existing EN: %i for point",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1888 existing_enode->m_index);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1889 gcc_assert (existing_enode->get_point () == point);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1890 const program_state &existing_state = existing_enode->get_state ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1891
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1892 /* This merges successfully within the loop. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1893
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1894 program_state merged_state (m_ext_state);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1895 if (pruned_state.can_merge_with_p (existing_state, m_ext_state,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1896 &merged_state))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1897 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1898 if (logger)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1899 logger->log ("merging new state with that of EN: %i",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1900 existing_enode->m_index);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1901
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1902 /* Try again for a cache hit.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1903 Whether we get one or not, merged_state's value_ids have no
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1904 relationship to those of the input state, and thus to those
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1905 of CHANGE, so we must purge any svalue_ids from *CHANGE. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1906 ps.set_state (merged_state);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1907 if (change)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1908 change->on_svalue_purge (svalue_id::from_int (0));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1909
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1910 if (exploded_node **slot = m_point_and_state_to_node.get (&ps))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1911 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1912 /* An exploded_node for PS already exists. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1913 if (logger)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1914 logger->log ("reused EN: %i", (*slot)->m_index);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1915 m_global_stats.m_node_reuse_after_merge_count++;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1916 per_fn_stats->m_node_reuse_after_merge_count++;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1917 per_cs_stats->m_node_reuse_after_merge_count++;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1918 return *slot;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1919 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1920 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1921 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1922 if (logger)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1923 logger->log ("not merging new state with that of EN: %i",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1924 existing_enode->m_index);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1925 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1926 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1927
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1928 /* Impose a limit on the number of enodes per program point, and
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1929 simply stop if we exceed it. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1930 if ((int)per_point_data->m_enodes.length ()
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1931 > param_analyzer_max_enodes_per_program_point)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1932 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1933 if (logger)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1934 logger->log ("not creating enode; too many at program point");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1935 warning_at (point.get_location (), OPT_Wanalyzer_too_complex,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1936 "terminating analysis for this program point");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1937 return NULL;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1938 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1939
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1940 ps.validate (m_ext_state);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1941
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1942 /* An exploded_node for "ps" doesn't already exist; create one. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1943 exploded_node *node = new exploded_node (ps, m_nodes.length ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1944 add_node (node);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1945 m_point_and_state_to_node.put (node->get_ps_key (), node);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1946
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1947 /* Update per-program_point data. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1948 per_point_data->m_enodes.safe_push (node);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1949
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1950 const enum point_kind node_pk = node->get_point ().get_kind ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1951 m_global_stats.m_num_nodes[node_pk]++;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1952 per_fn_stats->m_num_nodes[node_pk]++;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1953 per_cs_stats->m_num_nodes[node_pk]++;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1954
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1955 if (node_pk == PK_AFTER_SUPERNODE)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1956 m_PK_AFTER_SUPERNODE_per_snode[point.get_supernode ()->m_index]++;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1957
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1958 if (logger)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1959 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1960 format f (false);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1961 pretty_printer *pp = logger->get_printer ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1962 logger->log ("created EN: %i", node->m_index);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1963 logger->start_log_line ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1964 pp_string (pp, "point: ");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1965 point.print (pp, f);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1966 logger->end_log_line ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1967 logger->start_log_line ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1968 pp_string (pp, "pruned_state: ");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1969 pruned_state.dump_to_pp (m_ext_state, true, pp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1970 logger->end_log_line ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1971 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1972
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1973 /* Add the new node to the worlist. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1974 m_worklist.add_node (node);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1975 return node;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1976 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1977
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1978 /* Add an exploded_edge from SRC to DEST, recording its association
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1979 with SEDGE (which may be NULL), and, if non-NULL, taking ownership
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1980 of REWIND_INFO.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1981 Return the newly-created eedge. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1982
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1983 exploded_edge *
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1984 exploded_graph::add_edge (exploded_node *src, exploded_node *dest,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1985 const superedge *sedge,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1986 const state_change &change,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1987 exploded_edge::custom_info_t *custom_info)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1988 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1989 exploded_edge *e = new exploded_edge (src, dest, m_ext_state,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1990 sedge, change, custom_info);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1991 digraph<eg_traits>::add_edge (e);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1992 return e;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1993 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1994
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1995 /* Ensure that this graph has per-program_point-data for POINT;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1996 borrow a pointer to it. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1997
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1998 per_program_point_data *
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1999 exploded_graph::
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2000 get_or_create_per_program_point_data (const program_point &point)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2001 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2002 if (per_program_point_data **slot = m_per_point_data.get (&point))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2003 return *slot;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2004
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2005 per_program_point_data *per_point_data = new per_program_point_data (point);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2006 m_per_point_data.put (&per_point_data->m_key, per_point_data);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2007 return per_point_data;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2008 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2009
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2010 /* Ensure that this graph has per-call_string-data for CS;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2011 borrow a pointer to it. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2012
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2013 per_call_string_data *
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2014 exploded_graph::get_or_create_per_call_string_data (const call_string &cs)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2015 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2016 if (per_call_string_data **slot = m_per_call_string_data.get (&cs))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2017 return *slot;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2018
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2019 per_call_string_data *data = new per_call_string_data (cs, m_sg.num_nodes ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2020 m_per_call_string_data.put (&data->m_key,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2021 data);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2022 return data;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2023 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2024
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2025 /* Ensure that this graph has per-function-data for FUN;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2026 borrow a pointer to it. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2027
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2028 per_function_data *
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2029 exploded_graph::get_or_create_per_function_data (function *fun)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2030 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2031 if (per_function_data **slot = m_per_function_data.get (fun))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2032 return *slot;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2033
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2034 per_function_data *data = new per_function_data ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2035 m_per_function_data.put (fun, data);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2036 return data;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2037 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2038
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2039 /* Get this graph's per-function-data for FUN if there is any,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2040 otherwise NULL. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2041
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2042 per_function_data *
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2043 exploded_graph::get_per_function_data (function *fun) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2044 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2045 if (per_function_data **slot
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2046 = const_cast <per_function_data_t &> (m_per_function_data).get (fun))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2047 return *slot;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2048
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2049 return NULL;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2050 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2051
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2052 /* Return true if NODE and FUN should be traversed directly, rather than
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2053 called via other functions. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2054
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2055 static bool
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2056 toplevel_function_p (cgraph_node *node, function *fun, logger *logger)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2057 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2058 /* TODO: better logic here
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2059 e.g. only if more than one caller, and significantly complicated.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2060 Perhaps some whole-callgraph analysis to decide if it's worth summarizing
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2061 an edge, and if so, we need summaries. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2062 if (flag_analyzer_call_summaries)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2063 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2064 int num_call_sites = 0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2065 for (cgraph_edge *edge = node->callers; edge; edge = edge->next_caller)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2066 ++num_call_sites;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2067
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2068 /* For now, if there's more than one in-edge, and we want call
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2069 summaries, do it at the top level so that there's a chance
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2070 we'll have a summary when we need one. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2071 if (num_call_sites > 1)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2072 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2073 if (logger)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2074 logger->log ("traversing %qE (%i call sites)",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2075 fun->decl, num_call_sites);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2076 return true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2077 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2078 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2079
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2080 if (!TREE_PUBLIC (fun->decl))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2081 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2082 if (logger)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2083 logger->log ("not traversing %qE (static)", fun->decl);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2084 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2085 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2086
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2087 if (logger)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2088 logger->log ("traversing %qE (all checks passed)", fun->decl);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2089
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2090 return true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2091 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2092
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2093 /* Add initial nodes to EG, with entrypoints for externally-callable
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2094 functions. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2095
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2096 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2097 exploded_graph::build_initial_worklist ()
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2098 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2099 logger * const logger = get_logger ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2100 LOG_SCOPE (logger);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2101
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2102 cgraph_node *node;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2103 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2104 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2105 function *fun = node->get_fun ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2106 if (!toplevel_function_p (node, fun, logger))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2107 continue;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2108 exploded_node *enode = add_function_entry (fun);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2109 if (logger)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2110 logger->log ("created EN %i for %qE entrypoint",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2111 enode->m_index, fun->decl);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2112 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2113 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2114
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2115 /* The main loop of the analysis.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2116 Take freshly-created exploded_nodes from the worklist, calling
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2117 process_node on them to explore the <point, state> graph.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2118 Add edges to their successors, potentially creating new successors
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2119 (which are also added to the worklist). */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2120
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2121 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2122 exploded_graph::process_worklist ()
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2123 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2124 logger * const logger = get_logger ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2125 LOG_SCOPE (logger);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2126 auto_timevar tv (TV_ANALYZER_WORKLIST);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2127
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2128 while (m_worklist.length () > 0)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2129 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2130 exploded_node *node = m_worklist.take_next ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2131 gcc_assert (node->get_status () == exploded_node::STATUS_WORKLIST);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2132 gcc_assert (node->m_succs.length () == 0
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2133 || node == m_origin);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2134
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2135 if (logger)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2136 logger->log ("next to process: EN: %i", node->m_index);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2137
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2138 /* Avoid exponential explosions of nodes by attempting to merge
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2139 nodes that are at the same program point and which have
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2140 sufficiently similar state. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2141 if (flag_analyzer_state_merge && node != m_origin)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2142 if (exploded_node *node_2 = m_worklist.peek_next ())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2143 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2144 gcc_assert (node_2->get_status ()
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2145 == exploded_node::STATUS_WORKLIST);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2146 gcc_assert (node->m_succs.length () == 0);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2147 gcc_assert (node_2->m_succs.length () == 0);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2148
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2149 gcc_assert (node != node_2);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2150
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2151 if (logger)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2152 logger->log ("peek worklist: EN: %i", node_2->m_index);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2153
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2154 if (node->get_point () == node_2->get_point ())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2155 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2156 if (logger)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2157 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2158 format f (false);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2159 pretty_printer *pp = logger->get_printer ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2160 logger->start_log_line ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2161 logger->log_partial
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2162 ("got potential merge EN: %i and EN: %i at ",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2163 node->m_index, node_2->m_index);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2164 node->get_point ().print (pp, f);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2165 logger->end_log_line ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2166 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2167
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2168 const program_state &state = node->get_state ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2169 const program_state &state_2 = node_2->get_state ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2170
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2171 /* They shouldn't be equal, or we wouldn't have two
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2172 separate nodes. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2173 gcc_assert (state != state_2);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2174
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2175 program_state merged_state (m_ext_state);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2176 state_change change;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2177 if (state.can_merge_with_p (state_2, m_ext_state,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2178 &merged_state))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2179 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2180 if (logger)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2181 logger->log ("merging EN: %i and EN: %i",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2182 node->m_index, node_2->m_index);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2183
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2184 if (merged_state == state)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2185 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2186 /* Then merge node_2 into node by adding an edge. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2187 add_edge (node_2, node, NULL, change);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2188
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2189 /* Remove node_2 from the worklist. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2190 m_worklist.take_next ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2191 node_2->set_status (exploded_node::STATUS_MERGER);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2192
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2193 /* Continue processing "node" below. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2194 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2195 else if (merged_state == state_2)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2196 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2197 /* Then merge node into node_2, and leave node_2
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2198 in the worklist, to be processed on the next
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2199 iteration. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2200 add_edge (node, node_2, NULL, change);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2201 node->set_status (exploded_node::STATUS_MERGER);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2202 continue;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2203 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2204 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2205 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2206 /* We have a merged state that differs from
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2207 both state and state_2. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2208
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2209 /* Remove node_2 from the worklist. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2210 m_worklist.take_next ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2211
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2212 /* Create (or get) an exploded node for the merged
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2213 states, adding to the worklist. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2214 exploded_node *merged_enode
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2215 = get_or_create_node (node->get_point (),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2216 merged_state, &change);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2217 if (merged_enode == NULL)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2218 continue;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2219
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2220 if (logger)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2221 logger->log ("merged EN: %i and EN: %i into EN: %i",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2222 node->m_index, node_2->m_index,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2223 merged_enode->m_index);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2224
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2225 /* "node" and "node_2" have both now been removed
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2226 from the worklist; we should not process them.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2227
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2228 "merged_enode" may be a new node; if so it will be
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2229 processed in a subsequent iteration.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2230 Alternatively, "merged_enode" could be an existing
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2231 node; one way the latter can
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2232 happen is if we end up merging a succession of
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2233 similar nodes into one. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2234
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2235 /* If merged_node is one of the two we were merging,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2236 add it back to the worklist to ensure it gets
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2237 processed.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2238
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2239 Add edges from the merged nodes to it (but not a
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2240 self-edge). */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2241 if (merged_enode == node)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2242 m_worklist.add_node (merged_enode);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2243 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2244 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2245 add_edge (node, merged_enode, NULL, change);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2246 node->set_status (exploded_node::STATUS_MERGER);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2247 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2248
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2249 if (merged_enode == node_2)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2250 m_worklist.add_node (merged_enode);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2251 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2252 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2253 add_edge (node_2, merged_enode, NULL, change);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2254 node_2->set_status (exploded_node::STATUS_MERGER);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2255 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2256
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2257 continue;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2258 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2259 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2260
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2261 /* TODO: should we attempt more than two nodes,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2262 or just do pairs of nodes? (and hope that we get
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2263 a cascade of mergers). */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2264 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2265 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2266
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2267 process_node (node);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2268
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2269 /* Impose a hard limit on the number of exploded nodes, to ensure
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2270 that the analysis terminates in the face of pathological state
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2271 explosion (or bugs).
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2272
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2273 Specifically, the limit is on the number of PK_AFTER_SUPERNODE
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2274 exploded nodes, looking at supernode exit events.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2275
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2276 We use exit rather than entry since there can be multiple
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2277 entry ENs, one per phi; the number of PK_AFTER_SUPERNODE ought
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2278 to be equivalent to the number of supernodes multiplied by the
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2279 number of states. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2280 const int limit = m_sg.num_nodes () * param_analyzer_bb_explosion_factor;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2281 if (m_global_stats.m_num_nodes[PK_AFTER_SUPERNODE] > limit)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2282 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2283 if (logger)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2284 logger->log ("bailing out; too many nodes");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2285 warning_at (node->get_point ().get_location (),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2286 OPT_Wanalyzer_too_complex,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2287 "analysis bailed out early"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2288 " (%i 'after-snode' enodes; %i enodes)",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2289 m_global_stats.m_num_nodes[PK_AFTER_SUPERNODE],
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2290 m_nodes.length ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2291 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2292 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2293 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2294 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2295
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2296 /* Return true if STMT must appear at the start of its exploded node, and
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2297 thus we can't consolidate its effects within a run of other statements,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2298 where PREV_STMT was the previous statement. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2299
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2300 static bool
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2301 stmt_requires_new_enode_p (const gimple *stmt,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2302 const gimple *prev_stmt)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2303 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2304 /* Stop consolidating at calls to
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2305 "__analyzer_dump_exploded_nodes", so they always appear at the
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2306 start of an exploded_node. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2307 if (const gcall *call = dyn_cast <const gcall *> (stmt))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2308 if (is_special_named_call_p (call, "__analyzer_dump_exploded_nodes",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2309 1))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2310 return true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2311
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2312 /* If we had a PREV_STMT with an unknown location, and this stmt
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2313 has a known location, then if a state change happens here, it
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2314 could be consolidated into PREV_STMT, giving us an event with
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2315 no location. Ensure that STMT gets its own exploded_node to
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2316 avoid this. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2317 if (get_pure_location (prev_stmt->location) == UNKNOWN_LOCATION
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2318 && get_pure_location (stmt->location) != UNKNOWN_LOCATION)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2319 return true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2320
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2321 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2322 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2323
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2324 /* The core of exploded_graph::process_worklist (the main analysis loop),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2325 handling one node in the worklist.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2326
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2327 Get successor <point, state> pairs for NODE, calling get_or_create on
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2328 them, and adding an exploded_edge to each successors.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2329
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2330 Freshly-created nodes will be added to the worklist. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2331
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2332 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2333 exploded_graph::process_node (exploded_node *node)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2334 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2335 logger * const logger = get_logger ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2336 LOG_FUNC_1 (logger, "EN: %i", node->m_index);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2337
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2338 node->set_status (exploded_node::STATUS_PROCESSED);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2339
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2340 const program_point &point = node->get_point ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2341
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2342 /* Update cfun and input_location in case of an ICE: make it easier to
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2343 track down which source construct we're failing to handle. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2344 auto_cfun sentinel (node->get_function ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2345 const gimple *stmt = point.get_stmt ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2346 if (stmt)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2347 input_location = stmt->location;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2348
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2349 const program_state &state = node->get_state ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2350 if (logger)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2351 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2352 pretty_printer *pp = logger->get_printer ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2353 logger->start_log_line ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2354 pp_string (pp, "point: ");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2355 point.print (pp, format (false));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2356 pp_string (pp, ", state: ");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2357 state.dump_to_pp (m_ext_state, true, pp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2358 logger->end_log_line ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2359 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2360
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2361 switch (point.get_kind ())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2362 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2363 default:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2364 gcc_unreachable ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2365 case PK_ORIGIN:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2366 /* This node exists to simplify finding the shortest path
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2367 to an exploded_node. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2368 break;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2369
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2370 case PK_BEFORE_SUPERNODE:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2371 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2372 program_state next_state (state);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2373 state_change change;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2374
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2375 if (point.get_from_edge ())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2376 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2377 impl_region_model_context ctxt (*this, node,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2378 &state, &next_state, &change,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2379 NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2380 const cfg_superedge *last_cfg_superedge
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2381 = point.get_from_edge ()->dyn_cast_cfg_superedge ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2382 if (last_cfg_superedge)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2383 next_state.m_region_model->update_for_phis
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2384 (node->get_supernode (),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2385 last_cfg_superedge,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2386 &ctxt);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2387 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2388
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2389 if (point.get_supernode ()->m_stmts.length () > 0)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2390 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2391 program_point next_point
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2392 = program_point::before_stmt (point.get_supernode (), 0,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2393 point.get_call_string ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2394 exploded_node *next
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2395 = get_or_create_node (next_point, next_state, &change);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2396 if (next)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2397 add_edge (node, next, NULL, change);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2398 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2399 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2400 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2401 program_point next_point
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2402 = program_point::after_supernode (point.get_supernode (),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2403 point.get_call_string ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2404 exploded_node *next = get_or_create_node (next_point, next_state,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2405 &change);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2406 if (next)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2407 add_edge (node, next, NULL, change);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2408 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2409 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2410 break;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2411 case PK_BEFORE_STMT:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2412 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2413 /* Determine the effect of a run of one or more statements
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2414 within one supernode, generating an edge to the program_point
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2415 after the last statement that's processed.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2416
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2417 Stop iterating statements and thus consolidating into one enode
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2418 when:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2419 - reaching the end of the statements in the supernode
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2420 - if an sm-state-change occurs (so that it gets its own
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2421 exploded_node)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2422 - if "-fanalyzer-fine-grained" is active
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2423 - encountering certain statements must appear at the start of
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2424 their enode (for which stmt_requires_new_enode_p returns true)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2425
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2426 Update next_state in-place, to get the result of the one
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2427 or more stmts that are processed. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2428 program_state next_state (state);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2429 state_change change;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2430 const supernode *snode = point.get_supernode ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2431 unsigned stmt_idx;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2432 const gimple *prev_stmt = NULL;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2433 for (stmt_idx = point.get_stmt_idx ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2434 stmt_idx < snode->m_stmts.length ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2435 stmt_idx++)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2436 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2437 const gimple *stmt = snode->m_stmts[stmt_idx];
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2438
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2439 if (stmt_idx > point.get_stmt_idx ())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2440 if (stmt_requires_new_enode_p (stmt, prev_stmt))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2441 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2442 stmt_idx--;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2443 break;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2444 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2445 prev_stmt = stmt;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2446
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2447 /* Process the stmt. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2448 exploded_node::on_stmt_flags flags
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2449 = node->on_stmt (*this, snode, stmt, &next_state, &change);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2450
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2451 /* If flags.m_terminate_path, stop analyzing; any nodes/edges
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2452 will have been added by on_stmt (e.g. for handling longjmp). */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2453 if (flags.m_terminate_path)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2454 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2455
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2456 if (flags.m_sm_changes || flag_analyzer_fine_grained)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2457 break;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2458 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2459 unsigned next_idx = stmt_idx + 1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2460 program_point next_point
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2461 = (next_idx < point.get_supernode ()->m_stmts.length ()
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2462 ? program_point::before_stmt (point.get_supernode (), next_idx,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2463 point.get_call_string ())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2464 : program_point::after_supernode (point.get_supernode (),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2465 point.get_call_string ()));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2466 exploded_node *next = get_or_create_node (next_point,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2467 next_state, &change);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2468 if (next)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2469 add_edge (node, next, NULL, change);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2470 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2471 break;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2472 case PK_AFTER_SUPERNODE:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2473 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2474 /* If this is an EXIT BB, detect leaks, and potentially
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2475 create a function summary. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2476 if (point.get_supernode ()->return_p ())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2477 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2478 node->detect_leaks (*this);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2479 if (flag_analyzer_call_summaries
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2480 && point.get_call_string ().empty_p ())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2481 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2482 /* TODO: create function summary
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2483 There can be more than one; each corresponds to a different
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2484 final enode in the function. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2485 if (logger)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2486 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2487 pretty_printer *pp = logger->get_printer ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2488 logger->start_log_line ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2489 logger->log_partial
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2490 ("would create function summary for %qE; state: ",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2491 point.get_fndecl ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2492 state.dump_to_pp (m_ext_state, true, pp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2493 logger->end_log_line ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2494 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2495 per_function_data *per_fn_data
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2496 = get_or_create_per_function_data (point.get_function ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2497 per_fn_data->add_call_summary (node);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2498 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2499 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2500 /* Traverse into successors of the supernode. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2501 int i;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2502 superedge *succ;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2503 FOR_EACH_VEC_ELT (point.get_supernode ()->m_succs, i, succ)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2504 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2505 if (logger)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2506 logger->log ("considering SN: %i -> SN: %i",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2507 succ->m_src->m_index, succ->m_dest->m_index);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2508
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2509 state_change change;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2510
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2511 program_point next_point
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2512 = program_point::before_supernode (succ->m_dest, succ,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2513 point.get_call_string ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2514 program_state next_state (state);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2515
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2516 if (!node->on_edge (*this, succ, &next_point, &next_state, &change))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2517 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2518 if (logger)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2519 logger->log ("skipping impossible edge to SN: %i",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2520 succ->m_dest->m_index);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2521 continue;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2522 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2523
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2524 exploded_node *next = get_or_create_node (next_point, next_state,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2525 &change);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2526 if (next)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2527 add_edge (node, next, succ, change);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2528 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2529 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2530 break;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2531 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2532 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2533
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2534 /* Ensure that this graph has a stats instance for FN, return it.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2535 FN can be NULL, in which case a stats instances is returned covering
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2536 "functionless" parts of the graph (the origin node). */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2537
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2538 stats *
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2539 exploded_graph::get_or_create_function_stats (function *fn)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2540 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2541 if (!fn)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2542 return &m_functionless_stats;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2543
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2544 if (stats **slot = m_per_function_stats.get (fn))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2545 return *slot;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2546 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2547 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2548 int num_supernodes = fn ? n_basic_blocks_for_fn (fn) : 0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2549 /* not quite the num supernodes, but nearly. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2550 stats *new_stats = new stats (num_supernodes);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2551 m_per_function_stats.put (fn, new_stats);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2552 return new_stats;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2553 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2554 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2555
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2556 /* Write all stats information to this graph's logger, if any. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2557
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2558 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2559 exploded_graph::log_stats () const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2560 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2561 logger * const logger = get_logger ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2562 if (!logger)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2563 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2564
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2565 LOG_SCOPE (logger);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2566
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2567 logger->log ("m_sg.num_nodes (): %i", m_sg.num_nodes ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2568 logger->log ("m_nodes.length (): %i", m_nodes.length ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2569 logger->log ("m_edges.length (): %i", m_edges.length ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2570
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2571 logger->log ("global stats:");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2572 m_global_stats.log (logger);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2573
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2574 for (function_stat_map_t::iterator iter = m_per_function_stats.begin ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2575 iter != m_per_function_stats.end ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2576 ++iter)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2577 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2578 function *fn = (*iter).first;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2579 log_scope s (logger, function_name (fn));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2580 (*iter).second->log (logger);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2581 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2582 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2583
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2584 /* Dump all stats information to OUT. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2585
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2586 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2587 exploded_graph::dump_stats (FILE *out) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2588 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2589 fprintf (out, "m_sg.num_nodes (): %i\n", m_sg.num_nodes ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2590 fprintf (out, "m_nodes.length (): %i\n", m_nodes.length ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2591 fprintf (out, "m_edges.length (): %i\n", m_edges.length ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2592
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2593 fprintf (out, "global stats:\n");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2594 m_global_stats.dump (out);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2595
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2596 for (function_stat_map_t::iterator iter = m_per_function_stats.begin ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2597 iter != m_per_function_stats.end ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2598 ++iter)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2599 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2600 function *fn = (*iter).first;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2601 fprintf (out, "function: %s\n", function_name (fn));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2602 (*iter).second->dump (out);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2603 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2604
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2605 fprintf (out, "PK_AFTER_SUPERNODE per supernode:\n");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2606 for (unsigned i = 0; i < m_PK_AFTER_SUPERNODE_per_snode.length (); i++)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2607 fprintf (out, " SN %i: %3i\n", i, m_PK_AFTER_SUPERNODE_per_snode[i]);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2608 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2609
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2610 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2611 exploded_graph::dump_states_for_supernode (FILE *out,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2612 const supernode *snode) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2613 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2614 fprintf (out, "PK_AFTER_SUPERNODE nodes for SN: %i\n", snode->m_index);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2615 int i;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2616 exploded_node *enode;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2617 int state_idx = 0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2618 FOR_EACH_VEC_ELT (m_nodes, i, enode)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2619 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2620 const supernode *iter_snode = enode->get_supernode ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2621 if (enode->get_point ().get_kind () == PK_AFTER_SUPERNODE
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2622 && iter_snode == snode)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2623 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2624 pretty_printer pp;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2625 pp_format_decoder (&pp) = default_tree_printer;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2626 enode->get_state ().dump_to_pp (m_ext_state, true, &pp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2627 fprintf (out, "state %i: EN: %i\n %s\n",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2628 state_idx++, enode->m_index,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2629 pp_formatted_text (&pp));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2630 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2631 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2632 fprintf (out, "#exploded_node for PK_AFTER_SUPERNODE for SN: %i = %i\n",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2633 snode->m_index, state_idx);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2634 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2635
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2636 /* Look for the last use of SEARCH_STMT within this path.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2637 If found write the edge's index to *OUT_IDX and return true, otherwise
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2638 return false. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2639
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2640 bool
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2641 exploded_path::find_stmt_backwards (const gimple *search_stmt,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2642 int *out_idx) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2643 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2644 int i;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2645 const exploded_edge *eedge;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2646 FOR_EACH_VEC_ELT_REVERSE (m_edges, i, eedge)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2647 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2648 const exploded_node *dst_node = eedge->m_dest;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2649 const program_point &dst_point = dst_node->get_point ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2650 const gimple *stmt = dst_point.get_stmt ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2651 if (stmt == search_stmt)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2652 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2653 *out_idx = i;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2654 return true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2655 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2656 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2657 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2658 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2659
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2660 /* Get the final exploded_node in this path, which must be non-empty. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2661
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2662 exploded_node *
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2663 exploded_path::get_final_enode () const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2664 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2665 gcc_assert (m_edges.length () > 0);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2666 return m_edges[m_edges.length () - 1]->m_dest;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2667 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2668
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2669 /* Check state along this path, returning true if it is feasible. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2670
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2671 bool
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2672 exploded_path::feasible_p (logger *logger) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2673 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2674 LOG_SCOPE (logger);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2675
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2676 /* Traverse the path, updating this model. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2677 region_model model;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2678 for (unsigned i = 0; i < m_edges.length (); i++)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2679 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2680 const exploded_edge *eedge = m_edges[i];
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2681 if (logger)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2682 logger->log ("considering edge %i: EN:%i -> EN:%i",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2683 i,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2684 eedge->m_src->m_index,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2685 eedge->m_dest->m_index);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2686 const exploded_node &src_enode = *eedge->m_src;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2687 const program_point &src_point = src_enode.get_point ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2688 if (logger)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2689 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2690 logger->start_log_line ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2691 src_point.print (logger->get_printer (), format (false));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2692 logger->end_log_line ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2693 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2694
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2695 if (const gimple *stmt = src_point.get_stmt ())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2696 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2697 /* Update cfun and input_location in case of ICE: make it easier to
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2698 track down which source construct we're failing to handle. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2699 auto_cfun sentinel (src_point.get_function ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2700 input_location = stmt->location;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2701
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2702 if (const gassign *assign = dyn_cast <const gassign *> (stmt))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2703 model.on_assignment (assign, NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2704 else if (const greturn *return_ = dyn_cast <const greturn *> (stmt))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2705 model.on_return (return_, NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2706 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2707
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2708 const superedge *sedge = eedge->m_sedge;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2709 if (sedge)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2710 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2711 if (logger)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2712 logger->log (" sedge: SN:%i -> SN:%i %s",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2713 sedge->m_src->m_index,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2714 sedge->m_dest->m_index,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2715 sedge->get_description (false));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2716
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2717 const gimple *last_stmt = src_point.get_supernode ()->get_last_stmt ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2718 if (!model.maybe_update_for_edge (*sedge, last_stmt, NULL))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2719 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2720 if (logger)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2721 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2722 logger->log ("rejecting due to region model");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2723 model.dump_to_pp (logger->get_printer (), false);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2724 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2725 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2726 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2727 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2728 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2729 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2730 /* Special-case the initial eedge from the origin node to the
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2731 initial function by pushing a frame for it. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2732 if (i == 0)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2733 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2734 gcc_assert (eedge->m_src->m_index == 0);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2735 gcc_assert (src_point.get_kind () == PK_ORIGIN);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2736 gcc_assert (eedge->m_dest->get_point ().get_kind ()
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2737 == PK_BEFORE_SUPERNODE);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2738 function *fun = eedge->m_dest->get_function ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2739 gcc_assert (fun);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2740 model.push_frame (fun, NULL, NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2741 if (logger)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2742 logger->log (" pushing frame for %qD", fun->decl);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2743 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2744 else if (eedge->m_custom_info)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2745 eedge->m_custom_info->update_model (&model, *eedge);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2746 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2747
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2748 /* Handle phi nodes on an edge leaving a PK_BEFORE_SUPERNODE (to
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2749 a PK_BEFORE_STMT, or a PK_AFTER_SUPERNODE if no stmts).
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2750 This will typically not be associated with a superedge. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2751 if (src_point.get_from_edge ())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2752 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2753 const cfg_superedge *last_cfg_superedge
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2754 = src_point.get_from_edge ()->dyn_cast_cfg_superedge ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2755 if (last_cfg_superedge)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2756 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2757 if (logger)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2758 logger->log (" update for phis");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2759 model.update_for_phis (src_enode.get_supernode (),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2760 last_cfg_superedge,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2761 NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2762 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2763 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2764
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2765 if (logger)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2766 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2767 logger->log ("state after edge %i: EN:%i -> EN:%i",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2768 i,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2769 eedge->m_src->m_index,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2770 eedge->m_dest->m_index);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2771 logger->start_log_line ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2772 model.dump_to_pp (logger->get_printer (), true);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2773 logger->end_log_line ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2774 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2775 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2776
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2777 return true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2778 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2779
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2780 /* Dump this path in multiline form to PP. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2781
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2782 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2783 exploded_path::dump_to_pp (pretty_printer *pp) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2784 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2785 for (unsigned i = 0; i < m_edges.length (); i++)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2786 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2787 const exploded_edge *eedge = m_edges[i];
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2788 pp_printf (pp, "m_edges[%i]: EN %i -> EN %i",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2789 i,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2790 eedge->m_src->m_index,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2791 eedge->m_dest->m_index);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2792 pp_newline (pp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2793 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2794 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2795
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2796 /* Dump this path in multiline form to FP. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2797
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2798 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2799 exploded_path::dump (FILE *fp) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2800 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2801 pretty_printer pp;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2802 pp_format_decoder (&pp) = default_tree_printer;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2803 pp_show_color (&pp) = pp_show_color (global_dc->printer);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2804 pp.buffer->stream = fp;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2805 dump_to_pp (&pp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2806 pp_flush (&pp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2807 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2808
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2809 /* Dump this path in multiline form to stderr. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2810
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2811 DEBUG_FUNCTION void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2812 exploded_path::dump () const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2813 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2814 dump (stderr);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2815 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2816
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2817 /* A family of cluster subclasses for use when generating .dot output for
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2818 exploded graphs (-fdump-analyzer-exploded-graph), for grouping the
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2819 enodes into hierarchical boxes.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2820
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2821 All functionless enodes appear in the top-level graph.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2822 Every (function, call_string) pair gets its own cluster. Within that
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2823 cluster, each supernode gets its own cluster.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2824
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2825 Hence all enodes relating to a particular function with a particular
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2826 callstring will be be in a cluster together; all enodes for the same
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2827 function but with a different callstring will be in a different
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2828 cluster. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2829
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2830 /* Base class of cluster for clustering exploded_node instances in .dot
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2831 output, based on various subclass-specific criteria. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2832
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2833 class exploded_cluster : public cluster<eg_traits>
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2834 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2835 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2836
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2837 /* Cluster containing all exploded_node instances for one supernode. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2838
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2839 class supernode_cluster : public exploded_cluster
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2840 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2841 public:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2842 supernode_cluster (const supernode *supernode) : m_supernode (supernode) {}
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2843
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2844 // TODO: dtor?
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2845
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2846 void dump_dot (graphviz_out *gv, const dump_args_t &args) const FINAL OVERRIDE
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2847 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2848 gv->println ("subgraph \"cluster_supernode_%p\" {",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2849 (const void *)this);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2850 gv->indent ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2851 gv->println ("style=\"dashed\";");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2852 gv->println ("label=\"SN: %i (bb: %i)\";",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2853 m_supernode->m_index, m_supernode->m_bb->index);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2854
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2855 int i;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2856 exploded_node *enode;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2857 FOR_EACH_VEC_ELT (m_enodes, i, enode)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2858 enode->dump_dot (gv, args);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2859
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2860 /* Terminate subgraph. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2861 gv->outdent ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2862 gv->println ("}");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2863 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2864
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2865 void add_node (exploded_node *en) FINAL OVERRIDE
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2866 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2867 m_enodes.safe_push (en);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2868 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2869
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2870 private:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2871 const supernode *m_supernode;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2872 auto_vec <exploded_node *> m_enodes;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2873 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2874
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2875 /* Cluster containing all supernode_cluster instances for one
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2876 (function, call_string) pair. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2877
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2878 class function_call_string_cluster : public exploded_cluster
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2879 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2880 public:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2881 function_call_string_cluster (function *fun, call_string cs)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2882 : m_fun (fun), m_cs (cs) {}
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2883
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2884 ~function_call_string_cluster ()
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2885 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2886 for (map_t::iterator iter = m_map.begin ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2887 iter != m_map.end ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2888 ++iter)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2889 delete (*iter).second;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2890 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2891
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2892 void dump_dot (graphviz_out *gv, const dump_args_t &args) const FINAL OVERRIDE
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2893 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2894 const char *funcname = function_name (m_fun);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2895
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2896 gv->println ("subgraph \"cluster_function_%p\" {", (const void *)this);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2897 gv->indent ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2898 gv->write_indent ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2899 gv->print ("label=\"call string: ");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2900 m_cs.print (gv->get_pp ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2901 gv->print (" function: %s \";", funcname);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2902 gv->print ("\n");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2903
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2904 for (map_t::iterator iter = m_map.begin ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2905 iter != m_map.end ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2906 ++iter)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2907 (*iter).second->dump_dot (gv, args);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2908
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2909 /* Terminate subgraph. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2910 gv->outdent ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2911 gv->println ("}");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2912 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2913
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2914 void add_node (exploded_node *en) FINAL OVERRIDE
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2915 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2916 const supernode *supernode = en->get_supernode ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2917 gcc_assert (supernode);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2918 supernode_cluster **slot = m_map.get (supernode);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2919 if (slot)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2920 (*slot)->add_node (en);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2921 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2922 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2923 supernode_cluster *child = new supernode_cluster (supernode);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2924 m_map.put (supernode, child);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2925 child->add_node (en);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2926 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2927 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2928
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2929 private:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2930 function *m_fun;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2931 call_string m_cs;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2932 typedef ordered_hash_map<const supernode *, supernode_cluster *> map_t;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2933 map_t m_map;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2934 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2935
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2936 /* Keys for root_cluster. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2937
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2938 struct function_call_string
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2939 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2940 function_call_string (function *fun, call_string cs)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2941 : m_fun (fun), m_cs (cs)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2942 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2943 gcc_assert (fun);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2944 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2945
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2946 function *m_fun;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2947 call_string m_cs;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2948 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2949
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2950 } // namespace ana
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2951
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2952 template <> struct default_hash_traits<function_call_string>
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2953 : public pod_hash_traits<function_call_string>
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2954 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2955 static const bool empty_zero_p = false;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2956 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2957
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2958 template <>
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2959 inline hashval_t
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2960 pod_hash_traits<function_call_string>::hash (value_type v)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2961 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2962 return pointer_hash <function>::hash (v.m_fun) ^ v.m_cs.hash ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2963 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2964
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2965 template <>
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2966 inline bool
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2967 pod_hash_traits<function_call_string>::equal (const value_type &existing,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2968 const value_type &candidate)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2969 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2970 return existing.m_fun == candidate.m_fun && existing.m_cs == candidate.m_cs;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2971 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2972 template <>
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2973 inline void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2974 pod_hash_traits<function_call_string>::mark_deleted (value_type &v)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2975 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2976 v.m_fun = reinterpret_cast<function *> (1);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2977 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2978 template <>
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2979 inline void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2980 pod_hash_traits<function_call_string>::mark_empty (value_type &v)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2981 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2982 v.m_fun = NULL;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2983 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2984 template <>
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2985 inline bool
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2986 pod_hash_traits<function_call_string>::is_deleted (value_type v)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2987 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2988 return v.m_fun == reinterpret_cast<function *> (1);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2989 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2990 template <>
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2991 inline bool
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2992 pod_hash_traits<function_call_string>::is_empty (value_type v)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2993 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2994 return v.m_fun == NULL;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2995 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2996
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2997 namespace ana {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2998
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2999 /* Top-level cluster for generating .dot output for exploded graphs,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3000 handling the functionless nodes, and grouping the remaining nodes by
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3001 callstring. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3002
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3003 class root_cluster : public exploded_cluster
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3004 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3005 public:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3006 ~root_cluster ()
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3007 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3008 for (map_t::iterator iter = m_map.begin ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3009 iter != m_map.end ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3010 ++iter)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3011 delete (*iter).second;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3012 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3013
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3014 void dump_dot (graphviz_out *gv, const dump_args_t &args) const FINAL OVERRIDE
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3015 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3016 int i;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3017 exploded_node *enode;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3018 FOR_EACH_VEC_ELT (m_functionless_enodes, i, enode)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3019 enode->dump_dot (gv, args);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3020
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3021 for (map_t::iterator iter = m_map.begin ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3022 iter != m_map.end ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3023 ++iter)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3024 (*iter).second->dump_dot (gv, args);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3025 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3026
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3027 void add_node (exploded_node *en) FINAL OVERRIDE
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3028 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3029 function *fun = en->get_function ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3030 if (!fun)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3031 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3032 m_functionless_enodes.safe_push (en);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3033 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3034 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3035
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3036 const call_string &cs = en->get_point ().get_call_string ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3037 function_call_string key (fun, cs);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3038 function_call_string_cluster **slot = m_map.get (key);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3039 if (slot)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3040 (*slot)->add_node (en);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3041 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3042 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3043 function_call_string_cluster *child
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3044 = new function_call_string_cluster (fun, cs);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3045 m_map.put (key, child);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3046 child->add_node (en);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3047 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3048 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3049
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3050 private:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3051 /* This can't be an ordered_hash_map, as we can't store vec<call_string>,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3052 since it's not a POD; vec<>::quick_push has:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3053 *slot = obj;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3054 and the slot isn't initialized, so the assignment op dies when cleaning up
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3055 un-inited *slot (within the truncate call). */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3056 typedef hash_map<function_call_string, function_call_string_cluster *> map_t;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3057 map_t m_map;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3058
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3059 /* This should just be the origin exploded_node. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3060 auto_vec <exploded_node *> m_functionless_enodes;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3061 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3062
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3063 /* Subclass of range_label for use within
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3064 exploded_graph::dump_exploded_nodes for implementing
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3065 -fdump-analyzer-exploded-nodes: a label for a specific
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3066 exploded_node. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3067
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3068 class enode_label : public range_label
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3069 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3070 public:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3071 enode_label (const extrinsic_state &ext_state,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3072 exploded_node *enode)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3073 : m_ext_state (ext_state), m_enode (enode) {}
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3074
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3075 label_text get_text (unsigned) const FINAL OVERRIDE
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3076 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3077 pretty_printer pp;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3078 pp_format_decoder (&pp) = default_tree_printer;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3079 m_enode->get_state ().dump_to_pp (m_ext_state, true, &pp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3080 return make_label_text (false, "EN: %i: %s",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3081 m_enode->m_index, pp_formatted_text (&pp));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3082 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3083
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3084 private:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3085 const extrinsic_state &m_ext_state;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3086 exploded_node *m_enode;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3087 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3088
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3089 /* Postprocessing support for dumping the exploded nodes.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3090 Handle -fdump-analyzer-exploded-nodes,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3091 -fdump-analyzer-exploded-nodes-2, and the
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3092 "__analyzer_dump_exploded_nodes" builtin. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3093
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3094 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3095 exploded_graph::dump_exploded_nodes () const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3096 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3097 // TODO
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3098 /* Locate calls to __analyzer_dump_exploded_nodes. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3099 // Print how many egs there are for them?
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3100 /* Better: log them as we go, and record the exploded nodes
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3101 in question. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3102
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3103 /* Show every enode. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3104
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3105 /* Gather them by stmt, so that we can more clearly see the
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3106 "hotspots" requiring numerous exploded nodes. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3107
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3108 /* Alternatively, simply throw them all into one big rich_location
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3109 and see if the label-printing will sort it out...
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3110 This requires them all to be in the same source file. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3111
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3112 if (flag_dump_analyzer_exploded_nodes)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3113 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3114 auto_timevar tv (TV_ANALYZER_DUMP);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3115 gcc_rich_location richloc (UNKNOWN_LOCATION);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3116 unsigned i;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3117 exploded_node *enode;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3118 FOR_EACH_VEC_ELT (m_nodes, i, enode)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3119 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3120 if (const gimple *stmt = enode->get_stmt ())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3121 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3122 if (get_pure_location (richloc.get_loc ()) == UNKNOWN_LOCATION)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3123 richloc.set_range (0, stmt->location, SHOW_RANGE_WITH_CARET);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3124 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3125 richloc.add_range (stmt->location,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3126 SHOW_RANGE_WITHOUT_CARET,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3127 new enode_label (m_ext_state, enode));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3128 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3129 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3130 warning_at (&richloc, 0, "%i exploded nodes", m_nodes.length ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3131
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3132 /* Repeat the warning without all the labels, so that message is visible
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3133 (the other one may well have scrolled past the terminal limit). */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3134 warning_at (richloc.get_loc (), 0,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3135 "%i exploded nodes", m_nodes.length ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3136
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3137 if (m_worklist.length () > 0)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3138 warning_at (richloc.get_loc (), 0,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3139 "worklist still contains %i nodes", m_worklist.length ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3140 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3141
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3142 /* Dump the egraph in textual form to a dump file. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3143 if (flag_dump_analyzer_exploded_nodes_2)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3144 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3145 auto_timevar tv (TV_ANALYZER_DUMP);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3146 char *filename
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3147 = concat (dump_base_name, ".eg.txt", NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3148 FILE *outf = fopen (filename, "w");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3149 if (!outf)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3150 error_at (UNKNOWN_LOCATION, "unable to open %qs for writing", filename);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3151 free (filename);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3152
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3153 fprintf (outf, "exploded graph for %s\n", dump_base_name);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3154 fprintf (outf, " nodes: %i\n", m_nodes.length ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3155 fprintf (outf, " edges: %i\n", m_edges.length ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3156
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3157 unsigned i;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3158 exploded_node *enode;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3159 FOR_EACH_VEC_ELT (m_nodes, i, enode)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3160 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3161 fprintf (outf, "\nEN %i:\n", enode->m_index);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3162 enode->dump_succs_and_preds (outf);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3163 pretty_printer pp;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3164 enode->get_point ().print (&pp, format (true));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3165 fprintf (outf, "%s\n", pp_formatted_text (&pp));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3166 enode->get_state ().dump_to_file (m_ext_state, false, outf);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3167 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3168
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3169 fclose (outf);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3170 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3171
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3172 /* Dump the egraph in textual form to multiple dump files, one per enode. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3173 if (flag_dump_analyzer_exploded_nodes_3)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3174 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3175 auto_timevar tv (TV_ANALYZER_DUMP);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3176
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3177 unsigned i;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3178 exploded_node *enode;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3179 FOR_EACH_VEC_ELT (m_nodes, i, enode)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3180 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3181 char *filename
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3182 = xasprintf ("%s.en-%i.txt", dump_base_name, i);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3183 FILE *outf = fopen (filename, "w");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3184 if (!outf)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3185 error_at (UNKNOWN_LOCATION, "unable to open %qs for writing", filename);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3186 free (filename);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3187
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3188 fprintf (outf, "EN %i:\n", enode->m_index);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3189 enode->dump_succs_and_preds (outf);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3190 pretty_printer pp;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3191 enode->get_point ().print (&pp, format (true));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3192 fprintf (outf, "%s\n", pp_formatted_text (&pp));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3193 enode->get_state ().dump_to_file (m_ext_state, false, outf);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3194
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3195 fclose (outf);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3196 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3197 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3198
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3199 /* Emit a warning at any call to "__analyzer_dump_exploded_nodes",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3200 giving the number of processed exploded nodes for "before-stmt",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3201 and the IDs of processed, merger, and worklist enodes.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3202
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3203 We highlight the count of *processed* enodes since this is of most
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3204 interest in DejaGnu tests for ensuring that state merger has
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3205 happened.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3206
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3207 We don't show the count of merger and worklist enodes, as this is
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3208 more of an implementation detail of the merging/worklist that we
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3209 don't want to bake into our expected DejaGnu messages. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3210
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3211 unsigned i;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3212 exploded_node *enode;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3213 hash_set<const gimple *> seen;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3214 FOR_EACH_VEC_ELT (m_nodes, i, enode)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3215 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3216 if (enode->get_point ().get_kind () != PK_BEFORE_STMT)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3217 continue;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3218
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3219 if (const gimple *stmt = enode->get_stmt ())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3220 if (const gcall *call = dyn_cast <const gcall *> (stmt))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3221 if (is_special_named_call_p (call, "__analyzer_dump_exploded_nodes",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3222 1))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3223 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3224 if (seen.contains (stmt))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3225 continue;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3226
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3227 auto_vec<exploded_node *> processed_enodes;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3228 auto_vec<exploded_node *> merger_enodes;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3229 auto_vec<exploded_node *> worklist_enodes;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3230 /* This is O(N^2). */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3231 unsigned j;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3232 exploded_node *other_enode;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3233 FOR_EACH_VEC_ELT (m_nodes, j, other_enode)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3234 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3235 if (other_enode->get_point ().get_kind () != PK_BEFORE_STMT)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3236 continue;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3237 if (other_enode->get_stmt () == stmt)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3238 switch (other_enode->get_status ())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3239 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3240 default:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3241 gcc_unreachable ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3242 case exploded_node::STATUS_WORKLIST:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3243 worklist_enodes.safe_push (other_enode);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3244 break;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3245 case exploded_node::STATUS_PROCESSED:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3246 processed_enodes.safe_push (other_enode);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3247 break;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3248 case exploded_node::STATUS_MERGER:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3249 merger_enodes.safe_push (other_enode);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3250 break;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3251 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3252 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3253
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3254 pretty_printer pp;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3255 pp_character (&pp, '[');
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3256 print_enode_indices (&pp, processed_enodes);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3257 if (merger_enodes.length () > 0)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3258 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3259 pp_string (&pp, "] merger(s): [");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3260 print_enode_indices (&pp, merger_enodes);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3261 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3262 if (worklist_enodes.length () > 0)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3263 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3264 pp_string (&pp, "] worklist: [");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3265 print_enode_indices (&pp, worklist_enodes);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3266 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3267 pp_character (&pp, ']');
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3268
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3269 warning_n (stmt->location, 0, processed_enodes.length (),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3270 "%i processed enode: %s",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3271 "%i processed enodes: %s",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3272 processed_enodes.length (), pp_formatted_text (&pp));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3273 seen.add (stmt);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3274
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3275 /* If the argument is non-zero, then print all of the states
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3276 of the various enodes. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3277 tree t_arg = fold (gimple_call_arg (call, 0));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3278 if (TREE_CODE (t_arg) != INTEGER_CST)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3279 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3280 error_at (call->location,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3281 "integer constant required for arg 1");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3282 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3283 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3284 int i_arg = TREE_INT_CST_LOW (t_arg);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3285 if (i_arg)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3286 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3287 exploded_node *other_enode;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3288 FOR_EACH_VEC_ELT (processed_enodes, j, other_enode)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3289 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3290 fprintf (stderr, "%i of %i: EN %i:\n",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3291 j + 1, processed_enodes.length (),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3292 other_enode->m_index);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3293 other_enode->dump_succs_and_preds (stderr);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3294 /* Dump state. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3295 other_enode->get_state ().dump (m_ext_state, false);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3296 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3297 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3298 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3299 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3300 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3301
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3302 /* A collection of classes for visualizing the callgraph in .dot form
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3303 (as represented in the supergraph). */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3304
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3305 /* Forward decls. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3306 class viz_callgraph_node;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3307 class viz_callgraph_edge;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3308 class viz_callgraph;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3309 class viz_callgraph_cluster;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3310
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3311 /* Traits for using "digraph.h" to visualize the callgraph. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3312
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3313 struct viz_callgraph_traits
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3314 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3315 typedef viz_callgraph_node node_t;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3316 typedef viz_callgraph_edge edge_t;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3317 typedef viz_callgraph graph_t;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3318 struct dump_args_t
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3319 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3320 dump_args_t (const exploded_graph *eg) : m_eg (eg) {}
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3321 const exploded_graph *m_eg;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3322 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3323 typedef viz_callgraph_cluster cluster_t;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3324 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3325
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3326 /* Subclass of dnode representing a function within the callgraph. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3327
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3328 class viz_callgraph_node : public dnode<viz_callgraph_traits>
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3329 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3330 friend class viz_callgraph;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3331
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3332 public:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3333 viz_callgraph_node (function *fun, int index)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3334 : m_fun (fun), m_index (index), m_num_supernodes (0), m_num_superedges (0)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3335 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3336 gcc_assert (fun);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3337 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3338
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3339 void dump_dot (graphviz_out *gv, const dump_args_t &args) const FINAL OVERRIDE
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3340 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3341 pretty_printer *pp = gv->get_pp ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3342
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3343 dump_dot_id (pp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3344 pp_printf (pp, " [shape=none,margin=0,style=filled,fillcolor=%s,label=<",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3345 "lightgrey");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3346 pp_string (pp, "<TABLE BORDER=\"0\">");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3347 pp_write_text_to_stream (pp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3348
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3349 gv->begin_tr ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3350 pp_printf (pp, "VCG: %i: %s", m_index, function_name (m_fun));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3351 gv->end_tr ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3352 pp_newline (pp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3353
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3354 gv->begin_tr ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3355 pp_printf (pp, "supernodes: %i\n", m_num_supernodes);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3356 gv->end_tr ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3357 pp_newline (pp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3358
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3359 gv->begin_tr ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3360 pp_printf (pp, "superedges: %i\n", m_num_superedges);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3361 gv->end_tr ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3362 pp_newline (pp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3363
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3364 if (args.m_eg)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3365 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3366 unsigned i;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3367 exploded_node *enode;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3368 unsigned num_enodes = 0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3369 FOR_EACH_VEC_ELT (args.m_eg->m_nodes, i, enode)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3370 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3371 if (enode->get_point ().get_function () == m_fun)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3372 num_enodes++;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3373 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3374 gv->begin_tr ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3375 pp_printf (pp, "enodes: %i\n", num_enodes);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3376 gv->end_tr ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3377 pp_newline (pp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3378
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3379 // TODO: also show the per-callstring breakdown
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3380 const exploded_graph::call_string_data_map_t *per_cs_data
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3381 = args.m_eg->get_per_call_string_data ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3382 for (exploded_graph::call_string_data_map_t::iterator iter
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3383 = per_cs_data->begin ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3384 iter != per_cs_data->end ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3385 ++iter)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3386 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3387 const call_string *cs = (*iter).first;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3388 //per_call_string_data *data = (*iter).second;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3389 num_enodes = 0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3390 FOR_EACH_VEC_ELT (args.m_eg->m_nodes, i, enode)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3391 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3392 if (enode->get_point ().get_function () == m_fun
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3393 && enode->get_point ().get_call_string () == *cs)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3394 num_enodes++;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3395 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3396 if (num_enodes > 0)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3397 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3398 gv->begin_tr ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3399 cs->print (pp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3400 pp_printf (pp, ": %i\n", num_enodes);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3401 pp_write_text_as_html_like_dot_to_stream (pp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3402 gv->end_tr ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3403 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3404 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3405
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3406 /* Show any summaries. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3407 per_function_data *data = args.m_eg->get_per_function_data (m_fun);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3408 if (data)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3409 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3410 pp_newline (pp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3411 gv->begin_tr ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3412 pp_printf (pp, "summaries: %i\n", data->m_summaries.length ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3413 pp_write_text_as_html_like_dot_to_stream (pp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3414 gv->end_tr ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3415 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3416 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3417
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3418 pp_string (pp, "</TABLE>>];\n\n");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3419 pp_flush (pp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3420 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3421
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3422 void dump_dot_id (pretty_printer *pp) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3423 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3424 pp_printf (pp, "vcg_%i", m_index);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3425 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3426
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3427 private:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3428 function *m_fun;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3429 int m_index;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3430 int m_num_supernodes;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3431 int m_num_superedges;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3432 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3433
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3434 /* Subclass of dedge representing a callgraph edge. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3435
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3436 class viz_callgraph_edge : public dedge<viz_callgraph_traits>
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3437 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3438 public:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3439 viz_callgraph_edge (viz_callgraph_node *src, viz_callgraph_node *dest,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3440 const call_superedge *call_sedge)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3441 : dedge<viz_callgraph_traits> (src, dest),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3442 m_call_sedge (call_sedge)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3443 {}
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3444
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3445 void dump_dot (graphviz_out *gv, const dump_args_t &) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3446 FINAL OVERRIDE
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3447 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3448 pretty_printer *pp = gv->get_pp ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3449
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3450 const char *style = "\"solid,bold\"";
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3451 const char *color = "black";
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3452 int weight = 10;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3453 const char *constraint = "true";
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3454
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3455 m_src->dump_dot_id (pp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3456 pp_string (pp, " -> ");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3457 m_dest->dump_dot_id (pp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3458 pp_printf (pp,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3459 (" [style=%s, color=%s, weight=%d, constraint=%s,"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3460 " headlabel=\""),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3461 style, color, weight, constraint);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3462 pp_printf (pp, "\"];\n");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3463 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3464
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3465 private:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3466 const call_superedge * const m_call_sedge;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3467 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3468
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3469 /* Subclass of digraph representing the callgraph. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3470
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3471 class viz_callgraph : public digraph<viz_callgraph_traits>
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3472 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3473 public:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3474 viz_callgraph (const supergraph &sg);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3475
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3476 viz_callgraph_node *get_vcg_node_for_function (function *fun)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3477 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3478 return *m_map.get (fun);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3479 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3480
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3481 viz_callgraph_node *get_vcg_node_for_snode (supernode *snode)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3482 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3483 return get_vcg_node_for_function (snode->m_fun);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3484 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3485
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3486 private:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3487 const supergraph &m_sg;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3488 hash_map<function *, viz_callgraph_node *> m_map;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3489 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3490
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3491 /* Placeholder subclass of cluster. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3492
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3493 class viz_callgraph_cluster : public cluster<viz_callgraph_traits>
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3494 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3495 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3496
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3497 /* viz_callgraph's ctor. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3498
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3499 viz_callgraph::viz_callgraph (const supergraph &sg)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3500 : m_sg (sg)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3501 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3502 cgraph_node *node;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3503 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3504 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3505 function *fun = node->get_fun ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3506 viz_callgraph_node *vcg_node
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3507 = new viz_callgraph_node (fun, m_nodes.length ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3508 m_map.put (fun, vcg_node);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3509 add_node (vcg_node);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3510 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3511
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3512 unsigned i;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3513 superedge *sedge;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3514 FOR_EACH_VEC_ELT (sg.m_edges, i, sedge)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3515 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3516 viz_callgraph_node *vcg_src = get_vcg_node_for_snode (sedge->m_src);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3517 if (vcg_src->m_fun)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3518 get_vcg_node_for_function (vcg_src->m_fun)->m_num_superedges++;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3519 if (const call_superedge *call_sedge = sedge->dyn_cast_call_superedge ())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3520 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3521 viz_callgraph_node *vcg_dest = get_vcg_node_for_snode (sedge->m_dest);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3522 viz_callgraph_edge *vcg_edge
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3523 = new viz_callgraph_edge (vcg_src, vcg_dest, call_sedge);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3524 add_edge (vcg_edge);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3525 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3526 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3527
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3528 supernode *snode;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3529 FOR_EACH_VEC_ELT (sg.m_nodes, i, snode)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3530 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3531 if (snode->m_fun)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3532 get_vcg_node_for_function (snode->m_fun)->m_num_supernodes++;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3533 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3534 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3535
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3536 /* Dump the callgraph to FILENAME. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3537
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3538 static void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3539 dump_callgraph (const supergraph &sg, const char *filename,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3540 const exploded_graph *eg)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3541 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3542 FILE *outf = fopen (filename, "w");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3543 if (!outf)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3544 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3545
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3546 // TODO
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3547 viz_callgraph vcg (sg);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3548 vcg.dump_dot (filename, NULL, viz_callgraph_traits::dump_args_t (eg));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3549
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3550 fclose (outf);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3551 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3552
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3553 /* Dump the callgraph to "<srcfile>.callgraph.dot". */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3554
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3555 static void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3556 dump_callgraph (const supergraph &sg, const exploded_graph *eg)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3557 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3558 auto_timevar tv (TV_ANALYZER_DUMP);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3559 char *filename = concat (dump_base_name, ".callgraph.dot", NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3560 dump_callgraph (sg, filename, eg);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3561 free (filename);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3562 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3563
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3564 /* Run the analysis "engine". */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3565
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3566 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3567 impl_run_checkers (logger *logger)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3568 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3569 LOG_SCOPE (logger);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3570
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3571 /* If using LTO, ensure that the cgraph nodes have function bodies. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3572 cgraph_node *node;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3573 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3574 node->get_untransformed_body ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3575
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3576 /* Create the supergraph. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3577 supergraph sg (logger);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3578
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3579 state_purge_map *purge_map = NULL;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3580
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3581 if (flag_analyzer_state_purge)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3582 purge_map = new state_purge_map (sg, logger);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3583
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3584 if (flag_dump_analyzer_supergraph)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3585 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3586 auto_timevar tv (TV_ANALYZER_DUMP);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3587 char *filename = concat (dump_base_name, ".supergraph.dot", NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3588 supergraph::dump_args_t args ((enum supergraph_dot_flags)0, NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3589 sg.dump_dot (filename, args);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3590 free (filename);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3591 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3592
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3593 if (flag_dump_analyzer_state_purge)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3594 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3595 auto_timevar tv (TV_ANALYZER_DUMP);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3596 state_purge_annotator a (purge_map);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3597 char *filename = concat (dump_base_name, ".state-purge.dot", NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3598 supergraph::dump_args_t args ((enum supergraph_dot_flags)0, &a);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3599 sg.dump_dot (filename, args);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3600 free (filename);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3601 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3602
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3603 auto_delete_vec <state_machine> checkers;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3604 make_checkers (checkers, logger);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3605
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3606 if (logger)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3607 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3608 int i;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3609 state_machine *sm;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3610 FOR_EACH_VEC_ELT (checkers, i, sm)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3611 logger->log ("checkers[%i]: %s", i, sm->get_name ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3612 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3613
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3614 /* Extrinsic state shared by nodes in the graph. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3615 const extrinsic_state ext_state (checkers);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3616
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3617 const analysis_plan plan (sg, logger);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3618
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3619 /* The exploded graph. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3620 exploded_graph eg (sg, logger, ext_state, purge_map, plan,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3621 analyzer_verbosity);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3622
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3623 /* Add entrypoints to the graph for externally-callable functions. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3624 eg.build_initial_worklist ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3625
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3626 /* Now process the worklist, exploring the <point, state> graph. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3627 eg.process_worklist ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3628
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3629 if (flag_dump_analyzer_exploded_graph)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3630 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3631 auto_timevar tv (TV_ANALYZER_DUMP);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3632 char *filename
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3633 = concat (dump_base_name, ".eg.dot", NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3634 exploded_graph::dump_args_t args (eg);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3635 root_cluster c;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3636 eg.dump_dot (filename, &c, args);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3637 free (filename);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3638 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3639
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3640 /* Now emit any saved diagnostics. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3641 eg.get_diagnostic_manager ().emit_saved_diagnostics (eg);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3642
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3643 eg.dump_exploded_nodes ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3644
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3645 eg.log_stats ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3646
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3647 if (flag_dump_analyzer_callgraph)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3648 dump_callgraph (sg, &eg);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3649
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3650 delete purge_map;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3651 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3652
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3653 /* External entrypoint to the analysis "engine".
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3654 Set up any dumps, then call impl_run_checkers. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3655
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3656 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3657 run_checkers ()
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3658 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3659 /* Save input_location. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3660 location_t saved_input_location = input_location;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3661
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3662 /* Handle -fdump-analyzer and -fdump-analyzer-stderr. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3663 FILE *dump_fout = NULL;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3664 /* Track if we're responsible for closing dump_fout. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3665 bool owns_dump_fout = false;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3666 if (flag_dump_analyzer_stderr)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3667 dump_fout = stderr;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3668 else if (flag_dump_analyzer)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3669 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3670 char *dump_filename = concat (dump_base_name, ".analyzer.txt", NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3671 dump_fout = fopen (dump_filename, "w");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3672 free (dump_filename);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3673 if (dump_fout)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3674 owns_dump_fout = true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3675 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3676
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3677 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3678 log_user the_logger (NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3679 if (dump_fout)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3680 the_logger.set_logger (new logger (dump_fout, 0, 0,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3681 *global_dc->printer));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3682 LOG_SCOPE (the_logger.get_logger ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3683
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3684 impl_run_checkers (the_logger.get_logger ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3685
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3686 /* end of lifetime of the_logger (so that dump file is closed after the
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3687 various dtors run). */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3688 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3689
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3690 if (owns_dump_fout)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3691 fclose (dump_fout);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3692
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3693 /* Restore input_location. Subsequent passes may assume that input_location
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3694 is some arbitrary value *not* in the block tree, which might be violated
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3695 if we didn't restore it. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3696 input_location = saved_input_location;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3697 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3698
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3699 } // namespace ana
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3700
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3701 #endif /* #if ENABLE_ANALYZER */