annotate gcc/analyzer/exploded-graph.h @ 145:1830386684a0

gcc-9.2.0
author anatofuz
date Thu, 13 Feb 2020 11:34:05 +0900
parents
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 /* Classes for managing a directed graph of <point, state> pairs.
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 #ifndef GCC_ANALYZER_EXPLODED_GRAPH_H
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
22 #define GCC_ANALYZER_EXPLODED_GRAPH_H
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
23
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
24 namespace ana {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
25
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
26 /* Concrete implementation of region_model_context, wiring it up to the
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
27 rest of the analysis engine. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
28
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
29 class impl_region_model_context : public region_model_context
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
30 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
31 public:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
32 impl_region_model_context (exploded_graph &eg,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
33 const exploded_node *enode_for_diag,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
34
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
35 /* TODO: should we be getting the ECs from the
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
36 old state, rather than the new? */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
37 const program_state *old_state,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
38 program_state *new_state,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
39 state_change *change,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
40
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
41 const gimple *stmt,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
42 stmt_finder *stmt_finder = NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
43
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
44 impl_region_model_context (program_state *state,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
45 state_change *change,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
46 const extrinsic_state &ext_state);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
47
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
48 void warn (pending_diagnostic *d) FINAL OVERRIDE;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
49
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
50 void remap_svalue_ids (const svalue_id_map &map) FINAL OVERRIDE;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
51
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
52 int on_svalue_purge (svalue_id first_unused_sid,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
53 const svalue_id_map &map) FINAL OVERRIDE;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
54
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
55 logger *get_logger () FINAL OVERRIDE
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
56 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
57 return m_logger.get_logger ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
58 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
59
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
60 void on_state_leak (const state_machine &sm,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
61 int sm_idx,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
62 svalue_id sid,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
63 svalue_id first_unused_sid,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
64 const svalue_id_map &map,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
65 state_machine::state_t state);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
66
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
67 void on_inherited_svalue (svalue_id parent_sid,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
68 svalue_id child_sid) FINAL OVERRIDE;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
69
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
70 void on_cast (svalue_id src_sid,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
71 svalue_id dst_sid) FINAL OVERRIDE;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
72
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
73 void on_condition (tree lhs, enum tree_code op, tree rhs) FINAL OVERRIDE;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
74
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
75 void on_unknown_change (svalue_id sid ATTRIBUTE_UNUSED) FINAL OVERRIDE;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
76
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
77 void on_phi (const gphi *phi, tree rhs) FINAL OVERRIDE;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
78
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
79 exploded_graph *m_eg;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
80 log_user m_logger;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
81 const exploded_node *m_enode_for_diag;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
82 const program_state *m_old_state;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
83 program_state *m_new_state;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
84 state_change *m_change;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
85 const gimple *m_stmt;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
86 stmt_finder *m_stmt_finder;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
87 const extrinsic_state &m_ext_state;
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 /* A <program_point, program_state> pair, used internally by
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
91 exploded_node as its immutable data, and as a key for identifying
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
92 exploded_nodes we've already seen in the graph. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
93
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
94 class point_and_state
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
95 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
96 public:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
97 point_and_state (const program_point &point,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
98 const program_state &state)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
99 : m_point (point),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
100 m_state (state),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
101 m_hash (m_point.hash () ^ m_state.hash ())
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
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
105 hashval_t hash () const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
106 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
107 return m_hash;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
108 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
109 bool operator== (const point_and_state &other) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
110 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
111 return m_point == other.m_point && m_state == other.m_state;
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 const program_point &get_point () const { return m_point; }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
115 const program_state &get_state () const { return m_state; }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
116
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
117 void set_state (const program_state &state)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
118 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
119 m_state = state;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
120 m_hash = m_point.hash () ^ m_state.hash ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
121 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
122
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
123 void validate (const extrinsic_state &ext_state) const;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
124
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
125 private:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
126 program_point m_point;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
127 program_state m_state;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
128 hashval_t m_hash;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
129 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
130
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
131 /* A traits class for exploded graphs and their nodes and edges. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
132
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
133 struct eg_traits
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
134 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
135 typedef exploded_node node_t;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
136 typedef exploded_edge edge_t;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
137 typedef exploded_graph graph_t;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
138 struct dump_args_t
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
139 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
140 dump_args_t (const exploded_graph &eg) : m_eg (eg) {}
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
141 const exploded_graph &m_eg;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
142 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
143 typedef exploded_cluster cluster_t;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
144 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
145
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
146 /* An exploded_node is a unique, immutable <point, state> pair within the
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
147 exploded_graph.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
148 Each exploded_node has a unique index within the graph
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
149 (for ease of debugging). */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
150
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
151 class exploded_node : public dnode<eg_traits>
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
152 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
153 public:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
154 /* Has this enode had exploded_graph::process_node called on it?
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
155 This allows us to distinguish enodes that were merged during
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
156 worklist-handling, and thus never had process_node called on them
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
157 (in favor of processing the merged node). */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
158 enum status
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
159 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
160 /* Node is in the worklist. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
161 STATUS_WORKLIST,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
162
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
163 /* Node has had exploded_graph::process_node called on it. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
164 STATUS_PROCESSED,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
165
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
166 /* Node was left unprocessed due to merger; it won't have had
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
167 exploded_graph::process_node called on it. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
168 STATUS_MERGER
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
169 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
170
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
171 exploded_node (point_and_state ps,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
172 int index)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
173 : m_ps (ps), m_status (STATUS_WORKLIST), m_index (index)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
174 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
175 gcc_checking_assert (ps.get_state ().m_region_model->canonicalized_p ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
176 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
177
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
178 hashval_t hash () const { return m_ps.hash (); }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
179
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
180 void dump_dot (graphviz_out *gv, const dump_args_t &args)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
181 const FINAL OVERRIDE;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
182 void dump_dot_id (pretty_printer *pp) const;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
183
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
184 void dump_to_pp (pretty_printer *pp, const extrinsic_state &ext_state) const;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
185 void dump (FILE *fp, const extrinsic_state &ext_state) const;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
186 void dump (const extrinsic_state &ext_state) const;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
187
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
188 /* The result of on_stmt. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
189 struct on_stmt_flags
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
190 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
191 on_stmt_flags (bool sm_changes)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
192 : m_sm_changes (sm_changes),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
193 m_terminate_path (false)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
194 {}
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
195
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
196 static on_stmt_flags terminate_path ()
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
197 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
198 return on_stmt_flags (true, true);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
199 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
200
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
201 static on_stmt_flags state_change (bool any_sm_changes)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
202 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
203 return on_stmt_flags (any_sm_changes, false);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
204 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
205
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
206 /* Did any sm-changes occur handling the stmt. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
207 bool m_sm_changes : 1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
208
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
209 /* Should we stop analyzing this path (on_stmt may have already
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
210 added nodes/edges, e.g. when handling longjmp). */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
211 bool m_terminate_path : 1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
212
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
213 private:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
214 on_stmt_flags (bool sm_changes,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
215 bool terminate_path)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
216 : m_sm_changes (sm_changes),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
217 m_terminate_path (terminate_path)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
218 {}
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
219 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
220
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
221 on_stmt_flags on_stmt (exploded_graph &eg,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
222 const supernode *snode,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
223 const gimple *stmt,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
224 program_state *state,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
225 state_change *change) const;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
226 bool on_edge (exploded_graph &eg,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
227 const superedge *succ,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
228 program_point *next_point,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
229 program_state *next_state,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
230 state_change *change) const;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
231 void on_longjmp (exploded_graph &eg,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
232 const gcall *call,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
233 program_state *new_state,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
234 region_model_context *ctxt) const;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
235
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
236 void detect_leaks (exploded_graph &eg) const;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
237
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
238 const program_point &get_point () const { return m_ps.get_point (); }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
239 const supernode *get_supernode () const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
240 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
241 return get_point ().get_supernode ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
242 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
243 function *get_function () const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
244 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
245 return get_point ().get_function ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
246 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
247 int get_stack_depth () const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
248 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
249 return get_point ().get_stack_depth ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
250 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
251 const gimple *get_stmt () const { return get_point ().get_stmt (); }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
252
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
253 const program_state &get_state () const { return m_ps.get_state (); }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
254
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
255 const point_and_state *get_ps_key () const { return &m_ps; }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
256 const program_point *get_point_key () const { return &m_ps.get_point (); }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
257
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
258 void dump_succs_and_preds (FILE *outf) const;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
259
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
260 enum status get_status () const { return m_status; }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
261 void set_status (enum status status)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
262 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
263 gcc_assert (m_status == STATUS_WORKLIST);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
264 m_status = status;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
265 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
266
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
267 private:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
268 DISABLE_COPY_AND_ASSIGN (exploded_node);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
269
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
270 const char * get_dot_fillcolor () const;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
271
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
272 /* The <program_point, program_state> pair. This is const, as it
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
273 is immutable once the exploded_node has been created. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
274 const point_and_state m_ps;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
275
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
276 enum status m_status;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
277
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
278 public:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
279 /* The index of this exploded_node. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
280 const int m_index;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
281 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
282
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
283 /* An edge within the exploded graph.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
284 Some exploded_edges have an underlying superedge; others don't. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
285
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
286 class exploded_edge : public dedge<eg_traits>
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
287 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
288 public:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
289 /* Abstract base class for associating custom data with an
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
290 exploded_edge, for handling non-standard edges such as
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
291 rewinding from a longjmp, signal handlers, etc. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
292 class custom_info_t
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
293 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
294 public:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
295 virtual ~custom_info_t () {}
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
296
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
297 /* Hook for making .dot label more readable . */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
298 virtual void print (pretty_printer *pp) = 0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
299
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
300 /* Hook for updating MODEL within exploded_path::feasible_p. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
301 virtual void update_model (region_model *model,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
302 const exploded_edge &eedge) = 0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
303
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
304 virtual void add_events_to_path (checker_path *emission_path,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
305 const exploded_edge &eedge) = 0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
306 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
307
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
308 exploded_edge (exploded_node *src, exploded_node *dest,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
309 const extrinsic_state &ext_state,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
310 const superedge *sedge,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
311 const state_change &change,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
312 custom_info_t *custom_info);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
313 ~exploded_edge ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
314 void dump_dot (graphviz_out *gv, const dump_args_t &args)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
315 const FINAL OVERRIDE;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
316
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
317 //private:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
318 const superedge *const m_sedge;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
319
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
320 const state_change m_change;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
321
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
322 /* NULL for most edges; will be non-NULL for special cases
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
323 such as an unwind from a longjmp to a setjmp, or when
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
324 a signal is delivered to a signal-handler.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
325
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
326 Owned by this class. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
327 custom_info_t *m_custom_info;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
328
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
329 private:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
330 DISABLE_COPY_AND_ASSIGN (exploded_edge);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
331 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
332
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
333 /* Extra data for an exploded_edge that represents a rewind from a
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
334 longjmp to a setjmp (or from a siglongjmp to a sigsetjmp). */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
335
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
336 class rewind_info_t : public exploded_edge::custom_info_t
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
337 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
338 public:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
339 rewind_info_t (const setjmp_record &setjmp_record,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
340 const gcall *longjmp_call)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
341 : m_setjmp_record (setjmp_record),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
342 m_longjmp_call (longjmp_call)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
343 {}
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
344
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
345 void print (pretty_printer *pp) FINAL OVERRIDE
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
346 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
347 pp_string (pp, "rewind");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
348 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
349
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
350 void update_model (region_model *model,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
351 const exploded_edge &eedge) FINAL OVERRIDE;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
352
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
353 void add_events_to_path (checker_path *emission_path,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
354 const exploded_edge &eedge) FINAL OVERRIDE;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
355
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
356 const program_point &get_setjmp_point () const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
357 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
358 const program_point &origin_point = get_enode_origin ()->get_point ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
359
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
360 /* "origin_point" ought to be before the call to "setjmp". */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
361 gcc_assert (origin_point.get_kind () == PK_BEFORE_STMT);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
362
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
363 /* TODO: assert that it's the final stmt in its supernode. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
364
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
365 return origin_point;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
366 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
367
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
368 const gcall *get_setjmp_call () const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
369 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
370 return m_setjmp_record.m_setjmp_call;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
371 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
372
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
373 const gcall *get_longjmp_call () const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
374 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
375 return m_longjmp_call;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
376 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
377
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
378 const exploded_node *get_enode_origin () const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
379 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
380 return m_setjmp_record.m_enode;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
381 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
382
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
383 private:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
384 setjmp_record m_setjmp_record;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
385 const gcall *m_longjmp_call;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
386 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
387
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
388 /* Statistics about aspects of an exploded_graph. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
389
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
390 struct stats
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
391 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
392 stats (int num_supernodes);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
393 void log (logger *logger) const;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
394 void dump (FILE *out) const;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
395
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
396 int m_num_nodes[NUM_POINT_KINDS];
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
397 int m_node_reuse_count;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
398 int m_node_reuse_after_merge_count;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
399 int m_num_supernodes;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
400 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
401
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
402 /* Traits class for ensuring uniqueness of point_and_state data within
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
403 an exploded_graph. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
404
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
405 struct eg_hash_map_traits
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
406 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
407 typedef const point_and_state *key_type;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
408 typedef exploded_node *value_type;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
409 typedef exploded_node *compare_type;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
410
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
411 static inline hashval_t hash (const key_type &k)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
412 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
413 gcc_assert (k != NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
414 gcc_assert (k != reinterpret_cast<key_type> (1));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
415 return k->hash ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
416 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
417 static inline bool equal_keys (const key_type &k1, const key_type &k2)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
418 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
419 gcc_assert (k1 != NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
420 gcc_assert (k2 != NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
421 gcc_assert (k1 != reinterpret_cast<key_type> (1));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
422 gcc_assert (k2 != reinterpret_cast<key_type> (1));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
423 if (k1 && k2)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
424 return *k1 == *k2;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
425 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
426 /* Otherwise they must both be non-NULL. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
427 return k1 == k2;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
428 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
429 template <typename T>
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
430 static inline void remove (T &)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
431 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
432 /* empty; the nodes are handled elsewhere. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
433 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
434 template <typename T>
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
435 static inline void mark_deleted (T &entry)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
436 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
437 entry.m_key = reinterpret_cast<key_type> (1);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
438 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
439 template <typename T>
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
440 static inline void mark_empty (T &entry)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
441 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
442 entry.m_key = NULL;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
443 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
444 template <typename T>
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
445 static inline bool is_deleted (const T &entry)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
446 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
447 return entry.m_key == reinterpret_cast<key_type> (1);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
448 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
449 template <typename T>
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
450 static inline bool is_empty (const T &entry)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
451 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
452 return entry.m_key == NULL;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
453 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
454 static const bool empty_zero_p = false;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
455 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
456
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
457 /* Per-program_point data for an exploded_graph. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
458
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
459 struct per_program_point_data
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
460 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
461 per_program_point_data (const program_point &key)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
462 : m_key (key)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
463 {}
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
464
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
465 const program_point m_key;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
466 auto_vec<exploded_node *> m_enodes;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
467 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
468
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
469 /* Traits class for storing per-program_point data within
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
470 an exploded_graph. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
471
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
472 struct eg_point_hash_map_traits
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
473 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
474 typedef const program_point *key_type;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
475 typedef per_program_point_data *value_type;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
476 typedef per_program_point_data *compare_type;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
477
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
478 static inline hashval_t hash (const key_type &k)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
479 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
480 gcc_assert (k != NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
481 gcc_assert (k != reinterpret_cast<key_type> (1));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
482 return k->hash ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
483 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
484 static inline bool equal_keys (const key_type &k1, const key_type &k2)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
485 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
486 gcc_assert (k1 != NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
487 gcc_assert (k2 != NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
488 gcc_assert (k1 != reinterpret_cast<key_type> (1));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
489 gcc_assert (k2 != reinterpret_cast<key_type> (1));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
490 if (k1 && k2)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
491 return *k1 == *k2;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
492 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
493 /* Otherwise they must both be non-NULL. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
494 return k1 == k2;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
495 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
496 template <typename T>
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
497 static inline void remove (T &)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
498 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
499 /* empty; the nodes are handled elsewhere. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
500 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
501 template <typename T>
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
502 static inline void mark_deleted (T &entry)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
503 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
504 entry.m_key = reinterpret_cast<key_type> (1);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
505 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
506 template <typename T>
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
507 static inline void mark_empty (T &entry)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
508 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
509 entry.m_key = NULL;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
510 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
511 template <typename T>
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
512 static inline bool is_deleted (const T &entry)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
513 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
514 return entry.m_key == reinterpret_cast<key_type> (1);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
515 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
516 template <typename T>
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
517 static inline bool is_empty (const T &entry)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
518 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
519 return entry.m_key == NULL;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
520 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
521 static const bool empty_zero_p = false;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
522 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
523
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
524 /* Data about a particular call_string within an exploded_graph. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
525
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
526 struct per_call_string_data
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
527 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
528 per_call_string_data (const call_string &key, int num_supernodes)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
529 : m_key (key), m_stats (num_supernodes)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
530 {}
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
531
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
532 const call_string m_key;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
533 stats m_stats;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
534 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
535
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
536 /* Traits class for storing per-call_string data within
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
537 an exploded_graph. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
538
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
539 struct eg_call_string_hash_map_traits
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
540 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
541 typedef const call_string *key_type;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
542 typedef per_call_string_data *value_type;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
543 typedef per_call_string_data *compare_type;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
544
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
545 static inline hashval_t hash (const key_type &k)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
546 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
547 gcc_assert (k != NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
548 gcc_assert (k != reinterpret_cast<key_type> (1));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
549 return k->hash ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
550 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
551 static inline bool equal_keys (const key_type &k1, const key_type &k2)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
552 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
553 gcc_assert (k1 != NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
554 gcc_assert (k2 != NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
555 gcc_assert (k1 != reinterpret_cast<key_type> (1));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
556 gcc_assert (k2 != reinterpret_cast<key_type> (1));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
557 if (k1 && k2)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
558 return *k1 == *k2;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
559 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
560 /* Otherwise they must both be non-NULL. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
561 return k1 == k2;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
562 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
563 template <typename T>
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
564 static inline void remove (T &)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
565 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
566 /* empty; the nodes are handled elsewhere. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
567 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
568 template <typename T>
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
569 static inline void mark_deleted (T &entry)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
570 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
571 entry.m_key = reinterpret_cast<key_type> (1);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
572 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
573 template <typename T>
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
574 static inline void mark_empty (T &entry)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
575 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
576 entry.m_key = NULL;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
577 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
578 template <typename T>
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
579 static inline bool is_deleted (const T &entry)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
580 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
581 return entry.m_key == reinterpret_cast<key_type> (1);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
582 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
583 template <typename T>
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
584 static inline bool is_empty (const T &entry)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
585 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
586 return entry.m_key == NULL;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
587 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
588 static const bool empty_zero_p = false;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
589 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
590
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
591 /* Data about a particular function within an exploded_graph. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
592
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
593 struct per_function_data
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
594 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
595 per_function_data () {}
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
596
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
597 void add_call_summary (exploded_node *node)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
598 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
599 m_summaries.safe_push (node);
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 auto_vec<exploded_node *> m_summaries;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
603 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
604
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
605
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
606 /* The strongly connected components of a supergraph.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
607 In particular, this allows us to compute a partial ordering
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
608 of supernodes. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
609
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
610 class strongly_connected_components
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
611 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
612 public:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
613 strongly_connected_components (const supergraph &sg, logger *logger);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
614
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
615 int get_scc_id (int node_index) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
616 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
617 return m_per_node[node_index].m_lowlink;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
618 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
619
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
620 void dump () const;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
621
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
622 private:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
623 struct per_node_data
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
624 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
625 per_node_data ()
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
626 : m_index (-1), m_lowlink (-1), m_on_stack (false)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
627 {}
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
628
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
629 int m_index;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
630 int m_lowlink;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
631 bool m_on_stack;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
632 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
633
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
634 void strong_connect (unsigned index);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
635
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
636 const supergraph &m_sg;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
637 auto_vec<unsigned> m_stack;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
638 auto_vec<per_node_data> m_per_node;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
639 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
640
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
641 /* The worklist of exploded_node instances that have been added to
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
642 an exploded_graph, but that haven't yet been processed to find
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
643 their successors (or warnings).
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
644
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
645 The enodes are stored in a priority queue, ordered by a topological
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
646 sort of the SCCs in the supergraph, so that enodes for the same
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
647 program_point should appear at the front of the queue together.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
648 This allows for state-merging at CFG join-points, so that
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
649 sufficiently-similar enodes can be merged into one. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
650
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
651 class worklist
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
652 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
653 public:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
654 worklist (const exploded_graph &eg, const analysis_plan &plan);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
655 unsigned length () const;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
656 exploded_node *take_next ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
657 exploded_node *peek_next ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
658 void add_node (exploded_node *enode);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
659
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
660 private:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
661 class key_t
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
662 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
663 public:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
664 key_t (const worklist &w, exploded_node *enode)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
665 : m_worklist (w), m_enode (enode)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
666 {}
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
667
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
668 bool operator< (const key_t &other) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
669 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
670 return cmp (*this, other) < 0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
671 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
672
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
673 bool operator== (const key_t &other) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
674 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
675 return cmp (*this, other) == 0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
676 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
677
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
678 bool operator> (const key_t &other) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
679 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
680 return !(*this == other || *this < other);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
681 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
682
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
683 private:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
684 static int cmp (const key_t &ka, const key_t &kb);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
685
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
686 int get_scc_id (const exploded_node *enode) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
687 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
688 const supernode *snode = enode->get_supernode ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
689 if (snode == NULL)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
690 return 0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
691 return m_worklist.m_scc.get_scc_id (snode->m_index);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
692 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
693
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
694 const worklist &m_worklist;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
695 exploded_node *m_enode;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
696 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
697
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
698 /* The order is important here: m_scc needs to stick around
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
699 until after m_queue has finished being cleaned up (the dtor
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
700 calls the ordering fns). */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
701 const exploded_graph &m_eg;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
702 strongly_connected_components m_scc;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
703 const analysis_plan &m_plan;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
704
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
705 /* Priority queue, backed by a fibonacci_heap. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
706 typedef fibonacci_heap<key_t, exploded_node> queue_t;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
707 queue_t m_queue;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
708 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
709
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
710 /* An exploded_graph is a directed graph of unique <point, state> pairs.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
711 It also has a worklist of nodes that are waiting for their successors
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
712 to be added to the graph. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
713
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
714 class exploded_graph : public digraph<eg_traits>
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
715 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
716 public:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
717 typedef hash_map <const call_string *, per_call_string_data *,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
718 eg_call_string_hash_map_traits> call_string_data_map_t;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
719
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
720 exploded_graph (const supergraph &sg, logger *logger,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
721 const extrinsic_state &ext_state,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
722 const state_purge_map *purge_map,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
723 const analysis_plan &plan,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
724 int verbosity);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
725 ~exploded_graph ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
726
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
727 logger *get_logger () const { return m_logger.get_logger (); }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
728
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
729 const supergraph &get_supergraph () const { return m_sg; }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
730 const extrinsic_state &get_ext_state () const { return m_ext_state; }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
731 const state_purge_map *get_purge_map () const { return m_purge_map; }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
732 const analysis_plan &get_analysis_plan () const { return m_plan; }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
733
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
734 exploded_node *get_origin () const { return m_origin; }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
735
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
736 exploded_node *add_function_entry (function *fun);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
737
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
738 void build_initial_worklist ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
739 void process_worklist ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
740 void process_node (exploded_node *node);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
741
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
742 exploded_node *get_or_create_node (const program_point &point,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
743 const program_state &state,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
744 state_change *change);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
745 exploded_edge *add_edge (exploded_node *src, exploded_node *dest,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
746 const superedge *sedge,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
747 const state_change &change,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
748 exploded_edge::custom_info_t *custom = NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
749
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
750 per_program_point_data *
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
751 get_or_create_per_program_point_data (const program_point &);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
752
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
753 per_call_string_data *
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
754 get_or_create_per_call_string_data (const call_string &);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
755
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
756 per_function_data *
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
757 get_or_create_per_function_data (function *);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
758 per_function_data *get_per_function_data (function *) const;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
759
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
760 void save_diagnostic (const state_machine &sm,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
761 const exploded_node *enode,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
762 const supernode *node, const gimple *stmt,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
763 stmt_finder *finder,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
764 tree var, state_machine::state_t state,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
765 pending_diagnostic *d);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
766
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
767 diagnostic_manager &get_diagnostic_manager ()
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
768 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
769 return m_diagnostic_manager;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
770 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
771
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
772 stats *get_global_stats () { return &m_global_stats; }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
773 stats *get_or_create_function_stats (function *fn);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
774 void log_stats () const;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
775 void dump_stats (FILE *) const;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
776 void dump_states_for_supernode (FILE *, const supernode *snode) const;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
777 void dump_exploded_nodes () const;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
778
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
779 const call_string_data_map_t *get_per_call_string_data () const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
780 { return &m_per_call_string_data; }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
781
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
782 private:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
783 DISABLE_COPY_AND_ASSIGN (exploded_graph);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
784
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
785 const supergraph &m_sg;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
786
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
787 log_user m_logger;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
788
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
789 /* Map from point/state to exploded node.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
790 To avoid duplication we store point_and_state
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
791 *pointers* as keys, rather than point_and_state, using the
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
792 instance from within the exploded_node, with a custom hasher. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
793 typedef hash_map <const point_and_state *, exploded_node *,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
794 eg_hash_map_traits> map_t;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
795 map_t m_point_and_state_to_node;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
796
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
797 /* Map from program_point to per-program_point data. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
798 typedef hash_map <const program_point *, per_program_point_data *,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
799 eg_point_hash_map_traits> point_map_t;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
800 point_map_t m_per_point_data;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
801
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
802 worklist m_worklist;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
803
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
804 exploded_node *m_origin;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
805
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
806 const extrinsic_state &m_ext_state;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
807
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
808 const state_purge_map *const m_purge_map;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
809
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
810 const analysis_plan &m_plan;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
811
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
812 typedef hash_map<function *, per_function_data *> per_function_data_t;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
813 per_function_data_t m_per_function_data;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
814
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
815 diagnostic_manager m_diagnostic_manager;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
816
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
817 /* Stats. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
818 stats m_global_stats;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
819 typedef ordered_hash_map<function *, stats *> function_stat_map_t;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
820 function_stat_map_t m_per_function_stats;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
821 stats m_functionless_stats;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
822
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
823 call_string_data_map_t m_per_call_string_data;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
824
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
825 auto_vec<int> m_PK_AFTER_SUPERNODE_per_snode;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
826 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
827
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
828 /* A path within an exploded_graph: a sequence of edges. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
829
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
830 class exploded_path
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
831 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
832 public:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
833 exploded_path () : m_edges () {}
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
834 exploded_path (const exploded_path &other);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
835 exploded_path & operator= (const exploded_path &other);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
836
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
837 unsigned length () const { return m_edges.length (); }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
838
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
839 bool find_stmt_backwards (const gimple *search_stmt,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
840 int *out_idx) const;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
841
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
842 exploded_node *get_final_enode () const;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
843
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
844 void dump_to_pp (pretty_printer *pp) const;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
845 void dump (FILE *fp) const;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
846 void dump () const;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
847
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
848 bool feasible_p (logger *logger) const;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
849
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
850 auto_vec<const exploded_edge *> m_edges;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
851 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
852
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
853 /* Finding the shortest exploded_path within an exploded_graph. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
854
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
855 typedef shortest_paths<eg_traits, exploded_path> shortest_exploded_paths;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
856
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
857 /* Abstract base class for use when passing NULL as the stmt for
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
858 a possible warning, allowing the choice of stmt to be deferred
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
859 until after we have an emission path (and know we're emitting a
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
860 warning). */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
861
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
862 class stmt_finder
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
863 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
864 public:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
865 virtual ~stmt_finder () {}
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
866 virtual stmt_finder *clone () const = 0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
867 virtual const gimple *find_stmt (const exploded_path &epath) = 0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
868 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
869
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
870 // TODO: split the above up?
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
871
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
872 } // namespace ana
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
873
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
874 #endif /* GCC_ANALYZER_EXPLODED_GRAPH_H */