1/* Symbolic values.
2 Copyright (C) 2019-2024 Free Software Foundation, Inc.
3 Contributed by David Malcolm <dmalcolm@redhat.com>.
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it
8under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 3, or (at your option)
10any later version.
11
12GCC is distributed in the hope that it will be useful, but
13WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GCC; see the file COPYING3. If not see
19<http://www.gnu.org/licenses/>. */
20
21#include "config.h"
22#define INCLUDE_MEMORY
23#include "system.h"
24#include "coretypes.h"
25#include "tree.h"
26#include "diagnostic-core.h"
27#include "gimple-pretty-print.h"
28#include "function.h"
29#include "basic-block.h"
30#include "gimple.h"
31#include "gimple-iterator.h"
32#include "diagnostic-core.h"
33#include "graphviz.h"
34#include "options.h"
35#include "cgraph.h"
36#include "tree-dfa.h"
37#include "stringpool.h"
38#include "convert.h"
39#include "target.h"
40#include "fold-const.h"
41#include "tree-pretty-print.h"
42#include "bitmap.h"
43#include "analyzer/analyzer.h"
44#include "analyzer/analyzer-logging.h"
45#include "analyzer/call-string.h"
46#include "analyzer/program-point.h"
47#include "analyzer/store.h"
48#include "analyzer/svalue.h"
49#include "analyzer/region-model.h"
50#include "diagnostic.h"
51#include "tree-diagnostic.h"
52
53#if ENABLE_ANALYZER
54
55namespace ana {
56
57static int cmp_csts_and_types (const_tree cst1, const_tree cst2);
58
59/* class svalue and its various subclasses. */
60
61/* class svalue. */
62
63/* Dump a representation of this svalue to stderr. */
64
65DEBUG_FUNCTION void
66svalue::dump (bool simple) const
67{
68 pretty_printer pp;
69 pp_format_decoder (&pp) = default_tree_printer;
70 pp_show_color (&pp) = pp_show_color (global_dc->printer);
71 pp.buffer->stream = stderr;
72 dump_to_pp (pp: &pp, simple);
73 pp_newline (&pp);
74 pp_flush (&pp);
75}
76
77/* Generate a textual representation of this svalue for debugging purposes. */
78
79label_text
80svalue::get_desc (bool simple) const
81{
82 pretty_printer pp;
83 pp_format_decoder (&pp) = default_tree_printer;
84 dump_to_pp (pp: &pp, simple);
85 return label_text::take (buffer: xstrdup (pp_formatted_text (&pp)));
86}
87
88/* Return a new json::string describing the svalue. */
89
90json::value *
91svalue::to_json () const
92{
93 label_text desc = get_desc (simple: true);
94 json::value *sval_js = new json::string (desc.get ());
95 return sval_js;
96}
97
98/* Class for optionally adding open/close paren pairs within
99 svalue::maybe_print_for_user. */
100
101class auto_add_parens
102{
103public:
104 auto_add_parens (pretty_printer *pp,
105 const svalue *outer_sval,
106 const svalue &inner_sval)
107 : m_pp (pp),
108 m_needs_parens (needs_parens_p (outer_sval, inner_sval))
109 {
110 if (m_needs_parens)
111 pp_string (m_pp, "(");
112 }
113 ~auto_add_parens ()
114 {
115 if (m_needs_parens)
116 pp_string (m_pp, ")");
117 }
118
119private:
120 static bool needs_parens_p (const svalue *outer_sval,
121 const svalue &inner_sval)
122 {
123 if (!outer_sval)
124 return false;
125 if (inner_sval.get_kind () == SK_BINOP)
126 return true;
127 return false;
128 }
129
130 pretty_printer *m_pp;
131 bool m_needs_parens;
132};
133
134/* Attempt to print a user-facing description of this svalue to PP,
135 using MODEL for extracting representative tree values if necessary.
136 Use OUTER_SVAL (which can be null) to determine if we need to wrap
137 this value in parentheses. */
138
139bool
140svalue::maybe_print_for_user (pretty_printer *pp,
141 const region_model &model,
142 const svalue *outer_sval) const
143{
144 auto_add_parens p (pp, outer_sval, *this);
145
146 switch (get_kind ())
147 {
148 default:
149 break;
150 case SK_CONSTANT:
151 {
152 const constant_svalue *sval = (const constant_svalue *)this;
153 pp_printf (pp, "%E", sval->get_constant ());
154 return true;
155 }
156 case SK_INITIAL:
157 {
158 const initial_svalue *sval = (const initial_svalue *)this;
159 return sval->get_region ()->maybe_print_for_user (pp, model);
160 }
161 case SK_UNARYOP:
162 {
163 const unaryop_svalue *sval = (const unaryop_svalue *)this;
164 if (sval->get_op () == NOP_EXPR)
165 {
166 if (!sval->get_arg ()->maybe_print_for_user (pp, model, outer_sval))
167 return false;
168 return true;
169 }
170 }
171 break;
172 case SK_BINOP:
173 {
174 const binop_svalue *sval = (const binop_svalue *)this;
175 switch (sval->get_op ())
176 {
177 default:
178 break;
179
180 case PLUS_EXPR:
181 case MINUS_EXPR:
182 case MULT_EXPR:
183 {
184 if (!sval->get_arg0 ()->maybe_print_for_user (pp, model, outer_sval: this))
185 return false;
186 pp_printf (pp, " %s ", op_symbol_code (sval->get_op ()));
187 if (!sval->get_arg1 ()->maybe_print_for_user (pp, model, outer_sval: this))
188 return false;
189 return true;
190 }
191 }
192 }
193 break;
194 }
195
196 if (tree expr = model.get_representative_tree (sval: this))
197 {
198 expr = remove_ssa_names (expr);
199 print_expr_for_user (pp, t: expr);
200 return true;
201 }
202
203 return false;
204}
205
206/* If this svalue is a constant_svalue, return the underlying tree constant.
207 Otherwise return NULL_TREE. */
208
209tree
210svalue::maybe_get_constant () const
211{
212 const svalue *sval = unwrap_any_unmergeable ();
213 if (const constant_svalue *cst_sval = sval->dyn_cast_constant_svalue ())
214 return cst_sval->get_constant ();
215 else
216 return NULL_TREE;
217}
218
219/* If this svalue is a region_svalue, return the region it points to.
220 Otherwise return NULL. */
221
222const region *
223svalue::maybe_get_region () const
224{
225 if (const region_svalue *region_sval = dyn_cast_region_svalue ())
226 return region_sval->get_pointee ();
227 else
228 return NULL;
229}
230
231/* If this svalue is a cast (i.e a unaryop NOP_EXPR or VIEW_CONVERT_EXPR),
232 return the underlying svalue.
233 Otherwise return NULL. */
234
235const svalue *
236svalue::maybe_undo_cast () const
237{
238 if (const unaryop_svalue *unaryop_sval = dyn_cast_unaryop_svalue ())
239 {
240 enum tree_code op = unaryop_sval->get_op ();
241 if (op == NOP_EXPR || op == VIEW_CONVERT_EXPR)
242 return unaryop_sval->get_arg ();
243 }
244 return NULL;
245}
246
247/* If this svalue is an unmergeable decorator around another svalue, return
248 the underlying svalue.
249 Otherwise return this svalue. */
250
251const svalue *
252svalue::unwrap_any_unmergeable () const
253{
254 if (const unmergeable_svalue *unmergeable = dyn_cast_unmergeable_svalue ())
255 return unmergeable->get_arg ();
256 return this;
257}
258
259/* Attempt to merge THIS with OTHER, returning the merged svalue.
260 Return NULL if not mergeable. */
261
262const svalue *
263svalue::can_merge_p (const svalue *other,
264 region_model_manager *mgr,
265 model_merger *merger) const
266{
267 if (!(get_type () && other->get_type ()))
268 return NULL;
269
270 if (!types_compatible_p (type1: get_type (), type2: other->get_type ()))
271 return NULL;
272
273 /* Reject attempts to merge unmergeable svalues. */
274 if ((get_kind () == SK_UNMERGEABLE)
275 || (other->get_kind () == SK_UNMERGEABLE))
276 return NULL;
277
278 /* Reject attempts to merge poisoned svalues with other svalues
279 (either non-poisoned, or other kinds of poison), so that e.g.
280 we identify paths in which a variable is conditionally uninitialized. */
281 if (get_kind () == SK_POISONED
282 || other->get_kind () == SK_POISONED)
283 return NULL;
284
285 /* Reject attempts to merge NULL pointers with not-NULL-pointers. */
286 if (POINTER_TYPE_P (get_type ()))
287 {
288 bool null0 = false;
289 bool null1 = false;
290 if (tree cst0 = maybe_get_constant ())
291 if (zerop (cst0))
292 null0 = true;
293 if (tree cst1 = other->maybe_get_constant ())
294 if (zerop (cst1))
295 null1 = true;
296 if (null0 != null1)
297 return NULL;
298 }
299
300 /* Reject merging svalues that have non-purgable sm-state,
301 to avoid falsely reporting memory leaks by merging them
302 with something else. */
303 if (!merger->mergeable_svalue_p (this))
304 return NULL;
305 if (!merger->mergeable_svalue_p (other))
306 return NULL;
307
308 /* Widening. */
309 /* Merge: (new_cst, existing_cst) -> widen (existing, new). */
310 if (maybe_get_constant () && other->maybe_get_constant ())
311 {
312 return mgr->get_or_create_widening_svalue (type: other->get_type (),
313 point: merger->get_function_point (),
314 base_svalue: other, iter_svalue: this);
315 }
316
317 /* Merger of:
318 this: BINOP (X, OP, CST)
319 other: X, where X is non-widening
320 to: WIDENING (other, this). */
321 if (const binop_svalue *binop_sval = dyn_cast_binop_svalue ())
322 if (binop_sval->get_arg0 () == other
323 && binop_sval->get_arg1 ()->get_kind () == SK_CONSTANT
324 && other->get_kind () != SK_WIDENING)
325 return mgr->get_or_create_widening_svalue (type: other->get_type (),
326 point: merger->get_function_point (),
327 base_svalue: other, iter_svalue: this);
328
329 /* Merge: (Widen(existing_val, V), existing_val) -> Widen (existing_val, V)
330 and thus get a fixed point. */
331 if (const widening_svalue *widen_sval = dyn_cast_widening_svalue ())
332 {
333 if (other == widen_sval->get_base_svalue ())
334 return this;
335 if (other == widen_sval->get_iter_svalue ())
336 return this;
337 }
338
339 if (const binop_svalue *binop_sval = dyn_cast_binop_svalue ())
340 if (const widening_svalue *widen_arg0
341 = binop_sval->get_arg0 ()->dyn_cast_widening_svalue ())
342 {
343 if (other == binop_sval->get_arg1 ())
344 {
345 /* Merger of: (Widen(..., OTHER) BINOP X)
346 and : OTHER
347 to : (Widen(..., OTHER) BINOP X)
348 e.g. merge of Widen(0, 1) + 1 with 1 to the Widen(0, 1) + 1. */
349 return this;
350 }
351
352 /* Merger of : (Widen() BINOP X)
353 and : Widen()
354 to : Widen()
355 e.g. merge of Widen(0, 1) + 1 and Widen(0, 1) to Widen(0, 1).
356 However, we want to update constraints for this case, since we're
357 considering another iteration.
358 Presumably we also want to ensure that it converges; we don't want
359 a descending chain of constraints. */
360 if (other == widen_arg0)
361 {
362 merger->on_widening_reuse (widening_sval: widen_arg0);
363 return widen_arg0;
364 }
365
366 /* Merger of:
367 this: BINOP(WIDENING(BASE, BINOP(BASE, X)), X)
368 other: BINOP(BASE, X)
369 to: WIDENING(BASE, BINOP(BASE, X)). */
370 if (widen_arg0->get_iter_svalue () == other)
371 if (const binop_svalue *other_binop_sval
372 = other->dyn_cast_binop_svalue ())
373 if (other_binop_sval->get_arg0 () == widen_arg0->get_base_svalue ()
374 && other_binop_sval->get_arg1 () == binop_sval->get_arg1 ())
375 return widen_arg0;
376 }
377
378 return mgr->get_or_create_unknown_svalue (type: get_type ());
379}
380
381/* Determine if this svalue is either within LIVE_SVALUES, or is implicitly
382 live with respect to LIVE_SVALUES and MODEL.
383 LIVE_SVALUES can be NULL, in which case determine if this svalue is
384 intrinsically live. */
385
386bool
387svalue::live_p (const svalue_set *live_svalues,
388 const region_model *model) const
389{
390 /* Determine if SVAL is explicitly live. */
391 if (live_svalues)
392 if (const_cast<svalue_set *> (live_svalues)->contains (k: this))
393 return true;
394
395 /* Otherwise, determine if SVAL is implicitly live due to being made of
396 other live svalues. */
397 return implicitly_live_p (live_svalues, model);
398}
399
400/* Base implementation of svalue::implicitly_live_p. */
401
402bool
403svalue::implicitly_live_p (const svalue_set *, const region_model *) const
404{
405 return false;
406}
407
408/* Comparator for imposing a deterministic order on constants that are
409 of the same type. */
410
411static int
412cmp_csts_same_type (const_tree cst1, const_tree cst2)
413{
414 gcc_assert (TREE_TYPE (cst1) == TREE_TYPE (cst2));
415 gcc_assert (TREE_CODE (cst1) == TREE_CODE (cst2));
416 switch (TREE_CODE (cst1))
417 {
418 default:
419 gcc_unreachable ();
420 case INTEGER_CST:
421 return tree_int_cst_compare (t1: cst1, t2: cst2);
422 case STRING_CST:
423 return strcmp (TREE_STRING_POINTER (cst1),
424 TREE_STRING_POINTER (cst2));
425 case REAL_CST:
426 /* Impose an arbitrary but deterministic order. */
427 return memcmp (TREE_REAL_CST_PTR (cst1),
428 TREE_REAL_CST_PTR (cst2),
429 n: sizeof (real_value));
430 case COMPLEX_CST:
431 if (int cmp_real = cmp_csts_and_types (TREE_REALPART (cst1),
432 TREE_REALPART (cst2)))
433 return cmp_real;
434 return cmp_csts_and_types (TREE_IMAGPART (cst1), TREE_IMAGPART (cst2));
435 case VECTOR_CST:
436 if (int cmp_log2_npatterns
437 = ((int)VECTOR_CST_LOG2_NPATTERNS (cst1)
438 - (int)VECTOR_CST_LOG2_NPATTERNS (cst2)))
439 return cmp_log2_npatterns;
440 if (int cmp_nelts_per_pattern
441 = ((int)VECTOR_CST_NELTS_PER_PATTERN (cst1)
442 - (int)VECTOR_CST_NELTS_PER_PATTERN (cst2)))
443 return cmp_nelts_per_pattern;
444 unsigned encoded_nelts = vector_cst_encoded_nelts (t: cst1);
445 for (unsigned i = 0; i < encoded_nelts; i++)
446 {
447 const_tree elt1 = VECTOR_CST_ENCODED_ELT (cst1, i);
448 const_tree elt2 = VECTOR_CST_ENCODED_ELT (cst2, i);
449 if (int el_cmp = cmp_csts_and_types (cst1: elt1, cst2: elt2))
450 return el_cmp;
451 }
452 return 0;
453 }
454}
455
456/* Comparator for imposing a deterministic order on constants that might
457 not be of the same type. */
458
459static int
460cmp_csts_and_types (const_tree cst1, const_tree cst2)
461{
462 int t1 = TYPE_UID (TREE_TYPE (cst1));
463 int t2 = TYPE_UID (TREE_TYPE (cst2));
464 if (int cmp_type = t1 - t2)
465 return cmp_type;
466 return cmp_csts_same_type (cst1, cst2);
467}
468
469/* Comparator for imposing a deterministic order on svalues. */
470
471int
472svalue::cmp_ptr (const svalue *sval1, const svalue *sval2)
473{
474 if (sval1 == sval2)
475 return 0;
476 if (int cmp_kind = sval1->get_kind () - sval2->get_kind ())
477 return cmp_kind;
478 int t1 = sval1->get_type () ? TYPE_UID (sval1->get_type ()) : -1;
479 int t2 = sval2->get_type () ? TYPE_UID (sval2->get_type ()) : -1;
480 if (int cmp_type = t1 - t2)
481 return cmp_type;
482 switch (sval1->get_kind ())
483 {
484 default:
485 gcc_unreachable ();
486 case SK_REGION:
487 {
488 const region_svalue *region_sval1 = (const region_svalue *)sval1;
489 const region_svalue *region_sval2 = (const region_svalue *)sval2;
490 return region::cmp_ids (s1: region_sval1->get_pointee (),
491 s2: region_sval2->get_pointee ());
492 }
493 break;
494 case SK_CONSTANT:
495 {
496 const constant_svalue *constant_sval1 = (const constant_svalue *)sval1;
497 const constant_svalue *constant_sval2 = (const constant_svalue *)sval2;
498 const_tree cst1 = constant_sval1->get_constant ();
499 const_tree cst2 = constant_sval2->get_constant ();
500 /* The svalues have the same type, but the underlying trees
501 might not (for the case where both svalues are typeless). */
502 return cmp_csts_and_types (cst1, cst2);
503 }
504 break;
505 case SK_UNKNOWN:
506 {
507 gcc_assert (sval1 == sval2);
508 return 0;
509 }
510 break;
511 case SK_POISONED:
512 {
513 const poisoned_svalue *poisoned_sval1 = (const poisoned_svalue *)sval1;
514 const poisoned_svalue *poisoned_sval2 = (const poisoned_svalue *)sval2;
515 return (poisoned_sval1->get_poison_kind ()
516 - poisoned_sval2->get_poison_kind ());
517 }
518 break;
519 case SK_SETJMP:
520 {
521 const setjmp_svalue *setjmp_sval1 = (const setjmp_svalue *)sval1;
522 const setjmp_svalue *setjmp_sval2 = (const setjmp_svalue *)sval2;
523 const setjmp_record &rec1 = setjmp_sval1->get_setjmp_record ();
524 const setjmp_record &rec2 = setjmp_sval2->get_setjmp_record ();
525 return setjmp_record::cmp (rec1, rec2);
526 }
527 break;
528 case SK_INITIAL:
529 {
530 const initial_svalue *initial_sval1 = (const initial_svalue *)sval1;
531 const initial_svalue *initial_sval2 = (const initial_svalue *)sval2;
532 return region::cmp_ids (s1: initial_sval1->get_region (),
533 s2: initial_sval2->get_region ());
534 }
535 break;
536 case SK_UNARYOP:
537 {
538 const unaryop_svalue *unaryop_sval1 = (const unaryop_svalue *)sval1;
539 const unaryop_svalue *unaryop_sval2 = (const unaryop_svalue *)sval2;
540 if (int op_cmp = unaryop_sval1->get_op () - unaryop_sval2->get_op ())
541 return op_cmp;
542 return svalue::cmp_ptr (sval1: unaryop_sval1->get_arg (),
543 sval2: unaryop_sval2->get_arg ());
544 }
545 break;
546 case SK_BINOP:
547 {
548 const binop_svalue *binop_sval1 = (const binop_svalue *)sval1;
549 const binop_svalue *binop_sval2 = (const binop_svalue *)sval2;
550 if (int op_cmp = binop_sval1->get_op () - binop_sval2->get_op ())
551 return op_cmp;
552 if (int arg0_cmp = svalue::cmp_ptr (sval1: binop_sval1->get_arg0 (),
553 sval2: binop_sval2->get_arg0 ()))
554 return arg0_cmp;
555 return svalue::cmp_ptr (sval1: binop_sval1->get_arg1 (),
556 sval2: binop_sval2->get_arg1 ());
557 }
558 break;
559 case SK_SUB:
560 {
561 const sub_svalue *sub_sval1 = (const sub_svalue *)sval1;
562 const sub_svalue *sub_sval2 = (const sub_svalue *)sval2;
563 if (int parent_cmp = svalue::cmp_ptr (sval1: sub_sval1->get_parent (),
564 sval2: sub_sval2->get_parent ()))
565 return parent_cmp;
566 return region::cmp_ids (s1: sub_sval1->get_subregion (),
567 s2: sub_sval2->get_subregion ());
568 }
569 break;
570 case SK_REPEATED:
571 {
572 const repeated_svalue *repeated_sval1 = (const repeated_svalue *)sval1;
573 const repeated_svalue *repeated_sval2 = (const repeated_svalue *)sval2;
574 return svalue::cmp_ptr (sval1: repeated_sval1->get_inner_svalue (),
575 sval2: repeated_sval2->get_inner_svalue ());
576 }
577 break;
578 case SK_BITS_WITHIN:
579 {
580 const bits_within_svalue *bits_within_sval1
581 = (const bits_within_svalue *)sval1;
582 const bits_within_svalue *bits_within_sval2
583 = (const bits_within_svalue *)sval2;
584 if (int cmp = bit_range::cmp (br1: bits_within_sval1->get_bits (),
585 br2: bits_within_sval2->get_bits ()))
586 return cmp;
587 return svalue::cmp_ptr (sval1: bits_within_sval1->get_inner_svalue (),
588 sval2: bits_within_sval2->get_inner_svalue ());
589 }
590 break;
591 case SK_UNMERGEABLE:
592 {
593 const unmergeable_svalue *unmergeable_sval1
594 = (const unmergeable_svalue *)sval1;
595 const unmergeable_svalue *unmergeable_sval2
596 = (const unmergeable_svalue *)sval2;
597 return svalue::cmp_ptr (sval1: unmergeable_sval1->get_arg (),
598 sval2: unmergeable_sval2->get_arg ());
599 }
600 break;
601 case SK_PLACEHOLDER:
602 {
603 const placeholder_svalue *placeholder_sval1
604 = (const placeholder_svalue *)sval1;
605 const placeholder_svalue *placeholder_sval2
606 = (const placeholder_svalue *)sval2;
607 return strcmp (s1: placeholder_sval1->get_name (),
608 s2: placeholder_sval2->get_name ());
609 }
610 break;
611 case SK_WIDENING:
612 {
613 const widening_svalue *widening_sval1 = (const widening_svalue *)sval1;
614 const widening_svalue *widening_sval2 = (const widening_svalue *)sval2;
615 if (int point_cmp = function_point::cmp (point_a: widening_sval1->get_point (),
616 point_b: widening_sval2->get_point ()))
617 return point_cmp;
618 if (int base_cmp = svalue::cmp_ptr (sval1: widening_sval1->get_base_svalue (),
619 sval2: widening_sval2->get_base_svalue ()))
620 return base_cmp;
621 return svalue::cmp_ptr (sval1: widening_sval1->get_iter_svalue (),
622 sval2: widening_sval2->get_iter_svalue ());
623 }
624 break;
625 case SK_COMPOUND:
626 {
627 const compound_svalue *compound_sval1 = (const compound_svalue *)sval1;
628 const compound_svalue *compound_sval2 = (const compound_svalue *)sval2;
629 return binding_map::cmp (map1: compound_sval1->get_map (),
630 map2: compound_sval2->get_map ());
631 }
632 break;
633 case SK_CONJURED:
634 {
635 const conjured_svalue *conjured_sval1 = (const conjured_svalue *)sval1;
636 const conjured_svalue *conjured_sval2 = (const conjured_svalue *)sval2;
637 if (int stmt_cmp = (conjured_sval1->get_stmt ()->uid
638 - conjured_sval2->get_stmt ()->uid))
639 return stmt_cmp;
640 return region::cmp_ids (s1: conjured_sval1->get_id_region (),
641 s2: conjured_sval2->get_id_region ());
642 }
643 break;
644 case SK_ASM_OUTPUT:
645 {
646 const asm_output_svalue *asm_output_sval1
647 = (const asm_output_svalue *)sval1;
648 const asm_output_svalue *asm_output_sval2
649 = (const asm_output_svalue *)sval2;
650 if (int asm_string_cmp = strcmp (s1: asm_output_sval1->get_asm_string (),
651 s2: asm_output_sval2->get_asm_string ()))
652 return asm_string_cmp;
653 if (int output_idx_cmp = ((int)asm_output_sval1->get_output_idx ()
654 - (int)asm_output_sval2->get_output_idx ()))
655 return output_idx_cmp;
656 if (int cmp = ((int)asm_output_sval1->get_num_inputs ()
657 - (int)asm_output_sval2->get_num_inputs ()))
658 return cmp;
659 for (unsigned i = 0; i < asm_output_sval1->get_num_inputs (); i++)
660 if (int input_cmp
661 = svalue::cmp_ptr (sval1: asm_output_sval1->get_input (idx: i),
662 sval2: asm_output_sval2->get_input (idx: i)))
663 return input_cmp;
664 return 0;
665 }
666 break;
667 case SK_CONST_FN_RESULT:
668 {
669 const const_fn_result_svalue *const_fn_result_sval1
670 = (const const_fn_result_svalue *)sval1;
671 const const_fn_result_svalue *const_fn_result_sval2
672 = (const const_fn_result_svalue *)sval2;
673 int d1 = DECL_UID (const_fn_result_sval1->get_fndecl ());
674 int d2 = DECL_UID (const_fn_result_sval2->get_fndecl ());
675 if (int cmp_fndecl = d1 - d2)
676 return cmp_fndecl;
677 if (int cmp = ((int)const_fn_result_sval1->get_num_inputs ()
678 - (int)const_fn_result_sval2->get_num_inputs ()))
679 return cmp;
680 for (unsigned i = 0; i < const_fn_result_sval1->get_num_inputs (); i++)
681 if (int input_cmp
682 = svalue::cmp_ptr (sval1: const_fn_result_sval1->get_input (idx: i),
683 sval2: const_fn_result_sval2->get_input (idx: i)))
684 return input_cmp;
685 return 0;
686 }
687 }
688}
689
690/* Comparator for use by vec<const svalue *>::qsort. */
691
692int
693svalue::cmp_ptr_ptr (const void *p1, const void *p2)
694{
695 const svalue *sval1 = *(const svalue * const *)p1;
696 const svalue *sval2 = *(const svalue * const *)p2;
697 return cmp_ptr (sval1, sval2);
698}
699
700/* Subclass of visitor for use in implementing svalue::involves_p. */
701
702class involvement_visitor : public visitor
703{
704public:
705 involvement_visitor (const svalue *needle)
706 : m_needle (needle), m_found (false) {}
707
708 void visit_initial_svalue (const initial_svalue *candidate) final override
709 {
710 if (candidate == m_needle)
711 m_found = true;
712 }
713
714 void visit_conjured_svalue (const conjured_svalue *candidate) final override
715 {
716 if (candidate == m_needle)
717 m_found = true;
718 }
719
720 void visit_widening_svalue (const widening_svalue *candidate) final override
721 {
722 if (candidate == m_needle)
723 m_found = true;
724 }
725
726 bool found_p () const { return m_found; }
727
728private:
729 const svalue *m_needle;
730 bool m_found;
731};
732
733/* Return true iff this svalue is defined in terms of OTHER. */
734
735bool
736svalue::involves_p (const svalue *other) const
737{
738 /* Currently only implemented for these kinds. */
739 gcc_assert (other->get_kind () == SK_INITIAL
740 || other->get_kind () == SK_CONJURED
741 || other->get_kind () == SK_WIDENING);
742
743 involvement_visitor v (other);
744 accept (v: &v);
745 return v.found_p ();
746}
747
748/* Extract SUBRANGE from this value, of type TYPE. */
749
750const svalue *
751svalue::extract_bit_range (tree type,
752 const bit_range &subrange,
753 region_model_manager *mgr) const
754{
755 return mgr->get_or_create_bits_within (type, bits: subrange, inner_svalue: this);
756}
757
758/* Base implementation of svalue::maybe_fold_bits_within vfunc. */
759
760const svalue *
761svalue::maybe_fold_bits_within (tree,
762 const bit_range &,
763 region_model_manager *) const
764{
765 /* By default, don't fold. */
766 return NULL;
767}
768
769/* Base implementation of svalue::all_zeroes_p.
770 Return true if this value is known to be all zeroes. */
771
772bool
773svalue::all_zeroes_p () const
774{
775 return false;
776}
777
778/* If this svalue is a pointer, attempt to determine the base region it points
779 to. Return NULL on any problems. */
780
781const region *
782svalue::maybe_get_deref_base_region () const
783{
784 const svalue *iter = this;
785 while (1)
786 {
787 switch (iter->get_kind ())
788 {
789 default:
790 return NULL;
791
792 case SK_REGION:
793 {
794 const region_svalue *region_sval
795 = as_a <const region_svalue *> (p: iter);
796 return region_sval->get_pointee ()->get_base_region ();
797 }
798
799 case SK_BINOP:
800 {
801 const binop_svalue *binop_sval
802 = as_a <const binop_svalue *> (p: iter);
803 switch (binop_sval->get_op ())
804 {
805 case POINTER_PLUS_EXPR:
806 /* If we have a symbolic value expressing pointer arithmetic,
807 use the LHS. */
808 iter = binop_sval->get_arg0 ();
809 continue;
810
811 default:
812 return NULL;
813 }
814 return NULL;
815 }
816 }
817 }
818}
819
820/* class region_svalue : public svalue. */
821
822/* Implementation of svalue::dump_to_pp vfunc for region_svalue. */
823
824void
825region_svalue::dump_to_pp (pretty_printer *pp, bool simple) const
826{
827 if (simple)
828 {
829 pp_string (pp, "&");
830 m_reg->dump_to_pp (pp, simple);
831 }
832 else
833 {
834 pp_string (pp, "region_svalue(");
835 if (get_type ())
836 {
837 print_quoted_type (pp, t: get_type ());
838 pp_string (pp, ", ");
839 }
840 m_reg->dump_to_pp (pp, simple);
841 pp_string (pp, ")");
842 }
843}
844
845/* Implementation of svalue::accept vfunc for region_svalue. */
846
847void
848region_svalue::accept (visitor *v) const
849{
850 m_reg->accept (v);
851 v->visit_region_svalue (this);
852}
853
854/* Implementation of svalue::implicitly_live_p vfunc for region_svalue. */
855
856bool
857region_svalue::implicitly_live_p (const svalue_set *,
858 const region_model *model) const
859{
860 /* Pointers into clusters that have escaped should be treated as live. */
861 const region *base_reg = get_pointee ()->get_base_region ();
862 const store *store = model->get_store ();
863 if (const binding_cluster *c = store->get_cluster (base_reg))
864 if (c->escaped_p ())
865 return true;
866
867 return false;
868}
869
870/* Evaluate the condition LHS OP RHS.
871 Subroutine of region_model::eval_condition for when we have a pair of
872 pointers. */
873
874tristate
875region_svalue::eval_condition (const region_svalue *lhs,
876 enum tree_code op,
877 const region_svalue *rhs)
878{
879 /* See if they point to the same region. */
880 const region *lhs_reg = lhs->get_pointee ();
881 const region *rhs_reg = rhs->get_pointee ();
882 bool ptr_equality = lhs_reg == rhs_reg;
883 switch (op)
884 {
885 default:
886 gcc_unreachable ();
887
888 case EQ_EXPR:
889 if (ptr_equality)
890 return tristate::TS_TRUE;
891 else
892 return tristate::TS_FALSE;
893 break;
894
895 case NE_EXPR:
896 if (ptr_equality)
897 return tristate::TS_FALSE;
898 else
899 return tristate::TS_TRUE;
900 break;
901
902 case GE_EXPR:
903 case LE_EXPR:
904 if (ptr_equality)
905 return tristate::TS_TRUE;
906 break;
907
908 case GT_EXPR:
909 case LT_EXPR:
910 if (ptr_equality)
911 return tristate::TS_FALSE;
912 break;
913 }
914
915 return tristate::TS_UNKNOWN;
916}
917
918/* class constant_svalue : public svalue. */
919
920/* Implementation of svalue::dump_to_pp vfunc for constant_svalue. */
921
922void
923constant_svalue::dump_to_pp (pretty_printer *pp, bool simple) const
924{
925 if (simple)
926 {
927 pp_string (pp, "(");
928 dump_tree (pp, t: get_type ());
929 pp_string (pp, ")");
930 dump_tree (pp, t: m_cst_expr);
931 }
932 else
933 {
934 pp_string (pp, "constant_svalue(");
935 if (get_type ())
936 {
937 print_quoted_type (pp, t: get_type ());
938 pp_string (pp, ", ");
939 }
940 dump_tree (pp, t: m_cst_expr);
941 pp_string (pp, ")");
942 }
943}
944
945/* Implementation of svalue::accept vfunc for constant_svalue. */
946
947void
948constant_svalue::accept (visitor *v) const
949{
950 v->visit_constant_svalue (this);
951}
952
953/* Implementation of svalue::implicitly_live_p vfunc for constant_svalue.
954 Constants are implicitly live. */
955
956bool
957constant_svalue::implicitly_live_p (const svalue_set *,
958 const region_model *) const
959{
960 return true;
961}
962
963/* Given EXPR, a non-NULL expression of boolean type, convert to
964 a tristate based on whether this is known to be true, false,
965 or is not known. */
966
967static tristate
968tristate_from_boolean_tree_node (tree expr)
969{
970 gcc_assert (TREE_TYPE (expr) == boolean_type_node);
971
972 if (expr == boolean_true_node)
973 return tristate (tristate::TS_TRUE);
974 else if (expr == boolean_false_node)
975 return tristate (tristate::TS_FALSE);
976 else
977 return tristate (tristate::TS_UNKNOWN);
978}
979
980/* Evaluate the condition LHS OP RHS.
981 Subroutine of region_model::eval_condition for when we have a pair of
982 constants. */
983
984tristate
985constant_svalue::eval_condition (const constant_svalue *lhs,
986 enum tree_code op,
987 const constant_svalue *rhs)
988{
989 tree lhs_const = lhs->get_constant ();
990 tree rhs_const = rhs->get_constant ();
991
992 gcc_assert (CONSTANT_CLASS_P (lhs_const));
993 gcc_assert (CONSTANT_CLASS_P (rhs_const));
994
995 if ((lhs->get_type () == NULL_TREE || rhs->get_type () == NULL_TREE)
996 && TREE_CODE (lhs_const) == INTEGER_CST
997 && TREE_CODE (rhs_const) == INTEGER_CST
998 )
999 {
1000 if (tree tree_cmp = const_binop (op, boolean_type_node,
1001 lhs_const, rhs_const))
1002 {
1003 tristate ts = tristate_from_boolean_tree_node (expr: tree_cmp);
1004 if (ts.is_known ())
1005 return ts;
1006 }
1007 }
1008
1009 /* Check for comparable types. */
1010 if (types_compatible_p (TREE_TYPE (lhs_const), TREE_TYPE (rhs_const)))
1011 {
1012 tree tree_cmp
1013 = fold_binary (op, boolean_type_node, lhs_const, rhs_const);
1014 tristate ts = tristate_from_boolean_tree_node (expr: tree_cmp);
1015 if (ts.is_known ())
1016 return ts;
1017 }
1018 return tristate::TS_UNKNOWN;
1019}
1020
1021/* Implementation of svalue::maybe_fold_bits_within vfunc
1022 for constant_svalue. */
1023
1024const svalue *
1025constant_svalue::maybe_fold_bits_within (tree type,
1026 const bit_range &bits,
1027 region_model_manager *mgr) const
1028{
1029 /* Bits within an all-zero value are also all zero. */
1030 if (zerop (m_cst_expr))
1031 {
1032 if (type)
1033 return mgr->get_or_create_cast (type, arg: this);
1034 else
1035 return this;
1036 }
1037
1038 /* Handle the case of extracting a single bit. */
1039 if (bits.m_size_in_bits == 1
1040 && TREE_CODE (m_cst_expr) == INTEGER_CST
1041 && type
1042 && INTEGRAL_TYPE_P (type)
1043 && tree_fits_uhwi_p (m_cst_expr))
1044 {
1045 unsigned HOST_WIDE_INT bit = bits.m_start_bit_offset.to_uhwi ();
1046 unsigned HOST_WIDE_INT mask = (1 << bit);
1047 unsigned HOST_WIDE_INT val_as_hwi = tree_to_uhwi (m_cst_expr);
1048 unsigned HOST_WIDE_INT masked_val = val_as_hwi & mask;
1049 int result = masked_val ? 1 : 0;
1050 return mgr->get_or_create_int_cst (type, cst: result);
1051 }
1052
1053 /* Otherwise, don't fold. */
1054 return NULL;
1055}
1056
1057/* Implementation of svalue::all_zeroes_p for constant_svalue. */
1058
1059bool
1060constant_svalue::all_zeroes_p () const
1061{
1062 return zerop (m_cst_expr);
1063}
1064
1065/* class unknown_svalue : public svalue. */
1066
1067/* Implementation of svalue::dump_to_pp vfunc for unknown_svalue. */
1068
1069void
1070unknown_svalue::dump_to_pp (pretty_printer *pp, bool simple) const
1071{
1072 if (simple)
1073 {
1074 pp_string (pp, "UNKNOWN(");
1075 if (get_type ())
1076 dump_tree (pp, t: get_type ());
1077 pp_character (pp, ')');
1078 }
1079 else
1080 {
1081 pp_string (pp, "unknown_svalue(");
1082 if (get_type ())
1083 dump_tree (pp, t: get_type ());
1084 pp_character (pp, ')');
1085 }
1086}
1087
1088/* Implementation of svalue::accept vfunc for unknown_svalue. */
1089
1090void
1091unknown_svalue::accept (visitor *v) const
1092{
1093 v->visit_unknown_svalue (this);
1094}
1095
1096/* Implementation of svalue::maybe_fold_bits_within vfunc
1097 for unknown_svalue. */
1098
1099const svalue *
1100unknown_svalue::maybe_fold_bits_within (tree type,
1101 const bit_range &,
1102 region_model_manager *mgr) const
1103{
1104 /* Bits within an unknown_svalue are themselves unknown. */
1105 return mgr->get_or_create_unknown_svalue (type);
1106}
1107
1108/* Get a string for KIND for use in debug dumps. */
1109
1110const char *
1111poison_kind_to_str (enum poison_kind kind)
1112{
1113 switch (kind)
1114 {
1115 default:
1116 gcc_unreachable ();
1117 case POISON_KIND_UNINIT:
1118 return "uninit";
1119 case POISON_KIND_FREED:
1120 return "freed";
1121 case POISON_KIND_DELETED:
1122 return "deleted";
1123 case POISON_KIND_POPPED_STACK:
1124 return "popped stack";
1125 }
1126}
1127
1128/* class poisoned_svalue : public svalue. */
1129
1130/* Implementation of svalue::dump_to_pp vfunc for poisoned_svalue. */
1131
1132void
1133poisoned_svalue::dump_to_pp (pretty_printer *pp, bool simple) const
1134{
1135 if (simple)
1136 {
1137 pp_string (pp, "POISONED(");
1138 print_quoted_type (pp, t: get_type ());
1139 pp_printf (pp, ", %s)", poison_kind_to_str (kind: m_kind));
1140 }
1141 else
1142 {
1143 pp_string (pp, "poisoned_svalue(");
1144 print_quoted_type (pp, t: get_type ());
1145 pp_printf (pp, ", %s)", poison_kind_to_str (kind: m_kind));
1146 }
1147}
1148
1149/* Implementation of svalue::accept vfunc for poisoned_svalue. */
1150
1151void
1152poisoned_svalue::accept (visitor *v) const
1153{
1154 v->visit_poisoned_svalue (this);
1155}
1156
1157/* Implementation of svalue::maybe_fold_bits_within vfunc
1158 for poisoned_svalue. */
1159
1160const svalue *
1161poisoned_svalue::maybe_fold_bits_within (tree type,
1162 const bit_range &,
1163 region_model_manager *mgr) const
1164{
1165 /* Bits within a poisoned value are also poisoned. */
1166 return mgr->get_or_create_poisoned_svalue (kind: m_kind, type);
1167}
1168
1169/* class setjmp_svalue's implementation is in engine.cc, so that it can use
1170 the declaration of exploded_node. */
1171
1172/* class initial_svalue : public svalue. */
1173
1174/* Implementation of svalue::dump_to_pp vfunc for initial_svalue. */
1175
1176void
1177initial_svalue::dump_to_pp (pretty_printer *pp, bool simple) const
1178{
1179 if (simple)
1180 {
1181 pp_string (pp, "INIT_VAL(");
1182 m_reg->dump_to_pp (pp, simple);
1183 pp_string (pp, ")");
1184 }
1185 else
1186 {
1187 pp_string (pp, "initial_svalue(");
1188 if (get_type ())
1189 {
1190 print_quoted_type (pp, t: get_type ());
1191 pp_string (pp, ", ");
1192 }
1193 m_reg->dump_to_pp (pp, simple);
1194 pp_string (pp, ")");
1195 }
1196}
1197
1198/* Implementation of svalue::accept vfunc for initial_svalue. */
1199
1200void
1201initial_svalue::accept (visitor *v) const
1202{
1203 m_reg->accept (v);
1204 v->visit_initial_svalue (this);
1205}
1206
1207/* Implementation of svalue::implicitly_live_p vfunc for initial_svalue. */
1208
1209bool
1210initial_svalue::implicitly_live_p (const svalue_set *,
1211 const region_model *model) const
1212{
1213 /* This svalue may be implicitly live if the region still implicitly
1214 has its initial value and is reachable. */
1215
1216 /* It must be a region that exists; we don't want to consider
1217 INIT_VAL(R) as still being implicitly reachable if R is in
1218 a popped stack frame. */
1219 if (model->region_exists_p (reg: m_reg))
1220 {
1221 const svalue *reg_sval = model->get_store_value (reg: m_reg, NULL);
1222 if (reg_sval == this)
1223 return true;
1224 }
1225
1226 /* Assume that the initial values of params for the top level frame
1227 are still live, because (presumably) they're still
1228 live in the external caller. */
1229 if (initial_value_of_param_p ())
1230 if (const frame_region *frame_reg = m_reg->maybe_get_frame_region ())
1231 if (frame_reg->get_calling_frame () == NULL)
1232 return true;
1233
1234 return false;
1235}
1236
1237/* Return true if this is the initial value of a function parameter. */
1238
1239bool
1240initial_svalue::initial_value_of_param_p () const
1241{
1242 if (tree reg_decl = m_reg->maybe_get_decl ())
1243 if (TREE_CODE (reg_decl) == SSA_NAME)
1244 {
1245 tree ssa_name = reg_decl;
1246 if (SSA_NAME_IS_DEFAULT_DEF (ssa_name)
1247 && SSA_NAME_VAR (ssa_name)
1248 && TREE_CODE (SSA_NAME_VAR (ssa_name)) == PARM_DECL)
1249 return true;
1250 }
1251 return false;
1252}
1253
1254/* class unaryop_svalue : public svalue. */
1255
1256/* Implementation of svalue::dump_to_pp vfunc for unaryop_svalue. */
1257
1258void
1259unaryop_svalue::dump_to_pp (pretty_printer *pp, bool simple) const
1260{
1261 if (simple)
1262 {
1263 if (m_op == VIEW_CONVERT_EXPR || m_op == NOP_EXPR)
1264 {
1265 pp_string (pp, "CAST(");
1266 dump_tree (pp, t: get_type ());
1267 pp_string (pp, ", ");
1268 m_arg->dump_to_pp (pp, simple);
1269 pp_character (pp, ')');
1270 }
1271 else
1272 {
1273 pp_character (pp, '(');
1274 pp_string (pp, get_tree_code_name (m_op));
1275 //pp_string (pp, op_symbol_code (m_op));
1276 m_arg->dump_to_pp (pp, simple);
1277 pp_character (pp, ')');
1278 }
1279 }
1280 else
1281 {
1282 pp_string (pp, "unaryop_svalue (");
1283 pp_string (pp, get_tree_code_name (m_op));
1284 pp_string (pp, ", ");
1285 m_arg->dump_to_pp (pp, simple);
1286 pp_character (pp, ')');
1287 }
1288}
1289
1290/* Implementation of svalue::accept vfunc for unaryop_svalue. */
1291
1292void
1293unaryop_svalue::accept (visitor *v) const
1294{
1295 m_arg->accept (v);
1296 v->visit_unaryop_svalue (this);
1297}
1298
1299/* Implementation of svalue::implicitly_live_p vfunc for unaryop_svalue. */
1300
1301bool
1302unaryop_svalue::implicitly_live_p (const svalue_set *live_svalues,
1303 const region_model *model) const
1304{
1305 return get_arg ()->live_p (live_svalues, model);
1306}
1307
1308/* Implementation of svalue::maybe_fold_bits_within vfunc
1309 for unaryop_svalue. */
1310
1311const svalue *
1312unaryop_svalue::maybe_fold_bits_within (tree type,
1313 const bit_range &,
1314 region_model_manager *mgr) const
1315{
1316 switch (m_op)
1317 {
1318 default:
1319 break;
1320 case NOP_EXPR:
1321 /* A cast of zero is zero. */
1322 if (tree cst = m_arg->maybe_get_constant ())
1323 if (zerop (cst))
1324 {
1325 if (type)
1326 return mgr->get_or_create_cast (type, arg: this);
1327 else
1328 return this;
1329 }
1330 break;
1331 }
1332 /* Otherwise, don't fold. */
1333 return NULL;
1334}
1335
1336/* class binop_svalue : public svalue. */
1337
1338/* Return whether OP be printed as an infix operator. */
1339
1340static bool
1341infix_p (enum tree_code op)
1342{
1343 switch (op)
1344 {
1345 default:
1346 return true;
1347 case MAX_EXPR:
1348 case MIN_EXPR:
1349 return false;
1350 }
1351}
1352
1353/* Implementation of svalue::dump_to_pp vfunc for binop_svalue. */
1354
1355void
1356binop_svalue::dump_to_pp (pretty_printer *pp, bool simple) const
1357{
1358 if (simple)
1359 {
1360 if (infix_p (op: m_op))
1361 {
1362 /* Print "(A OP B)". */
1363 pp_character (pp, '(');
1364 m_arg0->dump_to_pp (pp, simple);
1365 pp_string (pp, op_symbol_code (m_op));
1366 m_arg1->dump_to_pp (pp, simple);
1367 pp_character (pp, ')');
1368 }
1369 else
1370 {
1371 /* Print "OP(A, B)". */
1372 pp_string (pp, op_symbol_code (m_op));
1373 pp_character (pp, '(');
1374 m_arg0->dump_to_pp (pp, simple);
1375 pp_string (pp, ", ");
1376 m_arg1->dump_to_pp (pp, simple);
1377 pp_character (pp, ')');
1378 }
1379 }
1380 else
1381 {
1382 pp_string (pp, "binop_svalue (");
1383 pp_string (pp, get_tree_code_name (m_op));
1384 pp_string (pp, ", ");
1385 m_arg0->dump_to_pp (pp, simple);
1386 pp_string (pp, ", ");
1387 m_arg1->dump_to_pp (pp, simple);
1388 pp_character (pp, ')');
1389 }
1390}
1391
1392/* Implementation of svalue::accept vfunc for binop_svalue. */
1393
1394void
1395binop_svalue::accept (visitor *v) const
1396{
1397 m_arg0->accept (v);
1398 m_arg1->accept (v);
1399 v->visit_binop_svalue (this);
1400}
1401
1402/* Implementation of svalue::implicitly_live_p vfunc for binop_svalue. */
1403
1404bool
1405binop_svalue::implicitly_live_p (const svalue_set *live_svalues,
1406 const region_model *model) const
1407{
1408 return (get_arg0 ()->live_p (live_svalues, model)
1409 && get_arg1 ()->live_p (live_svalues, model));
1410}
1411
1412/* class sub_svalue : public svalue. */
1413
1414/* sub_svalue'c ctor. */
1415
1416sub_svalue::sub_svalue (symbol::id_t id,
1417 tree type, const svalue *parent_svalue,
1418 const region *subregion)
1419: svalue (complexity::from_pair (c1: parent_svalue->get_complexity (),
1420 c: subregion->get_complexity ()),
1421 id,
1422 type),
1423 m_parent_svalue (parent_svalue), m_subregion (subregion)
1424{
1425 gcc_assert (parent_svalue->can_have_associated_state_p ());
1426}
1427
1428/* Implementation of svalue::dump_to_pp vfunc for sub_svalue. */
1429
1430void
1431sub_svalue::dump_to_pp (pretty_printer *pp, bool simple) const
1432{
1433 if (simple)
1434 {
1435 pp_string (pp, "SUB(");
1436 m_parent_svalue->dump_to_pp (pp, simple);
1437 pp_string (pp, ", ");
1438 m_subregion->dump_to_pp (pp, simple);
1439 pp_character (pp, ')');
1440 }
1441 else
1442 {
1443 pp_string (pp, "sub_svalue (");
1444 pp_string (pp, ", ");
1445 m_parent_svalue->dump_to_pp (pp, simple);
1446 pp_string (pp, ", ");
1447 m_subregion->dump_to_pp (pp, simple);
1448 pp_character (pp, ')');
1449 }
1450}
1451
1452/* Implementation of svalue::accept vfunc for sub_svalue. */
1453
1454void
1455sub_svalue::accept (visitor *v) const
1456{
1457 m_parent_svalue->accept (v);
1458 m_subregion->accept (v);
1459 v->visit_sub_svalue (this);
1460}
1461
1462/* Implementation of svalue::implicitly_live_p vfunc for sub_svalue. */
1463
1464bool
1465sub_svalue::implicitly_live_p (const svalue_set *live_svalues,
1466 const region_model *model) const
1467{
1468 return get_parent ()->live_p (live_svalues, model);
1469}
1470
1471/* class repeated_svalue : public svalue. */
1472
1473/* repeated_svalue'c ctor. */
1474
1475repeated_svalue::repeated_svalue (symbol::id_t id,
1476 tree type,
1477 const svalue *outer_size,
1478 const svalue *inner_svalue)
1479: svalue (complexity::from_pair (c1: outer_size, c: inner_svalue), id, type),
1480 m_outer_size (outer_size),
1481 m_inner_svalue (inner_svalue)
1482{
1483 gcc_assert (outer_size->can_have_associated_state_p ());
1484 gcc_assert (inner_svalue->can_have_associated_state_p ());
1485}
1486
1487/* Implementation of svalue::dump_to_pp vfunc for repeated_svalue. */
1488
1489void
1490repeated_svalue::dump_to_pp (pretty_printer *pp, bool simple) const
1491{
1492 if (simple)
1493 {
1494 pp_string (pp, "REPEATED(");
1495 if (get_type ())
1496 {
1497 print_quoted_type (pp, t: get_type ());
1498 pp_string (pp, ", ");
1499 }
1500 pp_string (pp, "outer_size: ");
1501 m_outer_size->dump_to_pp (pp, simple);
1502 pp_string (pp, ", inner_val: ");
1503 m_inner_svalue->dump_to_pp (pp, simple);
1504 pp_character (pp, ')');
1505 }
1506 else
1507 {
1508 pp_string (pp, "repeated_svalue (");
1509 if (get_type ())
1510 {
1511 print_quoted_type (pp, t: get_type ());
1512 pp_string (pp, ", ");
1513 }
1514 pp_string (pp, "outer_size: ");
1515 m_outer_size->dump_to_pp (pp, simple);
1516 pp_string (pp, ", inner_val: ");
1517 m_inner_svalue->dump_to_pp (pp, simple);
1518 pp_character (pp, ')');
1519 }
1520}
1521
1522/* Implementation of svalue::accept vfunc for repeated_svalue. */
1523
1524void
1525repeated_svalue::accept (visitor *v) const
1526{
1527 m_inner_svalue->accept (v);
1528 v->visit_repeated_svalue (this);
1529}
1530
1531/* Implementation of svalue::all_zeroes_p for repeated_svalue. */
1532
1533bool
1534repeated_svalue::all_zeroes_p () const
1535{
1536 return m_inner_svalue->all_zeroes_p ();
1537}
1538
1539/* Implementation of svalue::maybe_fold_bits_within vfunc
1540 for repeated_svalue. */
1541
1542const svalue *
1543repeated_svalue::maybe_fold_bits_within (tree type,
1544 const bit_range &bits,
1545 region_model_manager *mgr) const
1546{
1547 const svalue *innermost_sval = m_inner_svalue;
1548 /* Fold
1549 BITS_WITHIN (range, REPEATED_SVALUE (ZERO))
1550 to:
1551 REPEATED_SVALUE (ZERO). */
1552 if (all_zeroes_p ())
1553 {
1554 byte_range bytes (0,0);
1555 if (bits.as_byte_range (out: &bytes))
1556 {
1557 const svalue *byte_size
1558 = mgr->get_or_create_int_cst (size_type_node,
1559 cst: bytes.m_size_in_bytes.to_uhwi ());
1560 return mgr->get_or_create_repeated_svalue (type, outer_size: byte_size,
1561 inner_svalue: innermost_sval);
1562 }
1563 }
1564
1565 /* Fold:
1566 BITS_WITHIN (range, REPEATED_SVALUE (INNERMOST_SVALUE))
1567 to:
1568 BITS_WITHIN (range - offset, INNERMOST_SVALUE)
1569 if range is fully within one instance of INNERMOST_SVALUE. */
1570 if (tree innermost_type = innermost_sval->get_type ())
1571 {
1572 bit_size_t element_bit_size;
1573 if (int_size_in_bits (type: innermost_type, out: &element_bit_size)
1574 && element_bit_size > 0)
1575 {
1576 HOST_WIDE_INT start_idx
1577 = (bits.get_start_bit_offset ()
1578 / element_bit_size).to_shwi ();
1579 HOST_WIDE_INT last_idx
1580 = (bits.get_last_bit_offset ()
1581 / element_bit_size).to_shwi ();
1582 if (start_idx == last_idx)
1583 {
1584 bit_offset_t start_of_element
1585 = start_idx * element_bit_size;
1586 bit_range range_within_element
1587 (bits.m_start_bit_offset - start_of_element,
1588 bits.m_size_in_bits);
1589 return mgr->get_or_create_bits_within (type,
1590 bits: range_within_element,
1591 inner_svalue: innermost_sval);
1592 }
1593 }
1594 }
1595
1596 return NULL;
1597}
1598
1599/* class bits_within_svalue : public svalue. */
1600
1601/* bits_within_svalue'c ctor. */
1602
1603bits_within_svalue::bits_within_svalue (symbol::id_t id,
1604 tree type,
1605 const bit_range &bits,
1606 const svalue *inner_svalue)
1607: svalue (complexity (inner_svalue), id, type),
1608 m_bits (bits),
1609 m_inner_svalue (inner_svalue)
1610{
1611 gcc_assert (inner_svalue->can_have_associated_state_p ());
1612}
1613
1614/* Implementation of svalue::dump_to_pp vfunc for bits_within_svalue. */
1615
1616void
1617bits_within_svalue::dump_to_pp (pretty_printer *pp, bool simple) const
1618{
1619 if (simple)
1620 {
1621 pp_string (pp, "BITS_WITHIN(");
1622 if (get_type ())
1623 {
1624 print_quoted_type (pp, t: get_type ());
1625 pp_string (pp, ", ");
1626 }
1627 m_bits.dump_to_pp (pp);
1628 pp_string (pp, ", inner_val: ");
1629 m_inner_svalue->dump_to_pp (pp, simple);
1630 pp_character (pp, ')');
1631 }
1632 else
1633 {
1634 pp_string (pp, "bits_within_svalue (");
1635 if (get_type ())
1636 {
1637 print_quoted_type (pp, t: get_type ());
1638 pp_string (pp, ", ");
1639 }
1640 m_bits.dump_to_pp (pp);
1641 pp_string (pp, ", inner_val: ");
1642 m_inner_svalue->dump_to_pp (pp, simple);
1643 pp_character (pp, ')');
1644 }
1645}
1646
1647/* Implementation of svalue::maybe_fold_bits_within vfunc
1648 for bits_within_svalue. */
1649
1650const svalue *
1651bits_within_svalue::maybe_fold_bits_within (tree type,
1652 const bit_range &bits,
1653 region_model_manager *mgr) const
1654{
1655 /* Fold:
1656 BITS_WITHIN (range1, BITS_WITHIN (range2, VAL))
1657 to:
1658 BITS_WITHIN (range1 in range 2, VAL). */
1659 bit_range offset_bits (m_bits.get_start_bit_offset ()
1660 + bits.m_start_bit_offset,
1661 bits.m_size_in_bits);
1662 return mgr->get_or_create_bits_within (type, bits: offset_bits, inner_svalue: m_inner_svalue);
1663}
1664
1665/* Implementation of svalue::accept vfunc for bits_within_svalue. */
1666
1667void
1668bits_within_svalue::accept (visitor *v) const
1669{
1670 m_inner_svalue->accept (v);
1671 v->visit_bits_within_svalue (this);
1672}
1673
1674/* Implementation of svalue::implicitly_live_p vfunc for bits_within_svalue. */
1675
1676bool
1677bits_within_svalue::implicitly_live_p (const svalue_set *live_svalues,
1678 const region_model *model) const
1679{
1680 return m_inner_svalue->live_p (live_svalues, model);
1681}
1682
1683/* class widening_svalue : public svalue. */
1684
1685/* Implementation of svalue::dump_to_pp vfunc for widening_svalue. */
1686
1687void
1688widening_svalue::dump_to_pp (pretty_printer *pp, bool simple) const
1689{
1690 if (simple)
1691 {
1692 pp_string (pp, "WIDENING(");
1693 pp_character (pp, '{');
1694 m_point.print (pp, f: format (false));
1695 pp_string (pp, "}, ");
1696 m_base_sval->dump_to_pp (pp, simple);
1697 pp_string (pp, ", ");
1698 m_iter_sval->dump_to_pp (pp, simple);
1699 pp_character (pp, ')');
1700 }
1701 else
1702 {
1703 pp_string (pp, "widening_svalue (");
1704 pp_string (pp, ", ");
1705 pp_character (pp, '{');
1706 m_point.print (pp, f: format (false));
1707 pp_string (pp, "}, ");
1708 m_base_sval->dump_to_pp (pp, simple);
1709 pp_string (pp, ", ");
1710 m_iter_sval->dump_to_pp (pp, simple);
1711 pp_character (pp, ')');
1712 }
1713}
1714
1715/* Implementation of svalue::accept vfunc for widening_svalue. */
1716
1717void
1718widening_svalue::accept (visitor *v) const
1719{
1720 m_base_sval->accept (v);
1721 m_iter_sval->accept (v);
1722 v->visit_widening_svalue (this);
1723}
1724
1725/* Attempt to determine in which direction this value is changing
1726 w.r.t. the initial value. */
1727
1728enum widening_svalue::direction_t
1729widening_svalue::get_direction () const
1730{
1731 tree base_cst = m_base_sval->maybe_get_constant ();
1732 if (base_cst == NULL_TREE)
1733 return DIR_UNKNOWN;
1734 tree iter_cst = m_iter_sval->maybe_get_constant ();
1735 if (iter_cst == NULL_TREE)
1736 return DIR_UNKNOWN;
1737
1738 tree iter_gt_base = fold_binary (GT_EXPR, boolean_type_node,
1739 iter_cst, base_cst);
1740 if (iter_gt_base == boolean_true_node)
1741 return DIR_ASCENDING;
1742
1743 tree iter_lt_base = fold_binary (LT_EXPR, boolean_type_node,
1744 iter_cst, base_cst);
1745 if (iter_lt_base == boolean_true_node)
1746 return DIR_DESCENDING;
1747
1748 return DIR_UNKNOWN;
1749}
1750
1751/* Compare this value against constant RHS_CST. */
1752
1753tristate
1754widening_svalue::eval_condition_without_cm (enum tree_code op,
1755 tree rhs_cst) const
1756{
1757 tree base_cst = m_base_sval->maybe_get_constant ();
1758 if (base_cst == NULL_TREE)
1759 return tristate::TS_UNKNOWN;
1760 tree iter_cst = m_iter_sval->maybe_get_constant ();
1761 if (iter_cst == NULL_TREE)
1762 return tristate::TS_UNKNOWN;
1763
1764 switch (get_direction ())
1765 {
1766 default:
1767 gcc_unreachable ();
1768 case DIR_ASCENDING:
1769 /* LHS is in [base_cst, +ve infinity), assuming no overflow. */
1770 switch (op)
1771 {
1772 case LE_EXPR:
1773 case LT_EXPR:
1774 {
1775 /* [BASE, +INF) OP RHS:
1776 This is either true or false at +ve ininity,
1777 It can be true for points X where X OP RHS, so we have either
1778 "false", or "unknown". */
1779 tree base_op_rhs = fold_binary (op, boolean_type_node,
1780 base_cst, rhs_cst);
1781 if (base_op_rhs == boolean_true_node)
1782 return tristate::TS_UNKNOWN;
1783 else
1784 return tristate::TS_FALSE;
1785 }
1786
1787 case GE_EXPR:
1788 case GT_EXPR:
1789 {
1790 /* [BASE, +INF) OP RHS:
1791 This is true at +ve infinity. It will be true everywhere
1792 in the range if BASE >= RHS. */
1793 tree base_op_rhs = fold_binary (op, boolean_type_node,
1794 base_cst, rhs_cst);
1795 if (base_op_rhs == boolean_true_node)
1796 return tristate::TS_TRUE;
1797 else
1798 return tristate::TS_UNKNOWN;
1799 }
1800
1801 case EQ_EXPR:
1802 {
1803 /* [BASE, +INF) == RHS:
1804 Could this be true at any point in the range? If so we
1805 have "unknown", otherwise we have "false". */
1806 tree base_le_rhs = fold_binary (LE_EXPR, boolean_type_node,
1807 base_cst, rhs_cst);
1808 if (base_le_rhs == boolean_true_node)
1809 return tristate::TS_UNKNOWN;
1810 else
1811 return tristate::TS_FALSE;
1812 }
1813
1814 case NE_EXPR:
1815 {
1816 /* [BASE, +INF) != RHS:
1817 Could we have equality at any point in the range? If so we
1818 have "unknown", otherwise we have "true". */
1819 tree base_le_rhs = fold_binary (LE_EXPR, boolean_type_node,
1820 base_cst, rhs_cst);
1821 if (base_le_rhs == boolean_true_node)
1822 return tristate::TS_UNKNOWN;
1823 else
1824 return tristate::TS_TRUE;
1825 }
1826
1827 default:
1828 return tristate::TS_UNKNOWN;
1829 }
1830
1831 case DIR_DESCENDING:
1832 /* LHS is in (-ve infinity, base_cst], assuming no overflow. */
1833 return tristate::TS_UNKNOWN;
1834
1835 case DIR_UNKNOWN:
1836 return tristate::TS_UNKNOWN;
1837 }
1838}
1839
1840/* class placeholder_svalue : public svalue. */
1841
1842/* Implementation of svalue::dump_to_pp vfunc for placeholder_svalue. */
1843
1844void
1845placeholder_svalue::dump_to_pp (pretty_printer *pp, bool simple) const
1846{
1847 if (simple)
1848 pp_printf (pp, "PLACEHOLDER(%qs)", m_name);
1849 else
1850 pp_printf (pp, "placeholder_svalue (%qs)", m_name);
1851}
1852
1853/* Implementation of svalue::accept vfunc for placeholder_svalue. */
1854
1855void
1856placeholder_svalue::accept (visitor *v) const
1857{
1858 v->visit_placeholder_svalue (this);
1859}
1860
1861/* class unmergeable_svalue : public svalue. */
1862
1863/* Implementation of svalue::dump_to_pp vfunc for unmergeable_svalue. */
1864
1865void
1866unmergeable_svalue::dump_to_pp (pretty_printer *pp, bool simple) const
1867{
1868 if (simple)
1869 {
1870 pp_string (pp, "UNMERGEABLE(");
1871 m_arg->dump_to_pp (pp, simple);
1872 pp_character (pp, ')');
1873 }
1874 else
1875 {
1876 pp_string (pp, "unmergeable_svalue (");
1877 m_arg->dump_to_pp (pp, simple);
1878 pp_character (pp, ')');
1879 }
1880}
1881
1882/* Implementation of svalue::accept vfunc for unmergeable_svalue. */
1883
1884void
1885unmergeable_svalue::accept (visitor *v) const
1886{
1887 m_arg->accept (v);
1888 v->visit_unmergeable_svalue (this);
1889}
1890
1891/* Implementation of svalue::implicitly_live_p vfunc for unmergeable_svalue. */
1892
1893bool
1894unmergeable_svalue::implicitly_live_p (const svalue_set *live_svalues,
1895 const region_model *model) const
1896{
1897 return get_arg ()->live_p (live_svalues, model);
1898}
1899
1900/* class compound_svalue : public svalue. */
1901
1902compound_svalue::compound_svalue (symbol::id_t id,
1903 tree type,
1904 const binding_map &map)
1905: svalue (calc_complexity (map), id, type), m_map (map)
1906{
1907#if CHECKING_P
1908 for (iterator_t iter = begin (); iter != end (); ++iter)
1909 {
1910 /* All keys within the underlying binding_map are required to be concrete,
1911 not symbolic. */
1912 const binding_key *key = (*iter).first;
1913 gcc_assert (key->concrete_p ());
1914
1915 /* We don't nest compound svalues. */
1916 const svalue *sval = (*iter).second;
1917 gcc_assert (sval->get_kind () != SK_COMPOUND);
1918 }
1919#endif
1920}
1921
1922/* Implementation of svalue::dump_to_pp vfunc for compound_svalue. */
1923
1924void
1925compound_svalue::dump_to_pp (pretty_printer *pp, bool simple) const
1926{
1927 if (simple)
1928 {
1929 pp_string (pp, "COMPOUND(");
1930 if (get_type ())
1931 {
1932 print_quoted_type (pp, t: get_type ());
1933 pp_string (pp, ", ");
1934 }
1935 pp_character (pp, '{');
1936 m_map.dump_to_pp (pp, simple, multiline: false);
1937 pp_string (pp, "})");
1938 }
1939 else
1940 {
1941 pp_string (pp, "compound_svalue (");
1942 if (get_type ())
1943 {
1944 print_quoted_type (pp, t: get_type ());
1945 pp_string (pp, ", ");
1946 }
1947 pp_character (pp, '{');
1948 m_map.dump_to_pp (pp, simple, multiline: false);
1949 pp_string (pp, "})");
1950 }
1951}
1952
1953/* Implementation of svalue::accept vfunc for compound_svalue. */
1954
1955void
1956compound_svalue::accept (visitor *v) const
1957{
1958 for (binding_map::iterator_t iter = m_map.begin ();
1959 iter != m_map.end (); ++iter)
1960 {
1961 //(*iter).first.accept (v);
1962 (*iter).second->accept (v);
1963 }
1964 v->visit_compound_svalue (this);
1965}
1966
1967/* Calculate what the complexity of a compound_svalue instance for MAP
1968 will be, based on the svalues bound within MAP. */
1969
1970complexity
1971compound_svalue::calc_complexity (const binding_map &map)
1972{
1973 unsigned num_child_nodes = 0;
1974 unsigned max_child_depth = 0;
1975 for (binding_map::iterator_t iter = map.begin ();
1976 iter != map.end (); ++iter)
1977 {
1978 const complexity &sval_c = (*iter).second->get_complexity ();
1979 num_child_nodes += sval_c.m_num_nodes;
1980 max_child_depth = MAX (max_child_depth, sval_c.m_max_depth);
1981 }
1982 return complexity (num_child_nodes + 1, max_child_depth + 1);
1983}
1984
1985/* Implementation of svalue::maybe_fold_bits_within vfunc
1986 for compound_svalue. */
1987
1988const svalue *
1989compound_svalue::maybe_fold_bits_within (tree type,
1990 const bit_range &bits,
1991 region_model_manager *mgr) const
1992{
1993 binding_map result_map;
1994 for (auto iter : m_map)
1995 {
1996 const binding_key *key = iter.first;
1997 if (const concrete_binding *conc_key
1998 = key->dyn_cast_concrete_binding ())
1999 {
2000 /* Ignore concrete bindings outside BITS. */
2001 if (!conc_key->get_bit_range ().intersects_p (other: bits))
2002 continue;
2003
2004 const svalue *sval = iter.second;
2005 /* Get the position of conc_key relative to BITS. */
2006 bit_range result_location (conc_key->get_start_bit_offset ()
2007 - bits.get_start_bit_offset (),
2008 conc_key->get_size_in_bits ());
2009 /* If conc_key starts after BITS, trim off leading bits
2010 from the svalue and adjust binding location. */
2011 if (result_location.m_start_bit_offset < 0)
2012 {
2013 bit_size_t leading_bits_to_drop
2014 = -result_location.m_start_bit_offset;
2015 result_location = bit_range
2016 (0, result_location.m_size_in_bits - leading_bits_to_drop);
2017 bit_range bits_within_sval (leading_bits_to_drop,
2018 result_location.m_size_in_bits);
2019 /* Trim off leading bits from iter_sval. */
2020 sval = mgr->get_or_create_bits_within (NULL_TREE,
2021 bits: bits_within_sval,
2022 inner_svalue: sval);
2023 }
2024 /* If conc_key finishes after BITS, trim off trailing bits
2025 from the svalue and adjust binding location. */
2026 if (conc_key->get_next_bit_offset ()
2027 > bits.get_next_bit_offset ())
2028 {
2029 bit_size_t trailing_bits_to_drop
2030 = (conc_key->get_next_bit_offset ()
2031 - bits.get_next_bit_offset ());
2032 result_location = bit_range
2033 (result_location.m_start_bit_offset,
2034 result_location.m_size_in_bits - trailing_bits_to_drop);
2035 bit_range bits_within_sval (0,
2036 result_location.m_size_in_bits);
2037 /* Trim off leading bits from iter_sval. */
2038 sval = mgr->get_or_create_bits_within (NULL_TREE,
2039 bits: bits_within_sval,
2040 inner_svalue: sval);
2041 }
2042 const concrete_binding *offset_conc_key
2043 = mgr->get_store_manager ()->get_concrete_binding
2044 (bits: result_location);
2045 result_map.put (k: offset_conc_key, v: sval);
2046 }
2047 else
2048 /* If we have any symbolic keys we can't get it as bits. */
2049 return NULL;
2050 }
2051 return mgr->get_or_create_compound_svalue (type, map: result_map);
2052}
2053
2054/* class conjured_svalue : public svalue. */
2055
2056/* Implementation of svalue::dump_to_pp vfunc for conjured_svalue. */
2057
2058void
2059conjured_svalue::dump_to_pp (pretty_printer *pp, bool simple) const
2060{
2061 if (simple)
2062 {
2063 pp_string (pp, "CONJURED(");
2064 pp_gimple_stmt_1 (pp, m_stmt, 0, (dump_flags_t)0);
2065 pp_string (pp, ", ");
2066 m_id_reg->dump_to_pp (pp, simple);
2067 pp_character (pp, ')');
2068 }
2069 else
2070 {
2071 pp_string (pp, "conjured_svalue (");
2072 if (get_type ())
2073 {
2074 print_quoted_type (pp, t: get_type ());
2075 pp_string (pp, ", ");
2076 }
2077 pp_gimple_stmt_1 (pp, m_stmt, 0, (dump_flags_t)0);
2078 pp_string (pp, ", ");
2079 m_id_reg->dump_to_pp (pp, simple);
2080 pp_character (pp, ')');
2081 }
2082}
2083
2084/* Implementation of svalue::accept vfunc for conjured_svalue. */
2085
2086void
2087conjured_svalue::accept (visitor *v) const
2088{
2089 m_id_reg->accept (v);
2090 v->visit_conjured_svalue (this);
2091}
2092
2093/* Return true iff this conjured_svalue is for the LHS of the
2094 stmt that conjured it. */
2095
2096bool
2097conjured_svalue::lhs_value_p () const
2098{
2099 if (tree decl = m_id_reg->maybe_get_decl ())
2100 return decl == gimple_get_lhs (m_stmt);
2101 return false;
2102}
2103
2104/* class asm_output_svalue : public svalue. */
2105
2106/* Implementation of svalue::dump_to_pp vfunc for asm_output_svalue. */
2107
2108void
2109asm_output_svalue::dump_to_pp (pretty_printer *pp, bool simple) const
2110{
2111 if (simple)
2112 {
2113 pp_printf (pp, "ASM_OUTPUT(%qs, %%%i, {",
2114 get_asm_string (),
2115 get_output_idx ());
2116 for (unsigned i = 0; i < m_num_inputs; i++)
2117 {
2118 if (i > 0)
2119 pp_string (pp, ", ");
2120 dump_input (pp, input_idx: 0, sval: m_input_arr[i], simple);
2121 }
2122 pp_string (pp, "})");
2123 }
2124 else
2125 {
2126 pp_printf (pp, "asm_output_svalue (%qs, %%%i, {",
2127 get_asm_string (),
2128 get_output_idx ());
2129 for (unsigned i = 0; i < m_num_inputs; i++)
2130 {
2131 if (i > 0)
2132 pp_string (pp, ", ");
2133 dump_input (pp, input_idx: 0, sval: m_input_arr[i], simple);
2134 }
2135 pp_string (pp, "})");
2136 }
2137}
2138
2139/* Subroutine of asm_output_svalue::dump_to_pp. */
2140
2141void
2142asm_output_svalue::dump_input (pretty_printer *pp,
2143 unsigned input_idx,
2144 const svalue *sval,
2145 bool simple) const
2146{
2147 pp_printf (pp, "%%%i: ", input_idx_to_asm_idx (input_idx));
2148 sval->dump_to_pp (pp, simple);
2149}
2150
2151/* Convert INPUT_IDX from an index into the array of inputs
2152 into the index of all operands for the asm stmt. */
2153
2154unsigned
2155asm_output_svalue::input_idx_to_asm_idx (unsigned input_idx) const
2156{
2157 return input_idx + m_num_outputs;
2158}
2159
2160/* Implementation of svalue::accept vfunc for asm_output_svalue. */
2161
2162void
2163asm_output_svalue::accept (visitor *v) const
2164{
2165 for (unsigned i = 0; i < m_num_inputs; i++)
2166 m_input_arr[i]->accept (v);
2167 v->visit_asm_output_svalue (this);
2168}
2169
2170/* class const_fn_result_svalue : public svalue. */
2171
2172/* Implementation of svalue::dump_to_pp vfunc for const_fn_result_svalue. */
2173
2174void
2175const_fn_result_svalue::dump_to_pp (pretty_printer *pp, bool simple) const
2176{
2177 if (simple)
2178 {
2179 pp_printf (pp, "CONST_FN_RESULT(%qD, {", m_fndecl);
2180 for (unsigned i = 0; i < m_num_inputs; i++)
2181 {
2182 if (i > 0)
2183 pp_string (pp, ", ");
2184 dump_input (pp, input_idx: i, sval: m_input_arr[i], simple);
2185 }
2186 pp_string (pp, "})");
2187 }
2188 else
2189 {
2190 pp_printf (pp, "CONST_FN_RESULT(%qD, {", m_fndecl);
2191 for (unsigned i = 0; i < m_num_inputs; i++)
2192 {
2193 if (i > 0)
2194 pp_string (pp, ", ");
2195 dump_input (pp, input_idx: i, sval: m_input_arr[i], simple);
2196 }
2197 pp_string (pp, "})");
2198 }
2199}
2200
2201/* Subroutine of const_fn_result_svalue::dump_to_pp. */
2202
2203void
2204const_fn_result_svalue::dump_input (pretty_printer *pp,
2205 unsigned input_idx,
2206 const svalue *sval,
2207 bool simple) const
2208{
2209 pp_printf (pp, "arg%i: ", input_idx);
2210 sval->dump_to_pp (pp, simple);
2211}
2212
2213/* Implementation of svalue::accept vfunc for const_fn_result_svalue. */
2214
2215void
2216const_fn_result_svalue::accept (visitor *v) const
2217{
2218 for (unsigned i = 0; i < m_num_inputs; i++)
2219 m_input_arr[i]->accept (v);
2220 v->visit_const_fn_result_svalue (this);
2221}
2222
2223} // namespace ana
2224
2225#endif /* #if ENABLE_ANALYZER */
2226

source code of gcc/analyzer/svalue.cc