Branch data Line data Source code
1 : : /* Classes for modeling the state of memory.
2 : : Copyright (C) 2020-2025 Free Software Foundation, Inc.
3 : : Contributed by David Malcolm <dmalcolm@redhat.com>.
4 : :
5 : : This file is part of GCC.
6 : :
7 : : GCC is free software; you can redistribute it and/or modify it
8 : : under the terms of the GNU General Public License as published by
9 : : the Free Software Foundation; either version 3, or (at your option)
10 : : any later version.
11 : :
12 : : GCC is distributed in the hope that it will be useful, but
13 : : WITHOUT ANY WARRANTY; without even the implied warranty of
14 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 : : General Public License for more details.
16 : :
17 : : You should have received a copy of the GNU General Public License
18 : : along with GCC; see the file COPYING3. If not see
19 : : <http://www.gnu.org/licenses/>. */
20 : :
21 : : #include "analyzer/common.h"
22 : :
23 : : #include "ordered-hash-map.h"
24 : : #include "cfg.h"
25 : : #include "sbitmap.h"
26 : : #include "stor-layout.h"
27 : :
28 : : #include "text-art/tree-widget.h"
29 : :
30 : : #include "analyzer/analyzer-logging.h"
31 : : #include "analyzer/supergraph.h"
32 : : #include "analyzer/call-string.h"
33 : : #include "analyzer/program-point.h"
34 : : #include "analyzer/store.h"
35 : : #include "analyzer/region-model.h"
36 : : #include "analyzer/call-summary.h"
37 : : #include "analyzer/analyzer-selftests.h"
38 : :
39 : : #if ENABLE_ANALYZER
40 : :
41 : : namespace ana {
42 : :
43 : : /* Dump SVALS to PP, sorting them to ensure determinism. */
44 : :
45 : : static void
46 : 496 : dump_svalue_set (const hash_set <const svalue *> &svals,
47 : : pretty_printer *pp, bool simple)
48 : : {
49 : 496 : auto_vec <const svalue *> v;
50 : 496 : for (hash_set<const svalue *>::iterator iter = svals.begin ();
51 : 560 : iter != svals.end (); ++iter)
52 : : {
53 : 32 : v.safe_push (*iter);
54 : : }
55 : 496 : v.qsort (svalue::cmp_ptr_ptr);
56 : :
57 : 496 : pp_character (pp, '{');
58 : 496 : const svalue *sval;
59 : 496 : unsigned i;
60 : 1024 : FOR_EACH_VEC_ELT (v, i, sval)
61 : : {
62 : 32 : if (i > 0)
63 : 19 : pp_string (pp, ", ");
64 : 32 : sval->dump_to_pp (pp, simple);
65 : : }
66 : 496 : pp_character (pp, '}');
67 : 496 : }
68 : :
69 : : /* class uncertainty_t. */
70 : :
71 : : /* Dump this object to PP. */
72 : :
73 : : void
74 : 248 : uncertainty_t::dump_to_pp (pretty_printer *pp, bool simple) const
75 : : {
76 : 248 : pp_string (pp, "{m_maybe_bound_svals: ");
77 : 248 : dump_svalue_set (m_maybe_bound_svals, pp, simple);
78 : :
79 : 248 : pp_string (pp, ", m_mutable_at_unknown_call_svals: ");
80 : 248 : dump_svalue_set (m_mutable_at_unknown_call_svals, pp, simple);
81 : 248 : pp_string (pp, "}");
82 : 248 : }
83 : :
84 : : /* Dump this object to stderr. */
85 : :
86 : : DEBUG_FUNCTION void
87 : 0 : uncertainty_t::dump (bool simple) const
88 : : {
89 : 0 : tree_dump_pretty_printer pp (stderr);
90 : 0 : dump_to_pp (&pp, simple);
91 : 0 : pp_newline (&pp);
92 : 0 : }
93 : :
94 : : /* class binding_key. */
95 : :
96 : : const binding_key *
97 : 3515955 : binding_key::make (store_manager *mgr, const region *r)
98 : : {
99 : 3515955 : region_offset offset = r->get_offset (mgr->get_svalue_manager ());
100 : 3515955 : if (offset.symbolic_p ())
101 : 36504 : return mgr->get_symbolic_binding (r);
102 : : else
103 : : {
104 : 3479451 : bit_size_t bit_size;
105 : 3479451 : if (r->get_bit_size (&bit_size))
106 : : {
107 : : /* Must be non-empty. */
108 : 2188267 : gcc_assert (bit_size > 0);
109 : 2188267 : return mgr->get_concrete_binding (offset.get_bit_offset (),
110 : 2188267 : bit_size);
111 : : }
112 : : else
113 : 1291184 : return mgr->get_symbolic_binding (r);
114 : : }
115 : : }
116 : :
117 : : /* Dump this binding_key to stderr. */
118 : :
119 : : DEBUG_FUNCTION void
120 : 0 : binding_key::dump (bool simple) const
121 : : {
122 : 0 : tree_dump_pretty_printer pp (stderr);
123 : 0 : dump_to_pp (&pp, simple);
124 : 0 : pp_newline (&pp);
125 : 0 : }
126 : :
127 : : /* Get a description of this binding_key. */
128 : :
129 : : label_text
130 : 0 : binding_key::get_desc (bool simple) const
131 : : {
132 : 0 : pretty_printer pp;
133 : 0 : pp_format_decoder (&pp) = default_tree_printer;
134 : 0 : dump_to_pp (&pp, simple);
135 : 0 : return label_text::take (xstrdup (pp_formatted_text (&pp)));
136 : 0 : }
137 : :
138 : : /* qsort callback. */
139 : :
140 : : int
141 : 1668 : binding_key::cmp_ptrs (const void *p1, const void *p2)
142 : : {
143 : 1668 : const binding_key * const *pk1 = (const binding_key * const *)p1;
144 : 1668 : const binding_key * const *pk2 = (const binding_key * const *)p2;
145 : 1668 : return cmp (*pk1, *pk2);
146 : : }
147 : :
148 : : /* Comparator for binding_keys. */
149 : :
150 : : int
151 : 1720 : binding_key::cmp (const binding_key *k1, const binding_key *k2)
152 : : {
153 : 1720 : int concrete1 = k1->concrete_p ();
154 : 1720 : int concrete2 = k2->concrete_p ();
155 : 1720 : if (int concrete_cmp = concrete1 - concrete2)
156 : : return concrete_cmp;
157 : 1720 : if (concrete1)
158 : : {
159 : 1720 : const concrete_binding *b1 = (const concrete_binding *)k1;
160 : 1720 : const concrete_binding *b2 = (const concrete_binding *)k2;
161 : 1720 : if (int start_cmp = wi::cmp (b1->get_start_bit_offset (),
162 : 1720 : b2->get_start_bit_offset (),
163 : : SIGNED))
164 : : return start_cmp;
165 : 52 : return wi::cmp (b1->get_next_bit_offset (), b2->get_next_bit_offset (),
166 : : SIGNED);
167 : : }
168 : : else
169 : : {
170 : 0 : const symbolic_binding *s1 = (const symbolic_binding *)k1;
171 : 0 : const symbolic_binding *s2 = (const symbolic_binding *)k2;
172 : 0 : if (s1 > s2)
173 : : return 1;
174 : 0 : if (s1 < s2)
175 : : return -1;
176 : 0 : return 0;
177 : : }
178 : : }
179 : :
180 : : /* struct bit_range. */
181 : :
182 : : void
183 : 2611 : bit_range::dump_to_pp (pretty_printer *pp) const
184 : : {
185 : 2611 : byte_range bytes (0, 0);
186 : 2611 : if (as_byte_range (&bytes))
187 : 2611 : bytes.dump_to_pp (pp);
188 : : else
189 : : {
190 : 0 : pp_string (pp, "start: ");
191 : 0 : pp_wide_int (pp, m_start_bit_offset, SIGNED);
192 : 0 : pp_string (pp, ", size: ");
193 : 0 : pp_wide_int (pp, m_size_in_bits, SIGNED);
194 : 0 : pp_string (pp, ", next: ");
195 : 0 : pp_wide_int (pp, get_next_bit_offset (), SIGNED);
196 : : }
197 : 2611 : }
198 : :
199 : : /* Dump this object to stderr. */
200 : :
201 : : DEBUG_FUNCTION void
202 : 0 : bit_range::dump () const
203 : : {
204 : 0 : tree_dump_pretty_printer pp (stderr);
205 : 0 : dump_to_pp (&pp);
206 : 0 : pp_newline (&pp);
207 : 0 : }
208 : :
209 : : /* Generate a JSON value for this bit_range.
210 : : This is intended for debugging the analyzer rather
211 : : than serialization. */
212 : :
213 : : std::unique_ptr<json::object>
214 : 4 : bit_range::to_json () const
215 : : {
216 : 4 : auto obj = std::make_unique<json::object> ();
217 : 4 : obj->set ("start_bit_offset",
218 : 4 : bit_offset_to_json (m_start_bit_offset));
219 : 4 : obj->set ("size_in_bits",
220 : 4 : bit_offset_to_json (m_size_in_bits));
221 : 4 : return obj;
222 : : }
223 : :
224 : : /* If OTHER is a subset of this, return true and, if OUT is
225 : : non-null, write to *OUT the relative range of OTHER within this.
226 : : Otherwise return false. */
227 : :
228 : : bool
229 : 35801 : bit_range::contains_p (const bit_range &other, bit_range *out) const
230 : : {
231 : 35801 : if (contains_p (other.get_start_bit_offset ())
232 : 35801 : && contains_p (other.get_last_bit_offset ()))
233 : : {
234 : 22763 : if (out)
235 : : {
236 : 22763 : out->m_start_bit_offset = other.m_start_bit_offset - m_start_bit_offset;
237 : 22763 : out->m_size_in_bits = other.m_size_in_bits;
238 : : }
239 : 22763 : return true;
240 : : }
241 : : else
242 : 13038 : return false;
243 : : }
244 : :
245 : : /* If OTHER intersects this, return true and write
246 : : the relative range of OTHER within THIS to *OUT_THIS,
247 : : and the relative range of THIS within OTHER to *OUT_OTHER.
248 : : Otherwise return false. */
249 : :
250 : : bool
251 : 84 : bit_range::intersects_p (const bit_range &other,
252 : : bit_range *out_this,
253 : : bit_range *out_other) const
254 : : {
255 : 84 : if (get_start_bit_offset () < other.get_next_bit_offset ()
256 : 168 : && other.get_start_bit_offset () < get_next_bit_offset ())
257 : : {
258 : 84 : bit_offset_t overlap_start
259 : 84 : = MAX (get_start_bit_offset (),
260 : : other.get_start_bit_offset ());
261 : 84 : bit_offset_t overlap_next
262 : 84 : = MIN (get_next_bit_offset (),
263 : : other.get_next_bit_offset ());
264 : 84 : if (overlap_next <= overlap_start)
265 : : /* If this has happened, some kind of overflow has happened in
266 : : our arithmetic. For now, reject such cases. */
267 : : return false;
268 : 84 : bit_range abs_overlap_bits (overlap_start, overlap_next - overlap_start);
269 : 84 : *out_this = abs_overlap_bits - get_start_bit_offset ();
270 : 84 : *out_other = abs_overlap_bits - other.get_start_bit_offset ();
271 : 84 : return true;
272 : : }
273 : : else
274 : 0 : return false;
275 : : }
276 : :
277 : : /* Return true if THIS and OTHER intersect and write the number
278 : : of bits both buffers overlap to *OUT_NUM_OVERLAP_BITS.
279 : :
280 : : Otherwise return false. */
281 : :
282 : : bool
283 : 0 : bit_range::intersects_p (const bit_range &other,
284 : : bit_size_t *out_num_overlap_bits) const
285 : : {
286 : 0 : if (get_start_bit_offset () < other.get_next_bit_offset ()
287 : 0 : && other.get_start_bit_offset () < get_next_bit_offset ())
288 : : {
289 : 0 : bit_offset_t overlap_start = MAX (get_start_bit_offset (),
290 : : other.get_start_bit_offset ());
291 : 0 : bit_offset_t overlap_next = MIN (get_next_bit_offset (),
292 : : other.get_next_bit_offset ());
293 : 0 : if (overlap_next <= overlap_start)
294 : : /* If this has happened, some kind of overflow has happened in
295 : : our arithmetic. For now, reject such cases. */
296 : : return false;
297 : 0 : *out_num_overlap_bits = overlap_next - overlap_start;
298 : 0 : return true;
299 : : }
300 : : else
301 : 0 : return false;
302 : : }
303 : :
304 : : /* Return true if THIS exceeds OTHER and write the overhanging
305 : : bit range to OUT_OVERHANGING_BIT_RANGE. */
306 : :
307 : : bool
308 : 644790 : bit_range::exceeds_p (const bit_range &other,
309 : : bit_range *out_overhanging_bit_range) const
310 : : {
311 : 644790 : gcc_assert (!empty_p ());
312 : :
313 : 644790 : if (other.get_next_bit_offset () < get_next_bit_offset ())
314 : : {
315 : : /* THIS definitely exceeds OTHER. */
316 : 487 : bit_offset_t start = MAX (get_start_bit_offset (),
317 : : other.get_next_bit_offset ());
318 : 487 : bit_offset_t size = get_next_bit_offset () - start;
319 : 487 : if (size <= 0)
320 : : /* If this has happened, some kind of overflow has happened in
321 : : our arithmetic. For now, reject such cases. */
322 : : return false;
323 : 467 : out_overhanging_bit_range->m_start_bit_offset = start;
324 : 467 : out_overhanging_bit_range->m_size_in_bits = size;
325 : 467 : return true;
326 : : }
327 : : else
328 : : return false;
329 : : }
330 : :
331 : : /* Return true if THIS falls short of OFFSET and write the
332 : : bit range fallen short to OUT_FALL_SHORT_BITS. */
333 : :
334 : : bool
335 : 648354 : bit_range::falls_short_of_p (bit_offset_t offset,
336 : : bit_range *out_fall_short_bits) const
337 : : {
338 : 648354 : gcc_assert (!empty_p ());
339 : :
340 : 648354 : if (get_start_bit_offset () < offset)
341 : : {
342 : : /* THIS falls short of OFFSET. */
343 : 192 : bit_offset_t start = get_start_bit_offset ();
344 : 192 : bit_offset_t size = MIN (offset, get_next_bit_offset ()) - start;
345 : 192 : if (size <= 0)
346 : : /* If this has happened, some kind of overflow has happened in
347 : : our arithmetic. For now, reject such cases. */
348 : : return false;
349 : 172 : out_fall_short_bits->m_start_bit_offset = start;
350 : 172 : out_fall_short_bits->m_size_in_bits = size;
351 : 172 : return true;
352 : : }
353 : : else
354 : : return false;
355 : : }
356 : :
357 : : int
358 : 1198 : bit_range::cmp (const bit_range &br1, const bit_range &br2)
359 : : {
360 : 1198 : if (int start_cmp = wi::cmps (br1.m_start_bit_offset,
361 : 1198 : br2.m_start_bit_offset))
362 : : return start_cmp;
363 : :
364 : 12 : return wi::cmpu (br1.m_size_in_bits, br2.m_size_in_bits);
365 : : }
366 : :
367 : : /* Offset this range by OFFSET. */
368 : :
369 : : bit_range
370 : 168 : bit_range::operator- (bit_offset_t offset) const
371 : : {
372 : 168 : return bit_range (m_start_bit_offset - offset, m_size_in_bits);
373 : : }
374 : :
375 : : /* If MASK is a contiguous range of set bits, write them
376 : : to *OUT and return true.
377 : : Otherwise return false. */
378 : :
379 : : bool
380 : 144 : bit_range::from_mask (unsigned HOST_WIDE_INT mask, bit_range *out)
381 : : {
382 : 144 : unsigned iter_bit_idx = 0;
383 : 144 : unsigned HOST_WIDE_INT iter_bit_mask = 1;
384 : :
385 : : /* Find the first contiguous run of set bits in MASK. */
386 : :
387 : : /* Find first set bit in MASK. */
388 : 780 : while (iter_bit_idx < HOST_BITS_PER_WIDE_INT)
389 : : {
390 : 776 : if (mask & iter_bit_mask)
391 : : break;
392 : 636 : iter_bit_idx++;
393 : 636 : iter_bit_mask <<= 1;
394 : : }
395 : 144 : if (iter_bit_idx == HOST_BITS_PER_WIDE_INT)
396 : : /* MASK is zero. */
397 : : return false;
398 : :
399 : 140 : unsigned first_set_iter_bit_idx = iter_bit_idx;
400 : 140 : unsigned num_set_bits = 1;
401 : 140 : iter_bit_idx++;
402 : 140 : iter_bit_mask <<= 1;
403 : :
404 : : /* Find next unset bit in MASK. */
405 : 396 : while (iter_bit_idx < HOST_BITS_PER_WIDE_INT)
406 : : {
407 : 396 : if (!(mask & iter_bit_mask))
408 : : break;
409 : 256 : num_set_bits++;
410 : 256 : iter_bit_idx++;
411 : 256 : iter_bit_mask <<= 1;
412 : : }
413 : 140 : if (iter_bit_idx == HOST_BITS_PER_WIDE_INT)
414 : : {
415 : 0 : *out = bit_range (first_set_iter_bit_idx, num_set_bits);
416 : 0 : return true;
417 : : }
418 : :
419 : : /* We now have the first contiguous run of set bits in MASK.
420 : : Fail if any other bits are set. */
421 : 7892 : while (iter_bit_idx < HOST_BITS_PER_WIDE_INT)
422 : : {
423 : 7760 : if (mask & iter_bit_mask)
424 : : return false;
425 : 7752 : iter_bit_idx++;
426 : 7752 : iter_bit_mask <<= 1;
427 : : }
428 : :
429 : 132 : *out = bit_range (first_set_iter_bit_idx, num_set_bits);
430 : 132 : return true;
431 : : }
432 : :
433 : : /* Attempt to convert this bit_range to a byte_range.
434 : : Return true if it is possible, writing the result to *OUT.
435 : : Otherwise return false. */
436 : :
437 : : bool
438 : 8228 : bit_range::as_byte_range (byte_range *out) const
439 : : {
440 : 8228 : if (m_start_bit_offset % BITS_PER_UNIT == 0
441 : 8228 : && m_size_in_bits % BITS_PER_UNIT == 0)
442 : : {
443 : 8207 : out->m_start_byte_offset = m_start_bit_offset / BITS_PER_UNIT;
444 : 8207 : out->m_size_in_bytes = m_size_in_bits / BITS_PER_UNIT;
445 : 8207 : return true;
446 : : }
447 : : return false;
448 : : }
449 : :
450 : : /* Dump this object to PP. */
451 : :
452 : : void
453 : 2611 : byte_range::dump_to_pp (pretty_printer *pp) const
454 : : {
455 : 2611 : if (m_size_in_bytes == 0)
456 : : {
457 : 0 : pp_string (pp, "empty");
458 : : }
459 : 2611 : else if (m_size_in_bytes == 1)
460 : : {
461 : 1595 : pp_string (pp, "byte ");
462 : 1595 : pp_wide_int (pp, m_start_byte_offset, SIGNED);
463 : : }
464 : : else
465 : : {
466 : 1016 : pp_string (pp, "bytes ");
467 : 1016 : pp_wide_int (pp, m_start_byte_offset, SIGNED);
468 : 1016 : pp_string (pp, "-");
469 : 1016 : pp_wide_int (pp, get_last_byte_offset (), SIGNED);
470 : : }
471 : 2611 : }
472 : :
473 : : /* Dump this object to stderr. */
474 : :
475 : : DEBUG_FUNCTION void
476 : 0 : byte_range::dump () const
477 : : {
478 : 0 : tree_dump_pretty_printer pp (stderr);
479 : 0 : dump_to_pp (&pp);
480 : 0 : pp_newline (&pp);
481 : 0 : }
482 : :
483 : : /* Generate a JSON value for this byte_range.
484 : : This is intended for debugging the analyzer rather
485 : : than serialization. */
486 : :
487 : : std::unique_ptr<json::object>
488 : 4 : byte_range::to_json () const
489 : : {
490 : 4 : auto obj = std::make_unique<json::object> ();
491 : 4 : obj->set ("start_byte_offset",
492 : 4 : byte_offset_to_json (m_start_byte_offset));
493 : 4 : obj->set ("size_in_bytes",
494 : 4 : byte_offset_to_json (m_size_in_bytes));
495 : 4 : return obj;
496 : : }
497 : :
498 : : /* If OTHER is a subset of this, return true and write
499 : : to *OUT the relative range of OTHER within this.
500 : : Otherwise return false. */
501 : :
502 : : bool
503 : 803 : byte_range::contains_p (const byte_range &other, byte_range *out) const
504 : : {
505 : 803 : if (contains_p (other.get_start_byte_offset ())
506 : 803 : && contains_p (other.get_last_byte_offset ()))
507 : : {
508 : 330 : out->m_start_byte_offset = other.m_start_byte_offset - m_start_byte_offset;
509 : 330 : out->m_size_in_bytes = other.m_size_in_bytes;
510 : 330 : return true;
511 : : }
512 : : else
513 : 473 : return false;
514 : : }
515 : :
516 : : /* qsort comparator for byte ranges. */
517 : :
518 : : int
519 : 571 : byte_range::cmp (const byte_range &br1, const byte_range &br2)
520 : : {
521 : : /* Order first by offset. */
522 : 571 : if (int start_cmp = wi::cmps (br1.m_start_byte_offset,
523 : 571 : br2.m_start_byte_offset))
524 : : return start_cmp;
525 : :
526 : : /* ...then by size. */
527 : 0 : return wi::cmpu (br1.m_size_in_bytes, br2.m_size_in_bytes);
528 : : }
529 : :
530 : : /* class concrete_binding : public binding_key. */
531 : :
532 : : /* Implementation of binding_key::dump_to_pp vfunc for concrete_binding. */
533 : :
534 : : void
535 : 1648 : concrete_binding::dump_to_pp (pretty_printer *pp, bool) const
536 : : {
537 : 1648 : m_bit_range.dump_to_pp (pp);
538 : 1648 : }
539 : :
540 : : /* Return true if this binding overlaps with OTHER. */
541 : :
542 : : bool
543 : 91470 : concrete_binding::overlaps_p (const concrete_binding &other) const
544 : : {
545 : 91470 : if (get_start_bit_offset () < other.get_next_bit_offset ()
546 : 91470 : && get_next_bit_offset () > other.get_start_bit_offset ())
547 : 53628 : return true;
548 : : return false;
549 : : }
550 : :
551 : : /* If this is expressible as a concrete byte range, return true
552 : : and write it to *OUT. Otherwise return false. */
553 : :
554 : : bool
555 : 683 : concrete_binding::get_byte_range (byte_range *out) const
556 : : {
557 : 683 : return m_bit_range.as_byte_range (out);
558 : : }
559 : :
560 : : /* Comparator for use by vec<const concrete_binding *>::qsort. */
561 : :
562 : : int
563 : 48 : concrete_binding::cmp_ptr_ptr (const void *p1, const void *p2)
564 : : {
565 : 48 : const concrete_binding *b1 = *(const concrete_binding * const *)p1;
566 : 48 : const concrete_binding *b2 = *(const concrete_binding * const *)p2;
567 : :
568 : 48 : return bit_range::cmp (b1->m_bit_range, b2->m_bit_range);
569 : : }
570 : :
571 : : /* class symbolic_binding : public binding_key. */
572 : :
573 : : void
574 : 2 : symbolic_binding::dump_to_pp (pretty_printer *pp, bool simple) const
575 : : {
576 : : //binding_key::dump_to_pp (pp, simple);
577 : 2 : pp_string (pp, "region: ");
578 : 2 : m_region->dump_to_pp (pp, simple);
579 : 2 : }
580 : :
581 : : /* Comparator for use by vec<const symbolic_binding *>::qsort. */
582 : :
583 : : int
584 : 4 : symbolic_binding::cmp_ptr_ptr (const void *p1, const void *p2)
585 : : {
586 : 4 : const symbolic_binding *b1 = *(const symbolic_binding * const *)p1;
587 : 4 : const symbolic_binding *b2 = *(const symbolic_binding * const *)p2;
588 : :
589 : 4 : return region::cmp_ids (b1->get_region (), b2->get_region ());
590 : : }
591 : :
592 : : /* The store is oblivious to the types of the svalues bound within
593 : : it: any type can get bound at any location.
594 : : Simplify any casts before binding.
595 : :
596 : : For example, if we have:
597 : : struct big { int ia[1024]; };
598 : : struct big src, dst;
599 : : memcpy (&dst, &src, sizeof (struct big));
600 : : this reaches us in gimple form as:
601 : : MEM <unsigned char[4096]> [(char * {ref-all})&dst]
602 : : = MEM <unsigned char[4096]> [(char * {ref-all})&src];
603 : : Using cast_region when handling the MEM_REF would give us:
604 : : INIT_VAL(CAST_REG(unsigned char[4096], src))
605 : : as rhs_sval, but we can fold that into a cast svalue:
606 : : CAST(unsigned char[4096], INIT_VAL(src))
607 : : We can discard that cast from the svalue when binding it in
608 : : the store for "dst", and simply store:
609 : : cluster for: dst
610 : : key: {kind: direct, start: 0, size: 32768, next: 32768}
611 : : value: ‘struct big’ {INIT_VAL(src)}. */
612 : :
613 : : static const svalue *
614 : 383707 : simplify_for_binding (const svalue *sval)
615 : : {
616 : 383707 : if (const svalue *cast_sval = sval->maybe_undo_cast ())
617 : 0 : sval = cast_sval;
618 : 58920 : return sval;
619 : : }
620 : :
621 : : /* class binding_map::const_iterator. */
622 : :
623 : : bool
624 : 67836568 : binding_map::const_iterator::operator== (const binding_map::const_iterator &other) const
625 : : {
626 : 67836568 : if (m_concrete != other.m_concrete)
627 : : return false;
628 : 36149045 : if (m_symbolic != other.m_symbolic)
629 : 3013217 : return false;
630 : : return true;
631 : : }
632 : :
633 : : binding_map::const_iterator &
634 : 34687794 : binding_map::const_iterator::operator++ ()
635 : : {
636 : 34687794 : if (m_concrete != m_map.m_concrete.end ())
637 : 31674577 : ++m_concrete;
638 : : else
639 : 3013217 : ++m_symbolic;
640 : 34687794 : return *this;
641 : : }
642 : :
643 : : binding_map::binding_pair
644 : 34700740 : binding_map::const_iterator::operator* ()
645 : : {
646 : 34700740 : if (m_concrete != m_map.m_concrete.end ())
647 : : {
648 : 31687523 : const bit_range &bits = m_concrete->first;
649 : 31687523 : const svalue *sval = m_concrete->second;
650 : 31687523 : return binding_pair (m_map.m_store_mgr.get_concrete_binding (bits), sval);
651 : : }
652 : : else
653 : : {
654 : 3013217 : gcc_assert (m_symbolic != m_map.m_symbolic.end ());
655 : 3013217 : const region *reg = m_symbolic->m_region;
656 : 3013217 : const svalue *sval = m_symbolic->m_sval;
657 : 3013217 : return binding_pair (m_map.m_store_mgr.get_symbolic_binding (reg), sval);
658 : : }
659 : : }
660 : :
661 : : /* class binding_map::iterator. */
662 : :
663 : : bool
664 : 13741330 : binding_map::iterator::operator== (const binding_map::iterator &other) const
665 : : {
666 : 13741330 : if (m_concrete != other.m_concrete)
667 : : return false;
668 : 7353995 : if (m_symbolic != other.m_symbolic)
669 : 641020 : return false;
670 : : return true;
671 : : }
672 : :
673 : : binding_map::iterator &
674 : 7026973 : binding_map::iterator::operator++ ()
675 : : {
676 : 7026973 : if (m_concrete != m_map.m_concrete.end ())
677 : 6385962 : ++m_concrete;
678 : : else
679 : 641011 : ++m_symbolic;
680 : 7026973 : return *this;
681 : : }
682 : :
683 : : binding_map::binding_pair
684 : 7106573 : binding_map::iterator::operator* ()
685 : : {
686 : 7106573 : if (m_concrete != m_map.m_concrete.end ())
687 : : {
688 : 6453831 : const bit_range &bits = m_concrete->first;
689 : 6453831 : const svalue *&sval = m_concrete->second;
690 : 6453831 : return binding_pair (m_map.m_store_mgr.get_concrete_binding (bits), sval);
691 : : }
692 : : else
693 : : {
694 : 652742 : gcc_assert (m_symbolic != m_map.m_symbolic.end ());
695 : 652742 : const region *reg = m_symbolic->m_region;
696 : 652742 : const svalue *&sval = m_symbolic->m_sval;
697 : 652742 : return binding_pair (m_map.m_store_mgr.get_symbolic_binding (reg), sval);
698 : : }
699 : : }
700 : :
701 : : /* class binding_map. */
702 : :
703 : : // Construct an empty binding_map.
704 : :
705 : 1684906 : binding_map::binding_map (store_manager &store_mgr)
706 : 1684906 : : m_store_mgr (store_mgr),
707 : 1684906 : m_concrete (),
708 : 1684906 : m_symbolic ()
709 : : {
710 : 1684906 : }
711 : :
712 : : /* binding_map's copy ctor. */
713 : :
714 : 24199947 : binding_map::binding_map (const binding_map &other)
715 : 24199947 : : m_store_mgr (other.m_store_mgr),
716 : 24199947 : m_concrete (other.m_concrete),
717 : 24199947 : m_symbolic (other.m_symbolic)
718 : : {
719 : 24199947 : }
720 : :
721 : : /* binding_map's assignment operator. */
722 : :
723 : : binding_map&
724 : 4 : binding_map::operator= (const binding_map &other)
725 : : {
726 : 4 : gcc_assert (&m_store_mgr == &other.m_store_mgr);
727 : :
728 : : /* For now, assume we only ever copy to an empty cluster. */
729 : 4 : gcc_assert (m_concrete.size () == 0);
730 : 4 : gcc_assert (m_symbolic.size () == 0);
731 : :
732 : 4 : m_concrete = other.m_concrete;
733 : 4 : m_symbolic = other.m_symbolic;
734 : :
735 : 4 : return *this;
736 : : }
737 : :
738 : : /* binding_map's equality operator. */
739 : :
740 : : bool
741 : 2036396 : binding_map::operator== (const binding_map &other) const
742 : : {
743 : 2036396 : if (m_concrete != other.m_concrete)
744 : : return false;
745 : 1993282 : if (m_symbolic != other.m_symbolic)
746 : : return false;
747 : :
748 : : return true;
749 : : }
750 : :
751 : : /* Generate a hash value for this binding_map. */
752 : :
753 : : hashval_t
754 : 14097422 : binding_map::hash () const
755 : : {
756 : 14097422 : hashval_t result = 0;
757 : 28591026 : for (auto iter : *this)
758 : : {
759 : : /* Use a new hasher for each key to avoid depending on the ordering
760 : : of keys when accumulating the result. */
761 : 14493604 : inchash::hash hstate;
762 : 14493604 : hstate.add_ptr (iter.m_key);
763 : 14493604 : hstate.add_ptr (iter.m_sval);
764 : 14493604 : result ^= hstate.end ();
765 : : }
766 : 14097422 : return result;
767 : : }
768 : :
769 : : const svalue *
770 : 4071360 : binding_map::get (const binding_key *key) const
771 : : {
772 : 4071360 : if (key->symbolic_p ())
773 : : {
774 : 470908 : const ana::symbolic_binding &sym_key
775 : : = *static_cast <const ana::symbolic_binding *> (key);
776 : 470908 : const region *reg = sym_key.get_region ();
777 : :
778 : 539013 : for (auto iter : m_symbolic)
779 : : {
780 : 366045 : if (iter.m_region == reg)
781 : 4071360 : return iter.m_sval;
782 : : }
783 : : return nullptr;
784 : : }
785 : : else
786 : : {
787 : 3600452 : const concrete_binding &conc_key
788 : : = *static_cast <const concrete_binding *> (key);
789 : 3600452 : const bit_range &bits = conc_key.get_bit_range ();
790 : :
791 : 3600452 : concrete_bindings_t::const_iterator iter (m_concrete.find (bits));
792 : 3600452 : if (iter != m_concrete.end ())
793 : 3235041 : return iter->second;
794 : : else
795 : : return nullptr;
796 : : }
797 : : }
798 : :
799 : : void
800 : 1729593 : binding_map::put (const binding_key *key, const svalue *sval)
801 : : {
802 : 1729593 : if (key->symbolic_p ())
803 : : {
804 : 147665 : const ana::symbolic_binding &sym_key
805 : : = *static_cast <const ana::symbolic_binding *> (key);
806 : 147665 : const region *reg = sym_key.get_region ();
807 : :
808 : 147665 : m_symbolic.clear ();
809 : :
810 : 147665 : m_symbolic.push_back ({reg, sval});
811 : : }
812 : : else
813 : : {
814 : 1581928 : const concrete_binding &conc_key
815 : : = *static_cast <const concrete_binding *> (key);
816 : 1581928 : const bit_range &bits = conc_key.get_bit_range ();
817 : :
818 : 1581928 : concrete_bindings_t::iterator iter (m_concrete.find (bits));
819 : 1581928 : if (iter != m_concrete.end ())
820 : 5813 : (*iter).second = sval;
821 : : else
822 : 1576115 : m_concrete.insert ({bits, sval});
823 : : }
824 : 1729593 : }
825 : :
826 : : void
827 : 142 : binding_map::overwrite (iterator_t &pos, const svalue *v)
828 : : {
829 : 142 : gcc_assert (&pos.m_map == this);
830 : 142 : if (pos.m_symbolic != m_symbolic.end ())
831 : 0 : (*(pos.m_symbolic)).m_sval = v;
832 : : else
833 : : {
834 : 142 : gcc_assert (pos.m_concrete != m_concrete.end ());
835 : 142 : (*(pos.m_concrete)).second = v;
836 : : }
837 : 142 : }
838 : :
839 : : void
840 : 264910 : binding_map::remove (const binding_key *key)
841 : : {
842 : 264910 : if (key->symbolic_p ())
843 : 14676 : m_symbolic.clear ();
844 : : else
845 : : {
846 : 250234 : const concrete_binding &conc_key
847 : : = *static_cast <const concrete_binding *> (key);
848 : 250234 : const bit_range &bits = conc_key.get_bit_range ();
849 : 250234 : m_concrete.erase (bits);
850 : : }
851 : 264910 : }
852 : :
853 : : binding_map::const_iterator_t
854 : 33148774 : binding_map::begin () const
855 : : {
856 : 33148774 : return binding_map::const_iterator_t (*this,
857 : : m_concrete.begin (),
858 : 33148774 : m_symbolic.begin ());
859 : : }
860 : :
861 : : binding_map::const_iterator_t
862 : 33163694 : binding_map::end () const
863 : : {
864 : 33163694 : return binding_map::const_iterator_t (*this,
865 : : m_concrete.end (),
866 : 33163694 : m_symbolic.end ());
867 : : }
868 : :
869 : : binding_map::iterator_t
870 : 6714357 : binding_map::begin ()
871 : : {
872 : 6714357 : return binding_map::iterator_t (*this,
873 : : m_concrete.begin (),
874 : 6714357 : m_symbolic.begin ());
875 : : }
876 : :
877 : : binding_map::iterator_t
878 : 13020579 : binding_map::end ()
879 : : {
880 : 13020579 : return binding_map::iterator_t (*this,
881 : : m_concrete.end (),
882 : 13020579 : m_symbolic.end ());
883 : : }
884 : :
885 : : size_t
886 : 679521 : binding_map::elements () const
887 : : {
888 : 679521 : return m_concrete.size () + m_symbolic.size ();
889 : : }
890 : :
891 : : /* Dump a representation of this binding_map to PP.
892 : : SIMPLE controls how values and regions are to be printed.
893 : : If MULTILINE, then split the dump over multiple lines and
894 : : use whitespace for readability, otherwise put all on one line. */
895 : :
896 : : void
897 : 2257 : binding_map::dump_to_pp (pretty_printer *pp, bool simple,
898 : : bool multiline) const
899 : : {
900 : 2257 : bool first = true;
901 : 3900 : for (auto iter : *this)
902 : : {
903 : 1643 : const binding_key *key = iter.m_key;
904 : 1643 : const svalue *value = iter.m_sval;
905 : 1643 : if (multiline)
906 : : {
907 : 328 : pp_string (pp, " key: {");
908 : 328 : key->dump_to_pp (pp, simple);
909 : 328 : pp_string (pp, "}");
910 : 328 : pp_newline (pp);
911 : 328 : pp_string (pp, " value: ");
912 : 328 : if (tree t = value->get_type ())
913 : 328 : dump_quoted_tree (pp, t);
914 : 328 : pp_string (pp, " {");
915 : 328 : value->dump_to_pp (pp, simple);
916 : 328 : pp_string (pp, "}");
917 : 328 : pp_newline (pp);
918 : : }
919 : : else
920 : : {
921 : 1315 : if (first)
922 : : first = false;
923 : : else
924 : 566 : pp_string (pp, ", ");
925 : 1315 : pp_string (pp, "binding key: {");
926 : 1315 : key->dump_to_pp (pp, simple);
927 : 1315 : pp_string (pp, "}, value: {");
928 : 1315 : value->dump_to_pp (pp, simple);
929 : 1315 : pp_string (pp, "}");
930 : : }
931 : : }
932 : 2257 : }
933 : :
934 : : /* Dump a multiline representation of this binding_map to stderr. */
935 : :
936 : : DEBUG_FUNCTION void
937 : 0 : binding_map::dump (bool simple) const
938 : : {
939 : 0 : tree_dump_pretty_printer pp (stderr);
940 : 0 : dump_to_pp (&pp, simple, true);
941 : 0 : pp_newline (&pp);
942 : 0 : }
943 : :
944 : : /* Return a new json::object of the form
945 : : {KEY_DESC : SVALUE_DESC,
946 : : ...for the various key/value pairs in this binding_map}. */
947 : :
948 : : std::unique_ptr<json::object>
949 : 0 : binding_map::to_json () const
950 : : {
951 : 0 : auto map_obj = std::make_unique<json::object> ();
952 : :
953 : 0 : for (auto iter : *this)
954 : : {
955 : 0 : const svalue *value = iter.m_sval;
956 : 0 : label_text key_desc = iter.m_key->get_desc ();
957 : 0 : map_obj->set (key_desc.get (), value->to_json ());
958 : 0 : }
959 : :
960 : 0 : return map_obj;
961 : : }
962 : :
963 : : /* Add a child to PARENT_WIDGET expressing a binding between
964 : : KEY and SVAL. */
965 : :
966 : : static void
967 : 0 : add_binding_to_tree_widget (text_art::tree_widget &parent_widget,
968 : : const text_art::dump_widget_info &dwi,
969 : : const binding_key *key,
970 : : const svalue *sval)
971 : : {
972 : 0 : pretty_printer the_pp;
973 : 0 : pretty_printer * const pp = &the_pp;
974 : 0 : pp_format_decoder (pp) = default_tree_printer;
975 : 0 : pp_show_color (pp) = true;
976 : 0 : const bool simple = true;
977 : :
978 : 0 : key->dump_to_pp (pp, simple);
979 : 0 : pp_string (pp, ": ");
980 : 0 : if (tree t = sval->get_type ())
981 : 0 : dump_quoted_tree (pp, t);
982 : 0 : pp_string (pp, " {");
983 : 0 : sval->dump_to_pp (pp, simple);
984 : 0 : pp_string (pp, "}");
985 : :
986 : 0 : parent_widget.add_child (text_art::tree_widget::make (dwi, pp));
987 : 0 : }
988 : :
989 : : void
990 : 0 : binding_map::add_to_tree_widget (text_art::tree_widget &parent_widget,
991 : : const text_art::dump_widget_info &dwi) const
992 : : {
993 : 0 : for (auto iter : *this)
994 : : {
995 : 0 : const binding_key *key = iter.m_key;
996 : 0 : const svalue *sval = iter.m_sval;
997 : 0 : add_binding_to_tree_widget (parent_widget, dwi,
998 : : key, sval);
999 : : }
1000 : 0 : }
1001 : :
1002 : :
1003 : : /* Comparator for imposing an order on binding_maps. */
1004 : :
1005 : : int
1006 : 52 : binding_map::cmp (const binding_map &map1, const binding_map &map2)
1007 : : {
1008 : 52 : if (int count_cmp = map1.elements () - map2.elements ())
1009 : : return count_cmp;
1010 : :
1011 : 52 : auto_vec <const binding_key *> keys1 (map1.elements ());
1012 : 104 : for (auto iter : map1)
1013 : 52 : keys1.quick_push (iter.m_key);
1014 : 52 : keys1.qsort (binding_key::cmp_ptrs);
1015 : :
1016 : 52 : auto_vec <const binding_key *> keys2 (map2.elements ());
1017 : 104 : for (auto iter : map2)
1018 : 52 : keys2.quick_push (iter.m_key);
1019 : 52 : keys2.qsort (binding_key::cmp_ptrs);
1020 : :
1021 : 104 : for (size_t i = 0; i < keys1.length (); i++)
1022 : : {
1023 : 52 : const binding_key *k1 = keys1[i];
1024 : 52 : const binding_key *k2 = keys2[i];
1025 : 52 : if (int key_cmp = binding_key::cmp (k1, k2))
1026 : : return key_cmp;
1027 : 52 : gcc_assert (k1 == k2);
1028 : 52 : if (int sval_cmp = svalue::cmp_ptr (map1.get (k1), map2.get (k2)))
1029 : : return sval_cmp;
1030 : : }
1031 : :
1032 : : return 0;
1033 : 52 : }
1034 : :
1035 : : /* Get the child region of PARENT_REG based upon INDEX within a
1036 : : CONSTRUCTOR. */
1037 : :
1038 : : static const region *
1039 : 548 : get_subregion_within_ctor (const region *parent_reg, tree index,
1040 : : region_model_manager *mgr)
1041 : : {
1042 : 548 : switch (TREE_CODE (index))
1043 : : {
1044 : 0 : default:
1045 : 0 : gcc_unreachable ();
1046 : 412 : case INTEGER_CST:
1047 : 412 : {
1048 : 412 : const svalue *index_sval
1049 : 412 : = mgr->get_or_create_constant_svalue (index);
1050 : 412 : return mgr->get_element_region (parent_reg,
1051 : 412 : TREE_TYPE (parent_reg->get_type ()),
1052 : 412 : index_sval);
1053 : : }
1054 : 136 : break;
1055 : 136 : case FIELD_DECL:
1056 : 136 : return mgr->get_field_region (parent_reg, index);
1057 : : }
1058 : : }
1059 : :
1060 : : /* Get the child region of PARENT_REG based upon (INDEX, VALUE) within a
1061 : : CONSTRUCTOR. */
1062 : :
1063 : : static const region *
1064 : 548 : get_subregion_within_ctor_for_ctor_pair (const region *parent_reg,
1065 : : tree index,
1066 : : tree value,
1067 : : region_model_manager *mgr)
1068 : : {
1069 : 548 : if (TREE_CODE (index) == INTEGER_CST
1070 : 412 : && TREE_CODE (value) == RAW_DATA_CST)
1071 : : {
1072 : : /* Special-case; see tree.def's description of CONSTRUCTOR.
1073 : : We have RAW_DATA_LENGTH of bytes, starting at INDEX's start. */
1074 : 14 : const region *start_reg
1075 : 14 : = get_subregion_within_ctor (parent_reg, index, mgr);
1076 : : /* Build a bit range, relative to PARENT_REG. */
1077 : 14 : region_offset start_offset = start_reg->get_offset (mgr);
1078 : :
1079 : 14 : if (!start_offset.concrete_p ())
1080 : : return nullptr;
1081 : 14 : bit_offset_t start_bit_offset = start_offset.get_bit_offset ();
1082 : 14 : int length = RAW_DATA_LENGTH (value);
1083 : 14 : bit_range bits (start_bit_offset, length * BITS_PER_UNIT);
1084 : :
1085 : 14 : return mgr->get_bit_range (parent_reg, NULL_TREE, bits);
1086 : : }
1087 : :
1088 : 534 : return get_subregion_within_ctor (parent_reg, index, mgr);
1089 : : }
1090 : :
1091 : : /* Get the svalue for VAL, a non-CONSTRUCTOR value within a CONSTRUCTOR. */
1092 : :
1093 : : static const svalue *
1094 : 482 : get_svalue_for_ctor_val (tree val, region_model_manager *mgr)
1095 : : {
1096 : : /* Reuse the get_rvalue logic from region_model. */
1097 : 482 : region_model m (mgr);
1098 : 482 : return m.get_rvalue (path_var (val, 0), nullptr);
1099 : 482 : }
1100 : :
1101 : : /* Bind values from CONSTRUCTOR to this map, relative to
1102 : : PARENT_REG's relationship to its base region.
1103 : : Return true if successful, false if there was a problem (e.g. due
1104 : : to hitting a complexity limit). */
1105 : :
1106 : : bool
1107 : 214 : binding_map::apply_ctor_to_region (const region *parent_reg, tree ctor,
1108 : : region_model_manager *mgr)
1109 : : {
1110 : 214 : gcc_assert (parent_reg);
1111 : 214 : gcc_assert (TREE_CODE (ctor) == CONSTRUCTOR);
1112 : :
1113 : 214 : unsigned ix;
1114 : 214 : tree index;
1115 : 214 : tree val;
1116 : 214 : tree parent_type = parent_reg->get_type ();
1117 : 214 : tree field;
1118 : 214 : if (TREE_CODE (parent_type) == RECORD_TYPE)
1119 : 102 : field = TYPE_FIELDS (parent_type);
1120 : : else
1121 : : field = NULL_TREE;
1122 : 761 : FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), ix, index, val)
1123 : : {
1124 : 548 : if (!index)
1125 : : {
1126 : : /* If index is NULL, then iterate through the fields for
1127 : : a RECORD_TYPE, or use an INTEGER_CST otherwise.
1128 : : Compare with similar logic in output_constructor. */
1129 : 198 : if (field)
1130 : : {
1131 : 0 : index = field;
1132 : 0 : field = DECL_CHAIN (field);
1133 : : }
1134 : : else
1135 : 198 : index = build_int_cst (integer_type_node, ix);
1136 : : }
1137 : 350 : else if (TREE_CODE (index) == RANGE_EXPR)
1138 : : {
1139 : 0 : tree min_index = TREE_OPERAND (index, 0);
1140 : 0 : tree max_index = TREE_OPERAND (index, 1);
1141 : 0 : if (min_index == max_index)
1142 : : {
1143 : 0 : if (!apply_ctor_pair_to_child_region (parent_reg, mgr,
1144 : : min_index, val))
1145 : : return false;
1146 : : }
1147 : : else
1148 : : {
1149 : 0 : if (!apply_ctor_val_to_range (parent_reg, mgr,
1150 : : min_index, max_index, val))
1151 : : return false;
1152 : : }
1153 : 0 : continue;
1154 : 0 : }
1155 : 548 : if (!apply_ctor_pair_to_child_region (parent_reg, mgr, index, val))
1156 : : return false;
1157 : : }
1158 : : return true;
1159 : : }
1160 : :
1161 : : /* Bind the value VAL into the range of elements within PARENT_REF
1162 : : from MIN_INDEX to MAX_INDEX (including endpoints).
1163 : : For use in handling RANGE_EXPR within a CONSTRUCTOR.
1164 : : Return true if successful, false if there was a problem (e.g. due
1165 : : to hitting a complexity limit). */
1166 : :
1167 : : bool
1168 : 0 : binding_map::apply_ctor_val_to_range (const region *parent_reg,
1169 : : region_model_manager *mgr,
1170 : : tree min_index, tree max_index,
1171 : : tree val)
1172 : : {
1173 : 0 : gcc_assert (TREE_CODE (min_index) == INTEGER_CST);
1174 : 0 : gcc_assert (TREE_CODE (max_index) == INTEGER_CST);
1175 : :
1176 : : /* Generate a binding key for the range. */
1177 : 0 : const region *min_element
1178 : 0 : = get_subregion_within_ctor (parent_reg, min_index, mgr);
1179 : 0 : const region *max_element
1180 : 0 : = get_subregion_within_ctor (parent_reg, max_index, mgr);
1181 : 0 : region_offset min_offset = min_element->get_offset (mgr);
1182 : 0 : if (min_offset.symbolic_p ())
1183 : : return false;
1184 : 0 : bit_offset_t start_bit_offset = min_offset.get_bit_offset ();
1185 : 0 : store_manager *smgr = mgr->get_store_manager ();
1186 : 0 : if (max_element->empty_p ())
1187 : : return false;
1188 : 0 : const binding_key *max_element_key = binding_key::make (smgr, max_element);
1189 : 0 : if (max_element_key->symbolic_p ())
1190 : : return false;
1191 : 0 : const concrete_binding *max_element_ckey
1192 : 0 : = max_element_key->dyn_cast_concrete_binding ();
1193 : 0 : bit_size_t range_size_in_bits
1194 : 0 : = max_element_ckey->get_next_bit_offset () - start_bit_offset;
1195 : 0 : const concrete_binding *range_key
1196 : 0 : = smgr->get_concrete_binding (start_bit_offset, range_size_in_bits);
1197 : 0 : if (range_key->symbolic_p ())
1198 : : return false;
1199 : :
1200 : : /* Get the value. */
1201 : 0 : if (TREE_CODE (val) == CONSTRUCTOR)
1202 : : return false;
1203 : 0 : const svalue *sval = get_svalue_for_ctor_val (val, mgr);
1204 : :
1205 : : /* Bind the value to the range. */
1206 : 0 : put (range_key, sval);
1207 : 0 : return true;
1208 : : }
1209 : :
1210 : : /* Bind the value VAL into INDEX within PARENT_REF.
1211 : : For use in handling a pair of entries within a CONSTRUCTOR.
1212 : : Return true if successful, false if there was a problem (e.g. due
1213 : : to hitting a complexity limit). */
1214 : :
1215 : : bool
1216 : 548 : binding_map::apply_ctor_pair_to_child_region (const region *parent_reg,
1217 : : region_model_manager *mgr,
1218 : : tree index, tree val)
1219 : : {
1220 : 548 : const region *child_reg
1221 : 548 : = get_subregion_within_ctor_for_ctor_pair (parent_reg, index, val, mgr);
1222 : 548 : if (!child_reg)
1223 : : return false;
1224 : 548 : if (TREE_CODE (val) == CONSTRUCTOR)
1225 : 66 : return apply_ctor_to_region (child_reg, val, mgr);
1226 : : else
1227 : : {
1228 : 482 : const svalue *sval = get_svalue_for_ctor_val (val, mgr);
1229 : 482 : if (child_reg->empty_p ())
1230 : : return false;
1231 : 482 : const binding_key *k
1232 : 482 : = binding_key::make (mgr->get_store_manager (), child_reg);
1233 : : /* Handle the case where we have an unknown size for child_reg
1234 : : (e.g. due to it being a trailing field with incomplete array
1235 : : type. */
1236 : 482 : if (!k->concrete_p ())
1237 : : {
1238 : : /* Assume that sval has a well-defined size for this case. */
1239 : 5 : tree sval_type = sval->get_type ();
1240 : 5 : gcc_assert (sval_type);
1241 : 5 : HOST_WIDE_INT sval_byte_size = int_size_in_bytes (sval_type);
1242 : 5 : gcc_assert (sval_byte_size != -1);
1243 : 5 : bit_size_t sval_bit_size = sval_byte_size * BITS_PER_UNIT;
1244 : : /* Get offset of child relative to base region. */
1245 : 5 : region_offset child_base_offset = child_reg->get_offset (mgr);
1246 : 5 : if (child_base_offset.symbolic_p ())
1247 : 1 : return false;
1248 : : /* Convert to an offset relative to the parent region. */
1249 : 4 : region_offset parent_base_offset = parent_reg->get_offset (mgr);
1250 : 4 : gcc_assert (!parent_base_offset.symbolic_p ());
1251 : 4 : bit_offset_t child_parent_offset
1252 : 4 : = (child_base_offset.get_bit_offset ()
1253 : 4 : - parent_base_offset.get_bit_offset ());
1254 : : /* Create a concrete key for the child within the parent. */
1255 : 4 : k = mgr->get_store_manager ()->get_concrete_binding
1256 : 4 : (child_parent_offset, sval_bit_size);
1257 : : }
1258 : 481 : gcc_assert (k->concrete_p ());
1259 : 481 : put (k, sval);
1260 : 481 : return true;
1261 : : }
1262 : : }
1263 : :
1264 : : /* Populate OUT with all bindings within this map that overlap KEY. */
1265 : :
1266 : : void
1267 : 35881 : binding_map::get_overlapping_bindings (const binding_key *key,
1268 : : auto_vec<const binding_key *> *out)
1269 : : {
1270 : 103797 : for (auto iter : *this)
1271 : : {
1272 : 67916 : const binding_key *iter_key = iter.m_key;
1273 : 135832 : if (const concrete_binding *ckey
1274 : 67916 : = key->dyn_cast_concrete_binding ())
1275 : : {
1276 : 130598 : if (const concrete_binding *iter_ckey
1277 : 65299 : = iter_key->dyn_cast_concrete_binding ())
1278 : : {
1279 : 64560 : if (ckey->overlaps_p (*iter_ckey))
1280 : 26758 : out->safe_push (iter_key);
1281 : : }
1282 : : else
1283 : : {
1284 : : /* Assume overlap. */
1285 : 739 : out->safe_push (iter_key);
1286 : : }
1287 : : }
1288 : : else
1289 : : {
1290 : : /* Assume overlap. */
1291 : 2617 : out->safe_push (iter_key);
1292 : : }
1293 : : }
1294 : 35881 : }
1295 : :
1296 : : /* Remove, truncate, and/or split any bindings within this map that
1297 : : overlap DROP_KEY.
1298 : :
1299 : : For example, if we have:
1300 : :
1301 : : +------------------------------------+
1302 : : | old binding |
1303 : : +------------------------------------+
1304 : :
1305 : : which is to be overwritten with:
1306 : :
1307 : : .......+----------------------+.......
1308 : : .......| new binding |.......
1309 : : .......+----------------------+.......
1310 : :
1311 : : this function "cuts a hole" out of the old binding:
1312 : :
1313 : : +------+......................+------+
1314 : : |prefix| hole for new binding |suffix|
1315 : : +------+......................+------+
1316 : :
1317 : : into which the new binding can be added without
1318 : : overlapping the prefix or suffix.
1319 : :
1320 : : The prefix and suffix (if added) will be bound to the pertinent
1321 : : parts of the value of the old binding.
1322 : :
1323 : : For example, given:
1324 : : struct s5
1325 : : {
1326 : : char arr[8];
1327 : : };
1328 : : void test_5 (struct s5 *p)
1329 : : {
1330 : : struct s5 f = *p;
1331 : : f.arr[3] = 42;
1332 : : }
1333 : : then after the "f = *p;" we have:
1334 : : cluster for: f: INIT_VAL((*INIT_VAL(p_33(D))))
1335 : : and at the "f.arr[3] = 42;" we remove the bindings overlapping
1336 : : "f.arr[3]", replacing it with a prefix (bytes 0-2) and suffix (bytes 4-7)
1337 : : giving:
1338 : : cluster for: f
1339 : : key: {bytes 0-2}
1340 : : value: {BITS_WITHIN(bytes 0-2, inner_val: INIT_VAL((*INIT_VAL(p_33(D))).arr))}
1341 : : key: {bytes 4-7}
1342 : : value: {BITS_WITHIN(bytes 4-7, inner_val: INIT_VAL((*INIT_VAL(p_33(D))).arr))}
1343 : : punching a hole into which the new value can be written at byte 3:
1344 : : cluster for: f
1345 : : key: {bytes 0-2}
1346 : : value: {BITS_WITHIN(bytes 0-2, inner_val: INIT_VAL((*INIT_VAL(p_33(D))).arr))}
1347 : : key: {byte 3}
1348 : : value: 'char' {(char)42}
1349 : : key: {bytes 4-7}
1350 : : value: {BITS_WITHIN(bytes 4-7, inner_val: INIT_VAL((*INIT_VAL(p_33(D))).arr))}
1351 : :
1352 : : If UNCERTAINTY is non-NULL, use it to record any svalues that
1353 : : were removed, as being maybe-bound.
1354 : :
1355 : : If MAYBE_LIVE_VALUES is non-NULL, then use it to record any svalues that
1356 : : were removed as being maybe-live.
1357 : :
1358 : : If ALWAYS_OVERLAP, then assume that DROP_KEY can overlap anything
1359 : : in the map, due to one or both of the underlying clusters being
1360 : : symbolic (but not the same symbolic region). Hence even if DROP_KEY is a
1361 : : concrete binding it could actually be referring to the same memory as
1362 : : distinct concrete bindings in the map. Remove all bindings, but
1363 : : register any svalues with *UNCERTAINTY. */
1364 : :
1365 : : void
1366 : 92076 : binding_map::remove_overlapping_bindings (store_manager *mgr,
1367 : : const binding_key *drop_key,
1368 : : uncertainty_t *uncertainty,
1369 : : svalue_set *maybe_live_values,
1370 : : bool always_overlap)
1371 : : {
1372 : : /* Get the bindings of interest within this map. */
1373 : 92076 : auto_vec<const binding_key *> bindings;
1374 : 92076 : if (always_overlap)
1375 : 113324 : for (auto iter : *this)
1376 : 57129 : bindings.safe_push (iter.m_key); /* Add all bindings. */
1377 : : else
1378 : : /* Just add overlapping bindings. */
1379 : 35881 : get_overlapping_bindings (drop_key, &bindings);
1380 : :
1381 : : unsigned i;
1382 : : const binding_key *iter_binding;
1383 : 259701 : FOR_EACH_VEC_ELT (bindings, i, iter_binding)
1384 : : {
1385 : : /* Record any svalues that were removed to *UNCERTAINTY as being
1386 : : maybe-bound, provided at least some part of the binding is symbolic.
1387 : :
1388 : : Specifically, if at least one of the bindings is symbolic, or we
1389 : : have ALWAYS_OVERLAP for the case where we have possibly aliasing
1390 : : regions, then we don't know that the svalue has been overwritten,
1391 : : and should record that to *UNCERTAINTY.
1392 : :
1393 : : However, if we have concrete keys accessing within the same symbolic
1394 : : region, then we *know* that the symbolic region has been overwritten,
1395 : : so we don't record it to *UNCERTAINTY, as this could be a genuine
1396 : : leak. */
1397 : 87243 : const svalue *old_sval = get (iter_binding);
1398 : 87243 : if (uncertainty
1399 : 116074 : && (drop_key->symbolic_p ()
1400 : 26609 : || iter_binding->symbolic_p ()
1401 : 22958 : || always_overlap))
1402 : 24889 : uncertainty->on_maybe_bound_sval (old_sval);
1403 : :
1404 : : /* Record any svalues that were removed to *MAYBE_LIVE_VALUES as being
1405 : : maybe-live. */
1406 : 87243 : if (maybe_live_values)
1407 : 57129 : maybe_live_values->add (old_sval);
1408 : :
1409 : : /* Begin by removing the old binding. */
1410 : 87243 : remove (iter_binding);
1411 : :
1412 : : /* Don't attempt to handle prefixes/suffixes for the
1413 : : "always_overlap" case; everything's being removed. */
1414 : 87243 : if (always_overlap)
1415 : 57129 : continue;
1416 : :
1417 : : /* Now potentially add the prefix and suffix. */
1418 : 60228 : if (const concrete_binding *drop_ckey
1419 : 30114 : = drop_key->dyn_cast_concrete_binding ())
1420 : 54994 : if (const concrete_binding *iter_ckey
1421 : 27497 : = iter_binding->dyn_cast_concrete_binding ())
1422 : : {
1423 : 26758 : gcc_assert (drop_ckey->overlaps_p (*iter_ckey));
1424 : :
1425 : 26758 : const bit_range &drop_bits = drop_ckey->get_bit_range ();
1426 : 26758 : const bit_range &iter_bits = iter_ckey->get_bit_range ();
1427 : :
1428 : 26758 : if (iter_bits.get_start_bit_offset ()
1429 : 26758 : < drop_bits.get_start_bit_offset ())
1430 : : {
1431 : : /* We have a truncated prefix. */
1432 : 1704 : bit_range prefix_bits (iter_bits.get_start_bit_offset (),
1433 : 3408 : (drop_bits.get_start_bit_offset ()
1434 : 1704 : - iter_bits.get_start_bit_offset ()));
1435 : 1704 : const concrete_binding *prefix_key
1436 : 1704 : = mgr->get_concrete_binding (prefix_bits);
1437 : 1704 : bit_range rel_prefix (0, prefix_bits.m_size_in_bits);
1438 : 1704 : const svalue *prefix_sval
1439 : 1704 : = old_sval->extract_bit_range (NULL_TREE,
1440 : : rel_prefix,
1441 : : mgr->get_svalue_manager ());
1442 : 1704 : put (prefix_key, prefix_sval);
1443 : : }
1444 : :
1445 : 53516 : if (iter_bits.get_next_bit_offset ()
1446 : 53516 : > drop_bits.get_next_bit_offset ())
1447 : : {
1448 : : /* We have a truncated suffix. */
1449 : 9169 : bit_range suffix_bits (drop_bits.get_next_bit_offset (),
1450 : 9169 : (iter_bits.get_next_bit_offset ()
1451 : 18338 : - drop_bits.get_next_bit_offset ()));
1452 : 9169 : const concrete_binding *suffix_key
1453 : 9169 : = mgr->get_concrete_binding (suffix_bits);
1454 : 9169 : bit_range rel_suffix (drop_bits.get_next_bit_offset ()
1455 : 9169 : - iter_bits.get_start_bit_offset (),
1456 : 9169 : suffix_bits.m_size_in_bits);
1457 : 9169 : const svalue *suffix_sval
1458 : 9169 : = old_sval->extract_bit_range (NULL_TREE,
1459 : : rel_suffix,
1460 : : mgr->get_svalue_manager ());
1461 : 9169 : put (suffix_key, suffix_sval);
1462 : : }
1463 : : }
1464 : : }
1465 : 92076 : }
1466 : :
1467 : : /* class binding_cluster. */
1468 : :
1469 : 1487192 : binding_cluster::binding_cluster (store_manager &store_mgr,
1470 : 1487192 : const region *base_region)
1471 : 1487192 : : m_base_region (base_region), m_map (store_mgr),
1472 : 1487192 : m_escaped (false), m_touched (false)
1473 : : {
1474 : 1487192 : }
1475 : :
1476 : : /* binding_cluster's copy ctor. */
1477 : :
1478 : 24199290 : binding_cluster::binding_cluster (const binding_cluster &other)
1479 : 24199290 : : m_base_region (other.m_base_region), m_map (other.m_map),
1480 : 24199290 : m_escaped (other.m_escaped), m_touched (other.m_touched)
1481 : : {
1482 : 24199290 : }
1483 : :
1484 : : /* binding_cluster's assignment operator. */
1485 : :
1486 : : binding_cluster&
1487 : 0 : binding_cluster::operator= (const binding_cluster &other)
1488 : : {
1489 : 0 : gcc_assert (m_base_region == other.m_base_region);
1490 : 0 : m_map = other.m_map;
1491 : 0 : m_escaped = other.m_escaped;
1492 : 0 : m_touched = other.m_touched;
1493 : 0 : return *this;
1494 : : }
1495 : :
1496 : : /* binding_cluster's equality operator. */
1497 : :
1498 : : bool
1499 : 2019515 : binding_cluster::operator== (const binding_cluster &other) const
1500 : : {
1501 : 2019515 : if (m_map != other.m_map)
1502 : : return false;
1503 : :
1504 : 1988254 : if (m_base_region != other.m_base_region)
1505 : : return false;
1506 : :
1507 : 1988254 : if (m_escaped != other.m_escaped)
1508 : : return false;
1509 : :
1510 : 1987537 : if (m_touched != other.m_touched)
1511 : : return false;
1512 : :
1513 : 1986099 : gcc_checking_assert (hash () == other.hash ());
1514 : :
1515 : : return true;
1516 : : }
1517 : :
1518 : : /* Generate a hash value for this binding_cluster. */
1519 : :
1520 : : hashval_t
1521 : 14097422 : binding_cluster::hash () const
1522 : : {
1523 : 14097422 : return m_map.hash ();
1524 : : }
1525 : :
1526 : : /* Return true if this binding_cluster is symbolic
1527 : : i.e. its base region is symbolic. */
1528 : :
1529 : : bool
1530 : 7360047 : binding_cluster::symbolic_p () const
1531 : : {
1532 : 7360047 : return m_base_region->get_kind () == RK_SYMBOLIC;
1533 : : }
1534 : :
1535 : : /* Dump a representation of this binding_cluster to PP.
1536 : : SIMPLE controls how values and regions are to be printed.
1537 : : If MULTILINE, then split the dump over multiple lines and
1538 : : use whitespace for readability, otherwise put all on one line. */
1539 : :
1540 : : void
1541 : 2257 : binding_cluster::dump_to_pp (pretty_printer *pp, bool simple,
1542 : : bool multiline) const
1543 : : {
1544 : 2257 : if (m_escaped)
1545 : : {
1546 : 1506 : if (multiline)
1547 : : {
1548 : 1324 : pp_string (pp, " ESCAPED");
1549 : 1324 : pp_newline (pp);
1550 : : }
1551 : : else
1552 : 182 : pp_string (pp, "(ESCAPED)");
1553 : : }
1554 : 2257 : if (m_touched)
1555 : : {
1556 : 306 : if (multiline)
1557 : : {
1558 : 124 : pp_string (pp, " TOUCHED");
1559 : 124 : pp_newline (pp);
1560 : : }
1561 : : else
1562 : 182 : pp_string (pp, "(TOUCHED)");
1563 : : }
1564 : :
1565 : 2257 : m_map.dump_to_pp (pp, simple, multiline);
1566 : 2257 : }
1567 : :
1568 : : /* Dump a multiline representation of this binding_cluster to stderr. */
1569 : :
1570 : : DEBUG_FUNCTION void
1571 : 0 : binding_cluster::dump (bool simple) const
1572 : : {
1573 : 0 : tree_dump_pretty_printer pp (stderr);
1574 : 0 : pp_string (&pp, " cluster for: ");
1575 : 0 : m_base_region->dump_to_pp (&pp, simple);
1576 : 0 : pp_string (&pp, ": ");
1577 : 0 : pp_newline (&pp);
1578 : 0 : dump_to_pp (&pp, simple, true);
1579 : 0 : pp_newline (&pp);
1580 : 0 : }
1581 : :
1582 : : /* Assert that this object is valid. */
1583 : :
1584 : : void
1585 : 9097161 : binding_cluster::validate () const
1586 : : {
1587 : 9097161 : int num_symbolic = 0;
1588 : 9097161 : int num_concrete = 0;
1589 : 18485520 : for (auto iter : m_map)
1590 : : {
1591 : 9388359 : if (iter.m_key->symbolic_p ())
1592 : 848822 : num_symbolic++;
1593 : : else
1594 : 8539537 : num_concrete++;
1595 : : }
1596 : : /* We shouldn't have more than one symbolic key per cluster
1597 : : (or one would have clobbered the other). */
1598 : 9097161 : gcc_assert (num_symbolic < 2);
1599 : : /* We can't have both concrete and symbolic keys. */
1600 : 9097161 : gcc_assert (num_concrete == 0 || num_symbolic == 0);
1601 : 9097161 : }
1602 : :
1603 : : /* Return a new json::object of the form
1604 : : {"escaped": true/false,
1605 : : "touched": true/false,
1606 : : "map" : object for the binding_map. */
1607 : :
1608 : : std::unique_ptr<json::object>
1609 : 0 : binding_cluster::to_json () const
1610 : : {
1611 : 0 : auto cluster_obj = std::make_unique<json::object> ();
1612 : :
1613 : 0 : cluster_obj->set_bool ("escaped", m_escaped);
1614 : 0 : cluster_obj->set_bool ("touched", m_touched);
1615 : 0 : cluster_obj->set ("map", m_map.to_json ());
1616 : :
1617 : 0 : return cluster_obj;
1618 : : }
1619 : :
1620 : : std::unique_ptr<text_art::tree_widget>
1621 : 0 : binding_cluster::make_dump_widget (const text_art::dump_widget_info &dwi,
1622 : : store_manager *mgr) const
1623 : : {
1624 : 0 : pretty_printer the_pp;
1625 : 0 : pretty_printer * const pp = &the_pp;
1626 : 0 : pp_format_decoder (pp) = default_tree_printer;
1627 : 0 : pp_show_color (pp) = true;
1628 : 0 : const bool simple = true;
1629 : :
1630 : 0 : m_base_region->dump_to_pp (pp, simple);
1631 : 0 : pp_string (pp, ": ");
1632 : :
1633 : 0 : if (const svalue *sval = maybe_get_simple_value (mgr))
1634 : : {
1635 : : /* Special-case to simplify dumps for the common case where
1636 : : we just have one value directly bound to the whole of a
1637 : : region. */
1638 : 0 : sval->dump_to_pp (pp, simple);
1639 : 0 : if (escaped_p ())
1640 : 0 : pp_string (pp, " (ESCAPED)");
1641 : 0 : if (touched_p ())
1642 : 0 : pp_string (pp, " (TOUCHED)");
1643 : :
1644 : 0 : return text_art::tree_widget::make (dwi, pp);
1645 : : }
1646 : : else
1647 : : {
1648 : 0 : if (escaped_p ())
1649 : 0 : pp_string (pp, " (ESCAPED)");
1650 : 0 : if (touched_p ())
1651 : 0 : pp_string (pp, " (TOUCHED)");
1652 : :
1653 : 0 : std::unique_ptr<text_art::tree_widget> cluster_widget
1654 : 0 : (text_art::tree_widget::make (dwi, pp));
1655 : :
1656 : 0 : m_map.add_to_tree_widget (*cluster_widget, dwi);
1657 : :
1658 : 0 : return cluster_widget;
1659 : 0 : }
1660 : 0 : }
1661 : :
1662 : : /* Add a binding of SVAL of kind KIND to REG, unpacking SVAL if it is a
1663 : : compound_sval. */
1664 : :
1665 : : void
1666 : 420955 : binding_cluster::bind (store_manager *mgr,
1667 : : const region *reg, const svalue *sval)
1668 : : {
1669 : 841910 : if (const compound_svalue *compound_sval
1670 : 420955 : = sval->dyn_cast_compound_svalue ())
1671 : : {
1672 : 868 : bind_compound_sval (mgr, reg, compound_sval);
1673 : 868 : return;
1674 : : }
1675 : :
1676 : 420087 : if (reg->empty_p ())
1677 : : return;
1678 : 420087 : const binding_key *binding = binding_key::make (mgr, reg);
1679 : 420087 : bind_key (binding, sval);
1680 : : }
1681 : :
1682 : : /* Bind SVAL to KEY.
1683 : : Unpacking of compound_svalues should already have been done by the
1684 : : time this is called. */
1685 : :
1686 : : void
1687 : 424231 : binding_cluster::bind_key (const binding_key *key, const svalue *sval)
1688 : : {
1689 : 424231 : gcc_assert (sval->get_kind () != SK_COMPOUND);
1690 : :
1691 : 424231 : m_map.put (key, sval);
1692 : 424231 : if (key->symbolic_p ())
1693 : 32704 : m_touched = true;
1694 : 424231 : }
1695 : :
1696 : : /* Subroutine of binding_cluster::bind.
1697 : : Unpack compound_svals when binding them, so that we bind them
1698 : : element-wise. */
1699 : :
1700 : : void
1701 : 868 : binding_cluster::bind_compound_sval (store_manager *mgr,
1702 : : const region *reg,
1703 : : const compound_svalue *compound_sval)
1704 : : {
1705 : 868 : region_offset reg_offset
1706 : 868 : = reg->get_offset (mgr->get_svalue_manager ());
1707 : 868 : if (reg_offset.symbolic_p ())
1708 : : {
1709 : 4 : m_touched = true;
1710 : 4 : clobber_region (mgr, reg);
1711 : 4 : return;
1712 : : }
1713 : :
1714 : 3293 : for (auto iter : *compound_sval)
1715 : : {
1716 : 2429 : const binding_key *iter_key = iter.m_key;
1717 : 2429 : const svalue *iter_sval = iter.m_sval;
1718 : :
1719 : 4858 : if (const concrete_binding *concrete_key
1720 : 2429 : = iter_key->dyn_cast_concrete_binding ())
1721 : : {
1722 : 2429 : bit_offset_t effective_start
1723 : 2429 : = (concrete_key->get_start_bit_offset ()
1724 : 2429 : + reg_offset.get_bit_offset ());
1725 : 2429 : const concrete_binding *effective_concrete_key
1726 : 2429 : = mgr->get_concrete_binding (effective_start,
1727 : : concrete_key->get_size_in_bits ());
1728 : 2429 : bind_key (effective_concrete_key, iter_sval);
1729 : : }
1730 : : else
1731 : 0 : gcc_unreachable ();
1732 : : }
1733 : : }
1734 : :
1735 : : /* Remove all bindings overlapping REG within this cluster. */
1736 : :
1737 : : void
1738 : 5950 : binding_cluster::clobber_region (store_manager *mgr, const region *reg)
1739 : : {
1740 : 5950 : remove_overlapping_bindings (mgr, reg, nullptr, nullptr);
1741 : 5950 : }
1742 : :
1743 : : /* Remove any bindings for REG within this cluster. */
1744 : :
1745 : : void
1746 : 177667 : binding_cluster::purge_region (store_manager *mgr, const region *reg)
1747 : : {
1748 : 177667 : gcc_assert (reg->get_kind () == RK_DECL);
1749 : 177667 : if (reg->empty_p ())
1750 : : return;
1751 : 177667 : const binding_key *binding
1752 : 177667 : = binding_key::make (mgr, const_cast<region *> (reg));
1753 : 177667 : m_map.remove (binding);
1754 : : }
1755 : :
1756 : : /* Clobber REG and fill it with repeated copies of SVAL. */
1757 : :
1758 : : void
1759 : 1425 : binding_cluster::fill_region (store_manager *mgr,
1760 : : const region *reg,
1761 : : const svalue *sval)
1762 : : {
1763 : 1425 : clobber_region (mgr, reg);
1764 : :
1765 : 1425 : region_model_manager *sval_mgr = mgr->get_svalue_manager ();
1766 : 1425 : const svalue *byte_size_sval = reg->get_byte_size_sval (sval_mgr);
1767 : 1425 : const svalue *fill_sval
1768 : 1425 : = sval_mgr->get_or_create_repeated_svalue (reg->get_type (),
1769 : : byte_size_sval, sval);
1770 : 1425 : bind (mgr, reg, fill_sval);
1771 : 1425 : }
1772 : :
1773 : : /* Clobber REG within this cluster and fill it with zeroes. */
1774 : :
1775 : : void
1776 : 33 : binding_cluster::zero_fill_region (store_manager *mgr, const region *reg)
1777 : : {
1778 : 33 : region_model_manager *sval_mgr = mgr->get_svalue_manager ();
1779 : 33 : const svalue *zero_sval = sval_mgr->get_or_create_int_cst (char_type_node, 0);
1780 : 33 : fill_region (mgr, reg, zero_sval);
1781 : 33 : }
1782 : :
1783 : : /* Mark REG_TO_BIND within this cluster as being unknown.
1784 : :
1785 : : Remove any bindings overlapping REG_FOR_OVERLAP.
1786 : : If UNCERTAINTY is non-NULL, use it to record any svalues that
1787 : : had bindings to them removed, as being maybe-bound.
1788 : : If MAYBE_LIVE_VALUES is non-NULL, use it to record any svalues that
1789 : : had bindings to them removed, as being maybe-live.
1790 : :
1791 : : REG_TO_BIND and REG_FOR_OVERLAP are the same for
1792 : : store::mark_region_as_unknown, but are different in
1793 : : store::set_value's alias handling, for handling the case where
1794 : : we have a write to a symbolic REG_FOR_OVERLAP. */
1795 : :
1796 : : void
1797 : 56484 : binding_cluster::mark_region_as_unknown (store_manager *mgr,
1798 : : const region *reg_to_bind,
1799 : : const region *reg_for_overlap,
1800 : : uncertainty_t *uncertainty,
1801 : : svalue_set *maybe_live_values)
1802 : : {
1803 : 56484 : if (reg_to_bind->empty_p ())
1804 : : return;
1805 : :
1806 : 56484 : remove_overlapping_bindings (mgr, reg_for_overlap, uncertainty,
1807 : : maybe_live_values);
1808 : :
1809 : : /* Add a default binding to "unknown". */
1810 : 56484 : region_model_manager *sval_mgr = mgr->get_svalue_manager ();
1811 : 56484 : const svalue *sval
1812 : 56484 : = sval_mgr->get_or_create_unknown_svalue (reg_to_bind->get_type ());
1813 : 56484 : bind (mgr, reg_to_bind, sval);
1814 : : }
1815 : :
1816 : : /* Purge state involving SVAL. */
1817 : :
1818 : : void
1819 : 584011 : binding_cluster::purge_state_involving (const svalue *sval,
1820 : : region_model_manager *sval_mgr)
1821 : : {
1822 : 584011 : auto_vec<const binding_key *> to_remove;
1823 : 584011 : auto_vec<std::pair<const binding_key *, tree> > to_make_unknown;
1824 : 1169878 : for (auto iter : m_map)
1825 : : {
1826 : 585867 : const binding_key *iter_key = iter.m_key;
1827 : 1171734 : if (const symbolic_binding *symbolic_key
1828 : 585867 : = iter_key->dyn_cast_symbolic_binding ())
1829 : : {
1830 : 68981 : const region *reg = symbolic_key->get_region ();
1831 : 68981 : if (reg->involves_p (sval))
1832 : 0 : to_remove.safe_push (iter_key);
1833 : : }
1834 : 585867 : const svalue *iter_sval = iter.m_sval;
1835 : 585867 : if (iter_sval->involves_p (sval))
1836 : 4109 : to_make_unknown.safe_push (std::make_pair(iter_key,
1837 : 4109 : iter_sval->get_type ()));
1838 : : }
1839 : 584011 : for (auto iter : to_remove)
1840 : : {
1841 : 0 : m_map.remove (iter);
1842 : 0 : m_touched = true;
1843 : : }
1844 : 596338 : for (auto iter : to_make_unknown)
1845 : : {
1846 : 4109 : const svalue *new_sval
1847 : 4109 : = sval_mgr->get_or_create_unknown_svalue (iter.second);
1848 : 4109 : m_map.put (iter.first, new_sval);
1849 : : }
1850 : 584011 : }
1851 : :
1852 : : /* Get any SVAL bound to REG within this cluster via kind KIND,
1853 : : without checking parent regions of REG. */
1854 : :
1855 : : const svalue *
1856 : 1420256 : binding_cluster::get_binding (store_manager *mgr,
1857 : : const region *reg) const
1858 : : {
1859 : 1420256 : if (reg->empty_p ())
1860 : : return nullptr;
1861 : 1420256 : const binding_key *reg_binding = binding_key::make (mgr, reg);
1862 : 1420256 : const svalue *sval = m_map.get (reg_binding);
1863 : 1420256 : if (sval)
1864 : : {
1865 : : /* If we have a struct with a single field, then the binding of
1866 : : the field will equal that of the struct, and looking up e.g.
1867 : : PARENT_REG.field within:
1868 : : cluster for PARENT_REG: INIT_VAL(OTHER_REG)
1869 : : will erroneously return INIT_VAL(OTHER_REG), rather than
1870 : : SUB_VALUE(INIT_VAL(OTHER_REG), FIELD) == INIT_VAL(OTHER_REG.FIELD).
1871 : : Fix this issue by iterating upwards whilst the bindings are equal,
1872 : : expressing the lookups as subvalues.
1873 : : We have to gather a list of subregion accesses, then walk it
1874 : : in reverse to get the subvalues. */
1875 : 1103917 : auto_vec<const region *> regions;
1876 : 1115833 : while (const region *parent_reg = reg->get_parent_region ())
1877 : : {
1878 : 1115833 : const binding_key *parent_reg_binding
1879 : 1115833 : = binding_key::make (mgr, parent_reg);
1880 : 1115833 : if (parent_reg_binding == reg_binding
1881 : 14615 : && sval->get_type ()
1882 : 14603 : && reg->get_type ()
1883 : 1130436 : && sval->get_type () != reg->get_type ())
1884 : : {
1885 : 11916 : regions.safe_push (reg);
1886 : 11916 : reg = parent_reg;
1887 : : }
1888 : : else
1889 : : break;
1890 : 11916 : }
1891 : 1103917 : if (sval->get_type ()
1892 : 1095111 : && reg->get_type ()
1893 : 2198215 : && sval->get_type () == reg->get_type ())
1894 : : {
1895 : 905112 : unsigned i;
1896 : 905112 : const region *iter_reg;
1897 : 1137112 : FOR_EACH_VEC_ELT_REVERSE (regions, i, iter_reg)
1898 : : {
1899 : 11207 : region_model_manager *rmm_mgr = mgr->get_svalue_manager ();
1900 : 11207 : sval = rmm_mgr->get_or_create_sub_svalue (iter_reg->get_type (),
1901 : : sval, iter_reg);
1902 : : }
1903 : : }
1904 : 1103917 : }
1905 : : return sval;
1906 : : }
1907 : :
1908 : : /* Get any SVAL bound to REG within this cluster,
1909 : : either directly for REG, or recursively checking for bindings within
1910 : : parent regions and extracting subvalues if need be. */
1911 : :
1912 : : const svalue *
1913 : 1420256 : binding_cluster::get_binding_recursive (store_manager *mgr,
1914 : : const region *reg) const
1915 : : {
1916 : 1420256 : if (const svalue *sval = get_binding (mgr, reg))
1917 : : return sval;
1918 : 316339 : if (reg != m_base_region)
1919 : 189080 : if (const region *parent_reg = reg->get_parent_region ())
1920 : 378160 : if (const svalue *parent_sval
1921 : 189080 : = get_binding_recursive (mgr, parent_reg))
1922 : : {
1923 : : /* Extract child svalue from parent svalue. */
1924 : 58057 : region_model_manager *rmm_mgr = mgr->get_svalue_manager ();
1925 : 58057 : return rmm_mgr->get_or_create_sub_svalue (reg->get_type (),
1926 : 58057 : parent_sval, reg);
1927 : : }
1928 : : return nullptr;
1929 : : }
1930 : :
1931 : : /* Get any value bound for REG within this cluster. */
1932 : :
1933 : : const svalue *
1934 : 1231176 : binding_cluster::get_any_binding (store_manager *mgr,
1935 : : const region *reg) const
1936 : : {
1937 : : /* Look for a direct binding. */
1938 : 2462352 : if (const svalue *direct_sval
1939 : 1231176 : = get_binding_recursive (mgr, reg))
1940 : : return direct_sval;
1941 : :
1942 : : /* If we had a write to a cluster of unknown size, we might
1943 : : have a self-binding of the whole base region with an svalue,
1944 : : where the base region is symbolic.
1945 : : Handle such cases by returning sub_svalue instances. */
1946 : 127259 : if (const svalue *cluster_sval = maybe_get_simple_value (mgr))
1947 : : {
1948 : : /* Extract child svalue from parent svalue. */
1949 : 0 : region_model_manager *rmm_mgr = mgr->get_svalue_manager ();
1950 : 0 : return rmm_mgr->get_or_create_sub_svalue (reg->get_type (),
1951 : 0 : cluster_sval, reg);
1952 : : }
1953 : :
1954 : : /* If this cluster has been touched by a symbolic write, then the content
1955 : : of any subregion not currently specifically bound is "UNKNOWN". */
1956 : 127259 : if (m_touched)
1957 : : {
1958 : 5319 : region_model_manager *rmm_mgr = mgr->get_svalue_manager ();
1959 : 5319 : return rmm_mgr->get_or_create_unknown_svalue (reg->get_type ());
1960 : : }
1961 : :
1962 : : /* Alternatively, if this is a symbolic read and the cluster has any bindings,
1963 : : then we don't know if we're reading those values or not, so the result
1964 : : is also "UNKNOWN". */
1965 : 121940 : if (reg->get_offset (mgr->get_svalue_manager ()).symbolic_p ()
1966 : 121940 : && m_map.elements () > 0)
1967 : : {
1968 : 571 : region_model_manager *rmm_mgr = mgr->get_svalue_manager ();
1969 : 571 : return rmm_mgr->get_or_create_unknown_svalue (reg->get_type ());
1970 : : }
1971 : :
1972 : 121369 : if (const svalue *compound_sval = maybe_get_compound_binding (mgr, reg))
1973 : : return compound_sval;
1974 : :
1975 : : /* Otherwise, the initial value, or uninitialized. */
1976 : : return nullptr;
1977 : : }
1978 : :
1979 : : /* Attempt to get a compound_svalue for the bindings within the cluster
1980 : : affecting REG (which could be the base region itself).
1981 : :
1982 : : Create a compound_svalue with the subset of bindings the affect REG,
1983 : : offsetting them so that the offsets are relative to the start of REG
1984 : : within the cluster.
1985 : :
1986 : : For example, REG could be one element within an array of structs.
1987 : :
1988 : : Return the resulting compound_svalue, or nullptr if there's a problem. */
1989 : :
1990 : : const svalue *
1991 : 121369 : binding_cluster::maybe_get_compound_binding (store_manager *mgr,
1992 : : const region *reg) const
1993 : : {
1994 : 121369 : region_offset cluster_offset
1995 : 121369 : = m_base_region->get_offset (mgr->get_svalue_manager ());
1996 : 121369 : if (cluster_offset.symbolic_p ())
1997 : : return nullptr;
1998 : 121369 : region_offset reg_offset = reg->get_offset (mgr->get_svalue_manager ());
1999 : 121369 : if (reg_offset.symbolic_p ())
2000 : : return nullptr;
2001 : :
2002 : 96791 : if (reg->empty_p ())
2003 : : return nullptr;
2004 : :
2005 : 96791 : region_model_manager *sval_mgr = mgr->get_svalue_manager ();
2006 : :
2007 : : /* We will a build the result map in two parts:
2008 : : (a) result_map, holding the concrete keys from this cluster,
2009 : :
2010 : : (b) default_map, holding the initial values for the region
2011 : : (e.g. uninitialized, initializer values, or zero), unless this
2012 : : cluster has been touched.
2013 : :
2014 : : We will populate (a), and as we do, clobber (b), trimming and
2015 : : splitting its bindings as necessary.
2016 : : Finally, we will merge (b) into (a), giving a concrete map
2017 : : that merges both the initial values and the bound values from
2018 : : the binding_cluster.
2019 : : Doing it this way reduces N for the O(N^2) intersection-finding,
2020 : : perhaps we should have a spatial-organized data structure for
2021 : : concrete keys, though. */
2022 : :
2023 : 96791 : binding_map result_map (*mgr);
2024 : 96791 : binding_map default_map (*mgr);
2025 : :
2026 : : /* Set up default values in default_map. */
2027 : 96791 : const svalue *default_sval;
2028 : 96791 : if (m_touched)
2029 : 0 : default_sval = sval_mgr->get_or_create_unknown_svalue (reg->get_type ());
2030 : : else
2031 : 96791 : default_sval = sval_mgr->get_or_create_initial_value (reg);
2032 : 96791 : const binding_key *default_key = binding_key::make (mgr, reg);
2033 : :
2034 : : /* Express the bit-range of the default key for REG relative to REG,
2035 : : rather than to the base region. */
2036 : 96791 : const concrete_binding *concrete_default_key
2037 : 96791 : = default_key->dyn_cast_concrete_binding ();
2038 : 96791 : if (!concrete_default_key)
2039 : : return nullptr;
2040 : 95908 : const concrete_binding *default_key_relative_to_reg
2041 : 95908 : = mgr->get_concrete_binding (0, concrete_default_key->get_size_in_bits ());
2042 : :
2043 : 95908 : default_map.put (default_key_relative_to_reg, default_sval);
2044 : :
2045 : 178038 : for (auto iter : m_map)
2046 : : {
2047 : 95016 : const binding_key *key = iter.m_key;
2048 : 95016 : const svalue *sval = iter.m_sval;
2049 : :
2050 : 190032 : if (const concrete_binding *concrete_key
2051 : 95016 : = key->dyn_cast_concrete_binding ())
2052 : : {
2053 : 95016 : const bit_range &bound_range = concrete_key->get_bit_range ();
2054 : :
2055 : 95016 : bit_size_t reg_bit_size;
2056 : 95016 : if (!reg->get_bit_size (®_bit_size))
2057 : 12886 : return nullptr;
2058 : :
2059 : 95016 : bit_range reg_range (reg_offset.get_bit_offset (),
2060 : 95016 : reg_bit_size);
2061 : :
2062 : : /* Skip bindings that are outside the bit range of REG. */
2063 : 95016 : if (!bound_range.intersects_p (reg_range))
2064 : 72177 : continue;
2065 : :
2066 : : /* We shouldn't have an exact match; that should have been
2067 : : handled already. */
2068 : 22839 : gcc_assert (!(reg_range == bound_range));
2069 : :
2070 : 22839 : bit_range subrange (0, 0);
2071 : 22839 : if (reg_range.contains_p (bound_range, &subrange))
2072 : : {
2073 : : /* We have a bound range fully within REG.
2074 : : Add it to map, offsetting accordingly. */
2075 : :
2076 : : /* Get offset of KEY relative to REG, rather than to
2077 : : the cluster. */
2078 : 9877 : const concrete_binding *offset_concrete_key
2079 : 9877 : = mgr->get_concrete_binding (subrange);
2080 : 9877 : result_map.put (offset_concrete_key, sval);
2081 : :
2082 : : /* Clobber default_map, removing/trimming/spliting where
2083 : : it overlaps with offset_concrete_key. */
2084 : 9877 : default_map.remove_overlapping_bindings (mgr,
2085 : : offset_concrete_key,
2086 : : nullptr, nullptr, false);
2087 : : }
2088 : 12962 : else if (bound_range.contains_p (reg_range, &subrange))
2089 : : {
2090 : : /* REG is fully within the bound range, but
2091 : : is not equal to it; we're extracting a subvalue. */
2092 : 12886 : return sval->extract_bit_range (reg->get_type (),
2093 : : subrange,
2094 : 12886 : mgr->get_svalue_manager ());
2095 : : }
2096 : : else
2097 : : {
2098 : : /* REG and the bound range partially overlap. */
2099 : 76 : bit_range reg_subrange (0, 0);
2100 : 76 : bit_range bound_subrange (0, 0);
2101 : 76 : reg_range.intersects_p (bound_range,
2102 : : ®_subrange, &bound_subrange);
2103 : :
2104 : : /* Get the bits from the bound value for the bits at the
2105 : : intersection (relative to the bound value). */
2106 : 76 : const svalue *overlap_sval
2107 : 76 : = sval->extract_bit_range (NULL_TREE,
2108 : : bound_subrange,
2109 : : mgr->get_svalue_manager ());
2110 : :
2111 : : /* Get key for overlap, relative to the REG. */
2112 : 76 : const concrete_binding *overlap_concrete_key
2113 : 76 : = mgr->get_concrete_binding (reg_subrange);
2114 : 76 : result_map.put (overlap_concrete_key, overlap_sval);
2115 : :
2116 : : /* Clobber default_map, removing/trimming/spliting where
2117 : : it overlaps with overlap_concrete_key. */
2118 : 76 : default_map.remove_overlapping_bindings (mgr,
2119 : : overlap_concrete_key,
2120 : : nullptr, nullptr, false);
2121 : : }
2122 : : }
2123 : : else
2124 : : /* Can't handle symbolic bindings. */
2125 : : return nullptr;
2126 : : }
2127 : :
2128 : 83022 : if (result_map.elements () == 0)
2129 : : return nullptr;
2130 : :
2131 : : /* Merge any bindings from default_map into result_map. */
2132 : 3925 : for (auto iter : default_map)
2133 : : {
2134 : 368 : const binding_key *key = iter.m_key;
2135 : 368 : const svalue *sval = iter.m_sval;
2136 : 368 : result_map.put (key, sval);
2137 : : }
2138 : :
2139 : 3557 : return sval_mgr->get_or_create_compound_svalue (reg->get_type (), result_map);
2140 : 96791 : }
2141 : :
2142 : : /* Remove, truncate, and/or split any bindings within this map that
2143 : : could overlap REG.
2144 : :
2145 : : If REG's base region or this cluster is symbolic and they're different
2146 : : base regions, then remove everything in this cluster's map, on the
2147 : : grounds that REG could be referring to the same memory as anything
2148 : : in the map.
2149 : :
2150 : : If UNCERTAINTY is non-NULL, use it to record any svalues that
2151 : : were removed, as being maybe-bound.
2152 : :
2153 : : If MAYBE_LIVE_VALUES is non-NULL, use it to record any svalues that
2154 : : were removed, as being maybe-live. */
2155 : :
2156 : : void
2157 : 82123 : binding_cluster::remove_overlapping_bindings (store_manager *mgr,
2158 : : const region *reg,
2159 : : uncertainty_t *uncertainty,
2160 : : svalue_set *maybe_live_values)
2161 : : {
2162 : 82123 : if (reg->empty_p ())
2163 : : return;
2164 : 82123 : const binding_key *reg_binding = binding_key::make (mgr, reg);
2165 : :
2166 : 82123 : const region *cluster_base_reg = get_base_region ();
2167 : 82123 : const region *other_base_reg = reg->get_base_region ();
2168 : : /* If at least one of the base regions involved is symbolic, and they're
2169 : : not the same base region, then consider everything in the map as
2170 : : potentially overlapping with reg_binding (even if it's a concrete
2171 : : binding and things in the map are concrete - they could be referring
2172 : : to the same memory when the symbolic base regions are taken into
2173 : : account). */
2174 : 82123 : bool always_overlap = (cluster_base_reg != other_base_reg
2175 : 82123 : && (cluster_base_reg->get_kind () == RK_SYMBOLIC
2176 : 24509 : || other_base_reg->get_kind () == RK_SYMBOLIC));
2177 : 82123 : m_map.remove_overlapping_bindings (mgr, reg_binding, uncertainty,
2178 : : maybe_live_values,
2179 : : always_overlap);
2180 : : }
2181 : :
2182 : : /* Attempt to merge CLUSTER_A and CLUSTER_B into OUT_CLUSTER, using
2183 : : MGR and MERGER.
2184 : : Return true if they can be merged, false otherwise. */
2185 : :
2186 : : bool
2187 : 1157634 : binding_cluster::can_merge_p (const binding_cluster *cluster_a,
2188 : : const binding_cluster *cluster_b,
2189 : : binding_cluster *out_cluster,
2190 : : store *out_store,
2191 : : store_manager *mgr,
2192 : : model_merger *merger)
2193 : : {
2194 : 1157634 : gcc_assert (out_cluster);
2195 : :
2196 : : /* Merge flags ("ESCAPED" and "TOUCHED") by setting the merged flag to
2197 : : true if either of the inputs is true. */
2198 : 1157634 : if ((cluster_a && cluster_a->m_escaped)
2199 : 738427 : || (cluster_b && cluster_b->m_escaped))
2200 : 5016 : out_cluster->m_escaped = true;
2201 : 1157634 : if ((cluster_a && cluster_a->m_touched)
2202 : 790742 : || (cluster_b && cluster_b->m_touched))
2203 : 13078 : out_cluster->m_touched = true;
2204 : :
2205 : : /* At least one of CLUSTER_A and CLUSTER_B are non-NULL, but either
2206 : : could be NULL. Handle these cases. */
2207 : 1157634 : if (cluster_a == nullptr)
2208 : : {
2209 : 21987 : gcc_assert (cluster_b != nullptr);
2210 : 21987 : gcc_assert (cluster_b->m_base_region == out_cluster->m_base_region);
2211 : 21987 : out_cluster->make_unknown_relative_to (cluster_b, out_store, mgr);
2212 : 21987 : return true;
2213 : : }
2214 : 1135647 : if (cluster_b == nullptr)
2215 : : {
2216 : 80087 : gcc_assert (cluster_a != nullptr);
2217 : 80087 : gcc_assert (cluster_a->m_base_region == out_cluster->m_base_region);
2218 : 80087 : out_cluster->make_unknown_relative_to (cluster_a, out_store, mgr);
2219 : 80087 : return true;
2220 : : }
2221 : :
2222 : : /* The "both inputs are non-NULL" case. */
2223 : 1055560 : gcc_assert (cluster_a != nullptr && cluster_b != nullptr);
2224 : 1055560 : gcc_assert (cluster_a->m_base_region == out_cluster->m_base_region);
2225 : 1055560 : gcc_assert (cluster_b->m_base_region == out_cluster->m_base_region);
2226 : :
2227 : 1055560 : hash_set<const binding_key *> keys;
2228 : 2258137 : for (auto iter_a : cluster_a->m_map)
2229 : : {
2230 : 1202577 : const binding_key *key_a = iter_a.m_key;
2231 : 1202577 : keys.add (key_a);
2232 : : }
2233 : 2243272 : for (auto iter_b : cluster_b->m_map)
2234 : : {
2235 : 1187712 : const binding_key *key_b = iter_b.m_key;
2236 : 1187712 : keys.add (key_b);
2237 : : }
2238 : 1055560 : int num_symbolic_keys = 0;
2239 : 1055560 : int num_concrete_keys = 0;
2240 : 2135202 : for (hash_set<const binding_key *>::iterator iter = keys.begin ();
2241 : 3214844 : iter != keys.end (); ++iter)
2242 : : {
2243 : 1182916 : region_model_manager *sval_mgr = mgr->get_svalue_manager ();
2244 : 1182916 : const binding_key *key = *iter;
2245 : 1182916 : const svalue *sval_a = cluster_a->get_any_value (key);
2246 : 1182916 : const svalue *sval_b = cluster_b->get_any_value (key);
2247 : :
2248 : 1182916 : if (key->symbolic_p ())
2249 : 115522 : num_symbolic_keys++;
2250 : : else
2251 : 1067394 : num_concrete_keys++;
2252 : :
2253 : 1182916 : if (sval_a == sval_b)
2254 : : {
2255 : 878853 : gcc_assert (sval_a);
2256 : 878853 : out_cluster->m_map.put (key, sval_a);
2257 : 878853 : continue;
2258 : : }
2259 : 304063 : else if (sval_a && sval_b)
2260 : : {
2261 : 560253 : if (const svalue *merged_sval
2262 : 205960 : = sval_a->can_merge_p (sval_b, sval_mgr, merger))
2263 : : {
2264 : 148333 : out_cluster->m_map.put (key, merged_sval);
2265 : 148333 : continue;
2266 : : }
2267 : : /* Merger of the svalues failed. Reject merger of the cluster. */
2268 : 103274 : return false;
2269 : : }
2270 : :
2271 : : /* If we get here, then one cluster binds this key and the other
2272 : : doesn't; merge them as "UNKNOWN". */
2273 : 98103 : gcc_assert (sval_a || sval_b);
2274 : :
2275 : 98103 : const svalue *bound_sval = sval_a ? sval_a : sval_b;
2276 : 98103 : tree type = bound_sval->get_type ();
2277 : 98103 : const svalue *unknown_sval
2278 : 98103 : = mgr->get_svalue_manager ()->get_or_create_unknown_svalue (type);
2279 : :
2280 : : /* ...but reject the merger if this sval shouldn't be mergeable
2281 : : (e.g. reject merging svalues that have non-purgable sm-state,
2282 : : to avoid falsely reporting memory leaks by merging them
2283 : : with something else). */
2284 : 98103 : if (!bound_sval->can_merge_p (unknown_sval, sval_mgr, merger))
2285 : : return false;
2286 : :
2287 : 52456 : out_cluster->m_map.put (key, unknown_sval);
2288 : : }
2289 : :
2290 : : /* We can only have at most one symbolic key per cluster,
2291 : : and if we do, we can't have any concrete keys.
2292 : : If this happens, mark the cluster as touched, with no keys. */
2293 : 952286 : if (num_symbolic_keys >= 2
2294 : 951760 : || (num_concrete_keys > 0 && num_symbolic_keys > 0))
2295 : : {
2296 : 1639 : out_cluster->m_touched = true;
2297 : 1639 : out_cluster->m_map.clear ();
2298 : : }
2299 : :
2300 : : /* We don't handle other kinds of overlaps yet. */
2301 : :
2302 : : return true;
2303 : 1055560 : }
2304 : :
2305 : : /* Update this cluster to reflect an attempt to merge OTHER where there
2306 : : is no other cluster to merge with, and so we're notionally merging the
2307 : : bound values in OTHER with the initial value of the relevant regions.
2308 : :
2309 : : Any bound keys in OTHER should be bound to unknown in this. */
2310 : :
2311 : : void
2312 : 102074 : binding_cluster::make_unknown_relative_to (const binding_cluster *other,
2313 : : store *out_store,
2314 : : store_manager *mgr)
2315 : : {
2316 : 205398 : for (auto iter : *other)
2317 : : {
2318 : 103324 : const binding_key *iter_key = iter.m_key;
2319 : 103324 : const svalue *iter_sval = iter.m_sval;
2320 : 103324 : const svalue *unknown_sval
2321 : : = mgr->get_svalue_manager ()->get_or_create_unknown_svalue
2322 : 103324 : (iter_sval->get_type ());
2323 : 103324 : m_map.put (iter_key, unknown_sval);
2324 : :
2325 : : /* For any pointers in OTHER, the merger means that the
2326 : : concrete pointer becomes an unknown value, which could
2327 : : show up as a false report of a leak when considering what
2328 : : pointers are live before vs after.
2329 : : Avoid this by marking the base regions they point to as having
2330 : : escaped. */
2331 : 206648 : if (const region_svalue *region_sval
2332 : 103324 : = iter_sval->dyn_cast_region_svalue ())
2333 : : {
2334 : 5752 : const region *base_reg
2335 : 5752 : = region_sval->get_pointee ()->get_base_region ();
2336 : 5752 : if (base_reg->tracked_p ()
2337 : 5752 : && !base_reg->symbolic_for_unknown_ptr_p ())
2338 : : {
2339 : 5713 : binding_cluster *c
2340 : 5713 : = out_store->get_or_create_cluster (*mgr, base_reg);
2341 : 5713 : c->mark_as_escaped ();
2342 : : }
2343 : : }
2344 : : }
2345 : 102074 : }
2346 : :
2347 : : /* Mark this cluster as having escaped. */
2348 : :
2349 : : void
2350 : 46337 : binding_cluster::mark_as_escaped ()
2351 : : {
2352 : 46337 : m_escaped = true;
2353 : 46337 : }
2354 : :
2355 : : /* If this cluster has escaped (by this call, or by an earlier one, or
2356 : : by being an external param), then unbind all values and mark it
2357 : : as "touched", so that it has a conjured value, rather than an
2358 : : initial_svalue.
2359 : : Use P to purge state involving conjured_svalues. */
2360 : :
2361 : : void
2362 : 158022 : binding_cluster::on_unknown_fncall (const gcall &call,
2363 : : store_manager *mgr,
2364 : : const conjured_purge &p)
2365 : : {
2366 : 158022 : if (m_escaped)
2367 : : {
2368 : 28435 : m_map.clear ();
2369 : :
2370 : 28435 : if (!m_base_region->empty_p ())
2371 : : {
2372 : : /* Bind it to a new "conjured" value using CALL. */
2373 : 28435 : const svalue *sval
2374 : : = mgr->get_svalue_manager ()->get_or_create_conjured_svalue
2375 : 28435 : (m_base_region->get_type (), &call, m_base_region, p);
2376 : 28435 : bind (mgr, m_base_region, sval);
2377 : : }
2378 : :
2379 : 28435 : m_touched = true;
2380 : : }
2381 : 158022 : }
2382 : :
2383 : : /* Mark this cluster as having been clobbered by STMT.
2384 : : Use P to purge state involving conjured_svalues. */
2385 : :
2386 : : void
2387 : 522 : binding_cluster::on_asm (const gasm *stmt,
2388 : : store_manager *mgr,
2389 : : const conjured_purge &p)
2390 : : {
2391 : 522 : m_map.clear ();
2392 : :
2393 : : /* Bind it to a new "conjured" value using CALL. */
2394 : 522 : const svalue *sval
2395 : : = mgr->get_svalue_manager ()->get_or_create_conjured_svalue
2396 : 522 : (m_base_region->get_type (), stmt, m_base_region, p);
2397 : 522 : bind (mgr, m_base_region, sval);
2398 : :
2399 : 522 : m_touched = true;
2400 : 522 : }
2401 : :
2402 : : /* Return true if this cluster has escaped. */
2403 : :
2404 : : bool
2405 : 8387086 : binding_cluster::escaped_p () const
2406 : : {
2407 : : /* Consider the "errno" region to always have escaped. */
2408 : 8387086 : if (m_base_region->get_kind () == RK_ERRNO)
2409 : : return true;
2410 : 8357595 : return m_escaped;
2411 : : }
2412 : :
2413 : : /* Return true if this binding_cluster has no information
2414 : : i.e. if there are no bindings, and it hasn't been marked as having
2415 : : escaped, or touched symbolically. */
2416 : :
2417 : : bool
2418 : 182188 : binding_cluster::redundant_p () const
2419 : : {
2420 : 182188 : return (m_map.elements () == 0
2421 : 177044 : && !m_escaped
2422 : 358249 : && !m_touched);
2423 : : }
2424 : :
2425 : : /* Add PV to OUT_PVS, casting it to TYPE if it is not already of that type. */
2426 : :
2427 : : static void
2428 : 8468 : append_pathvar_with_type (path_var pv,
2429 : : tree type,
2430 : : auto_vec<path_var> *out_pvs)
2431 : : {
2432 : 8468 : gcc_assert (pv.m_tree);
2433 : :
2434 : 8468 : if (TREE_TYPE (pv.m_tree) != type)
2435 : 603 : pv.m_tree = build1 (NOP_EXPR, type, pv.m_tree);
2436 : :
2437 : 8468 : out_pvs->safe_push (pv);
2438 : 8468 : }
2439 : :
2440 : : /* Find representative path_vars for SVAL within this binding of BASE_REG,
2441 : : appending the results to OUT_PVS. */
2442 : :
2443 : : void
2444 : 58920 : binding_cluster::get_representative_path_vars (const region_model *model,
2445 : : svalue_set *visited,
2446 : : const region *base_reg,
2447 : : const svalue *sval,
2448 : : logger *logger,
2449 : : auto_vec<path_var> *out_pvs)
2450 : : const
2451 : : {
2452 : 58920 : sval = simplify_for_binding (sval);
2453 : :
2454 : 114247 : for (auto iter : m_map)
2455 : : {
2456 : 55327 : const binding_key *key = iter.m_key;
2457 : 55327 : const svalue *bound_sval = iter.m_sval;
2458 : 55327 : if (bound_sval == sval)
2459 : : {
2460 : 17790 : if (const concrete_binding *ckey
2461 : 8895 : = key->dyn_cast_concrete_binding ())
2462 : : {
2463 : 8831 : auto_vec <const region *> subregions;
2464 : 8831 : base_reg->get_subregions_for_binding
2465 : 8831 : (model->get_manager (),
2466 : : ckey->get_start_bit_offset (),
2467 : : ckey->get_size_in_bits (),
2468 : : sval->get_type (),
2469 : : &subregions);
2470 : 8831 : unsigned i;
2471 : 8831 : const region *subregion;
2472 : 25655 : FOR_EACH_VEC_ELT (subregions, i, subregion)
2473 : : {
2474 : 16824 : if (path_var pv
2475 : 8412 : = model->get_representative_path_var (subregion,
2476 : : visited,
2477 : 8412 : logger))
2478 : 8404 : append_pathvar_with_type (pv, sval->get_type (), out_pvs);
2479 : : }
2480 : 8831 : }
2481 : : else
2482 : : {
2483 : 64 : const symbolic_binding *skey = (const symbolic_binding *)key;
2484 : 128 : if (path_var pv
2485 : 64 : = model->get_representative_path_var (skey->get_region (),
2486 : : visited,
2487 : 64 : logger))
2488 : 64 : append_pathvar_with_type (pv, sval->get_type (), out_pvs);
2489 : : }
2490 : : }
2491 : : }
2492 : 58920 : }
2493 : :
2494 : : /* Get any svalue bound to KEY, or nullptr. */
2495 : :
2496 : : const svalue *
2497 : 2563177 : binding_cluster::get_any_value (const binding_key *key) const
2498 : : {
2499 : 2563177 : return m_map.get (key);
2500 : : }
2501 : :
2502 : : /* If this cluster has a single direct binding for the whole of the region,
2503 : : return it.
2504 : : For use in simplifying dumps. */
2505 : :
2506 : : const svalue *
2507 : 388954 : binding_cluster::maybe_get_simple_value (store_manager *mgr) const
2508 : : {
2509 : : /* Fail gracefully if MGR is nullptr to make it easier to dump store
2510 : : instances in the debugger. */
2511 : 388954 : if (mgr == nullptr)
2512 : : return nullptr;
2513 : :
2514 : 388954 : if (m_map.elements () != 1)
2515 : : return nullptr;
2516 : :
2517 : 197345 : if (m_base_region->empty_p ())
2518 : : return nullptr;
2519 : :
2520 : 197345 : const binding_key *key = binding_key::make (mgr, m_base_region);
2521 : 197345 : return get_any_value (key);
2522 : : }
2523 : :
2524 : : /* class store_manager. */
2525 : :
2526 : : logger *
2527 : 337250 : store_manager::get_logger () const
2528 : : {
2529 : 337250 : return m_mgr->get_logger ();
2530 : : }
2531 : :
2532 : : /* binding consolidation. */
2533 : :
2534 : : const concrete_binding *
2535 : 40449056 : store_manager::get_concrete_binding (bit_offset_t start_bit_offset,
2536 : : bit_offset_t size_in_bits)
2537 : : {
2538 : 40449056 : concrete_binding b (start_bit_offset, size_in_bits);
2539 : 80886033 : if (concrete_binding *existing = m_concrete_binding_key_mgr.get (b))
2540 : : return existing;
2541 : :
2542 : 12079 : concrete_binding *to_save = new concrete_binding (b);
2543 : 12079 : m_concrete_binding_key_mgr.put (b, to_save);
2544 : 12079 : return to_save;
2545 : 40449056 : }
2546 : :
2547 : : const symbolic_binding *
2548 : 4993647 : store_manager::get_symbolic_binding (const region *reg)
2549 : : {
2550 : 4993647 : symbolic_binding b (reg);
2551 : 9967803 : if (symbolic_binding *existing = m_symbolic_binding_key_mgr.get (b))
2552 : : return existing;
2553 : :
2554 : 19491 : symbolic_binding *to_save = new symbolic_binding (b);
2555 : 19491 : m_symbolic_binding_key_mgr.put (b, to_save);
2556 : 19491 : return to_save;
2557 : 4993647 : }
2558 : :
2559 : : /* class store. */
2560 : :
2561 : : /* store's default ctor. */
2562 : :
2563 : 360720 : store::store ()
2564 : 360720 : : m_called_unknown_fn (false)
2565 : : {
2566 : 360720 : }
2567 : :
2568 : : /* store's copy ctor. */
2569 : :
2570 : 3766755 : store::store (const store &other)
2571 : 3766755 : : m_cluster_map (other.m_cluster_map.elements ()),
2572 : 3766755 : m_called_unknown_fn (other.m_called_unknown_fn)
2573 : : {
2574 : 3766755 : for (cluster_map_t::iterator iter = other.m_cluster_map.begin ();
2575 : 27834774 : iter != other.m_cluster_map.end ();
2576 : 24068019 : ++iter)
2577 : : {
2578 : 24068019 : const region *reg = (*iter).first;
2579 : 0 : gcc_assert (reg);
2580 : 24068019 : binding_cluster *c = (*iter).second;
2581 : 24068019 : gcc_assert (c);
2582 : 24068019 : m_cluster_map.put (reg, new binding_cluster (*c));
2583 : : }
2584 : 3766755 : }
2585 : :
2586 : : /* store's dtor. */
2587 : :
2588 : 4127475 : store::~store ()
2589 : : {
2590 : 29456249 : for (cluster_map_t::iterator iter = m_cluster_map.begin ();
2591 : 29456249 : iter != m_cluster_map.end ();
2592 : 25328774 : ++iter)
2593 : 25328774 : delete (*iter).second;
2594 : 4127475 : }
2595 : :
2596 : : /* store's assignment operator. */
2597 : :
2598 : : store &
2599 : 17894 : store::operator= (const store &other)
2600 : : {
2601 : : /* Delete existing cluster map. */
2602 : 133076 : for (cluster_map_t::iterator iter = m_cluster_map.begin ();
2603 : 133076 : iter != m_cluster_map.end ();
2604 : 115182 : ++iter)
2605 : 230364 : delete (*iter).second;
2606 : 17894 : m_cluster_map.empty ();
2607 : :
2608 : 17894 : m_called_unknown_fn = other.m_called_unknown_fn;
2609 : :
2610 : 17894 : for (cluster_map_t::iterator iter = other.m_cluster_map.begin ();
2611 : 149165 : iter != other.m_cluster_map.end ();
2612 : 131271 : ++iter)
2613 : : {
2614 : 131271 : const region *reg = (*iter).first;
2615 : 131271 : gcc_assert (reg);
2616 : 131271 : binding_cluster *c = (*iter).second;
2617 : 131271 : gcc_assert (c);
2618 : 131271 : m_cluster_map.put (reg, new binding_cluster (*c));
2619 : : }
2620 : 17894 : return *this;
2621 : : }
2622 : :
2623 : : /* store's equality operator. */
2624 : :
2625 : : bool
2626 : 464181 : store::operator== (const store &other) const
2627 : : {
2628 : 464181 : if (m_called_unknown_fn != other.m_called_unknown_fn)
2629 : : return false;
2630 : :
2631 : 460026 : if (m_cluster_map.elements () != other.m_cluster_map.elements ())
2632 : : return false;
2633 : :
2634 : 2423015 : for (cluster_map_t::iterator iter = m_cluster_map.begin ();
2635 : 2423015 : iter != m_cluster_map.end ();
2636 : 1986099 : ++iter)
2637 : : {
2638 : 2020738 : const region *reg = (*iter).first;
2639 : 2020738 : binding_cluster *c = (*iter).second;
2640 : 2020738 : binding_cluster **other_slot
2641 : 2020738 : = const_cast <cluster_map_t &> (other.m_cluster_map).get (reg);
2642 : 2020738 : if (other_slot == nullptr)
2643 : 34639 : return false;
2644 : 2019515 : if (*c != **other_slot)
2645 : : return false;
2646 : : }
2647 : :
2648 : 402277 : gcc_checking_assert (hash () == other.hash ());
2649 : :
2650 : : return true;
2651 : : }
2652 : :
2653 : : /* Get a hash value for this store. */
2654 : :
2655 : : hashval_t
2656 : 2058756 : store::hash () const
2657 : : {
2658 : 2058756 : hashval_t result = 0;
2659 : 2058756 : for (cluster_map_t::iterator iter = m_cluster_map.begin ();
2660 : 12183980 : iter != m_cluster_map.end ();
2661 : 10125224 : ++iter)
2662 : 10125224 : result ^= (*iter).second->hash ();
2663 : 2058756 : return result;
2664 : : }
2665 : :
2666 : : /* Populate OUT with a sorted list of parent regions for the regions in IN,
2667 : : removing duplicate parents. */
2668 : :
2669 : : static void
2670 : 2016 : get_sorted_parent_regions (auto_vec<const region *> *out,
2671 : : auto_vec<const region *> &in)
2672 : : {
2673 : : /* Get the set of parent regions. */
2674 : 2016 : hash_set<const region *> parent_regions;
2675 : 2016 : const region *iter_reg;
2676 : 2016 : unsigned i;
2677 : 9998 : FOR_EACH_VEC_ELT (in, i, iter_reg)
2678 : : {
2679 : 7982 : const region *parent_reg = iter_reg->get_parent_region ();
2680 : 7982 : gcc_assert (parent_reg);
2681 : 7982 : parent_regions.add (parent_reg);
2682 : : }
2683 : :
2684 : : /* Write to OUT. */
2685 : 2016 : for (hash_set<const region *>::iterator iter = parent_regions.begin();
2686 : 10384 : iter != parent_regions.end(); ++iter)
2687 : 4184 : out->safe_push (*iter);
2688 : :
2689 : : /* Sort OUT. */
2690 : 3854 : out->qsort (region::cmp_ptr_ptr);
2691 : 2016 : }
2692 : :
2693 : : /* Dump a representation of this store to PP, using SIMPLE to control how
2694 : : svalues and regions are printed.
2695 : : MGR is used for simplifying dumps if non-NULL, but can also be nullptr
2696 : : (to make it easier to use from the debugger). */
2697 : :
2698 : : void
2699 : 2008 : store::dump_to_pp (pretty_printer *pp, bool simple, bool multiline,
2700 : : store_manager *mgr) const
2701 : : {
2702 : : /* Sort into some deterministic order. */
2703 : 2008 : auto_vec<const region *> base_regions;
2704 : 9990 : for (cluster_map_t::iterator iter = m_cluster_map.begin ();
2705 : 17972 : iter != m_cluster_map.end (); ++iter)
2706 : : {
2707 : 7982 : const region *base_reg = (*iter).first;
2708 : 7982 : base_regions.safe_push (base_reg);
2709 : : }
2710 : 2008 : base_regions.qsort (region::cmp_ptr_ptr);
2711 : :
2712 : : /* Gather clusters, organize by parent region, so that we can group
2713 : : together locals, globals, etc. */
2714 : 2008 : auto_vec<const region *> parent_regions;
2715 : 2008 : get_sorted_parent_regions (&parent_regions, base_regions);
2716 : :
2717 : 2008 : const region *parent_reg;
2718 : 2008 : unsigned i;
2719 : 6192 : FOR_EACH_VEC_ELT (parent_regions, i, parent_reg)
2720 : : {
2721 : 4184 : gcc_assert (parent_reg);
2722 : 4184 : pp_string (pp, "clusters within ");
2723 : 4184 : parent_reg->dump_to_pp (pp, simple);
2724 : 4184 : if (multiline)
2725 : 1697 : pp_newline (pp);
2726 : : else
2727 : 2487 : pp_string (pp, " {");
2728 : :
2729 : : const region *base_reg;
2730 : : unsigned j;
2731 : 23959 : FOR_EACH_VEC_ELT (base_regions, j, base_reg)
2732 : : {
2733 : : /* This is O(N * M), but N ought to be small. */
2734 : 19775 : if (base_reg->get_parent_region () != parent_reg)
2735 : 11793 : continue;
2736 : 7982 : binding_cluster *cluster
2737 : 7982 : = *const_cast<cluster_map_t &> (m_cluster_map).get (base_reg);
2738 : 7982 : if (!multiline)
2739 : : {
2740 : 4151 : if (j > 0)
2741 : 3152 : pp_string (pp, ", ");
2742 : : }
2743 : 7982 : if (const svalue *sval = cluster->maybe_get_simple_value (mgr))
2744 : : {
2745 : : /* Special-case to simplify dumps for the common case where
2746 : : we just have one value directly bound to the whole of a
2747 : : region. */
2748 : 5725 : if (multiline)
2749 : : {
2750 : 2323 : pp_string (pp, " cluster for: ");
2751 : 2323 : base_reg->dump_to_pp (pp, simple);
2752 : 2323 : pp_string (pp, ": ");
2753 : 2323 : sval->dump_to_pp (pp, simple);
2754 : 2323 : if (cluster->escaped_p ())
2755 : 144 : pp_string (pp, " (ESCAPED)");
2756 : 2323 : if (cluster->touched_p ())
2757 : 6 : pp_string (pp, " (TOUCHED)");
2758 : 2323 : pp_newline (pp);
2759 : : }
2760 : : else
2761 : : {
2762 : 3402 : pp_string (pp, "region: {");
2763 : 3402 : base_reg->dump_to_pp (pp, simple);
2764 : 3402 : pp_string (pp, ", value: ");
2765 : 3402 : sval->dump_to_pp (pp, simple);
2766 : 3402 : if (cluster->escaped_p ())
2767 : 813 : pp_string (pp, " (ESCAPED)");
2768 : 3402 : if (cluster->touched_p ())
2769 : 813 : pp_string (pp, " (TOUCHED)");
2770 : 3402 : pp_string (pp, "}");
2771 : : }
2772 : : }
2773 : 2257 : else if (multiline)
2774 : : {
2775 : 1508 : pp_string (pp, " cluster for: ");
2776 : 1508 : base_reg->dump_to_pp (pp, simple);
2777 : 1508 : pp_newline (pp);
2778 : 1508 : cluster->dump_to_pp (pp, simple, multiline);
2779 : : }
2780 : : else
2781 : : {
2782 : 749 : pp_string (pp, "base region: {");
2783 : 749 : base_reg->dump_to_pp (pp, simple);
2784 : 749 : pp_string (pp, "} has cluster: {");
2785 : 749 : cluster->dump_to_pp (pp, simple, multiline);
2786 : 749 : pp_string (pp, "}");
2787 : : }
2788 : : }
2789 : 4184 : if (!multiline)
2790 : 2487 : pp_string (pp, "}");
2791 : : }
2792 : 2008 : pp_printf (pp, "m_called_unknown_fn: %s",
2793 : 2008 : m_called_unknown_fn ? "TRUE" : "FALSE");
2794 : 2008 : if (multiline)
2795 : 912 : pp_newline (pp);
2796 : 2008 : }
2797 : :
2798 : : /* Dump a multiline representation of this store to stderr. */
2799 : :
2800 : : DEBUG_FUNCTION void
2801 : 0 : store::dump (bool simple) const
2802 : : {
2803 : 0 : tree_dump_pretty_printer pp (stderr);
2804 : 0 : dump_to_pp (&pp, simple, true, nullptr);
2805 : 0 : pp_newline (&pp);
2806 : 0 : }
2807 : :
2808 : : /* Assert that this object is valid. */
2809 : :
2810 : : void
2811 : 1763782 : store::validate () const
2812 : : {
2813 : 10860943 : for (auto iter : m_cluster_map)
2814 : 9097161 : iter.second->validate ();
2815 : 1763782 : }
2816 : :
2817 : : /* Return a new json::object of the form
2818 : : {PARENT_REGION_DESC: {BASE_REGION_DESC: object for binding_map,
2819 : : ... for each cluster within parent region},
2820 : : ...for each parent region,
2821 : : "called_unknown_fn": true/false}. */
2822 : :
2823 : : std::unique_ptr<json::object>
2824 : 4 : store::to_json () const
2825 : : {
2826 : 4 : auto store_obj = std::make_unique<json::object> ();
2827 : :
2828 : : /* Sort into some deterministic order. */
2829 : 4 : auto_vec<const region *> base_regions;
2830 : 4 : for (cluster_map_t::iterator iter = m_cluster_map.begin ();
2831 : 4 : iter != m_cluster_map.end (); ++iter)
2832 : : {
2833 : 0 : const region *base_reg = (*iter).first;
2834 : 0 : base_regions.safe_push (base_reg);
2835 : : }
2836 : 4 : base_regions.qsort (region::cmp_ptr_ptr);
2837 : :
2838 : : /* Gather clusters, organize by parent region, so that we can group
2839 : : together locals, globals, etc. */
2840 : 4 : auto_vec<const region *> parent_regions;
2841 : 4 : get_sorted_parent_regions (&parent_regions, base_regions);
2842 : :
2843 : 4 : const region *parent_reg;
2844 : 4 : unsigned i;
2845 : 4 : FOR_EACH_VEC_ELT (parent_regions, i, parent_reg)
2846 : : {
2847 : 0 : gcc_assert (parent_reg);
2848 : :
2849 : 0 : auto clusters_in_parent_reg_obj = std::make_unique<json::object> ();
2850 : :
2851 : 0 : const region *base_reg;
2852 : 0 : unsigned j;
2853 : 0 : FOR_EACH_VEC_ELT (base_regions, j, base_reg)
2854 : : {
2855 : : /* This is O(N * M), but N ought to be small. */
2856 : 0 : if (base_reg->get_parent_region () != parent_reg)
2857 : 0 : continue;
2858 : 0 : binding_cluster *cluster
2859 : 0 : = *const_cast<cluster_map_t &> (m_cluster_map).get (base_reg);
2860 : 0 : label_text base_reg_desc = base_reg->get_desc ();
2861 : 0 : clusters_in_parent_reg_obj->set (base_reg_desc.get (),
2862 : 0 : cluster->to_json ());
2863 : 0 : }
2864 : 0 : label_text parent_reg_desc = parent_reg->get_desc ();
2865 : 0 : store_obj->set (parent_reg_desc.get (),
2866 : : std::move (clusters_in_parent_reg_obj));
2867 : 0 : }
2868 : :
2869 : 4 : store_obj->set_bool ("called_unknown_fn", m_called_unknown_fn);
2870 : :
2871 : 4 : return store_obj;
2872 : 4 : }
2873 : :
2874 : : std::unique_ptr<text_art::tree_widget>
2875 : 4 : store::make_dump_widget (const text_art::dump_widget_info &dwi,
2876 : : store_manager *mgr) const
2877 : : {
2878 : 4 : std::unique_ptr<text_art::tree_widget> store_widget
2879 : 4 : (text_art::tree_widget::make (dwi, "Store"));
2880 : :
2881 : 4 : store_widget->add_child
2882 : 8 : (text_art::tree_widget::from_fmt (dwi, nullptr,
2883 : : "m_called_unknown_fn: %s",
2884 : 4 : m_called_unknown_fn ? "true" : "false"));
2885 : :
2886 : : /* Sort into some deterministic order. */
2887 : 4 : auto_vec<const region *> base_regions;
2888 : 4 : for (cluster_map_t::iterator iter = m_cluster_map.begin ();
2889 : 4 : iter != m_cluster_map.end (); ++iter)
2890 : : {
2891 : 0 : const region *base_reg = (*iter).first;
2892 : 0 : base_regions.safe_push (base_reg);
2893 : : }
2894 : 4 : base_regions.qsort (region::cmp_ptr_ptr);
2895 : :
2896 : : /* Gather clusters, organize by parent region, so that we can group
2897 : : together locals, globals, etc. */
2898 : 4 : auto_vec<const region *> parent_regions;
2899 : 4 : get_sorted_parent_regions (&parent_regions, base_regions);
2900 : :
2901 : 4 : const region *parent_reg;
2902 : 4 : unsigned i;
2903 : 4 : FOR_EACH_VEC_ELT (parent_regions, i, parent_reg)
2904 : : {
2905 : 0 : gcc_assert (parent_reg);
2906 : :
2907 : 0 : pretty_printer the_pp;
2908 : 0 : pretty_printer * const pp = &the_pp;
2909 : 0 : pp_format_decoder (pp) = default_tree_printer;
2910 : 0 : pp_show_color (pp) = true;
2911 : 0 : const bool simple = true;
2912 : :
2913 : 0 : parent_reg->dump_to_pp (pp, simple);
2914 : :
2915 : 0 : std::unique_ptr<text_art::tree_widget> parent_reg_widget
2916 : 0 : (text_art::tree_widget::make (dwi, pp));
2917 : :
2918 : 0 : const region *base_reg;
2919 : 0 : unsigned j;
2920 : 0 : FOR_EACH_VEC_ELT (base_regions, j, base_reg)
2921 : : {
2922 : : /* This is O(N * M), but N ought to be small. */
2923 : 0 : if (base_reg->get_parent_region () != parent_reg)
2924 : 0 : continue;
2925 : 0 : binding_cluster *cluster
2926 : 0 : = *const_cast<cluster_map_t &> (m_cluster_map).get (base_reg);
2927 : 0 : parent_reg_widget->add_child
2928 : 0 : (cluster->make_dump_widget (dwi, mgr));
2929 : : }
2930 : 0 : store_widget->add_child (std::move (parent_reg_widget));
2931 : 0 : }
2932 : :
2933 : 4 : return store_widget;
2934 : 4 : }
2935 : :
2936 : : /* Get any svalue bound to REG, or nullptr. */
2937 : :
2938 : : const svalue *
2939 : 3771852 : store::get_any_binding (store_manager *mgr, const region *reg) const
2940 : : {
2941 : 3771852 : const region *base_reg = reg->get_base_region ();
2942 : 3771852 : binding_cluster **cluster_slot
2943 : 3771852 : = const_cast <cluster_map_t &> (m_cluster_map).get (base_reg);
2944 : 3771852 : if (!cluster_slot)
2945 : : return nullptr;
2946 : 1231000 : return (*cluster_slot)->get_any_binding (mgr, reg);
2947 : : }
2948 : :
2949 : : /* Set the value of LHS_REG to RHS_SVAL. */
2950 : :
2951 : : void
2952 : 337250 : store::set_value (store_manager *mgr, const region *lhs_reg,
2953 : : const svalue *rhs_sval,
2954 : : uncertainty_t *uncertainty)
2955 : : {
2956 : 337250 : logger *logger = mgr->get_logger ();
2957 : 337250 : LOG_SCOPE (logger);
2958 : :
2959 : 337250 : remove_overlapping_bindings (mgr, lhs_reg, uncertainty);
2960 : :
2961 : 337250 : if (lhs_reg->get_type ())
2962 : 324787 : rhs_sval = simplify_for_binding (rhs_sval);
2963 : : /* ...but if we have no type for the region, retain any cast. */
2964 : :
2965 : 337250 : const region *lhs_base_reg = lhs_reg->get_base_region ();
2966 : 337250 : binding_cluster *lhs_cluster;
2967 : 337250 : if (lhs_base_reg->symbolic_for_unknown_ptr_p ())
2968 : : {
2969 : : /* Reject attempting to bind values into a symbolic region
2970 : : for an unknown ptr; merely invalidate values below. */
2971 : 3230 : lhs_cluster = nullptr;
2972 : :
2973 : : /* The LHS of the write is *UNKNOWN. If the RHS is a pointer,
2974 : : then treat the region being pointed to as having escaped. */
2975 : 3230 : if (const region_svalue *ptr_sval = rhs_sval->dyn_cast_region_svalue ())
2976 : : {
2977 : 161 : const region *ptr_dst = ptr_sval->get_pointee ();
2978 : 161 : const region *ptr_base_reg = ptr_dst->get_base_region ();
2979 : 161 : mark_as_escaped (*mgr, ptr_base_reg);
2980 : : }
2981 : 3230 : if (uncertainty)
2982 : 1568 : uncertainty->on_maybe_bound_sval (rhs_sval);
2983 : : }
2984 : 334020 : else if (lhs_base_reg->tracked_p ())
2985 : : {
2986 : 333913 : lhs_cluster = get_or_create_cluster (*mgr, lhs_base_reg);
2987 : 333913 : lhs_cluster->bind (mgr, lhs_reg, rhs_sval);
2988 : : }
2989 : : else
2990 : : {
2991 : : /* Reject attempting to bind values into an untracked region;
2992 : : merely invalidate values below. */
2993 : : lhs_cluster = nullptr;
2994 : : }
2995 : :
2996 : : /* Bindings to a cluster can affect other clusters if a symbolic
2997 : : base region is involved.
2998 : : Writes to concrete clusters can't affect other concrete clusters,
2999 : : but can affect symbolic clusters.
3000 : : Writes to symbolic clusters can affect both concrete and symbolic
3001 : : clusters.
3002 : : Invalidate our knowledge of other clusters that might have been
3003 : : affected by the write.
3004 : : Gather the set of all svalues that might still be live even if
3005 : : the store doesn't refer to them. */
3006 : 337250 : svalue_set maybe_live_values;
3007 : 4440452 : for (cluster_map_t::iterator iter = m_cluster_map.begin ();
3008 : 8543654 : iter != m_cluster_map.end (); ++iter)
3009 : : {
3010 : 4103202 : const region *iter_base_reg = (*iter).first;
3011 : 4103202 : binding_cluster *iter_cluster = (*iter).second;
3012 : 4103202 : if (iter_base_reg != lhs_base_reg
3013 : 4103202 : && (lhs_cluster == nullptr
3014 : 3717315 : || lhs_cluster->symbolic_p ()
3015 : 3642732 : || iter_cluster->symbolic_p ()))
3016 : : {
3017 : 552809 : tristate t_alias = eval_alias (lhs_base_reg, iter_base_reg);
3018 : 552809 : switch (t_alias.get_value ())
3019 : : {
3020 : 0 : default:
3021 : 0 : gcc_unreachable ();
3022 : :
3023 : 56195 : case tristate::TS_UNKNOWN:
3024 : 56195 : if (logger)
3025 : : {
3026 : 7 : pretty_printer *pp = logger->get_printer ();
3027 : 7 : logger->start_log_line ();
3028 : 7 : logger->log_partial ("possible aliasing of ");
3029 : 7 : iter_base_reg->dump_to_pp (pp, true);
3030 : 7 : logger->log_partial (" when writing SVAL: ");
3031 : 7 : rhs_sval->dump_to_pp (pp, true);
3032 : 7 : logger->log_partial (" to LHS_REG: ");
3033 : 7 : lhs_reg->dump_to_pp (pp, true);
3034 : 7 : logger->end_log_line ();
3035 : : }
3036 : : /* Mark all of iter_cluster's iter_base_reg as unknown,
3037 : : using LHS_REG when considering overlaps, to handle
3038 : : symbolic vs concrete issues. */
3039 : 56195 : iter_cluster->mark_region_as_unknown
3040 : 56195 : (mgr,
3041 : : iter_base_reg, /* reg_to_bind */
3042 : : lhs_reg, /* reg_for_overlap */
3043 : : uncertainty,
3044 : : &maybe_live_values);
3045 : 56195 : break;
3046 : :
3047 : 0 : case tristate::TS_TRUE:
3048 : 0 : gcc_unreachable ();
3049 : : break;
3050 : :
3051 : : case tristate::TS_FALSE:
3052 : : /* If they can't be aliases, then don't invalidate this
3053 : : cluster. */
3054 : : break;
3055 : : }
3056 : : }
3057 : : }
3058 : : /* Given the set of svalues that might still be live, process them
3059 : : (e.g. marking regions as escaped).
3060 : : We do this after the iteration to avoid potentially changing
3061 : : m_cluster_map whilst iterating over it. */
3062 : 337250 : on_maybe_live_values (*mgr, maybe_live_values);
3063 : 337250 : }
3064 : :
3065 : : /* Determine if BASE_REG_A could be an alias of BASE_REG_B. */
3066 : :
3067 : : tristate
3068 : 553370 : store::eval_alias (const region *base_reg_a,
3069 : : const region *base_reg_b) const
3070 : : {
3071 : : /* SSA names can't alias. */
3072 : 553370 : tree decl_a = base_reg_a->maybe_get_decl ();
3073 : 553370 : if (decl_a && TREE_CODE (decl_a) == SSA_NAME)
3074 : 369114 : return tristate::TS_FALSE;
3075 : 184256 : tree decl_b = base_reg_b->maybe_get_decl ();
3076 : 184256 : if (decl_b && TREE_CODE (decl_b) == SSA_NAME)
3077 : 60966 : return tristate::TS_FALSE;
3078 : :
3079 : : /* Try both ways, for symmetry. */
3080 : 123290 : tristate ts_ab = eval_alias_1 (base_reg_a, base_reg_b);
3081 : 123290 : if (ts_ab.is_false ())
3082 : 22307 : return tristate::TS_FALSE;
3083 : 100983 : tristate ts_ba = eval_alias_1 (base_reg_b, base_reg_a);
3084 : 100983 : if (ts_ba.is_false ())
3085 : 44522 : return tristate::TS_FALSE;
3086 : 56461 : return tristate::TS_UNKNOWN;
3087 : : }
3088 : :
3089 : : /* Half of store::eval_alias; called twice for symmetry. */
3090 : :
3091 : : tristate
3092 : 224273 : store::eval_alias_1 (const region *base_reg_a,
3093 : : const region *base_reg_b) const
3094 : : {
3095 : : /* If they're in different memory spaces, they can't alias. */
3096 : 224273 : {
3097 : 224273 : enum memory_space memspace_a = base_reg_a->get_memory_space ();
3098 : 224273 : if (memspace_a != MEMSPACE_UNKNOWN)
3099 : : {
3100 : 77197 : enum memory_space memspace_b = base_reg_b->get_memory_space ();
3101 : 77197 : if (memspace_b != MEMSPACE_UNKNOWN
3102 : 77197 : && memspace_a != memspace_b)
3103 : 249 : return tristate::TS_FALSE;
3104 : : }
3105 : : }
3106 : :
3107 : 448048 : if (const symbolic_region *sym_reg_a
3108 : 224024 : = base_reg_a->dyn_cast_symbolic_region ())
3109 : : {
3110 : 141699 : const svalue *sval_a = sym_reg_a->get_pointer ();
3111 : 141699 : if (tree decl_b = base_reg_b->maybe_get_decl ())
3112 : : {
3113 : 72298 : if (!may_be_aliased (decl_b))
3114 : 42078 : return tristate::TS_FALSE;
3115 : 30220 : if (sval_a->get_kind () == SK_INITIAL)
3116 : 18788 : if (!is_global_var (decl_b))
3117 : : {
3118 : : /* The initial value of a pointer can't point to a local. */
3119 : 13085 : return tristate::TS_FALSE;
3120 : : }
3121 : : }
3122 : 86536 : if (sval_a->get_kind () == SK_INITIAL
3123 : 86536 : && base_reg_b->get_kind () == RK_HEAP_ALLOCATED)
3124 : : {
3125 : : /* The initial value of a pointer can't point to a
3126 : : region that was allocated on the heap after the beginning of the
3127 : : path. */
3128 : 11122 : return tristate::TS_FALSE;
3129 : : }
3130 : 150828 : if (const widening_svalue *widening_sval_a
3131 : 75414 : = sval_a->dyn_cast_widening_svalue ())
3132 : : {
3133 : 3645 : const svalue *base = widening_sval_a->get_base_svalue ();
3134 : 7290 : if (const region_svalue *region_sval
3135 : 3645 : = base->dyn_cast_region_svalue ())
3136 : : {
3137 : 561 : const region *pointee = region_sval->get_pointee ();
3138 : : /* If we have sval_a is WIDENING(®ION, OP), and
3139 : : B can't alias REGION, then B can't alias A either.
3140 : : For example, A might arise from
3141 : : for (ptr = ®ION; ...; ptr++)
3142 : : where sval_a is ptr in the 2nd iteration of the loop.
3143 : : We want to ensure that "*ptr" can only clobber things
3144 : : within REGION's base region. */
3145 : 561 : tristate ts = eval_alias (pointee->get_base_region (),
3146 : : base_reg_b);
3147 : 561 : if (ts.is_false ())
3148 : 295 : return tristate::TS_FALSE;
3149 : : }
3150 : : }
3151 : : }
3152 : 157444 : return tristate::TS_UNKNOWN;
3153 : : }
3154 : :
3155 : : /* Record all of the values in MAYBE_LIVE_VALUES as being possibly live. */
3156 : :
3157 : : void
3158 : 337539 : store::on_maybe_live_values (store_manager &mgr,
3159 : : const svalue_set &maybe_live_values)
3160 : : {
3161 : 414041 : for (auto sval : maybe_live_values)
3162 : : {
3163 : 38251 : if (const region_svalue *ptr_sval = sval->dyn_cast_region_svalue ())
3164 : : {
3165 : 315 : const region *base_reg = ptr_sval->get_pointee ()->get_base_region ();
3166 : 315 : mark_as_escaped (mgr, base_reg);
3167 : : }
3168 : : }
3169 : 337539 : }
3170 : :
3171 : : /* Remove all bindings overlapping REG within this store. */
3172 : :
3173 : : void
3174 : 7011 : store::clobber_region (store_manager *mgr, const region *reg)
3175 : : {
3176 : 7011 : const region *base_reg = reg->get_base_region ();
3177 : 7011 : binding_cluster **slot = m_cluster_map.get (base_reg);
3178 : 7011 : if (!slot)
3179 : 2490 : return;
3180 : 4521 : binding_cluster *cluster = *slot;
3181 : 4521 : cluster->clobber_region (mgr, reg);
3182 : 4521 : if (cluster->redundant_p ())
3183 : : {
3184 : 2991 : delete cluster;
3185 : 2991 : m_cluster_map.remove (base_reg);
3186 : : }
3187 : : }
3188 : :
3189 : : /* Remove any bindings for REG within this store. */
3190 : :
3191 : : void
3192 : 177667 : store::purge_region (store_manager *mgr, const region *reg)
3193 : : {
3194 : 177667 : const region *base_reg = reg->get_base_region ();
3195 : 177667 : binding_cluster **slot = m_cluster_map.get (base_reg);
3196 : 177667 : if (!slot)
3197 : 0 : return;
3198 : 177667 : binding_cluster *cluster = *slot;
3199 : 177667 : cluster->purge_region (mgr, reg);
3200 : 177667 : if (cluster->redundant_p ())
3201 : : {
3202 : 172269 : delete cluster;
3203 : 172269 : m_cluster_map.remove (base_reg);
3204 : : }
3205 : : }
3206 : :
3207 : : /* Fill REG with SVAL. */
3208 : :
3209 : : void
3210 : 1426 : store::fill_region (store_manager *mgr, const region *reg, const svalue *sval)
3211 : : {
3212 : : /* Filling an empty region is a no-op. */
3213 : 1426 : if (reg->empty_p ())
3214 : : return;
3215 : :
3216 : 1398 : const region *base_reg = reg->get_base_region ();
3217 : 1398 : if (base_reg->symbolic_for_unknown_ptr_p ()
3218 : 1398 : || !base_reg->tracked_p ())
3219 : 6 : return;
3220 : 1392 : binding_cluster *cluster = get_or_create_cluster (*mgr, base_reg);
3221 : 1392 : cluster->fill_region (mgr, reg, sval);
3222 : : }
3223 : :
3224 : : /* Zero-fill REG. */
3225 : :
3226 : : void
3227 : 769 : store::zero_fill_region (store_manager *mgr, const region *reg)
3228 : : {
3229 : 769 : region_model_manager *sval_mgr = mgr->get_svalue_manager ();
3230 : 769 : const svalue *zero_sval = sval_mgr->get_or_create_int_cst (char_type_node, 0);
3231 : 769 : fill_region (mgr, reg, zero_sval);
3232 : 769 : }
3233 : :
3234 : : /* Mark REG as having unknown content. */
3235 : :
3236 : : void
3237 : 289 : store::mark_region_as_unknown (store_manager *mgr, const region *reg,
3238 : : uncertainty_t *uncertainty,
3239 : : svalue_set *maybe_live_values)
3240 : : {
3241 : 289 : const region *base_reg = reg->get_base_region ();
3242 : 289 : if (base_reg->symbolic_for_unknown_ptr_p ()
3243 : 289 : || !base_reg->tracked_p ())
3244 : 0 : return;
3245 : 289 : binding_cluster *cluster = get_or_create_cluster (*mgr, base_reg);
3246 : 289 : cluster->mark_region_as_unknown (mgr, reg, reg, uncertainty,
3247 : : maybe_live_values);
3248 : : }
3249 : :
3250 : : /* Purge state involving SVAL. */
3251 : :
3252 : : void
3253 : 38620 : store::purge_state_involving (const svalue *sval,
3254 : : region_model_manager *sval_mgr)
3255 : : {
3256 : 38620 : auto_vec <const region *> base_regs_to_purge;
3257 : 1207020 : for (auto iter : m_cluster_map)
3258 : : {
3259 : 584200 : const region *base_reg = iter.first;
3260 : 584200 : if (base_reg->involves_p (sval))
3261 : 189 : base_regs_to_purge.safe_push (base_reg);
3262 : : else
3263 : : {
3264 : 584011 : binding_cluster *cluster = iter.second;
3265 : 584011 : cluster->purge_state_involving (sval, sval_mgr);
3266 : : }
3267 : : }
3268 : :
3269 : 39187 : for (auto iter : base_regs_to_purge)
3270 : 189 : purge_cluster (iter);
3271 : 38620 : }
3272 : :
3273 : : /* Get the cluster for BASE_REG, or nullptr (const version). */
3274 : :
3275 : : const binding_cluster *
3276 : 2479251 : store::get_cluster (const region *base_reg) const
3277 : : {
3278 : 2479251 : gcc_assert (base_reg);
3279 : 2479251 : gcc_assert (base_reg->get_base_region () == base_reg);
3280 : 4958502 : if (binding_cluster **slot
3281 : 2479251 : = const_cast <cluster_map_t &> (m_cluster_map).get (base_reg))
3282 : 2354922 : return *slot;
3283 : : else
3284 : : return nullptr;
3285 : : }
3286 : :
3287 : : /* Get the cluster for BASE_REG, or nullptr (non-const version). */
3288 : :
3289 : : binding_cluster *
3290 : 9175289 : store::get_cluster (const region *base_reg)
3291 : : {
3292 : 9175289 : gcc_assert (base_reg);
3293 : 9175289 : gcc_assert (base_reg->get_base_region () == base_reg);
3294 : 9175289 : if (binding_cluster **slot = m_cluster_map.get (base_reg))
3295 : 7762171 : return *slot;
3296 : : else
3297 : : return nullptr;
3298 : : }
3299 : :
3300 : : /* Get the cluster for BASE_REG, creating it if doesn't already exist. */
3301 : :
3302 : : binding_cluster *
3303 : 1542557 : store::get_or_create_cluster (store_manager &store_mgr,
3304 : : const region *base_reg)
3305 : : {
3306 : 1542557 : gcc_assert (base_reg);
3307 : 1542557 : gcc_assert (base_reg->get_base_region () == base_reg);
3308 : :
3309 : : /* We shouldn't create clusters for dereferencing an UNKNOWN ptr. */
3310 : 1542557 : gcc_assert (!base_reg->symbolic_for_unknown_ptr_p ());
3311 : :
3312 : : /* We shouldn't create clusters for base regions that aren't trackable. */
3313 : 1542557 : gcc_assert (base_reg->tracked_p ());
3314 : :
3315 : 1542557 : if (binding_cluster **slot = m_cluster_map.get (base_reg))
3316 : 55574 : return *slot;
3317 : :
3318 : 1486983 : binding_cluster *cluster = new binding_cluster (store_mgr, base_reg);
3319 : 1486983 : m_cluster_map.put (base_reg, cluster);
3320 : :
3321 : 1486983 : return cluster;
3322 : : }
3323 : :
3324 : : /* Remove any cluster for BASE_REG, for use by
3325 : : region_model::unbind_region_and_descendents
3326 : : when popping stack frames and handling deleted heap regions. */
3327 : :
3328 : : void
3329 : 36077 : store::purge_cluster (const region *base_reg)
3330 : : {
3331 : 36077 : gcc_assert (base_reg->get_base_region () == base_reg);
3332 : 36077 : binding_cluster **slot = m_cluster_map.get (base_reg);
3333 : 36077 : if (!slot)
3334 : : return;
3335 : 36077 : binding_cluster *cluster = *slot;
3336 : 72154 : delete cluster;
3337 : 36077 : m_cluster_map.remove (base_reg);
3338 : : }
3339 : :
3340 : : /* Attempt to merge STORE_A and STORE_B into OUT_STORE.
3341 : : Return true if successful, or false if the stores can't be merged. */
3342 : :
3343 : : bool
3344 : 172300 : store::can_merge_p (const store *store_a, const store *store_b,
3345 : : store *out_store, store_manager *mgr,
3346 : : model_merger *merger)
3347 : : {
3348 : 172300 : if (store_a->m_called_unknown_fn || store_b->m_called_unknown_fn)
3349 : 82742 : out_store->m_called_unknown_fn = true;
3350 : :
3351 : : /* Get the union of all base regions for STORE_A and STORE_B. */
3352 : 172300 : hash_set<const region *> base_regions;
3353 : 1771282 : for (cluster_map_t::iterator iter_a = store_a->m_cluster_map.begin ();
3354 : 3370264 : iter_a != store_a->m_cluster_map.end (); ++iter_a)
3355 : : {
3356 : 1598982 : const region *base_reg_a = (*iter_a).first;
3357 : 1598982 : base_regions.add (base_reg_a);
3358 : : }
3359 : 1702093 : for (cluster_map_t::iterator iter_b = store_b->m_cluster_map.begin ();
3360 : 3231886 : iter_b != store_b->m_cluster_map.end (); ++iter_b)
3361 : : {
3362 : 1529793 : const region *base_reg_b = (*iter_b).first;
3363 : 1529793 : base_regions.add (base_reg_b);
3364 : : }
3365 : :
3366 : : /* Sort the base regions before considering them. This ought not to
3367 : : affect the results, but can affect which types UNKNOWN_REGIONs are
3368 : : created for in a run; sorting them thus avoids minor differences
3369 : : in logfiles. */
3370 : 172300 : auto_vec<const region *> vec_base_regions (base_regions.elements ());
3371 : 172300 : for (hash_set<const region *>::iterator iter = base_regions.begin ();
3372 : 3454240 : iter != base_regions.end (); ++iter)
3373 : 1640970 : vec_base_regions.quick_push (*iter);
3374 : 172300 : vec_base_regions.qsort (region::cmp_ptr_ptr);
3375 : : unsigned i;
3376 : : const region *base_reg;
3377 : 1398040 : FOR_EACH_VEC_ELT (vec_base_regions, i, base_reg)
3378 : : {
3379 : 1157634 : const binding_cluster *cluster_a = store_a->get_cluster (base_reg);
3380 : 1157634 : const binding_cluster *cluster_b = store_b->get_cluster (base_reg);
3381 : : /* At least one of cluster_a and cluster_b must be non-NULL. */
3382 : 1157634 : binding_cluster *out_cluster
3383 : 1157634 : = out_store->get_or_create_cluster (*mgr, base_reg);
3384 : 1157634 : if (!binding_cluster::can_merge_p (cluster_a, cluster_b,
3385 : : out_cluster, out_store, mgr, merger))
3386 : : return false;
3387 : : }
3388 : : return true;
3389 : 172300 : }
3390 : :
3391 : : /* Mark the cluster for BASE_REG as having escaped.
3392 : : For use when handling an unrecognized function call, and
3393 : : for params to "top-level" calls.
3394 : : Further unknown function calls could touch it, even if the cluster
3395 : : isn't reachable from args of those calls. */
3396 : :
3397 : : void
3398 : 43133 : store::mark_as_escaped (store_manager &mgr, const region *base_reg)
3399 : : {
3400 : 43133 : gcc_assert (base_reg);
3401 : 43133 : gcc_assert (base_reg->get_base_region () == base_reg);
3402 : :
3403 : 43133 : if (base_reg->symbolic_for_unknown_ptr_p ()
3404 : 43133 : || !base_reg->tracked_p ())
3405 : 5118 : return;
3406 : :
3407 : 38015 : binding_cluster *cluster = get_or_create_cluster (mgr, base_reg);
3408 : 38015 : cluster->mark_as_escaped ();
3409 : : }
3410 : :
3411 : : /* Handle an unknown fncall by updating any clusters that have escaped
3412 : : (either in this fncall, or in a prior one). */
3413 : :
3414 : : void
3415 : 19273 : store::on_unknown_fncall (const gcall &call, store_manager *mgr,
3416 : : const conjured_purge &p)
3417 : : {
3418 : 19273 : m_called_unknown_fn = true;
3419 : :
3420 : 177295 : for (cluster_map_t::iterator iter = m_cluster_map.begin ();
3421 : 335317 : iter != m_cluster_map.end (); ++iter)
3422 : 158022 : (*iter).second->on_unknown_fncall (call, mgr, p);
3423 : 19273 : }
3424 : :
3425 : : /* Return true if a non-const pointer to BASE_REG (or something within it)
3426 : : has escaped to code outside of the TU being analyzed. */
3427 : :
3428 : : bool
3429 : 7853965 : store::escaped_p (const region *base_reg) const
3430 : : {
3431 : 7853965 : gcc_assert (base_reg);
3432 : 7853965 : gcc_assert (base_reg->get_base_region () == base_reg);
3433 : :
3434 : : /* "errno" can always be modified by external code. */
3435 : 7853965 : if (base_reg->get_kind () == RK_ERRNO)
3436 : : return true;
3437 : :
3438 : 15509064 : if (binding_cluster **cluster_slot
3439 : 7754532 : = const_cast <cluster_map_t &>(m_cluster_map).get (base_reg))
3440 : 7754532 : return (*cluster_slot)->escaped_p ();
3441 : : return false;
3442 : : }
3443 : :
3444 : : /* Populate OUT_PVS with a list of path_vars for describing SVAL based on
3445 : : this store, using VISITED to ensure the traversal terminates. */
3446 : :
3447 : : void
3448 : 14186 : store::get_representative_path_vars (const region_model *model,
3449 : : svalue_set *visited,
3450 : : const svalue *sval,
3451 : : logger *logger,
3452 : : auto_vec<path_var> *out_pvs) const
3453 : : {
3454 : 14186 : gcc_assert (sval);
3455 : :
3456 : : /* Find all bindings that reference SVAL. */
3457 : 73106 : for (cluster_map_t::iterator iter = m_cluster_map.begin ();
3458 : 132026 : iter != m_cluster_map.end (); ++iter)
3459 : : {
3460 : 58920 : const region *base_reg = (*iter).first;
3461 : 58920 : binding_cluster *cluster = (*iter).second;
3462 : 58920 : cluster->get_representative_path_vars (model, visited, base_reg, sval,
3463 : : logger,
3464 : : out_pvs);
3465 : : }
3466 : :
3467 : 14186 : if (const initial_svalue *init_sval = sval->dyn_cast_initial_svalue ())
3468 : : {
3469 : 2567 : const region *reg = init_sval->get_region ();
3470 : 2567 : if (path_var pv = model->get_representative_path_var (reg,
3471 : : visited,
3472 : 2567 : logger))
3473 : 2447 : out_pvs->safe_push (pv);
3474 : : }
3475 : 14186 : }
3476 : :
3477 : : /* Remove all bindings overlapping REG within this store, removing
3478 : : any clusters that become redundant.
3479 : :
3480 : : If UNCERTAINTY is non-NULL, use it to record any svalues that
3481 : : were removed, as being maybe-bound. */
3482 : :
3483 : : void
3484 : 337250 : store::remove_overlapping_bindings (store_manager *mgr, const region *reg,
3485 : : uncertainty_t *uncertainty)
3486 : : {
3487 : 337250 : const region *base_reg = reg->get_base_region ();
3488 : 337250 : if (binding_cluster **cluster_slot = m_cluster_map.get (base_reg))
3489 : : {
3490 : 50669 : binding_cluster *cluster = *cluster_slot;
3491 : 50669 : if (reg == base_reg && !escaped_p (base_reg))
3492 : : {
3493 : : /* Remove whole cluster. */
3494 : 30980 : m_cluster_map.remove (base_reg);
3495 : 61960 : delete cluster;
3496 : 30980 : return;
3497 : : }
3498 : : /* Pass nullptr for the maybe_live_values here, as we don't want to
3499 : : record the old svalues as being maybe-bound. */
3500 : 19689 : cluster->remove_overlapping_bindings (mgr, reg, uncertainty, nullptr);
3501 : : }
3502 : : }
3503 : :
3504 : : /* Subclass of visitor that accumulates a hash_set of the regions that
3505 : : were visited. */
3506 : :
3507 : 2168710 : struct region_finder : public visitor
3508 : : {
3509 : 18900488 : void visit_region (const region *reg) final override
3510 : : {
3511 : 18900488 : m_regs.add (reg);
3512 : 18900488 : }
3513 : :
3514 : : hash_set<const region *> m_regs;
3515 : : };
3516 : :
3517 : : /* Canonicalize this store, to maximize the chance of equality between
3518 : : instances. */
3519 : :
3520 : : void
3521 : 1084355 : store::canonicalize (store_manager *mgr)
3522 : : {
3523 : : /* If we have e.g.:
3524 : : cluster for: HEAP_ALLOCATED_REGION(543)
3525 : : ESCAPED
3526 : : TOUCHED
3527 : : where the heap region is empty and unreferenced, then purge that
3528 : : cluster, to avoid unbounded state chains involving these. */
3529 : :
3530 : : /* Find regions that are referenced by bound values in the store. */
3531 : 1084355 : region_finder s;
3532 : 6905857 : for (cluster_map_t::iterator iter = m_cluster_map.begin ();
3533 : 12727359 : iter != m_cluster_map.end (); ++iter)
3534 : : {
3535 : 5821502 : binding_cluster *cluster = (*iter).second;
3536 : 5821502 : for (binding_cluster::iterator_t bind_iter = cluster->m_map.begin ();
3537 : 11905553 : bind_iter != cluster->m_map.end (); ++bind_iter)
3538 : 6084051 : (*bind_iter).m_sval->accept (&s);
3539 : : }
3540 : :
3541 : : /* Locate heap-allocated regions that have empty bindings that weren't
3542 : : found above. */
3543 : 1084355 : hash_set<const region *> purgeable_regions;
3544 : 6905857 : for (cluster_map_t::iterator iter = m_cluster_map.begin ();
3545 : 12727359 : iter != m_cluster_map.end (); ++iter)
3546 : : {
3547 : 5821502 : const region *base_reg = (*iter).first;
3548 : 5821502 : binding_cluster *cluster = (*iter).second;
3549 : 5821502 : if (base_reg->get_kind () == RK_HEAP_ALLOCATED)
3550 : : {
3551 : : /* Don't purge a heap-allocated region that's been marked as
3552 : : escaping, since this could be recording that a ptr to it
3553 : : was written to an unknown symbolic region along this
3554 : : path, and so we don't know whether it's referenced or
3555 : : not, and hence should report it as leaking
3556 : : (PR analyzer/106473). */
3557 : 483625 : if (cluster->escaped_p ())
3558 : 229912 : continue;
3559 : :
3560 : 253713 : if (cluster->empty_p ())
3561 : 612 : if (!s.m_regs.contains (base_reg))
3562 : 0 : purgeable_regions.add (base_reg);
3563 : :
3564 : : /* Also cover the UNKNOWN case. */
3565 : 253713 : if (const svalue *sval = cluster->maybe_get_simple_value (mgr))
3566 : 67683 : if (sval->get_kind () == SK_UNKNOWN)
3567 : 32427 : if (!s.m_regs.contains (base_reg))
3568 : 125 : purgeable_regions.add (base_reg);
3569 : : }
3570 : : }
3571 : :
3572 : : /* Purge them. */
3573 : 1084480 : for (hash_set<const region *>::iterator iter = purgeable_regions.begin ();
3574 : 2168960 : iter != purgeable_regions.end (); ++iter)
3575 : : {
3576 : 125 : const region *base_reg = *iter;
3577 : 125 : purge_cluster (base_reg);
3578 : : }
3579 : 1084355 : }
3580 : :
3581 : : /* Subroutine for use by exploded_path::feasible_p.
3582 : :
3583 : : We need to deal with state differences between:
3584 : : (a) when the exploded_graph is being initially constructed and
3585 : : (b) when replaying the state changes along a specific path in
3586 : : in exploded_path::feasible_p.
3587 : :
3588 : : In (a), state merging happens, so when exploring a loop
3589 : : for (i = 0; i < 1024; i++)
3590 : : on successive iterations we have i == 0, then i == WIDENING.
3591 : :
3592 : : In (b), no state merging happens, so naively replaying the path
3593 : : that goes twice through the loop then exits it
3594 : : would lead to i == 0, then i == 1, and then a (i >= 1024) eedge
3595 : : that exits the loop, which would be found to be infeasible as i == 1,
3596 : : and the path would be rejected.
3597 : :
3598 : : We need to fix up state during replay. This subroutine is
3599 : : called whenever we enter a supernode that we've already
3600 : : visited along this exploded_path, passing in OTHER_STORE
3601 : : from the destination enode's state.
3602 : :
3603 : : Find bindings to widening values in OTHER_STORE.
3604 : : For all that are found, update the binding in this store to UNKNOWN. */
3605 : :
3606 : : void
3607 : 8754 : store::loop_replay_fixup (const store *other_store,
3608 : : region_model_manager *mgr)
3609 : : {
3610 : 8754 : gcc_assert (other_store);
3611 : 75720 : for (cluster_map_t::iterator iter = other_store->m_cluster_map.begin ();
3612 : 142686 : iter != other_store->m_cluster_map.end (); ++iter)
3613 : : {
3614 : 66966 : const region *base_reg = (*iter).first;
3615 : 66966 : binding_cluster *cluster = (*iter).second;
3616 : 145184 : for (binding_cluster::iterator_t bind_iter = cluster->m_map.begin ();
3617 : 145184 : bind_iter != cluster->m_map.end (); ++bind_iter)
3618 : : {
3619 : 78218 : const binding_key *key = (*bind_iter).m_key;
3620 : 78218 : const svalue *sval = (*bind_iter).m_sval;
3621 : 78218 : if (sval->get_kind () == SK_WIDENING)
3622 : : {
3623 : 1715 : binding_cluster *this_cluster
3624 : 1715 : = get_or_create_cluster (*mgr->get_store_manager (),
3625 : : base_reg);
3626 : 1715 : const svalue *unknown
3627 : 1715 : = mgr->get_or_create_unknown_svalue (sval->get_type ());
3628 : 1715 : this_cluster->bind_key (key, unknown);
3629 : : }
3630 : : }
3631 : : }
3632 : 8754 : }
3633 : :
3634 : : /* Use R to replay the bindings from SUMMARY into this object. */
3635 : :
3636 : : void
3637 : 1528 : store::replay_call_summary (call_summary_replay &r,
3638 : : const store &summary)
3639 : : {
3640 : 1528 : if (summary.m_called_unknown_fn)
3641 : : {
3642 : : /* A call to an external function occurred in the summary.
3643 : : Hence we need to invalidate our knownledge of globals,
3644 : : escaped regions, etc. */
3645 : 87 : on_unknown_fncall (r.get_call_stmt (),
3646 : : r.get_store_manager (),
3647 : 87 : conjured_purge (r.get_caller_model (),
3648 : 87 : r.get_ctxt ()));
3649 : : }
3650 : :
3651 : 1528 : auto_vec<const region *> keys (summary.m_cluster_map.elements ());
3652 : 14776 : for (auto kv : summary.m_cluster_map)
3653 : 13248 : keys.quick_push (kv.first);
3654 : 1528 : keys.qsort (region::cmp_ptr_ptr);
3655 : 17792 : for (auto base_reg : keys)
3656 : 13248 : replay_call_summary_cluster (r, summary, base_reg);
3657 : 1528 : }
3658 : :
3659 : : /* Use R and SUMMARY to replay the bindings in SUMMARY_CLUSTER
3660 : : into this object. */
3661 : :
3662 : : void
3663 : 13248 : store::replay_call_summary_cluster (call_summary_replay &r,
3664 : : const store &summary,
3665 : : const region *summary_base_reg)
3666 : : {
3667 : 13248 : const call_details &cd = r.get_call_details ();
3668 : 13248 : region_model_manager *reg_mgr = r.get_manager ();
3669 : 13248 : store_manager *mgr = reg_mgr->get_store_manager ();
3670 : 13248 : const binding_cluster *summary_cluster
3671 : 13248 : = summary.get_cluster (summary_base_reg);
3672 : :
3673 : : /* Handle "ESCAPED" and "TOUCHED" flags. */
3674 : 13248 : if (summary_cluster->escaped_p () || summary_cluster->touched_p ())
3675 : 8850 : if (const region *caller_reg
3676 : 4425 : = r.convert_region_from_summary (summary_base_reg))
3677 : : {
3678 : 4332 : const region *caller_base_reg = caller_reg->get_base_region ();
3679 : 4332 : if (caller_base_reg->tracked_p ()
3680 : 4332 : && !caller_base_reg->symbolic_for_unknown_ptr_p ())
3681 : : {
3682 : 3364 : binding_cluster *caller_cluster
3683 : 3364 : = get_or_create_cluster (*mgr, caller_base_reg);
3684 : 3364 : if (summary_cluster->escaped_p ())
3685 : 2609 : caller_cluster->mark_as_escaped ();
3686 : 3364 : if (summary_cluster->touched_p ())
3687 : 2060 : caller_cluster->m_touched = true;
3688 : : }
3689 : : }
3690 : :
3691 : 13248 : switch (summary_base_reg->get_kind ())
3692 : : {
3693 : : /* Top-level regions. */
3694 : 0 : case RK_FRAME:
3695 : 0 : case RK_GLOBALS:
3696 : 0 : case RK_CODE:
3697 : 0 : case RK_STACK:
3698 : 0 : case RK_HEAP:
3699 : 0 : case RK_THREAD_LOCAL:
3700 : 0 : case RK_ROOT:
3701 : : /* Child regions. */
3702 : 0 : case RK_FIELD:
3703 : 0 : case RK_ELEMENT:
3704 : 0 : case RK_OFFSET:
3705 : 0 : case RK_SIZED:
3706 : 0 : case RK_CAST:
3707 : 0 : case RK_BIT_RANGE:
3708 : : /* Other regions. */
3709 : 0 : case RK_VAR_ARG:
3710 : 0 : case RK_UNKNOWN:
3711 : : /* These should never be the base region of a binding cluster. */
3712 : 0 : gcc_unreachable ();
3713 : : break;
3714 : :
3715 : : case RK_FUNCTION:
3716 : : case RK_LABEL:
3717 : : case RK_STRING:
3718 : : /* These can be marked as escaping. */
3719 : : break;
3720 : :
3721 : 3043 : case RK_SYMBOLIC:
3722 : 3043 : {
3723 : 3043 : const symbolic_region *summary_symbolic_reg
3724 : 3043 : = as_a <const symbolic_region *> (summary_base_reg);
3725 : 3043 : const svalue *summary_ptr_sval = summary_symbolic_reg->get_pointer ();
3726 : 3043 : const svalue *caller_ptr_sval
3727 : 3043 : = r.convert_svalue_from_summary (summary_ptr_sval);
3728 : 3043 : if (!caller_ptr_sval)
3729 : : return;
3730 : 2560 : const region *caller_dest_reg
3731 : 2560 : = cd.get_model ()->deref_rvalue (caller_ptr_sval,
3732 : : NULL_TREE,
3733 : : cd.get_ctxt ());
3734 : 2560 : const svalue *summary_sval
3735 : 2560 : = summary.get_any_binding (mgr, summary_base_reg);
3736 : 2560 : if (!summary_sval)
3737 : : return;
3738 : 2292 : const svalue *caller_sval
3739 : 2292 : = r.convert_svalue_from_summary (summary_sval);
3740 : 2292 : if (!caller_sval)
3741 : 2 : caller_sval =
3742 : 2 : reg_mgr->get_or_create_unknown_svalue (summary_sval->get_type ());
3743 : 2292 : set_value (mgr, caller_dest_reg,
3744 : : caller_sval, nullptr /* uncertainty_t * */);
3745 : : }
3746 : 2292 : break;
3747 : :
3748 : 10172 : case RK_HEAP_ALLOCATED:
3749 : 10172 : case RK_DECL:
3750 : 10172 : case RK_ERRNO:
3751 : 10172 : case RK_PRIVATE:
3752 : 10172 : {
3753 : 10172 : const region *caller_dest_reg
3754 : 10172 : = r.convert_region_from_summary (summary_base_reg);
3755 : 10172 : if (!caller_dest_reg)
3756 : : return;
3757 : 9887 : const svalue *summary_sval
3758 : 9887 : = summary.get_any_binding (mgr, summary_base_reg);
3759 : 9887 : if (!summary_sval)
3760 : 206 : summary_sval = reg_mgr->get_or_create_compound_svalue
3761 : 206 : (summary_base_reg->get_type (),
3762 : : summary_cluster->get_map ());
3763 : 9887 : const svalue *caller_sval
3764 : 9887 : = r.convert_svalue_from_summary (summary_sval);
3765 : 9887 : if (!caller_sval)
3766 : 2 : caller_sval =
3767 : 2 : reg_mgr->get_or_create_unknown_svalue (summary_sval->get_type ());
3768 : 9887 : set_value (mgr, caller_dest_reg,
3769 : : caller_sval, nullptr /* uncertainty_t * */);
3770 : : }
3771 : 9887 : break;
3772 : :
3773 : : case RK_ALLOCA:
3774 : : /* Ignore bindings of alloca regions in the summary. */
3775 : : break;
3776 : : }
3777 : : }
3778 : :
3779 : : #if CHECKING_P
3780 : :
3781 : : namespace selftest {
3782 : :
3783 : : /* Verify that bit_range::intersects_p works as expected. */
3784 : :
3785 : : static void
3786 : 4 : test_bit_range_intersects_p ()
3787 : : {
3788 : 4 : bit_range b0 (0, 1);
3789 : 4 : bit_range b1 (1, 1);
3790 : 4 : bit_range b2 (2, 1);
3791 : 4 : bit_range b3 (3, 1);
3792 : 4 : bit_range b4 (4, 1);
3793 : 4 : bit_range b5 (5, 1);
3794 : 4 : bit_range b6 (6, 1);
3795 : 4 : bit_range b7 (7, 1);
3796 : 4 : bit_range b1_to_6 (1, 6);
3797 : 4 : bit_range b0_to_7 (0, 8);
3798 : 4 : bit_range b3_to_5 (3, 3);
3799 : 4 : bit_range b6_to_7 (6, 2);
3800 : :
3801 : : /* self-intersection is true. */
3802 : 4 : ASSERT_TRUE (b0.intersects_p (b0));
3803 : 4 : ASSERT_TRUE (b7.intersects_p (b7));
3804 : 4 : ASSERT_TRUE (b1_to_6.intersects_p (b1_to_6));
3805 : 4 : ASSERT_TRUE (b0_to_7.intersects_p (b0_to_7));
3806 : :
3807 : 4 : ASSERT_FALSE (b0.intersects_p (b1));
3808 : 4 : ASSERT_FALSE (b1.intersects_p (b0));
3809 : 4 : ASSERT_FALSE (b0.intersects_p (b7));
3810 : 4 : ASSERT_FALSE (b7.intersects_p (b0));
3811 : :
3812 : 4 : ASSERT_TRUE (b0_to_7.intersects_p (b0));
3813 : 4 : ASSERT_TRUE (b0_to_7.intersects_p (b7));
3814 : 4 : ASSERT_TRUE (b0.intersects_p (b0_to_7));
3815 : 4 : ASSERT_TRUE (b7.intersects_p (b0_to_7));
3816 : :
3817 : 4 : ASSERT_FALSE (b0.intersects_p (b1_to_6));
3818 : 4 : ASSERT_FALSE (b1_to_6.intersects_p (b0));
3819 : 4 : ASSERT_TRUE (b1.intersects_p (b1_to_6));
3820 : 4 : ASSERT_TRUE (b1_to_6.intersects_p (b1));
3821 : 4 : ASSERT_TRUE (b1_to_6.intersects_p (b6));
3822 : 4 : ASSERT_FALSE (b1_to_6.intersects_p (b7));
3823 : :
3824 : 4 : ASSERT_TRUE (b1_to_6.intersects_p (b0_to_7));
3825 : 4 : ASSERT_TRUE (b0_to_7.intersects_p (b1_to_6));
3826 : :
3827 : 4 : ASSERT_FALSE (b3_to_5.intersects_p (b6_to_7));
3828 : 4 : ASSERT_FALSE (b6_to_7.intersects_p (b3_to_5));
3829 : :
3830 : 4 : bit_range r1 (0,0);
3831 : 4 : bit_range r2 (0,0);
3832 : 4 : ASSERT_TRUE (b1_to_6.intersects_p (b0_to_7, &r1, &r2));
3833 : 4 : ASSERT_EQ (r1.get_start_bit_offset (), 0);
3834 : 4 : ASSERT_EQ (r1.m_size_in_bits, 6);
3835 : 4 : ASSERT_EQ (r2.get_start_bit_offset (), 1);
3836 : 4 : ASSERT_EQ (r2.m_size_in_bits, 6);
3837 : :
3838 : 4 : ASSERT_TRUE (b0_to_7.intersects_p (b1_to_6, &r1, &r2));
3839 : 4 : ASSERT_EQ (r1.get_start_bit_offset (), 1);
3840 : 4 : ASSERT_EQ (r1.m_size_in_bits, 6);
3841 : 4 : ASSERT_EQ (r2.get_start_bit_offset (), 0);
3842 : 4 : ASSERT_EQ (r2.m_size_in_bits, 6);
3843 : 4 : }
3844 : :
3845 : : /* Implementation detail of ASSERT_BIT_RANGE_FROM_MASK_EQ. */
3846 : :
3847 : : static void
3848 : 76 : assert_bit_range_from_mask_eq (const location &loc,
3849 : : unsigned HOST_WIDE_INT mask,
3850 : : const bit_range &expected)
3851 : : {
3852 : 76 : bit_range actual (0, 0);
3853 : 76 : bool ok = bit_range::from_mask (mask, &actual);
3854 : 76 : ASSERT_TRUE_AT (loc, ok);
3855 : 76 : ASSERT_EQ_AT (loc, actual, expected);
3856 : 76 : }
3857 : :
3858 : : /* Assert that bit_range::from_mask (MASK) returns true, and writes
3859 : : out EXPECTED_BIT_RANGE. */
3860 : :
3861 : : #define ASSERT_BIT_RANGE_FROM_MASK_EQ(MASK, EXPECTED_BIT_RANGE) \
3862 : : SELFTEST_BEGIN_STMT \
3863 : : assert_bit_range_from_mask_eq (SELFTEST_LOCATION, MASK, \
3864 : : EXPECTED_BIT_RANGE); \
3865 : : SELFTEST_END_STMT
3866 : :
3867 : : /* Implementation detail of ASSERT_NO_BIT_RANGE_FROM_MASK. */
3868 : :
3869 : : static void
3870 : 12 : assert_no_bit_range_from_mask_eq (const location &loc,
3871 : : unsigned HOST_WIDE_INT mask)
3872 : : {
3873 : 12 : bit_range actual (0, 0);
3874 : 12 : bool ok = bit_range::from_mask (mask, &actual);
3875 : 12 : ASSERT_FALSE_AT (loc, ok);
3876 : 12 : }
3877 : :
3878 : : /* Assert that bit_range::from_mask (MASK) returns false. */
3879 : :
3880 : : #define ASSERT_NO_BIT_RANGE_FROM_MASK(MASK) \
3881 : : SELFTEST_BEGIN_STMT \
3882 : : assert_no_bit_range_from_mask_eq (SELFTEST_LOCATION, MASK); \
3883 : : SELFTEST_END_STMT
3884 : :
3885 : : /* Verify that bit_range::from_mask works as expected. */
3886 : :
3887 : : static void
3888 : 4 : test_bit_range_from_mask ()
3889 : : {
3890 : : /* Should fail on zero. */
3891 : 4 : ASSERT_NO_BIT_RANGE_FROM_MASK (0);
3892 : :
3893 : : /* Verify 1-bit masks. */
3894 : 4 : ASSERT_BIT_RANGE_FROM_MASK_EQ (1, bit_range (0, 1));
3895 : 4 : ASSERT_BIT_RANGE_FROM_MASK_EQ (2, bit_range (1, 1));
3896 : 4 : ASSERT_BIT_RANGE_FROM_MASK_EQ (4, bit_range (2, 1));
3897 : 4 : ASSERT_BIT_RANGE_FROM_MASK_EQ (8, bit_range (3, 1));
3898 : 4 : ASSERT_BIT_RANGE_FROM_MASK_EQ (16, bit_range (4, 1));
3899 : 4 : ASSERT_BIT_RANGE_FROM_MASK_EQ (32, bit_range (5, 1));
3900 : 4 : ASSERT_BIT_RANGE_FROM_MASK_EQ (64, bit_range (6, 1));
3901 : 4 : ASSERT_BIT_RANGE_FROM_MASK_EQ (128, bit_range (7, 1));
3902 : :
3903 : : /* Verify N-bit masks starting at bit 0. */
3904 : 4 : ASSERT_BIT_RANGE_FROM_MASK_EQ (3, bit_range (0, 2));
3905 : 4 : ASSERT_BIT_RANGE_FROM_MASK_EQ (7, bit_range (0, 3));
3906 : 4 : ASSERT_BIT_RANGE_FROM_MASK_EQ (15, bit_range (0, 4));
3907 : 4 : ASSERT_BIT_RANGE_FROM_MASK_EQ (31, bit_range (0, 5));
3908 : 4 : ASSERT_BIT_RANGE_FROM_MASK_EQ (63, bit_range (0, 6));
3909 : 4 : ASSERT_BIT_RANGE_FROM_MASK_EQ (127, bit_range (0, 7));
3910 : 4 : ASSERT_BIT_RANGE_FROM_MASK_EQ (255, bit_range (0, 8));
3911 : 4 : ASSERT_BIT_RANGE_FROM_MASK_EQ (0xffff, bit_range (0, 16));
3912 : :
3913 : : /* Various other tests. */
3914 : 4 : ASSERT_BIT_RANGE_FROM_MASK_EQ (0x30, bit_range (4, 2));
3915 : 4 : ASSERT_BIT_RANGE_FROM_MASK_EQ (0x700, bit_range (8, 3));
3916 : 4 : ASSERT_BIT_RANGE_FROM_MASK_EQ (0x600, bit_range (9, 2));
3917 : :
3918 : : /* Multiple ranges of set bits should fail. */
3919 : 4 : ASSERT_NO_BIT_RANGE_FROM_MASK (0x101);
3920 : 4 : ASSERT_NO_BIT_RANGE_FROM_MASK (0xf0f0f0f0);
3921 : 4 : }
3922 : :
3923 : : /* Implementation detail of ASSERT_OVERLAP. */
3924 : :
3925 : : static void
3926 : 56 : assert_overlap (const location &loc,
3927 : : const concrete_binding *b1,
3928 : : const concrete_binding *b2)
3929 : : {
3930 : 56 : ASSERT_TRUE_AT (loc, b1->overlaps_p (*b2));
3931 : 56 : ASSERT_TRUE_AT (loc, b2->overlaps_p (*b1));
3932 : 56 : }
3933 : :
3934 : : /* Implementation detail of ASSERT_DISJOINT. */
3935 : :
3936 : : static void
3937 : 20 : assert_disjoint (const location &loc,
3938 : : const concrete_binding *b1,
3939 : : const concrete_binding *b2)
3940 : : {
3941 : 20 : ASSERT_FALSE_AT (loc, b1->overlaps_p (*b2));
3942 : 20 : ASSERT_FALSE_AT (loc, b2->overlaps_p (*b1));
3943 : 20 : }
3944 : :
3945 : : /* Assert that B1 and B2 overlap, checking both ways. */
3946 : :
3947 : : #define ASSERT_OVERLAP(B1, B2) \
3948 : : SELFTEST_BEGIN_STMT \
3949 : : assert_overlap (SELFTEST_LOCATION, B1, B2); \
3950 : : SELFTEST_END_STMT
3951 : :
3952 : : /* Assert that B1 and B2 do not overlap, checking both ways. */
3953 : :
3954 : : #define ASSERT_DISJOINT(B1, B2) \
3955 : : SELFTEST_BEGIN_STMT \
3956 : : assert_disjoint (SELFTEST_LOCATION, B1, B2); \
3957 : : SELFTEST_END_STMT
3958 : :
3959 : : /* Verify that concrete_binding::overlaps_p works as expected. */
3960 : :
3961 : : static void
3962 : 4 : test_binding_key_overlap ()
3963 : : {
3964 : 4 : store_manager mgr (nullptr);
3965 : :
3966 : : /* Various 8-bit bindings. */
3967 : 4 : const concrete_binding *cb_0_7 = mgr.get_concrete_binding (0, 8);
3968 : 4 : const concrete_binding *cb_8_15 = mgr.get_concrete_binding (8, 8);
3969 : 4 : const concrete_binding *cb_16_23 = mgr.get_concrete_binding (16, 8);
3970 : 4 : const concrete_binding *cb_24_31 = mgr.get_concrete_binding (24, 8);
3971 : :
3972 : : /* 16-bit bindings. */
3973 : 4 : const concrete_binding *cb_0_15 = mgr.get_concrete_binding (0, 16);
3974 : 4 : const concrete_binding *cb_8_23 = mgr.get_concrete_binding (8, 16);
3975 : 4 : const concrete_binding *cb_16_31 = mgr.get_concrete_binding (16, 16);
3976 : :
3977 : : /* 32-bit binding. */
3978 : 4 : const concrete_binding *cb_0_31 = mgr.get_concrete_binding (0, 32);
3979 : :
3980 : : /* Everything should self-overlap. */
3981 : 4 : ASSERT_OVERLAP (cb_0_7, cb_0_7);
3982 : 4 : ASSERT_OVERLAP (cb_8_15, cb_8_15);
3983 : 4 : ASSERT_OVERLAP (cb_16_23, cb_16_23);
3984 : 4 : ASSERT_OVERLAP (cb_24_31, cb_24_31);
3985 : 4 : ASSERT_OVERLAP (cb_0_15, cb_0_15);
3986 : 4 : ASSERT_OVERLAP (cb_8_23, cb_8_23);
3987 : 4 : ASSERT_OVERLAP (cb_16_31, cb_16_31);
3988 : 4 : ASSERT_OVERLAP (cb_0_31, cb_0_31);
3989 : :
3990 : : /* Verify the 8-bit bindings that don't overlap each other. */
3991 : 4 : ASSERT_DISJOINT (cb_0_7, cb_8_15);
3992 : 4 : ASSERT_DISJOINT (cb_8_15, cb_16_23);
3993 : :
3994 : : /* Check for overlap of differently-sized bindings. */
3995 : 4 : ASSERT_OVERLAP (cb_0_7, cb_0_31);
3996 : : /* ...and with differing start points. */
3997 : 4 : ASSERT_OVERLAP (cb_8_15, cb_0_31);
3998 : 4 : ASSERT_DISJOINT (cb_8_15, cb_16_31);
3999 : 4 : ASSERT_OVERLAP (cb_16_23, cb_0_31);
4000 : 4 : ASSERT_OVERLAP (cb_16_31, cb_0_31);
4001 : :
4002 : 4 : ASSERT_DISJOINT (cb_0_7, cb_8_23);
4003 : 4 : ASSERT_OVERLAP (cb_8_23, cb_16_23);
4004 : 4 : ASSERT_OVERLAP (cb_8_23, cb_16_31);
4005 : 4 : ASSERT_DISJOINT (cb_8_23, cb_24_31);
4006 : 4 : }
4007 : :
4008 : : static void
4009 : 4 : test_binding_map_ops ()
4010 : : {
4011 : 4 : region_model_manager region_mgr;
4012 : 4 : store_manager store_mgr (®ion_mgr);
4013 : :
4014 : : /* Assignment of empty. */
4015 : 4 : {
4016 : 4 : binding_map src (store_mgr);
4017 : 4 : binding_map dst (store_mgr);
4018 : 4 : dst = src;
4019 : :
4020 : 4 : ASSERT_EQ (src, dst);
4021 : 4 : }
4022 : 4 : }
4023 : :
4024 : : /* Run all of the selftests within this file. */
4025 : :
4026 : : void
4027 : 4 : analyzer_store_cc_tests ()
4028 : : {
4029 : 4 : test_bit_range_intersects_p ();
4030 : 4 : test_bit_range_from_mask ();
4031 : 4 : test_binding_key_overlap ();
4032 : 4 : test_binding_map_ops ();
4033 : 4 : }
4034 : :
4035 : : } // namespace selftest
4036 : :
4037 : : #endif /* CHECKING_P */
4038 : :
4039 : : } // namespace ana
4040 : :
4041 : : #endif /* #if ENABLE_ANALYZER */
|