annotate gcc/analyzer/program-state.cc @ 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 representing the state of interest at a given path of analysis.
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 "diagnostic.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
26 #include "function.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
27 #include "analyzer/analyzer.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
28 #include "analyzer/analyzer-logging.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
29 #include "analyzer/sm.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
30 #include "sbitmap.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
31 #include "tristate.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
32 #include "ordered-hash-map.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
33 #include "selftest.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
34 #include "analyzer/region-model.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
35 #include "analyzer/program-state.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
36 #include "analyzer/constraint-manager.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
37 #include "alloc-pool.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
38 #include "fibonacci_heap.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
39 #include "shortest-paths.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
40 #include "analyzer/constraint-manager.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
41 #include "diagnostic-event-id.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
42 #include "analyzer/pending-diagnostic.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
43 #include "analyzer/diagnostic-manager.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
44 #include "cfg.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
45 #include "basic-block.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
46 #include "gimple.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
47 #include "gimple-iterator.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
48 #include "cgraph.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
49 #include "digraph.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
50 #include "analyzer/supergraph.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
51 #include "analyzer/call-string.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
52 #include "analyzer/program-point.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
53 #include "analyzer/program-state.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
54 #include "analyzer/exploded-graph.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
55 #include "analyzer/state-purge.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
56 #include "analyzer/analyzer-selftests.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
57
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
58 #if ENABLE_ANALYZER
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
59
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
60 namespace ana {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
61
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
62 /* class extrinsic_state. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
63
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
64 /* Dump a multiline representation of this state to PP. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
65
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
66 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
67 extrinsic_state::dump_to_pp (pretty_printer *pp) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
68 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
69 pp_printf (pp, "extrinsic_state: %i checker(s)\n", get_num_checkers ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
70 unsigned i;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
71 state_machine *checker;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
72 FOR_EACH_VEC_ELT (m_checkers, i, checker)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
73 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
74 pp_printf (pp, "m_checkers[%i]: %qs\n", i, checker->get_name ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
75 checker->dump_to_pp (pp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
76 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
77 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
78
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
79 /* Dump a multiline representation of this state to OUTF. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
80
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
81 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
82 extrinsic_state::dump_to_file (FILE *outf) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
83 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
84 pretty_printer pp;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
85 if (outf == stderr)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
86 pp_show_color (&pp) = pp_show_color (global_dc->printer);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
87 pp.buffer->stream = outf;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
88 dump_to_pp (&pp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
89 pp_flush (&pp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
90 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
91
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
92 /* Dump a multiline representation of this state to stderr. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
93
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
94 DEBUG_FUNCTION void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
95 extrinsic_state::dump () const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
96 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
97 dump_to_file (stderr);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
98 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
99
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
100 /* class sm_state_map. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
101
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
102 /* sm_state_map's ctor. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
103
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
104 sm_state_map::sm_state_map ()
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
105 : m_map (), m_global_state (0)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
106 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
107 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
108
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
109 /* Clone the sm_state_map. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
110
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
111 sm_state_map *
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
112 sm_state_map::clone () const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
113 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
114 return new sm_state_map (*this);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
115 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
116
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
117 /* Clone this sm_state_map, remapping all svalue_ids within it with ID_MAP.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
118
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
119 Return NULL if there are any svalue_ids that have sm-state for which
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
120 ID_MAP maps them to svalue_id::null (and thus the clone would have lost
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
121 the sm-state information). */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
122
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
123 sm_state_map *
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
124 sm_state_map::clone_with_remapping (const one_way_svalue_id_map &id_map) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
125 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
126 sm_state_map *result = new sm_state_map ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
127 result->m_global_state = m_global_state;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
128 for (map_t::iterator iter = m_map.begin ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
129 iter != m_map.end ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
130 ++iter)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
131 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
132 svalue_id sid = (*iter).first;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
133 gcc_assert (!sid.null_p ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
134 entry_t e = (*iter).second;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
135 /* TODO: what should we do if the origin maps from non-null to null?
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
136 Is that loss of information acceptable? */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
137 id_map.update (&e.m_origin);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
138
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
139 svalue_id new_sid = id_map.get_dst_for_src (sid);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
140 if (new_sid.null_p ())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
141 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
142 delete result;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
143 return NULL;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
144 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
145 result->m_map.put (new_sid, e);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
146 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
147 return result;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
148 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
149
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
150 /* Print this sm_state_map (for SM) to PP. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
151
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
152 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
153 sm_state_map::print (const state_machine &sm, pretty_printer *pp) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
154 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
155 bool first = true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
156 pp_string (pp, "{");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
157 if (m_global_state != 0)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
158 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
159 pp_printf (pp, "global: %s", sm.get_state_name (m_global_state));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
160 first = false;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
161 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
162 for (map_t::iterator iter = m_map.begin ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
163 iter != m_map.end ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
164 ++iter)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
165 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
166 if (!first)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
167 pp_string (pp, ", ");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
168 first = false;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
169 svalue_id sid = (*iter).first;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
170 sid.print (pp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
171
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
172 entry_t e = (*iter).second;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
173 pp_printf (pp, ": %s (origin: ",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
174 sm.get_state_name (e.m_state));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
175 e.m_origin.print (pp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
176 pp_string (pp, ")");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
177 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
178 pp_string (pp, "}");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
179 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
180
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
181 /* Dump this object (for SM) to stderr. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
182
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
183 DEBUG_FUNCTION void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
184 sm_state_map::dump (const state_machine &sm) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
185 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
186 pretty_printer pp;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
187 pp_show_color (&pp) = pp_show_color (global_dc->printer);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
188 pp.buffer->stream = stderr;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
189 print (sm, &pp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
190 pp_newline (&pp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
191 pp_flush (&pp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
192 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
193
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
194 /* Return true if no states have been set within this map
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
195 (all expressions are for the start state). */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
196
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
197 bool
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
198 sm_state_map::is_empty_p () const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
199 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
200 return m_map.elements () == 0 && m_global_state == 0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
201 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
202
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
203 /* Generate a hash value for this sm_state_map. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
204
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
205 hashval_t
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
206 sm_state_map::hash () const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
207 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
208 hashval_t result = 0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
209
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
210 /* Accumulate the result by xoring a hash for each slot, so that the
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
211 result doesn't depend on the ordering of the slots in the map. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
212
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
213 for (map_t::iterator iter = m_map.begin ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
214 iter != m_map.end ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
215 ++iter)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
216 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
217 inchash::hash hstate;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
218 inchash::add ((*iter).first, hstate);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
219 entry_t e = (*iter).second;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
220 hstate.add_int (e.m_state);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
221 inchash::add (e.m_origin, hstate);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
222 result ^= hstate.end ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
223 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
224 result ^= m_global_state;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
225
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
226 return result;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
227 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
228
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
229 /* Equality operator for sm_state_map. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
230
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
231 bool
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
232 sm_state_map::operator== (const sm_state_map &other) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
233 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
234 if (m_global_state != other.m_global_state)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
235 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
236
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
237 if (m_map.elements () != other.m_map.elements ())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
238 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
239
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
240 for (map_t::iterator iter = m_map.begin ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
241 iter != m_map.end ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
242 ++iter)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
243 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
244 svalue_id sid = (*iter).first;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
245 entry_t e = (*iter).second;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
246 entry_t *other_slot = const_cast <map_t &> (other.m_map).get (sid);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
247 if (other_slot == NULL)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
248 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
249 if (e != *other_slot)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
250 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
251 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
252
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
253 gcc_checking_assert (hash () == other.hash ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
254
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
255 return true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
256 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
257
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
258 /* Get the state of SID within this object.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
259 States default to the start state. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
260
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
261 state_machine::state_t
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
262 sm_state_map::get_state (svalue_id sid) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
263 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
264 gcc_assert (!sid.null_p ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
265
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
266 if (entry_t *slot
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
267 = const_cast <map_t &> (m_map).get (sid))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
268 return slot->m_state;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
269 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
270 return 0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
271 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
272
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
273 /* Get the "origin" svalue_id for any state of SID. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
274
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
275 svalue_id
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
276 sm_state_map::get_origin (svalue_id sid) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
277 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
278 gcc_assert (!sid.null_p ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
279
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
280 entry_t *slot
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
281 = const_cast <map_t &> (m_map).get (sid);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
282 if (slot)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
283 return slot->m_origin;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
284 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
285 return svalue_id::null ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
286 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
287
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
288 /* Set the state of SID within MODEL to STATE, recording that
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
289 the state came from ORIGIN. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
290
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
291 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
292 sm_state_map::set_state (region_model *model,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
293 svalue_id sid,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
294 state_machine::state_t state,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
295 svalue_id origin)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
296 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
297 if (model == NULL)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
298 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
299 equiv_class &ec = model->get_constraints ()->get_equiv_class (sid);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
300 if (!set_state (ec, state, origin))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
301 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
302
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
303 /* Also do it for all svalues that are equal via non-cm, so that
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
304 e.g. (void *)&r and (foo *)&r transition together. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
305 for (unsigned i = 0; i < model->get_num_svalues (); i++)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
306 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
307 svalue_id other_sid = svalue_id::from_int (i);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
308 if (other_sid == sid)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
309 continue;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
310
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
311 tristate eq = model->eval_condition_without_cm (sid, EQ_EXPR, other_sid);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
312 if (eq.is_true ())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
313 impl_set_state (other_sid, state, origin);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
314 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
315 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
316
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
317 /* Set the state of EC to STATE, recording that the state came from
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
318 ORIGIN.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
319 Return true if any states of svalue_ids within EC changed. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
320
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
321 bool
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
322 sm_state_map::set_state (const equiv_class &ec,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
323 state_machine::state_t state,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
324 svalue_id origin)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
325 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
326 int i;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
327 svalue_id *sid;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
328 bool any_changed = false;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
329 FOR_EACH_VEC_ELT (ec.m_vars, i, sid)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
330 any_changed |= impl_set_state (*sid, state, origin);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
331 return any_changed;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
332 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
333
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
334 /* Set state of SID to STATE, bypassing equivalence classes.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
335 Return true if the state changed. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
336
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
337 bool
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
338 sm_state_map::impl_set_state (svalue_id sid, state_machine::state_t state,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
339 svalue_id origin)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
340 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
341 if (get_state (sid) == state)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
342 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
343
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
344 /* Special-case state 0 as the default value. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
345 if (state == 0)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
346 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
347 if (m_map.get (sid))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
348 m_map.remove (sid);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
349 return true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
350 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
351 gcc_assert (!sid.null_p ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
352 m_map.put (sid, entry_t (state, origin));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
353 return true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
354 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
355
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
356 /* Set the "global" state within this state map to STATE. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
357
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
358 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
359 sm_state_map::set_global_state (state_machine::state_t state)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
360 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
361 m_global_state = state;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
362 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
363
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
364 /* Get the "global" state within this state map. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
365
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
366 state_machine::state_t
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
367 sm_state_map::get_global_state () const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
368 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
369 return m_global_state;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
370 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
371
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
372 /* Handle CALL to unknown FNDECL with an unknown function body, which
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
373 could do anything to the states passed to it.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
374 Clear any state for SM for the params and any LHS.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
375 Note that the function might be known to other state machines, but
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
376 not to this one. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
377
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
378 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
379 sm_state_map::purge_for_unknown_fncall (const exploded_graph &eg,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
380 const state_machine &sm,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
381 const gcall *call,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
382 tree fndecl,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
383 region_model *new_model)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
384 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
385 logger * const logger = eg.get_logger ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
386 if (logger)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
387 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
388 if (fndecl)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
389 logger->log ("function %qE is unknown to checker %qs",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
390 fndecl, sm.get_name ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
391 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
392 logger->log ("unknown function pointer for checker %qs",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
393 sm.get_name ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
394 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
395
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
396 /* Purge any state for parms. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
397 tree iter_param_types = NULL_TREE;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
398 if (fndecl)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
399 iter_param_types = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
400 for (unsigned arg_idx = 0; arg_idx < gimple_call_num_args (call); arg_idx++)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
401 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
402 /* Track expected param type, where available. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
403 if (iter_param_types)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
404 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
405 tree param_type = TREE_VALUE (iter_param_types);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
406 gcc_assert (param_type);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
407 iter_param_types = TREE_CHAIN (iter_param_types);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
408
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
409 /* Don't purge state if it was passed as a const pointer
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
410 e.g. for things like strlen (PTR). */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
411 if (TREE_CODE (param_type) == POINTER_TYPE)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
412 if (TYPE_READONLY (TREE_TYPE (param_type)))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
413 continue;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
414 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
415 tree parm = gimple_call_arg (call, arg_idx);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
416 svalue_id parm_sid = new_model->get_rvalue (parm, NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
417 set_state (new_model, parm_sid, 0, svalue_id::null ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
418
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
419 /* Also clear sm-state from svalue_ids that are passed via a
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
420 pointer. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
421 if (TREE_CODE (parm) == ADDR_EXPR)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
422 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
423 tree pointee = TREE_OPERAND (parm, 0);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
424 svalue_id parm_sid = new_model->get_rvalue (pointee, NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
425 set_state (new_model, parm_sid, 0, svalue_id::null ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
426 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
427 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
428
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
429 /* Purge any state for any LHS. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
430 if (tree lhs = gimple_call_lhs (call))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
431 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
432 svalue_id lhs_sid = new_model->get_rvalue (lhs, NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
433 set_state (new_model, lhs_sid, 0, svalue_id::null ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
434 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
435 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
436
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
437 /* Update this map based on MAP. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
438
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
439 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
440 sm_state_map::remap_svalue_ids (const svalue_id_map &map)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
441 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
442 map_t tmp_map;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
443
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
444 /* Build an intermediate map, using the new sids. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
445 for (map_t::iterator iter = m_map.begin ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
446 iter != m_map.end ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
447 ++iter)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
448 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
449 svalue_id sid = (*iter).first;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
450 entry_t e = (*iter).second;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
451
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
452 map.update (&sid);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
453 map.update (&e.m_origin);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
454 tmp_map.put (sid, e);
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 /* Clear the existing values. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
458 m_map.empty ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
459
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
460 /* Copy over from intermediate map. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
461 for (map_t::iterator iter = tmp_map.begin ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
462 iter != tmp_map.end ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
463 ++iter)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
464 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
465 svalue_id sid = (*iter).first;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
466 entry_t e = (*iter).second;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
467
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
468 impl_set_state (sid, e.m_state, e.m_origin);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
469 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
470 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
471
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
472 /* Purge any state for svalue_ids >= FIRST_UNUSED_SID.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
473 If !SM::can_purge_p, then report the state as leaking,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
474 using SM_IDX, CTXT, and MAP.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
475 Return the number of states that were purged. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
476
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
477 int
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
478 sm_state_map::on_svalue_purge (const state_machine &sm,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
479 int sm_idx,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
480 svalue_id first_unused_sid,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
481 const svalue_id_map &map,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
482 impl_region_model_context *ctxt)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
483 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
484 /* TODO: ideally remove the slot directly; for now
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
485 do it in two stages. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
486 auto_vec<svalue_id> to_remove;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
487 for (map_t::iterator iter = m_map.begin ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
488 iter != m_map.end ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
489 ++iter)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
490 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
491 svalue_id dst_sid ((*iter).first);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
492 if (dst_sid.as_int () >= first_unused_sid.as_int ())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
493 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
494 /* Complain about leaks here. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
495 entry_t e = (*iter).second;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
496
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
497 if (!sm.can_purge_p (e.m_state))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
498 ctxt->on_state_leak (sm, sm_idx, dst_sid, first_unused_sid,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
499 map, e.m_state);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
500
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
501 to_remove.safe_push (dst_sid);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
502 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
503 else if ((*iter).second.m_origin.as_int () >= first_unused_sid.as_int ())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
504 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
505 /* If the origin svalue is being purged, then reset it to null. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
506 (*iter).second.m_origin = svalue_id::null ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
507 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
508 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
509
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
510 int i;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
511 svalue_id *dst_sid;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
512 FOR_EACH_VEC_ELT (to_remove, i, dst_sid)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
513 m_map.remove (*dst_sid);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
514
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
515 return to_remove.length ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
516 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
517
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
518 /* Set the state of CHILD_SID to that of PARENT_SID. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
519
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
520 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
521 sm_state_map::on_inherited_svalue (svalue_id parent_sid,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
522 svalue_id child_sid)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
523 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
524 state_machine::state_t state = get_state (parent_sid);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
525 impl_set_state (child_sid, state, parent_sid);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
526 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
527
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
528 /* Set the state of DST_SID to that of SRC_SID. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
529
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
530 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
531 sm_state_map::on_cast (svalue_id src_sid,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
532 svalue_id dst_sid)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
533 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
534 state_machine::state_t state = get_state (src_sid);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
535 impl_set_state (dst_sid, state, get_origin (src_sid));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
536 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
537
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
538 /* Purge state from SID (in response to a call to an unknown function). */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
539
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
540 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
541 sm_state_map::on_unknown_change (svalue_id sid)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
542 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
543 impl_set_state (sid, (state_machine::state_t)0, svalue_id::null ());
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 /* Assert that this object is sane. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
547
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
548 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
549 sm_state_map::validate (const state_machine &sm,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
550 int num_svalues) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
551 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
552 /* Skip this in a release build. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
553 #if !CHECKING_P
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
554 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
555 #endif
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
556
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
557 for (map_t::iterator iter = m_map.begin ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
558 iter != m_map.end ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
559 ++iter)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
560 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
561 svalue_id sid = (*iter).first;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
562 entry_t e = (*iter).second;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
563
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
564 gcc_assert (sid.as_int () < num_svalues);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
565 sm.validate (e.m_state);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
566 gcc_assert (e.m_origin.as_int () < num_svalues);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
567 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
568 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
569
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
570 /* class program_state. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
571
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
572 /* program_state's ctor. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
573
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
574 program_state::program_state (const extrinsic_state &ext_state)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
575 : m_region_model (new region_model ()),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
576 m_checker_states (ext_state.get_num_checkers ())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
577 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
578 int num_states = ext_state.get_num_checkers ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
579 for (int i = 0; i < num_states; i++)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
580 m_checker_states.quick_push (new sm_state_map ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
581 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
582
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
583 /* program_state's copy ctor. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
584
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
585 program_state::program_state (const program_state &other)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
586 : m_region_model (new region_model (*other.m_region_model)),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
587 m_checker_states (other.m_checker_states.length ())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
588 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
589 int i;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
590 sm_state_map *smap;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
591 FOR_EACH_VEC_ELT (other.m_checker_states, i, smap)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
592 m_checker_states.quick_push (smap->clone ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
593 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
594
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
595 /* program_state's assignment operator. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
596
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
597 program_state&
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
598 program_state::operator= (const program_state &other)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
599 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
600 delete m_region_model;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
601 m_region_model = new region_model (*other.m_region_model);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
602
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
603 int i;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
604 sm_state_map *smap;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
605 FOR_EACH_VEC_ELT (m_checker_states, i, smap)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
606 delete smap;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
607 m_checker_states.truncate (0);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
608 gcc_assert (m_checker_states.space (other.m_checker_states.length ()));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
609
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
610 FOR_EACH_VEC_ELT (other.m_checker_states, i, smap)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
611 m_checker_states.quick_push (smap->clone ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
612
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
613 return *this;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
614 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
615
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
616 #if __cplusplus >= 201103
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
617 /* Move constructor for program_state (when building with C++11). */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
618 program_state::program_state (program_state &&other)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
619 : m_region_model (other.m_region_model),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
620 m_checker_states (other.m_checker_states.length ())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
621 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
622 other.m_region_model = NULL;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
623
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
624 int i;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
625 sm_state_map *smap;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
626 FOR_EACH_VEC_ELT (other.m_checker_states, i, smap)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
627 m_checker_states.quick_push (smap);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
628 other.m_checker_states.truncate (0);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
629 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
630 #endif
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
631
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
632 /* program_state's dtor. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
633
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
634 program_state::~program_state ()
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
635 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
636 delete m_region_model;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
637 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
638
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
639 /* Generate a hash value for this program_state. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
640
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
641 hashval_t
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
642 program_state::hash () const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
643 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
644 hashval_t result = m_region_model->hash ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
645
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
646 int i;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
647 sm_state_map *smap;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
648 FOR_EACH_VEC_ELT (m_checker_states, i, smap)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
649 result ^= smap->hash ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
650 return result;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
651 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
652
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
653 /* Equality operator for program_state.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
654 All parts of the program_state (region model, checker states) must
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
655 equal their counterparts in OTHER for the two program_states to be
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
656 considered equal. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
657
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
658 bool
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
659 program_state::operator== (const program_state &other) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
660 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
661 if (!(*m_region_model == *other.m_region_model))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
662 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
663
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
664 int i;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
665 sm_state_map *smap;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
666 FOR_EACH_VEC_ELT (m_checker_states, i, smap)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
667 if (!(*smap == *other.m_checker_states[i]))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
668 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
669
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
670 gcc_checking_assert (hash () == other.hash ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
671
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
672 return true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
673 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
674
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
675 /* Print a compact representation of this state to PP. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
676
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
677 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
678 program_state::print (const extrinsic_state &ext_state,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
679 pretty_printer *pp) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
680 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
681 pp_printf (pp, "rmodel: ");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
682 m_region_model->print (pp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
683 pp_newline (pp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
684
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
685 int i;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
686 sm_state_map *smap;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
687 FOR_EACH_VEC_ELT (m_checker_states, i, smap)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
688 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
689 if (!smap->is_empty_p ())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
690 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
691 pp_printf (pp, "%s: ", ext_state.get_name (i));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
692 smap->print (ext_state.get_sm (i), pp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
693 pp_newline (pp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
694 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
695 }
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 /* Dump a multiline representation of this state to PP. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
699
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
700 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
701 program_state::dump_to_pp (const extrinsic_state &ext_state,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
702 bool summarize,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
703 pretty_printer *pp) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
704 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
705 pp_printf (pp, "rmodel: ");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
706 m_region_model->dump_to_pp (pp, summarize);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
707
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
708 int i;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
709 sm_state_map *smap;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
710 FOR_EACH_VEC_ELT (m_checker_states, i, smap)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
711 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
712 if (!smap->is_empty_p ())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
713 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
714 pp_printf (pp, "%s: ", ext_state.get_name (i));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
715 smap->print (ext_state.get_sm (i), pp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
716 pp_newline (pp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
717 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
718 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
719 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
720
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
721 /* Dump a multiline representation of this state to OUTF. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
722
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
723 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
724 program_state::dump_to_file (const extrinsic_state &ext_state,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
725 bool summarize,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
726 FILE *outf) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
727 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
728 pretty_printer pp;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
729 pp_format_decoder (&pp) = default_tree_printer;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
730 if (outf == stderr)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
731 pp_show_color (&pp) = pp_show_color (global_dc->printer);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
732 pp.buffer->stream = outf;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
733 dump_to_pp (ext_state, summarize, &pp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
734 pp_flush (&pp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
735 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
736
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
737 /* Dump a multiline representation of this state to stderr. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
738
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
739 DEBUG_FUNCTION void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
740 program_state::dump (const extrinsic_state &ext_state,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
741 bool summarize) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
742 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
743 dump_to_file (ext_state, summarize, stderr);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
744 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
745
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
746 /* Determine if following edge SUCC from ENODE is valid within the graph EG
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
747 and update this state accordingly in-place.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
748
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
749 Return true if the edge can be followed, or false otherwise.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
750
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
751 Check for relevant conditionals and switch-values for conditionals
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
752 and switch statements, adding the relevant conditions to this state.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
753 Push/pop frames for interprocedural edges and update params/returned
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
754 values.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
755
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
756 This is the "state" half of exploded_node::on_edge. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
757
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
758 bool
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
759 program_state::on_edge (exploded_graph &eg,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
760 const exploded_node &enode,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
761 const superedge *succ,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
762 state_change *change)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
763 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
764 /* Update state. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
765 const program_point &point = enode.get_point ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
766 const gimple *last_stmt = point.get_supernode ()->get_last_stmt ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
767
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
768 /* For conditionals and switch statements, add the
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
769 relevant conditions (for the specific edge) to new_state;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
770 skip edges for which the resulting constraints
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
771 are impossible.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
772 This also updates frame information for call/return superedges.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
773 Adding the relevant conditions for the edge could also trigger
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
774 sm-state transitions (e.g. transitions due to ptrs becoming known
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
775 to be NULL or non-NULL) */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
776
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
777 impl_region_model_context ctxt (eg, &enode,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
778 &enode.get_state (),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
779 this, change,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
780 last_stmt);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
781 if (!m_region_model->maybe_update_for_edge (*succ,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
782 last_stmt,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
783 &ctxt))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
784 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
785 logger * const logger = eg.get_logger ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
786 if (logger)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
787 logger->log ("edge to SN: %i is impossible"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
788 " due to region_model constraints",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
789 succ->m_dest->m_index);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
790 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
791 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
792
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
793 return true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
794 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
795
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
796 /* Generate a simpler version of THIS, discarding state that's no longer
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
797 relevant at POINT.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
798 The idea is that we're more likely to be able to consolidate
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
799 multiple (point, state) into single exploded_nodes if we discard
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
800 irrelevant state (e.g. at the end of functions).
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
801
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
802 Retain state affected by CHANGE, to make it easier to generate
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
803 state_change_events. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
804
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
805 program_state
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
806 program_state::prune_for_point (exploded_graph &eg,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
807 const program_point &point,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
808 state_change *change) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
809 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
810 logger * const logger = eg.get_logger ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
811 LOG_SCOPE (logger);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
812
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
813 function *fun = point.get_function ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
814 if (!fun)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
815 return *this;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
816
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
817 program_state new_state (*this);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
818
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
819 purge_stats stats;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
820
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
821 const state_purge_map *pm = eg.get_purge_map ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
822 if (pm)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
823 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
824 region_id_set purgeable_ssa_regions (new_state.m_region_model);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
825 region_id frame_rid
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
826 = new_state.m_region_model->get_current_frame_id ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
827 frame_region *frame
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
828 = new_state.m_region_model->get_region <frame_region>(frame_rid);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
829
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
830 /* TODO: maybe move to a member of region_model? */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
831
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
832 auto_vec<tree> ssa_names_to_purge;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
833 for (frame_region::map_t::iterator iter = frame->begin ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
834 iter != frame->end ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
835 ++iter)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
836 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
837 tree var = (*iter).first;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
838 region_id rid = (*iter).second;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
839 if (TREE_CODE (var) == SSA_NAME)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
840 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
841 const state_purge_per_ssa_name &per_ssa
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
842 = pm->get_data_for_ssa_name (var);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
843 if (!per_ssa.needed_at_point_p (point.get_function_point ()))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
844 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
845 region *region
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
846 = new_state.m_region_model->get_region (rid);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
847 svalue_id sid = region->get_value_direct ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
848 if (!sid.null_p ())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
849 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
850 if (!new_state.can_purge_p (eg.get_ext_state (), sid))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
851 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
852 /* (currently only state maps can keep things
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
853 alive). */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
854 if (logger)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
855 logger->log ("not purging RID: %i for %qE"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
856 " (used by state map)",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
857 rid.as_int (), var);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
858 continue;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
859 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
860
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
861 /* Don't purge regions containing svalues that
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
862 have a change of sm-state, to make it easier to
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
863 generate state_change_event messages. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
864 if (change)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
865 if (change->affects_p (sid))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
866 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
867 if (logger)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
868 logger->log ("not purging RID: %i for %qE"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
869 " (affected by change)",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
870 rid.as_int (), var);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
871 continue;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
872 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
873 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
874 purgeable_ssa_regions.add_region (rid);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
875 ssa_names_to_purge.safe_push (var);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
876 if (logger)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
877 logger->log ("purging RID: %i for %qE", rid.as_int (), var);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
878 /* We also need to remove the region from the map.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
879 We're in mid-traversal, so the removal is done in
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
880 unbind below. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
881 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
882 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
883 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
884
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
885 /* Unbind the regions from the frame's map of vars-to-regions. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
886 unsigned i;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
887 tree var;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
888 FOR_EACH_VEC_ELT (ssa_names_to_purge, i, var)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
889 frame->unbind (var);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
890
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
891 /* Purge the regions. Nothing should point to them, and they
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
892 should have no children, as they are for SSA names. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
893 new_state.m_region_model->purge_regions (purgeable_ssa_regions,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
894 &stats,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
895 eg.get_logger ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
896 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
897
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
898 /* Purge unused svalues. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
899 // TODO: which enode to use, if any?
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
900 impl_region_model_context ctxt (eg, NULL,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
901 this,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
902 &new_state,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
903 change,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
904 NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
905 new_state.m_region_model->purge_unused_svalues (&stats, &ctxt);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
906 if (logger)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
907 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
908 logger->log ("num svalues purged: %i", stats.m_num_svalues);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
909 logger->log ("num regions purged: %i", stats.m_num_regions);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
910 logger->log ("num equiv_classes purged: %i", stats.m_num_equiv_classes);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
911 logger->log ("num constraints purged: %i", stats.m_num_constraints);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
912 logger->log ("num sm map items purged: %i", stats.m_num_client_items);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
913 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
914
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
915 new_state.m_region_model->canonicalize (&ctxt);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
916
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
917 return new_state;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
918 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
919
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
920 /* Remap all svalue_ids in this state's m_checker_states according to MAP.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
921 The svalues_ids in the region_model are assumed to already have been
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
922 remapped. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
923
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
924 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
925 program_state::remap_svalue_ids (const svalue_id_map &map)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
926 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
927 int i;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
928 sm_state_map *smap;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
929 FOR_EACH_VEC_ELT (m_checker_states, i, smap)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
930 smap->remap_svalue_ids (map);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
931 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
932
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
933 /* Attempt to return a tree that represents SID, or return NULL_TREE.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
934 Find the first region that stores the value (e.g. a local) and
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
935 generate a representative tree for it. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
936
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
937 tree
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
938 program_state::get_representative_tree (svalue_id sid) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
939 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
940 return m_region_model->get_representative_tree (sid);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
941 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
942
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
943 /* Attempt to merge this state with OTHER, both using EXT_STATE.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
944 Write the result to *OUT.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
945 If the states were merged successfully, return true. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
946
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
947 bool
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
948 program_state::can_merge_with_p (const program_state &other,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
949 const extrinsic_state &ext_state,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
950 program_state *out) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
951 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
952 gcc_assert (out);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
953
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
954 /* TODO: initially I had an early reject here if there
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
955 are sm-differences between the states. However, this was
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
956 falsely rejecting merger opportunities for states where the
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
957 only difference was in svalue_id ordering. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
958
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
959 /* Attempt to merge the region_models. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
960
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
961 svalue_id_merger_mapping sid_mapping (*m_region_model,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
962 *other.m_region_model);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
963 if (!m_region_model->can_merge_with_p (*other.m_region_model,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
964 out->m_region_model,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
965 &sid_mapping))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
966 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
967
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
968 /* Copy m_checker_states to result, remapping svalue_ids using
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
969 sid_mapping. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
970 int i;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
971 sm_state_map *smap;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
972 FOR_EACH_VEC_ELT (out->m_checker_states, i, smap)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
973 delete smap;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
974 out->m_checker_states.truncate (0);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
975
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
976 /* Remap this and other's m_checker_states using sid_mapping.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
977 Only merge states that have equality between the two end-results:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
978 sm-state differences are likely to be interesting to end-users, and
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
979 hence are worth exploring as separate paths in the exploded graph. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
980 FOR_EACH_VEC_ELT (m_checker_states, i, smap)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
981 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
982 sm_state_map *other_smap = other.m_checker_states[i];
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
983
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
984 /* If clone_with_remapping returns NULL for one of the input smaps,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
985 then it has sm-state for an svalue_id where the svalue_id is
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
986 being mapped to svalue_id::null in its sid_mapping, meaning that
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
987 the svalue is to be dropped during the merger. We don't want
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
988 to lose sm-state during a state merger, so return false for these
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
989 cases. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
990 sm_state_map *remapped_a_smap
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
991 = smap->clone_with_remapping (sid_mapping.m_map_from_a_to_m);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
992 if (!remapped_a_smap)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
993 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
994 sm_state_map *remapped_b_smap
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
995 = other_smap->clone_with_remapping (sid_mapping.m_map_from_b_to_m);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
996 if (!remapped_b_smap)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
997 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
998 delete remapped_a_smap;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
999 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1000 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1001
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1002 /* Both states have sm-state for the same values; now ensure that the
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1003 states are equal. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1004 if (*remapped_a_smap == *remapped_b_smap)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1005 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1006 out->m_checker_states.safe_push (remapped_a_smap);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1007 delete remapped_b_smap;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1008 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1009 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1010 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1011 /* Don't merge if there are sm-state differences. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1012 delete remapped_a_smap;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1013 delete remapped_b_smap;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1014 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1015 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1016 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1017
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1018 impl_region_model_context ctxt (out, NULL, ext_state);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1019 out->m_region_model->canonicalize (&ctxt);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1020
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1021 return true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1022 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1023
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1024 /* Assert that this object is valid. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1025
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1026 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1027 program_state::validate (const extrinsic_state &ext_state) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1028 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1029 /* Skip this in a release build. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1030 #if !CHECKING_P
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1031 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1032 #endif
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1033
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1034 m_region_model->validate ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1035 gcc_assert (m_checker_states.length () == ext_state.get_num_checkers ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1036 int sm_idx;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1037 sm_state_map *smap;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1038 FOR_EACH_VEC_ELT (m_checker_states, sm_idx, smap)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1039 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1040 const state_machine &sm = ext_state.get_sm (sm_idx);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1041 smap->validate (sm, m_region_model->get_num_svalues ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1042 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1043 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1044
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1045 /* Dump this sm_change to PP. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1046
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1047 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1048 state_change::sm_change::dump (pretty_printer *pp,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1049 const extrinsic_state &ext_state) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1050 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1051 const state_machine &sm = get_sm (ext_state);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1052 pp_string (pp, "(");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1053 m_new_sid.print (pp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1054 pp_printf (pp, ": %s: %qs -> %qs)",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1055 sm.get_name (),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1056 sm.get_state_name (m_old_state),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1057 sm.get_state_name (m_new_state));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1058 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1059
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1060 /* Remap all svalue_ids in this change according to MAP. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1061
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1062 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1063 state_change::sm_change::remap_svalue_ids (const svalue_id_map &map)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1064 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1065 map.update (&m_new_sid);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1066 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1067
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1068 /* Purge any svalue_ids >= FIRST_UNUSED_SID.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1069 Return the number of states that were purged. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1070
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1071 int
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1072 state_change::sm_change::on_svalue_purge (svalue_id first_unused_sid)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1073 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1074 if (m_new_sid.as_int () >= first_unused_sid.as_int ())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1075 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1076 m_new_sid = svalue_id::null ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1077 return 1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1078 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1079
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1080 return 0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1081 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1082
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1083 /* Assert that this object is sane. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1084
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1085 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1086 state_change::sm_change::validate (const program_state &new_state,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1087 const extrinsic_state &ext_state) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1088 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1089 gcc_assert ((unsigned)m_sm_idx < ext_state.get_num_checkers ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1090 const state_machine &sm = ext_state.get_sm (m_sm_idx);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1091 sm.validate (m_old_state);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1092 sm.validate (m_new_state);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1093 m_new_sid.validate (*new_state.m_region_model);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1094 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1095
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1096 /* state_change's ctor. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1097
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1098 state_change::state_change ()
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1099 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1100 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1101
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1102 /* state_change's copy ctor. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1103
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1104 state_change::state_change (const state_change &other)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1105 : m_sm_changes (other.m_sm_changes.length ())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1106 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1107 unsigned i;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1108 sm_change *change;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1109 FOR_EACH_VEC_ELT (other.m_sm_changes, i, change)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1110 m_sm_changes.quick_push (*change);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1111 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1112
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1113 /* Record a state-machine state change. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1114
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1115 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1116 state_change::add_sm_change (int sm_idx,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1117 svalue_id new_sid,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1118 state_machine::state_t old_state,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1119 state_machine::state_t new_state)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1120 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1121 m_sm_changes.safe_push (sm_change (sm_idx,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1122 new_sid,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1123 old_state, new_state));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1124 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1125
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1126 /* Return true if SID (in the new state) was affected by any
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1127 sm-state changes. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1128
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1129 bool
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1130 state_change::affects_p (svalue_id sid) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1131 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1132 unsigned i;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1133 sm_change *change;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1134 FOR_EACH_VEC_ELT (m_sm_changes, i, change)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1135 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1136 if (sid == change->m_new_sid)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1137 return true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1138 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1139 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1140 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1141
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1142 /* Dump this state_change to PP. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1143
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1144 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1145 state_change::dump (pretty_printer *pp,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1146 const extrinsic_state &ext_state) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1147 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1148 unsigned i;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1149 sm_change *change;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1150 FOR_EACH_VEC_ELT (m_sm_changes, i, change)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1151 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1152 if (i > 0)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1153 pp_string (pp, ", ");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1154 change->dump (pp, ext_state);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1155 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1156 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1157
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1158 /* Dump this state_change to stderr. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1159
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1160 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1161 state_change::dump (const extrinsic_state &ext_state) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1162 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1163 pretty_printer pp;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1164 pp_show_color (&pp) = pp_show_color (global_dc->printer);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1165 pp.buffer->stream = stderr;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1166 dump (&pp, ext_state);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1167 pp_newline (&pp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1168 pp_flush (&pp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1169 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1170
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1171 /* Remap all svalue_ids in this state_change according to MAP. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1172
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1173 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1174 state_change::remap_svalue_ids (const svalue_id_map &map)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1175 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1176 unsigned i;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1177 sm_change *change;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1178 FOR_EACH_VEC_ELT (m_sm_changes, i, change)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1179 change->remap_svalue_ids (map);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1180 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1181
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1182 /* Purge any svalue_ids >= FIRST_UNUSED_SID.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1183 Return the number of states that were purged. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1184
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1185 int
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1186 state_change::on_svalue_purge (svalue_id first_unused_sid)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1187 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1188 int result = 0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1189 unsigned i;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1190 sm_change *change;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1191 FOR_EACH_VEC_ELT (m_sm_changes, i, change)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1192 result += change->on_svalue_purge (first_unused_sid);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1193 return result;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1194 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1195
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1196 /* Assert that this object is sane. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1197
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1198 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1199 state_change::validate (const program_state &new_state,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1200 const extrinsic_state &ext_state) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1201 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1202 /* Skip this in a release build. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1203 #if !CHECKING_P
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1204 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1205 #endif
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1206 unsigned i;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1207 sm_change *change;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1208 FOR_EACH_VEC_ELT (m_sm_changes, i, change)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1209 change->validate (new_state, ext_state);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1210 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1211
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1212 #if CHECKING_P
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1213
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1214 namespace selftest {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1215
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1216 /* Tests for sm_state_map. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1217
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1218 static void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1219 test_sm_state_map ()
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1220 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1221 tree x = build_global_decl ("x", integer_type_node);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1222 tree y = build_global_decl ("y", integer_type_node);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1223 tree z = build_global_decl ("z", integer_type_node);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1224
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1225 /* Test setting states on svalue_id instances directly. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1226 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1227 region_model model;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1228 svalue_id sid_x = model.get_rvalue (x, NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1229 svalue_id sid_y = model.get_rvalue (y, NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1230 svalue_id sid_z = model.get_rvalue (z, NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1231
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1232 sm_state_map map;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1233 ASSERT_TRUE (map.is_empty_p ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1234 ASSERT_EQ (map.get_state (sid_x), 0);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1235
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1236 map.impl_set_state (sid_x, 42, sid_z);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1237 ASSERT_EQ (map.get_state (sid_x), 42);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1238 ASSERT_EQ (map.get_origin (sid_x), sid_z);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1239 ASSERT_EQ (map.get_state (sid_y), 0);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1240 ASSERT_FALSE (map.is_empty_p ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1241
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1242 map.impl_set_state (sid_y, 0, sid_z);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1243 ASSERT_EQ (map.get_state (sid_y), 0);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1244
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1245 map.impl_set_state (sid_x, 0, sid_z);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1246 ASSERT_EQ (map.get_state (sid_x), 0);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1247 ASSERT_TRUE (map.is_empty_p ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1248 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1249
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1250 /* Test setting states via equivalence classes. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1251 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1252 region_model model;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1253 svalue_id sid_x = model.get_rvalue (x, NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1254 svalue_id sid_y = model.get_rvalue (y, NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1255 svalue_id sid_z = model.get_rvalue (z, NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1256
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1257 sm_state_map map;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1258 ASSERT_TRUE (map.is_empty_p ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1259 ASSERT_EQ (map.get_state (sid_x), 0);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1260 ASSERT_EQ (map.get_state (sid_y), 0);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1261
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1262 model.add_constraint (x, EQ_EXPR, y, NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1263
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1264 /* Setting x to a state should also update y, as they
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1265 are in the same equivalence class. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1266 map.set_state (&model, sid_x, 5, sid_z);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1267 ASSERT_EQ (map.get_state (sid_x), 5);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1268 ASSERT_EQ (map.get_state (sid_y), 5);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1269 ASSERT_EQ (map.get_origin (sid_x), sid_z);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1270 ASSERT_EQ (map.get_origin (sid_y), sid_z);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1271 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1272
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1273 /* Test equality and hashing. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1274 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1275 region_model model;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1276 svalue_id sid_y = model.get_rvalue (y, NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1277 svalue_id sid_z = model.get_rvalue (z, NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1278
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1279 sm_state_map map0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1280 sm_state_map map1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1281 sm_state_map map2;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1282
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1283 ASSERT_EQ (map0.hash (), map1.hash ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1284 ASSERT_EQ (map0, map1);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1285
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1286 map1.impl_set_state (sid_y, 5, sid_z);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1287 ASSERT_NE (map0.hash (), map1.hash ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1288 ASSERT_NE (map0, map1);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1289
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1290 /* Make the same change to map2. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1291 map2.impl_set_state (sid_y, 5, sid_z);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1292 ASSERT_EQ (map1.hash (), map2.hash ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1293 ASSERT_EQ (map1, map2);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1294 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1295
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1296 /* Equality and hashing shouldn't depend on ordering. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1297 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1298 sm_state_map map0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1299 sm_state_map map1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1300 sm_state_map map2;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1301
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1302 ASSERT_EQ (map0.hash (), map1.hash ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1303 ASSERT_EQ (map0, map1);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1304
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1305 map1.impl_set_state (svalue_id::from_int (14), 2, svalue_id::null ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1306 map1.impl_set_state (svalue_id::from_int (16), 3, svalue_id::null ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1307 map1.impl_set_state (svalue_id::from_int (1), 2, svalue_id::null ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1308 map1.impl_set_state (svalue_id::from_int (9), 2, svalue_id::null ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1309
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1310 map2.impl_set_state (svalue_id::from_int (1), 2, svalue_id::null ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1311 map2.impl_set_state (svalue_id::from_int (16), 3, svalue_id::null ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1312 map2.impl_set_state (svalue_id::from_int (14), 2, svalue_id::null ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1313 map2.impl_set_state (svalue_id::from_int (9), 2, svalue_id::null ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1314
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1315 ASSERT_EQ (map1.hash (), map2.hash ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1316 ASSERT_EQ (map1, map2);
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 /* Test sm_state_map::remap_svalue_ids. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1320 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1321 sm_state_map map;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1322 svalue_id sid_0 = svalue_id::from_int (0);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1323 svalue_id sid_1 = svalue_id::from_int (1);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1324 svalue_id sid_2 = svalue_id::from_int (2);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1325
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1326 map.impl_set_state (sid_0, 42, sid_2);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1327 ASSERT_EQ (map.get_state (sid_0), 42);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1328 ASSERT_EQ (map.get_origin (sid_0), sid_2);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1329 ASSERT_EQ (map.get_state (sid_1), 0);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1330 ASSERT_EQ (map.get_state (sid_2), 0);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1331
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1332 /* Apply a remapping to the IDs. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1333 svalue_id_map remapping (3);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1334 remapping.put (sid_0, sid_1);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1335 remapping.put (sid_1, sid_2);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1336 remapping.put (sid_2, sid_0);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1337 map.remap_svalue_ids (remapping);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1338
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1339 /* Verify that the IDs have been remapped. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1340 ASSERT_EQ (map.get_state (sid_1), 42);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1341 ASSERT_EQ (map.get_origin (sid_1), sid_0);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1342 ASSERT_EQ (map.get_state (sid_2), 0);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1343 ASSERT_EQ (map.get_state (sid_0), 0);
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 // TODO: coverage for purging
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1347 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1348
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1349 /* Verify that program_states with identical sm-state can be merged,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1350 and that the merged program_state preserves the sm-state. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1351
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1352 static void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1353 test_program_state_merging ()
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1354 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1355 /* Create a program_state for a global ptr "p" that has
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1356 malloc sm-state, pointing to a region on the heap. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1357 tree p = build_global_decl ("p", ptr_type_node);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1358
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1359 auto_delete_vec <state_machine> checkers;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1360 checkers.safe_push (make_malloc_state_machine (NULL));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1361 extrinsic_state ext_state (checkers);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1362
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1363 program_state s0 (ext_state);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1364 impl_region_model_context ctxt (&s0, NULL, ext_state);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1365
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1366 region_model *model0 = s0.m_region_model;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1367 region_id new_rid = model0->add_new_malloc_region ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1368 svalue_id ptr_sid
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1369 = model0->get_or_create_ptr_svalue (ptr_type_node, new_rid);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1370 model0->set_value (model0->get_lvalue (p, &ctxt),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1371 ptr_sid, &ctxt);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1372 sm_state_map *smap = s0.m_checker_states[0];
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1373 const state_machine::state_t TEST_STATE = 3;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1374 smap->impl_set_state (ptr_sid, TEST_STATE, svalue_id::null ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1375 ASSERT_EQ (smap->get_state (ptr_sid), TEST_STATE);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1376
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1377 model0->canonicalize (&ctxt);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1378
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1379 /* Verify that canonicalization preserves sm-state. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1380 ASSERT_EQ (smap->get_state (model0->get_rvalue (p, NULL)), TEST_STATE);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1381
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1382 /* Make a copy of the program_state. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1383 program_state s1 (s0);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1384 ASSERT_EQ (s0, s1);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1385
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1386 /* We have two identical states with "p" pointing to a heap region
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1387 with the given sm-state.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1388 They ought to be mergeable, preserving the sm-state. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1389 program_state merged (ext_state);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1390 ASSERT_TRUE (s0.can_merge_with_p (s1, ext_state, &merged));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1391 merged.validate (ext_state);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1392
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1393 /* Verify that the merged state has the sm-state for "p". */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1394 region_model *merged_model = merged.m_region_model;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1395 sm_state_map *merged_smap = merged.m_checker_states[0];
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1396 ASSERT_EQ (merged_smap->get_state (merged_model->get_rvalue (p, NULL)),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1397 TEST_STATE);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1398
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1399 /* Try canonicalizing. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1400 impl_region_model_context merged_ctxt (&merged, NULL, ext_state);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1401 merged.m_region_model->canonicalize (&merged_ctxt);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1402 merged.validate (ext_state);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1403
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1404 /* Verify that the merged state still has the sm-state for "p". */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1405 ASSERT_EQ (merged_smap->get_state (merged_model->get_rvalue (p, NULL)),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1406 TEST_STATE);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1407
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1408 /* After canonicalization, we ought to have equality with the inputs. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1409 ASSERT_EQ (s0, merged);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1410 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1411
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1412 /* Verify that program_states with different global-state in an sm-state
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1413 can't be merged. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1414
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1415 static void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1416 test_program_state_merging_2 ()
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1417 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1418 auto_delete_vec <state_machine> checkers;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1419 checkers.safe_push (make_signal_state_machine (NULL));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1420 extrinsic_state ext_state (checkers);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1421
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1422 program_state s0 (ext_state);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1423 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1424 sm_state_map *smap0 = s0.m_checker_states[0];
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1425 const state_machine::state_t TEST_STATE_0 = 0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1426 smap0->set_global_state (TEST_STATE_0);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1427 ASSERT_EQ (smap0->get_global_state (), TEST_STATE_0);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1428 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1429
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1430 program_state s1 (ext_state);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1431 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1432 sm_state_map *smap1 = s1.m_checker_states[0];
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1433 const state_machine::state_t TEST_STATE_1 = 1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1434 smap1->set_global_state (TEST_STATE_1);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1435 ASSERT_EQ (smap1->get_global_state (), TEST_STATE_1);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1436 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1437
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1438 ASSERT_NE (s0, s1);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1439
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1440 /* They ought to not be mergeable. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1441 program_state merged (ext_state);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1442 ASSERT_FALSE (s0.can_merge_with_p (s1, ext_state, &merged));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1443 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1444
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1445 /* Run all of the selftests within this file. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1446
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1447 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1448 analyzer_program_state_cc_tests ()
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1449 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1450 test_sm_state_map ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1451 test_program_state_merging ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1452 test_program_state_merging_2 ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1453 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1454
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1455 } // namespace selftest
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1456
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1457 #endif /* CHECKING_P */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1458
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1459 } // namespace ana
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1460
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1461 #endif /* #if ENABLE_ANALYZER */