Branch data Line data Source code
1 : : /* Consolidation of svalues and regions.
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 "fold-const.h"
24 : : #include "ordered-hash-map.h"
25 : : #include "options.h"
26 : : #include "analyzer/supergraph.h"
27 : : #include "sbitmap.h"
28 : : #include "target.h"
29 : :
30 : : #include "analyzer/analyzer-logging.h"
31 : : #include "analyzer/call-string.h"
32 : : #include "analyzer/program-point.h"
33 : : #include "analyzer/store.h"
34 : : #include "analyzer/region-model.h"
35 : : #include "analyzer/constraint-manager.h"
36 : :
37 : : #if ENABLE_ANALYZER
38 : :
39 : : namespace ana {
40 : :
41 : : /* class region_model_manager. */
42 : :
43 : : /* region_model_manager's ctor. */
44 : :
45 : 3901 : region_model_manager::region_model_manager (logger *logger)
46 : 3901 : : m_logger (logger),
47 : 3901 : m_next_symbol_id (0),
48 : 3901 : m_empty_call_string (),
49 : 3901 : m_root_region (alloc_symbol_id ()),
50 : 3901 : m_stack_region (alloc_symbol_id (), &m_root_region),
51 : 3901 : m_heap_region (alloc_symbol_id (), &m_root_region),
52 : 3901 : m_unknown_NULL (NULL),
53 : 3901 : m_checking_feasibility (false),
54 : 3901 : m_max_complexity (0, 0),
55 : 3901 : m_code_region (alloc_symbol_id (), &m_root_region),
56 : 3901 : m_fndecls_map (), m_labels_map (),
57 : 3901 : m_globals_region (alloc_symbol_id (), &m_root_region),
58 : 3901 : m_globals_map (),
59 : 3901 : m_thread_local_region (alloc_symbol_id (), &m_root_region),
60 : 3901 : m_errno_region (alloc_symbol_id (), &m_thread_local_region),
61 : 3901 : m_store_mgr (this),
62 : 3901 : m_range_mgr (new bounded_ranges_manager ()),
63 : 11703 : m_known_fn_mgr (logger)
64 : : {
65 : 3901 : }
66 : :
67 : : /* region_model_manager's dtor. Delete all of the managed svalues
68 : : and regions. */
69 : :
70 : 7802 : region_model_manager::~region_model_manager ()
71 : : {
72 : : /* Delete consolidated svalues. */
73 : 57370 : for (constants_map_t::iterator iter = m_constants_map.begin ();
74 : 110839 : iter != m_constants_map.end (); ++iter)
75 : 53469 : delete (*iter).second;
76 : 12640 : for (unknowns_map_t::iterator iter = m_unknowns_map.begin ();
77 : 21379 : iter != m_unknowns_map.end (); ++iter)
78 : 8739 : delete (*iter).second;
79 : 3901 : delete m_unknown_NULL;
80 : 9102 : for (poisoned_values_map_t::iterator iter = m_poisoned_values_map.begin ();
81 : 14303 : iter != m_poisoned_values_map.end (); ++iter)
82 : 5201 : delete (*iter).second;
83 : 3935 : for (setjmp_values_map_t::iterator iter = m_setjmp_values_map.begin ();
84 : 3969 : iter != m_setjmp_values_map.end (); ++iter)
85 : 34 : delete (*iter).second;
86 : 28556 : for (initial_values_map_t::iterator iter = m_initial_values_map.begin ();
87 : 53211 : iter != m_initial_values_map.end (); ++iter)
88 : 24655 : delete (*iter).second;
89 : 28584 : for (pointer_values_map_t::iterator iter = m_pointer_values_map.begin ();
90 : 53267 : iter != m_pointer_values_map.end (); ++iter)
91 : 24683 : delete (*iter).second;
92 : 12525 : for (unaryop_values_map_t::iterator iter = m_unaryop_values_map.begin ();
93 : 21149 : iter != m_unaryop_values_map.end (); ++iter)
94 : 8624 : delete (*iter).second;
95 : 25169 : for (binop_values_map_t::iterator iter = m_binop_values_map.begin ();
96 : 46437 : iter != m_binop_values_map.end (); ++iter)
97 : 21268 : delete (*iter).second;
98 : 6382 : for (sub_values_map_t::iterator iter = m_sub_values_map.begin ();
99 : 8863 : iter != m_sub_values_map.end (); ++iter)
100 : 2481 : delete (*iter).second;
101 : 4903 : for (auto iter : m_repeated_values_map)
102 : 501 : delete iter.second;
103 : 5247 : for (auto iter : m_bits_within_values_map)
104 : 673 : delete iter.second;
105 : 4103 : for (unmergeable_values_map_t::iterator iter
106 : 3901 : = m_unmergeable_values_map.begin ();
107 : 4305 : iter != m_unmergeable_values_map.end (); ++iter)
108 : 202 : delete (*iter).second;
109 : 6384 : for (widening_values_map_t::iterator iter = m_widening_values_map.begin ();
110 : 8867 : iter != m_widening_values_map.end (); ++iter)
111 : 2483 : delete (*iter).second;
112 : 4558 : for (compound_values_map_t::iterator iter = m_compound_values_map.begin ();
113 : 5215 : iter != m_compound_values_map.end (); ++iter)
114 : 657 : delete (*iter).second;
115 : 32204 : for (conjured_values_map_t::iterator iter = m_conjured_values_map.begin ();
116 : 60507 : iter != m_conjured_values_map.end (); ++iter)
117 : 28303 : delete (*iter).second;
118 : 4275 : for (auto iter : m_asm_output_values_map)
119 : 187 : delete iter.second;
120 : 4411 : for (auto iter : m_const_fn_result_values_map)
121 : 255 : delete iter.second;
122 : :
123 : : /* Delete consolidated regions. */
124 : 13100 : for (fndecls_map_t::iterator iter = m_fndecls_map.begin ();
125 : 22299 : iter != m_fndecls_map.end (); ++iter)
126 : 9199 : delete (*iter).second;
127 : 3947 : for (labels_map_t::iterator iter = m_labels_map.begin ();
128 : 3993 : iter != m_labels_map.end (); ++iter)
129 : 46 : delete (*iter).second;
130 : 10285 : for (globals_map_t::iterator iter = m_globals_map.begin ();
131 : 16669 : iter != m_globals_map.end (); ++iter)
132 : 6384 : delete (*iter).second;
133 : 7657 : for (string_map_t::iterator iter = m_string_map.begin ();
134 : 11413 : iter != m_string_map.end (); ++iter)
135 : 3756 : delete (*iter).second;
136 : :
137 : 3901 : delete m_range_mgr;
138 : 7802 : }
139 : :
140 : : /* Return true if C exceeds the complexity limit for svalues. */
141 : :
142 : : bool
143 : 166046 : region_model_manager::too_complex_p (const complexity &c) const
144 : : {
145 : 166046 : if (c.m_max_depth > (unsigned)param_analyzer_max_svalue_depth)
146 : 1969 : return true;
147 : : return false;
148 : : }
149 : :
150 : : /* If SVAL exceeds the complexity limit for svalues, delete it
151 : : and return true.
152 : : Otherwise update m_max_complexity and return false. */
153 : :
154 : : bool
155 : 175645 : region_model_manager::reject_if_too_complex (svalue *sval)
156 : : {
157 : 175645 : if (m_checking_feasibility)
158 : : return false;
159 : :
160 : 166046 : const complexity &c = sval->get_complexity ();
161 : 166046 : if (!too_complex_p (c))
162 : : {
163 : 164077 : if (m_max_complexity.m_num_nodes < c.m_num_nodes)
164 : 11450 : m_max_complexity.m_num_nodes = c.m_num_nodes;
165 : 164077 : if (m_max_complexity.m_max_depth < c.m_max_depth)
166 : 10493 : m_max_complexity.m_max_depth = c.m_max_depth;
167 : 164077 : return false;
168 : : }
169 : :
170 : 1969 : pretty_printer pp;
171 : 1969 : pp_format_decoder (&pp) = default_tree_printer;
172 : 1969 : sval->dump_to_pp (&pp, true);
173 : 1969 : if (warning_at (input_location, OPT_Wanalyzer_symbol_too_complex,
174 : : "symbol too complicated: %qs",
175 : : pp_formatted_text (&pp)))
176 : 2 : inform (input_location,
177 : : "max_depth %i exceeds --param=analyzer-max-svalue-depth=%i",
178 : 2 : c.m_max_depth, param_analyzer_max_svalue_depth);
179 : :
180 : 1969 : delete sval;
181 : 1969 : return true;
182 : 1969 : }
183 : :
184 : : /* Macro for imposing a complexity limit on svalues, for use within
185 : : region_model_manager member functions.
186 : :
187 : : If SVAL exceeds the complexity limit, delete it and return an UNKNOWN
188 : : value of the same type.
189 : : Otherwise update m_max_complexity and carry on. */
190 : :
191 : : #define RETURN_UNKNOWN_IF_TOO_COMPLEX(SVAL) \
192 : : do { \
193 : : svalue *sval_ = (SVAL); \
194 : : tree type_ = sval_->get_type (); \
195 : : if (reject_if_too_complex (sval_)) \
196 : : return get_or_create_unknown_svalue (type_); \
197 : : } while (0)
198 : :
199 : : /* svalue consolidation. */
200 : :
201 : : /* Return the svalue * for a constant_svalue for CST_EXPR,
202 : : creating it if necessary.
203 : : The constant_svalue instances are reused, based on pointer equality
204 : : of trees */
205 : :
206 : : const svalue *
207 : 2178252 : region_model_manager::get_or_create_constant_svalue (tree type, tree cst_expr)
208 : : {
209 : 2178252 : gcc_assert (cst_expr);
210 : 2178252 : gcc_assert (CONSTANT_CLASS_P (cst_expr));
211 : 2178252 : gcc_assert (type == TREE_TYPE (cst_expr) || type == NULL_TREE);
212 : :
213 : 2178252 : constant_svalue::key_t key (type, cst_expr);
214 : 2178252 : constant_svalue **slot = m_constants_map.get (key);
215 : 2178252 : if (slot)
216 : 2124101 : return *slot;
217 : 54151 : constant_svalue *cst_sval
218 : 54151 : = new constant_svalue (alloc_symbol_id (), type, cst_expr);
219 : 54151 : RETURN_UNKNOWN_IF_TOO_COMPLEX (cst_sval);
220 : 53469 : m_constants_map.put (key, cst_sval);
221 : 53469 : return cst_sval;
222 : : }
223 : :
224 : : const svalue *
225 : 1415855 : region_model_manager::get_or_create_constant_svalue (tree cst_expr)
226 : : {
227 : 1415855 : tree type = TREE_TYPE (cst_expr);
228 : 1415855 : if (TREE_CODE (cst_expr) == RAW_DATA_CST)
229 : : /* The type of a RAW_DATA_CST is the type of each element, rather than
230 : : that of the constant as a whole, so use NULL_TREE for simplicity. */
231 : 14 : type = NULL_TREE;
232 : 1415855 : return get_or_create_constant_svalue (type, cst_expr);
233 : : }
234 : :
235 : : /* Return the svalue * for a constant_svalue for the INTEGER_CST
236 : : for VAL of type TYPE, creating it if necessary. */
237 : :
238 : : const svalue *
239 : 721880 : region_model_manager::get_or_create_int_cst (tree type,
240 : : const poly_wide_int_ref &cst)
241 : : {
242 : 721880 : tree effective_type = type;
243 : 721880 : if (!type)
244 : 6463 : effective_type = ptrdiff_type_node;
245 : 721880 : gcc_assert (INTEGRAL_TYPE_P (effective_type)
246 : : || POINTER_TYPE_P (effective_type));
247 : 721880 : tree tree_cst = wide_int_to_tree (effective_type, cst);
248 : 721880 : return get_or_create_constant_svalue (type, tree_cst);
249 : : }
250 : :
251 : : /* Return the svalue * for the constant_svalue for the NULL pointer
252 : : of POINTER_TYPE, creating it if necessary. */
253 : :
254 : : const svalue *
255 : 1267 : region_model_manager::get_or_create_null_ptr (tree pointer_type)
256 : : {
257 : 1267 : gcc_assert (pointer_type);
258 : 1267 : gcc_assert (POINTER_TYPE_P (pointer_type));
259 : 1267 : return get_or_create_int_cst (pointer_type, 0);
260 : : }
261 : :
262 : : /* Return the svalue * for a unknown_svalue for TYPE (which can be NULL),
263 : : creating it if necessary.
264 : : The unknown_svalue instances are reused, based on pointer equality
265 : : of the types */
266 : :
267 : : const svalue *
268 : 743331 : region_model_manager::get_or_create_unknown_svalue (tree type)
269 : : {
270 : : /* Don't create unknown values when doing feasibility testing;
271 : : instead, create a unique svalue. */
272 : 743331 : if (m_checking_feasibility)
273 : 14437 : return create_unique_svalue (type);
274 : :
275 : : /* Special-case NULL, so that the hash_map can use NULL as the
276 : : "empty" value. */
277 : 728894 : if (type == NULL_TREE)
278 : : {
279 : 145626 : if (!m_unknown_NULL)
280 : 1696 : m_unknown_NULL = new unknown_svalue (alloc_symbol_id (), type);
281 : 145626 : return m_unknown_NULL;
282 : : }
283 : :
284 : 583268 : unknown_svalue **slot = m_unknowns_map.get (type);
285 : 583268 : if (slot)
286 : 574529 : return *slot;
287 : 8739 : unknown_svalue *sval = new unknown_svalue (alloc_symbol_id (), type);
288 : 8739 : m_unknowns_map.put (type, sval);
289 : 8739 : return sval;
290 : : }
291 : :
292 : : /* Return a freshly-allocated svalue of TYPE, owned by this manager. */
293 : :
294 : : const svalue *
295 : 14437 : region_model_manager::create_unique_svalue (tree type)
296 : : {
297 : 14437 : svalue *sval = new placeholder_svalue (alloc_symbol_id (), type, "unique");
298 : 14437 : m_managed_dynamic_svalues.safe_push (sval);
299 : 14437 : return sval;
300 : : }
301 : :
302 : : /* Return the svalue * for the initial value of REG, creating it if
303 : : necessary. */
304 : :
305 : : const svalue *
306 : 2787348 : region_model_manager::get_or_create_initial_value (const region *reg,
307 : : bool check_poisoned)
308 : : {
309 : 2787348 : if (!reg->can_have_initial_svalue_p () && check_poisoned)
310 : 225038 : return get_or_create_poisoned_svalue (poison_kind::uninit,
311 : 225038 : reg->get_type ());
312 : :
313 : : /* The initial value of a cast is a cast of the initial value. */
314 : 2562310 : if (const cast_region *cast_reg = reg->dyn_cast_cast_region ())
315 : : {
316 : 2626 : const region *original_reg = cast_reg->get_parent_region ();
317 : 2626 : return get_or_create_cast (cast_reg->get_type (),
318 : 2626 : get_or_create_initial_value (original_reg));
319 : : }
320 : :
321 : : /* Simplify:
322 : : INIT_VAL(ELEMENT_REG(STRING_REG), CONSTANT_SVAL)
323 : : to:
324 : : CONSTANT_SVAL(STRING[N]). */
325 : 2559684 : if (const element_region *element_reg = reg->dyn_cast_element_region ())
326 : 12770 : if (tree cst_idx = element_reg->get_index ()->maybe_get_constant ())
327 : 15376 : if (const string_region *string_reg
328 : 7688 : = element_reg->get_parent_region ()->dyn_cast_string_region ())
329 : 834 : if (tree_fits_shwi_p (cst_idx))
330 : : {
331 : 834 : HOST_WIDE_INT idx = tree_to_shwi (cst_idx);
332 : 834 : tree string_cst = string_reg->get_string_cst ();
333 : 1668 : if (idx >= 0 && idx <= TREE_STRING_LENGTH (string_cst))
334 : : {
335 : 834 : int ch = TREE_STRING_POINTER (string_cst)[idx];
336 : 834 : return get_or_create_int_cst (reg->get_type (), ch);
337 : : }
338 : : }
339 : :
340 : : /* INIT_VAL (*UNKNOWN_PTR) -> UNKNOWN_VAL. */
341 : 2558850 : if (reg->symbolic_for_unknown_ptr_p ())
342 : 8384 : return get_or_create_unknown_svalue (reg->get_type ());
343 : :
344 : 2550466 : if (initial_svalue **slot = m_initial_values_map.get (reg))
345 : 2525266 : return *slot;
346 : 25200 : initial_svalue *initial_sval
347 : 25200 : = new initial_svalue (alloc_symbol_id (), reg->get_type (), reg);
348 : 25200 : RETURN_UNKNOWN_IF_TOO_COMPLEX (initial_sval);
349 : 24655 : m_initial_values_map.put (reg, initial_sval);
350 : 24655 : return initial_sval;
351 : : }
352 : :
353 : : /* Return the svalue * for R using type TYPE, creating it if
354 : : necessary. */
355 : :
356 : : const svalue *
357 : 34 : region_model_manager::get_or_create_setjmp_svalue (const setjmp_record &r,
358 : : tree type)
359 : : {
360 : 34 : setjmp_svalue::key_t key (r, type);
361 : 34 : if (setjmp_svalue **slot = m_setjmp_values_map.get (key))
362 : 0 : return *slot;
363 : 34 : setjmp_svalue *setjmp_sval = new setjmp_svalue (r, alloc_symbol_id (), type);
364 : 34 : RETURN_UNKNOWN_IF_TOO_COMPLEX (setjmp_sval);
365 : 34 : m_setjmp_values_map.put (key, setjmp_sval);
366 : 34 : return setjmp_sval;
367 : : }
368 : :
369 : : /* Return the svalue * for a poisoned value of KIND and TYPE, creating it if
370 : : necessary. */
371 : :
372 : : const svalue *
373 : 233739 : region_model_manager::get_or_create_poisoned_svalue (enum poison_kind kind,
374 : : tree type)
375 : : {
376 : 233739 : poisoned_svalue::key_t key (kind, type);
377 : 233739 : if (poisoned_svalue **slot = m_poisoned_values_map.get (key))
378 : 228538 : return *slot;
379 : 5201 : poisoned_svalue *poisoned_sval
380 : 5201 : = new poisoned_svalue (kind, alloc_symbol_id (), type);
381 : 5201 : RETURN_UNKNOWN_IF_TOO_COMPLEX (poisoned_sval);
382 : 5201 : m_poisoned_values_map.put (key, poisoned_sval);
383 : 5201 : return poisoned_sval;
384 : : }
385 : :
386 : : /* Return the svalue * for a pointer to POINTEE of type PTR_TYPE,
387 : : creating it if necessary. */
388 : :
389 : : const svalue *
390 : 967799 : region_model_manager::get_ptr_svalue (tree ptr_type, const region *pointee)
391 : : {
392 : : /* If this is a symbolic region from dereferencing a pointer, and the types
393 : : match, then return the original pointer. */
394 : 967799 : if (const symbolic_region *sym_reg = pointee->dyn_cast_symbolic_region ())
395 : 179 : if (ptr_type == sym_reg->get_pointer ()->get_type ())
396 : : return sym_reg->get_pointer ();
397 : :
398 : 967620 : region_svalue::key_t key (ptr_type, pointee);
399 : 967620 : if (region_svalue **slot = m_pointer_values_map.get (key))
400 : 942478 : return *slot;
401 : 25142 : region_svalue *sval
402 : 25142 : = new region_svalue (alloc_symbol_id (), ptr_type, pointee);
403 : 25142 : RETURN_UNKNOWN_IF_TOO_COMPLEX (sval);
404 : 24683 : m_pointer_values_map.put (key, sval);
405 : 24683 : return sval;
406 : : }
407 : :
408 : : /* Subroutine of region_model_manager::get_or_create_unaryop.
409 : : Attempt to fold the inputs and return a simpler svalue *.
410 : : Otherwise, return NULL. */
411 : :
412 : : const svalue *
413 : 261801 : region_model_manager::maybe_fold_unaryop (tree type, enum tree_code op,
414 : : const svalue *arg)
415 : : {
416 : : /* Ops on "unknown" are also unknown. */
417 : 263996 : if (arg->get_kind () == SK_UNKNOWN)
418 : 47680 : return get_or_create_unknown_svalue (type);
419 : : /* Likewise for "poisoned". */
420 : 432632 : else if (const poisoned_svalue *poisoned_sval
421 : 216316 : = arg->dyn_cast_poisoned_svalue ())
422 : 1859 : return get_or_create_poisoned_svalue (poisoned_sval->get_poison_kind (),
423 : 1859 : type);
424 : :
425 : 214457 : gcc_assert (arg->can_have_associated_state_p ());
426 : :
427 : 214457 : switch (op)
428 : : {
429 : : default: break;
430 : 213514 : case VIEW_CONVERT_EXPR:
431 : 213514 : case NOP_EXPR:
432 : 213514 : {
433 : 213514 : if (!type)
434 : : return nullptr;
435 : :
436 : : /* Handle redundant casts. */
437 : 212552 : if (arg->get_type ()
438 : 212552 : && useless_type_conversion_p (arg->get_type (), type))
439 : : return arg;
440 : :
441 : : /* Fold "cast<TYPE> (cast <INNER_TYPE> (innermost_arg))
442 : : => "cast<TYPE> (innermost_arg)",
443 : : unless INNER_TYPE is narrower than TYPE. */
444 : 78940 : if (const svalue *innermost_arg = arg->maybe_undo_cast ())
445 : : {
446 : 5546 : if (tree inner_type = arg->get_type ())
447 : 5407 : if (TYPE_SIZE (type)
448 : 5407 : && TYPE_SIZE (inner_type)
449 : 10814 : && (fold_binary (LE_EXPR, boolean_type_node,
450 : : TYPE_SIZE (type), TYPE_SIZE (inner_type))
451 : 5407 : == boolean_true_node))
452 : : return maybe_fold_unaryop (type, op, innermost_arg);
453 : : }
454 : : /* Avoid creating symbolic regions for pointer casts by
455 : : simplifying (T*)(®ION) to ((T*)®ION). */
456 : 76745 : if (const region_svalue *region_sval = arg->dyn_cast_region_svalue ())
457 : 4372 : if (POINTER_TYPE_P (type)
458 : 376 : && region_sval->get_type ()
459 : 4544 : && POINTER_TYPE_P (region_sval->get_type ()))
460 : 72 : return get_ptr_svalue (type, region_sval->get_pointee ());
461 : :
462 : : /* Casting all zeroes should give all zeroes. */
463 : 76673 : if (type
464 : 76673 : && arg->all_zeroes_p ()
465 : 5089 : && (INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type)))
466 : 4415 : return get_or_create_int_cst (type, 0);
467 : : }
468 : : break;
469 : 8 : case TRUTH_NOT_EXPR:
470 : 8 : {
471 : : /* Invert comparisons e.g. "!(x == y)" => "x != y". */
472 : 8 : if (const binop_svalue *binop = arg->dyn_cast_binop_svalue ())
473 : 8 : if (TREE_CODE_CLASS (binop->get_op ()) == tcc_comparison)
474 : : {
475 : 8 : enum tree_code inv_op
476 : 8 : = invert_tree_comparison (binop->get_op (),
477 : 8 : HONOR_NANS (binop->get_type ()));
478 : 8 : if (inv_op != ERROR_MARK)
479 : 8 : return get_or_create_binop (binop->get_type (), inv_op,
480 : : binop->get_arg0 (),
481 : 8 : binop->get_arg1 ());
482 : : }
483 : : }
484 : : break;
485 : 190 : case NEGATE_EXPR:
486 : 190 : {
487 : : /* -(-(VAL)) is VAL, for integer types. */
488 : 190 : if (const unaryop_svalue *unaryop = arg->dyn_cast_unaryop_svalue ())
489 : 13 : if (unaryop->get_op () == NEGATE_EXPR
490 : 1 : && type == unaryop->get_type ()
491 : 1 : && type
492 : 14 : && INTEGRAL_TYPE_P (type))
493 : 1 : return unaryop->get_arg ();
494 : : }
495 : : break;
496 : : }
497 : :
498 : : /* Constants. */
499 : 73192 : if (tree cst = arg->maybe_get_constant ())
500 : 13016 : if (tree result = fold_unary (op, type, cst))
501 : : {
502 : 12038 : if (CONSTANT_CLASS_P (result))
503 : 12038 : return get_or_create_constant_svalue (result);
504 : :
505 : : /* fold_unary can return casts of constants; try to handle them. */
506 : 0 : if (op != NOP_EXPR
507 : 0 : && type
508 : 0 : && TREE_CODE (result) == NOP_EXPR
509 : 0 : && CONSTANT_CLASS_P (TREE_OPERAND (result, 0)))
510 : : {
511 : 0 : const svalue *inner_cst
512 : 0 : = get_or_create_constant_svalue (TREE_OPERAND (result, 0));
513 : 0 : return get_or_create_cast (type,
514 : 0 : get_or_create_cast (TREE_TYPE (result),
515 : 0 : inner_cst));
516 : : }
517 : : }
518 : :
519 : : return NULL;
520 : : }
521 : :
522 : : /* Return the svalue * for an unary operation OP on ARG with a result of
523 : : type TYPE, creating it if necessary. */
524 : :
525 : : const svalue *
526 : 261801 : region_model_manager::get_or_create_unaryop (tree type, enum tree_code op,
527 : : const svalue *arg)
528 : : {
529 : 261801 : if (const svalue *folded = maybe_fold_unaryop (type, op, arg))
530 : : return folded;
531 : 62116 : unaryop_svalue::key_t key (type, op, arg);
532 : 62116 : if (unaryop_svalue **slot = m_unaryop_values_map.get (key))
533 : 53436 : return *slot;
534 : 8680 : unaryop_svalue *unaryop_sval
535 : 8680 : = new unaryop_svalue (alloc_symbol_id (), type, op, arg);
536 : 8680 : RETURN_UNKNOWN_IF_TOO_COMPLEX (unaryop_sval);
537 : 8624 : m_unaryop_values_map.put (key, unaryop_sval);
538 : 8624 : return unaryop_sval;
539 : : }
540 : :
541 : : /* Get a tree code for a cast to DST_TYPE from SRC_TYPE.
542 : : Use NOP_EXPR if possible (e.g. to help fold_unary convert casts
543 : : of 0 to (T*) to simple pointer constants), but use FIX_TRUNC_EXPR
544 : : and VIEW_CONVERT_EXPR for cases that fold_unary would otherwise crash
545 : : on. */
546 : :
547 : : static enum tree_code
548 : 212714 : get_code_for_cast (tree dst_type, tree src_type)
549 : : {
550 : 0 : if (!dst_type)
551 : : return NOP_EXPR;
552 : 0 : if (!src_type)
553 : : return NOP_EXPR;
554 : :
555 : 207146 : if (SCALAR_FLOAT_TYPE_P (src_type))
556 : : {
557 : 350 : if (TREE_CODE (dst_type) == INTEGER_TYPE)
558 : : return FIX_TRUNC_EXPR;
559 : : else
560 : 346 : return VIEW_CONVERT_EXPR;
561 : : }
562 : :
563 : : return NOP_EXPR;
564 : : }
565 : :
566 : : /* Return the svalue * for a cast of ARG to type TYPE, creating it
567 : : if necessary. */
568 : :
569 : : const svalue *
570 : 1152083 : region_model_manager::get_or_create_cast (tree type, const svalue *arg)
571 : : {
572 : : /* No-op if the types are the same. */
573 : 1152083 : if (type == arg->get_type ())
574 : : return arg;
575 : :
576 : : /* Don't attempt to handle casts involving vector types for now. */
577 : 221731 : if (type)
578 : 212828 : if (VECTOR_TYPE_P (type)
579 : 212828 : || (arg->get_type ()
580 : 207146 : && VECTOR_TYPE_P (arg->get_type ())))
581 : 114 : return get_or_create_unknown_svalue (type);
582 : :
583 : 212714 : enum tree_code op = get_code_for_cast (type, arg->get_type ());
584 : 221617 : return get_or_create_unaryop (type, op, arg);
585 : : }
586 : :
587 : : /* Subroutine of region_model_manager::maybe_fold_binop for handling
588 : : (TYPE)(COMPOUND_SVAL BIT_AND_EXPR CST) that may have been generated by
589 : : optimize_bit_field_compare, where CST is from ARG1.
590 : :
591 : : Support masking out bits from a compound_svalue for comparing a bitfield
592 : : against a value, as generated by optimize_bit_field_compare for
593 : : BITFIELD == VALUE.
594 : :
595 : : If COMPOUND_SVAL has a value for the appropriate bits, return it,
596 : : shifted accordingly.
597 : : Otherwise return NULL. */
598 : :
599 : : const svalue *
600 : 58 : region_model_manager::
601 : : maybe_undo_optimize_bit_field_compare (tree type,
602 : : const compound_svalue *compound_sval,
603 : : tree cst,
604 : : const svalue *arg1)
605 : : {
606 : 58 : if (!type)
607 : : return nullptr;
608 : 58 : if (!INTEGRAL_TYPE_P (type))
609 : : return NULL;
610 : :
611 : 56 : const binding_map &map = compound_sval->get_map ();
612 : 56 : unsigned HOST_WIDE_INT mask = TREE_INT_CST_LOW (cst);
613 : : /* If "mask" is a contiguous range of set bits, see if the
614 : : compound_sval has a value for those bits. */
615 : 56 : bit_range bits (0, 0);
616 : 56 : if (!bit_range::from_mask (mask, &bits))
617 : : return NULL;
618 : :
619 : 56 : bit_range bound_bits (bits);
620 : 56 : if (BYTES_BIG_ENDIAN)
621 : : bound_bits = bit_range (BITS_PER_UNIT - bits.get_next_bit_offset (),
622 : : bits.m_size_in_bits);
623 : 56 : const concrete_binding *conc
624 : 56 : = get_store_manager ()->get_concrete_binding (bound_bits);
625 : 56 : const svalue *sval = map.get (conc);
626 : 56 : if (!sval)
627 : 0 : return NULL;
628 : :
629 : : /* We have a value;
630 : : shift it by the correct number of bits. */
631 : 56 : const svalue *lhs = get_or_create_cast (type, sval);
632 : 56 : HOST_WIDE_INT bit_offset = bits.get_start_bit_offset ().to_shwi ();
633 : 56 : const svalue *shift_sval = get_or_create_int_cst (type, bit_offset);
634 : 56 : const svalue *shifted_sval = get_or_create_binop (type, LSHIFT_EXPR,
635 : : lhs, shift_sval);
636 : : /* Reapply the mask (needed for negative
637 : : signed bitfields). */
638 : 56 : return get_or_create_binop (type, BIT_AND_EXPR,
639 : 56 : shifted_sval, arg1);
640 : : }
641 : :
642 : : /* Subroutine of region_model_manager::get_or_create_binop.
643 : : Attempt to fold the inputs and return a simpler svalue *.
644 : : Otherwise, return NULL. */
645 : :
646 : : const svalue *
647 : 205853 : region_model_manager::maybe_fold_binop (tree type, enum tree_code op,
648 : : const svalue *arg0,
649 : : const svalue *arg1)
650 : : {
651 : 205853 : tree cst0 = arg0->maybe_get_constant ();
652 : 205853 : tree cst1 = arg1->maybe_get_constant ();
653 : : /* (CST OP CST). */
654 : 205853 : if (cst0 && cst1)
655 : : {
656 : 62995 : if (type)
657 : : {
658 : 22478 : if (tree result = fold_binary (op, type, cst0, cst1))
659 : 22416 : if (CONSTANT_CLASS_P (result))
660 : 22414 : return get_or_create_constant_svalue (result);
661 : : }
662 : : else
663 : : {
664 : 40517 : if (tree result = int_const_binop (op, cst0, cst1, -1))
665 : 40517 : return get_or_create_constant_svalue (NULL_TREE, result);
666 : : }
667 : : }
668 : :
669 : 97722 : if ((type && FLOAT_TYPE_P (type))
670 : 142384 : || (arg0->get_type () && FLOAT_TYPE_P (arg0->get_type ()))
671 : 285254 : || (arg1->get_type () && FLOAT_TYPE_P (arg1->get_type ())))
672 : : return NULL;
673 : :
674 : 142312 : switch (op)
675 : : {
676 : : default:
677 : : break;
678 : 95104 : case POINTER_PLUS_EXPR:
679 : 95104 : case PLUS_EXPR:
680 : : /* (VAL + 0) -> VAL. */
681 : 95104 : if (cst1 && zerop (cst1))
682 : 15216 : return get_or_create_cast (type, arg0);
683 : : break;
684 : 3569 : case MINUS_EXPR:
685 : : /* (VAL - 0) -> VAL. */
686 : 3569 : if (cst1 && zerop (cst1))
687 : 31 : return get_or_create_cast (type, arg0);
688 : : /* (0 - VAL) -> -VAL. */
689 : 3538 : if (cst0 && zerop (cst0))
690 : 16 : return get_or_create_unaryop (type, NEGATE_EXPR, arg1);
691 : : /* (X + Y) - X -> Y. */
692 : 3522 : if (const binop_svalue *binop = arg0->dyn_cast_binop_svalue ())
693 : 142 : if (binop->get_op () == PLUS_EXPR)
694 : 115 : if (binop->get_arg0 () == arg1)
695 : 15 : return get_or_create_cast (type, binop->get_arg1 ());
696 : : break;
697 : 27866 : case MULT_EXPR:
698 : : /* (VAL * 0). */
699 : 27866 : if (cst1
700 : 27142 : && zerop (cst1)
701 : 27906 : && (type == NULL_TREE || INTEGRAL_TYPE_P (type)))
702 : 32 : return get_or_create_int_cst (type, 0);
703 : : /* (VAL * 1) -> VAL. */
704 : 27834 : if (cst1 && integer_onep (cst1))
705 : 386 : return get_or_create_cast (type, arg0);
706 : : break;
707 : 3246 : case BIT_AND_EXPR:
708 : 3246 : if (cst1)
709 : : {
710 : 2668 : if (zerop (cst1)
711 : 2668 : && (type == NULL_TREE || INTEGRAL_TYPE_P (type)))
712 : : /* "(ARG0 & 0)" -> "0". */
713 : 82 : return get_or_create_int_cst (type, 0);
714 : :
715 : 5172 : if (const compound_svalue *compound_sval
716 : 2586 : = arg0->dyn_cast_compound_svalue ())
717 : 116 : if (const svalue *sval
718 : 58 : = maybe_undo_optimize_bit_field_compare (type,
719 : : compound_sval,
720 : : cst1, arg1))
721 : : return sval;
722 : : }
723 : 3108 : if (arg0->get_type () == boolean_type_node
724 : 3108 : && arg1->get_type () == boolean_type_node)
725 : : {
726 : : /* If the LHS are both _Bool, then... */
727 : : /* ..."(1 & x) -> x". */
728 : 442 : if (cst0 && !zerop (cst0))
729 : 0 : return get_or_create_cast (type, arg1);
730 : : /* ..."(x & 1) -> x". */
731 : 442 : if (cst1 && !zerop (cst1))
732 : 152 : return get_or_create_cast (type, arg0);
733 : : /* ..."(0 & x) -> 0". */
734 : 290 : if (cst0 && zerop (cst0))
735 : 0 : return get_or_create_int_cst (type, 0);
736 : : /* ..."(x & 0) -> 0". */
737 : 290 : if (cst1 && zerop (cst1))
738 : 0 : return get_or_create_int_cst (type, 0);
739 : : }
740 : : break;
741 : 741 : case BIT_IOR_EXPR:
742 : 741 : if (arg0->get_type () == boolean_type_node
743 : 741 : && arg1->get_type () == boolean_type_node)
744 : : {
745 : : /* If the LHS are both _Bool, then... */
746 : : /* ..."(1 | x) -> 1". */
747 : 138 : if (cst0 && !zerop (cst0))
748 : 0 : return get_or_create_int_cst (type, 1);
749 : : /* ..."(x | 1) -> 1". */
750 : 138 : if (cst1 && !zerop (cst1))
751 : 48 : return get_or_create_int_cst (type, 1);
752 : : /* ..."(0 | x) -> x". */
753 : 90 : if (cst0 && zerop (cst0))
754 : 0 : return get_or_create_cast (type, arg1);
755 : : /* ..."(x | 0) -> x". */
756 : 90 : if (cst1 && zerop (cst1))
757 : 32 : return get_or_create_cast (type, arg0);
758 : : }
759 : : break;
760 : 12 : case TRUTH_ANDIF_EXPR:
761 : 12 : case TRUTH_AND_EXPR:
762 : 12 : if (cst1)
763 : : {
764 : 12 : if (zerop (cst1) && INTEGRAL_TYPE_P (type))
765 : : /* "(ARG0 && 0)" -> "0". */
766 : 4 : return get_or_create_constant_svalue (build_int_cst (type, 0));
767 : : else
768 : : /* "(ARG0 && nonzero-cst)" -> "ARG0". */
769 : 8 : return get_or_create_cast (type, arg0);
770 : : }
771 : : break;
772 : 12 : case TRUTH_ORIF_EXPR:
773 : 12 : case TRUTH_OR_EXPR:
774 : 12 : if (cst1)
775 : : {
776 : 12 : if (zerop (cst1))
777 : : /* "(ARG0 || 0)" -> "ARG0". */
778 : 8 : return get_or_create_cast (type, arg0);
779 : : else
780 : : /* "(ARG0 && nonzero-cst)" -> "nonzero-cst". */
781 : 4 : return get_or_create_cast (type, arg1);
782 : : }
783 : : break;
784 : : }
785 : :
786 : : /* For associative ops, fold "(X op CST_A) op CST_B)" to
787 : : "X op (CST_A op CST_B)". */
788 : 126222 : if (cst1 && associative_tree_code (op))
789 : 78067 : if (const binop_svalue *binop = arg0->dyn_cast_binop_svalue ())
790 : 17530 : if (binop->get_op () == op
791 : 17530 : && binop->get_arg1 ()->maybe_get_constant ())
792 : 2582 : return get_or_create_binop
793 : 2582 : (type, op, binop->get_arg0 (),
794 : : get_or_create_binop (type, op,
795 : 2582 : binop->get_arg1 (), arg1));
796 : :
797 : : /* associative_tree_code is false for POINTER_PLUS_EXPR, but we
798 : : can fold:
799 : : "(PTR ptr+ CST_A) ptr+ CST_B)" to "PTR ptr+ (CST_A ptr+ CST_B)"
800 : : e.g. in data-model-1.c: test_4c. */
801 : 123640 : if (cst1 && op == POINTER_PLUS_EXPR)
802 : 12184 : if (const binop_svalue *binop = arg0->dyn_cast_binop_svalue ())
803 : 1101 : if (binop->get_op () == POINTER_PLUS_EXPR)
804 : 1101 : if (binop->get_arg1 ()->maybe_get_constant ())
805 : 865 : return get_or_create_binop
806 : 865 : (type, op, binop->get_arg0 (),
807 : : get_or_create_binop (size_type_node, op,
808 : 865 : binop->get_arg1 (), arg1));
809 : :
810 : : /* Distribute multiplication by a constant through addition/subtraction:
811 : : (X + Y) * CST => (X * CST) + (Y * CST). */
812 : 122775 : if (cst1 && op == MULT_EXPR)
813 : 26545 : if (const binop_svalue *binop = arg0->dyn_cast_binop_svalue ())
814 : 1683 : if (binop->get_op () == PLUS_EXPR
815 : 1683 : || binop->get_op () == MINUS_EXPR)
816 : : {
817 : 1030 : return get_or_create_binop
818 : 1030 : (type, binop->get_op (),
819 : : get_or_create_binop (type, op,
820 : : binop->get_arg0 (), arg1),
821 : : get_or_create_binop (type, op,
822 : 1030 : binop->get_arg1 (), arg1));
823 : : }
824 : :
825 : :
826 : : /* Typeless operations, assumed to be effectively arbitrary sized
827 : : integers following normal arithmetic rules. */
828 : 121745 : if (!type)
829 : 34399 : switch (op)
830 : : {
831 : : default:
832 : : break;
833 : 55 : case MINUS_EXPR:
834 : 55 : {
835 : : /* (X - X) -> 0. */
836 : 55 : if (arg0 == arg1)
837 : 11 : return get_or_create_int_cst (type, 0);
838 : :
839 : : /* (X + A) - (A + B) -> (A - B). */
840 : 44 : if (const binop_svalue *binop0 = arg0->dyn_cast_binop_svalue ())
841 : 44 : if (const binop_svalue *binop1 = arg1->dyn_cast_binop_svalue ())
842 : 36 : if (binop0->get_op () == PLUS_EXPR
843 : 28 : && binop1->get_op () == PLUS_EXPR
844 : 56 : && binop0->get_arg0 () == binop1->get_arg0 ())
845 : 20 : return get_or_create_binop (NULL_TREE, op,
846 : : binop0->get_arg1 (),
847 : 20 : binop1->get_arg1 ());
848 : : }
849 : : break;
850 : :
851 : 73 : case EXACT_DIV_EXPR:
852 : 73 : {
853 : 73 : if (const unaryop_svalue *unaryop0 = arg0->dyn_cast_unaryop_svalue ())
854 : : {
855 : 0 : if (unaryop0->get_op () == NOP_EXPR)
856 : 0 : if (const svalue *sval = maybe_fold_binop (NULL_TREE, op,
857 : : unaryop0->get_arg (),
858 : : arg1))
859 : : return sval;
860 : : }
861 : 73 : if (const binop_svalue *binop0 = arg0->dyn_cast_binop_svalue ())
862 : : {
863 : 72 : switch (binop0->get_op ())
864 : : {
865 : : default:
866 : : break;
867 : :
868 : 26 : case PLUS_EXPR:
869 : 26 : case MINUS_EXPR:
870 : : /* (A op B) / C -> (A / C) op (B / C). */
871 : 26 : {
872 : 26 : if (const svalue *op_on_a
873 : 26 : = maybe_fold_binop (NULL_TREE, op,
874 : : binop0->get_arg0 (), arg1))
875 : 26 : if (const svalue *op_on_b
876 : 26 : = maybe_fold_binop (NULL_TREE, op,
877 : : binop0->get_arg1 (), arg1))
878 : 26 : return get_or_create_binop (NULL_TREE,
879 : : binop0->get_op (),
880 : 26 : op_on_a, op_on_b);
881 : : }
882 : : break;
883 : :
884 : 46 : case MULT_EXPR:
885 : : /* (A * B) / C -> A * (B / C) if C is a divisor of B.
886 : : In particular, this should also handle the case
887 : : (A * B) / B -> A. */
888 : 46 : if (const svalue *b_div_c
889 : 46 : = maybe_fold_binop (NULL_TREE, op,
890 : : binop0->get_arg1 (), arg1))
891 : 46 : return get_or_create_binop (NULL_TREE, binop0->get_op (),
892 : 46 : binop0->get_arg0 (), b_div_c);
893 : : }
894 : : }
895 : : }
896 : : break;
897 : : }
898 : :
899 : : /* etc. */
900 : :
901 : : return NULL;
902 : : }
903 : :
904 : : /* Return the svalue * for an binary operation OP on ARG0 and ARG1
905 : : with a result of type TYPE, creating it if necessary. */
906 : :
907 : : const svalue *
908 : 205574 : region_model_manager::get_or_create_binop (tree type, enum tree_code op,
909 : : const svalue *arg0,
910 : : const svalue *arg1)
911 : : {
912 : : /* For commutative ops, put any constant on the RHS. */
913 : 205574 : if (arg0->maybe_get_constant () && commutative_tree_code (op))
914 : : std::swap (arg0, arg1);
915 : :
916 : 205574 : if (const svalue *folded = maybe_fold_binop (type, op, arg0, arg1))
917 : : return folded;
918 : :
919 : : /* Ops on "unknown"/"poisoned" are unknown (unless we were able to fold
920 : : it via an identity in maybe_fold_binop). */
921 : 122251 : if (!arg0->can_have_associated_state_p ()
922 : 122251 : || !arg1->can_have_associated_state_p ())
923 : 30706 : return get_or_create_unknown_svalue (type);
924 : :
925 : 91545 : binop_svalue::key_t key (type, op, arg0, arg1);
926 : 91545 : if (binop_svalue **slot = m_binop_values_map.get (key))
927 : 70151 : return *slot;
928 : 21394 : binop_svalue *binop_sval
929 : 21394 : = new binop_svalue (alloc_symbol_id (), type, op, arg0, arg1);
930 : 21394 : RETURN_UNKNOWN_IF_TOO_COMPLEX (binop_sval);
931 : 21268 : m_binop_values_map.put (key, binop_sval);
932 : 21268 : return binop_sval;
933 : : }
934 : :
935 : : /* Subroutine of region_model_manager::get_or_create_sub_svalue.
936 : : Return a folded svalue, or NULL. */
937 : :
938 : : const svalue *
939 : 63729 : region_model_manager::maybe_fold_sub_svalue (tree type,
940 : : const svalue *parent_svalue,
941 : : const region *subregion)
942 : : {
943 : : /* Subvalues of "unknown"/"poisoned" are unknown. */
944 : 63729 : if (!parent_svalue->can_have_associated_state_p ())
945 : 47921 : return get_or_create_unknown_svalue (type);
946 : :
947 : : /* If we have a subvalue of a zero constant, it's zero. */
948 : 15808 : if (tree cst = parent_svalue->maybe_get_constant ())
949 : 954 : if (TREE_CODE (cst) == INTEGER_CST)
950 : 114 : if (zerop (cst))
951 : 102 : return get_or_create_cast (type, parent_svalue);
952 : :
953 : : /* If we have a subregion of a zero-fill, it's zero. */
954 : 31412 : if (const unaryop_svalue *unary
955 : 15706 : = parent_svalue->dyn_cast_unaryop_svalue ())
956 : : {
957 : 582 : if (unary->get_op () == NOP_EXPR
958 : 582 : || unary->get_op () == VIEW_CONVERT_EXPR)
959 : 582 : if (tree cst = unary->get_arg ()->maybe_get_constant ())
960 : 582 : if (zerop (cst) && type)
961 : : {
962 : 570 : const svalue *cst_sval
963 : 570 : = get_or_create_constant_svalue (cst);
964 : 570 : return get_or_create_cast (type, cst_sval);
965 : : }
966 : : }
967 : :
968 : : /* Handle getting individual chars from a STRING_CST or RAW_DATA_CST. */
969 : 15136 : if (tree cst = parent_svalue->maybe_get_constant ())
970 : 852 : if (TREE_CODE (cst) == STRING_CST
971 : 852 : || TREE_CODE (cst) == RAW_DATA_CST)
972 : : {
973 : : /* If we have a concrete 1-byte access within the parent region... */
974 : 824 : byte_range subregion_bytes (0, 0);
975 : 824 : if (subregion->get_relative_concrete_byte_range (&subregion_bytes)
976 : 824 : && subregion_bytes.m_size_in_bytes == 1
977 : 1337 : && type)
978 : : {
979 : : /* ...then attempt to get that char from the constant. */
980 : 513 : HOST_WIDE_INT hwi_start_byte
981 : 513 : = subregion_bytes.m_start_byte_offset.to_shwi ();
982 : 513 : tree cst_idx
983 : 513 : = build_int_cst_type (size_type_node, hwi_start_byte);
984 : 1026 : if (const svalue *char_sval
985 : 513 : = maybe_get_char_from_cst (cst, cst_idx))
986 : 457 : return get_or_create_cast (type, char_sval);
987 : : }
988 : : }
989 : :
990 : 29358 : if (const initial_svalue *init_sval
991 : 14679 : = parent_svalue->dyn_cast_initial_svalue ())
992 : : {
993 : : /* SUB(INIT(r)).FIELD -> INIT(r.FIELD)
994 : : i.e.
995 : : Subvalue(InitialValue(R1), FieldRegion(R2, F))
996 : : -> InitialValue(FieldRegion(R1, F)). */
997 : 663 : if (const field_region *field_reg = subregion->dyn_cast_field_region ())
998 : : {
999 : 442 : const region *field_reg_new
1000 : 442 : = get_field_region (init_sval->get_region (),
1001 : : field_reg->get_field ());
1002 : 442 : return get_or_create_initial_value (field_reg_new);
1003 : : }
1004 : : /* SUB(INIT(r)[ELEMENT] -> INIT(e[ELEMENT])
1005 : : i.e.
1006 : : Subvalue(InitialValue(R1), ElementRegion(R2, IDX))
1007 : : -> InitialValue(ElementRegion(R1, IDX)). */
1008 : 221 : if (const element_region *element_reg = subregion->dyn_cast_element_region ())
1009 : : {
1010 : 124 : const region *element_reg_new
1011 : 124 : = get_element_region (init_sval->get_region (),
1012 : : element_reg->get_type (),
1013 : : element_reg->get_index ());
1014 : 124 : return get_or_create_initial_value (element_reg_new);
1015 : : }
1016 : : }
1017 : :
1018 : 28226 : if (const repeated_svalue *repeated_sval
1019 : 14113 : = parent_svalue->dyn_cast_repeated_svalue ())
1020 : 104 : if (type)
1021 : 100 : return get_or_create_cast (type, repeated_sval->get_inner_svalue ());
1022 : :
1023 : : return NULL;
1024 : : }
1025 : :
1026 : : /* Return the svalue * for extracting a subvalue of type TYPE from
1027 : : PARENT_SVALUE based on SUBREGION, creating it if necessary. */
1028 : :
1029 : : const svalue *
1030 : 63729 : region_model_manager::get_or_create_sub_svalue (tree type,
1031 : : const svalue *parent_svalue,
1032 : : const region *subregion)
1033 : : {
1034 : 127458 : if (const svalue *folded
1035 : 63729 : = maybe_fold_sub_svalue (type, parent_svalue, subregion))
1036 : : return folded;
1037 : :
1038 : 14013 : sub_svalue::key_t key (type, parent_svalue, subregion);
1039 : 14013 : if (sub_svalue **slot = m_sub_values_map.get (key))
1040 : 11532 : return *slot;
1041 : 2481 : sub_svalue *sub_sval
1042 : 2481 : = new sub_svalue (alloc_symbol_id (), type, parent_svalue, subregion);
1043 : 2481 : RETURN_UNKNOWN_IF_TOO_COMPLEX (sub_sval);
1044 : 2481 : m_sub_values_map.put (key, sub_sval);
1045 : 2481 : return sub_sval;
1046 : : }
1047 : :
1048 : : /* Subroutine of region_model_manager::get_or_create_repeated_svalue.
1049 : : Return a folded svalue, or NULL. */
1050 : :
1051 : : const svalue *
1052 : 3035 : region_model_manager::maybe_fold_repeated_svalue (tree type,
1053 : : const svalue *outer_size,
1054 : : const svalue *inner_svalue)
1055 : : {
1056 : : /* Repeated "unknown"/"poisoned" is unknown. */
1057 : 3035 : if (!outer_size->can_have_associated_state_p ()
1058 : 3035 : || !inner_svalue->can_have_associated_state_p ())
1059 : 4 : return get_or_create_unknown_svalue (type);
1060 : :
1061 : : /* If INNER_SVALUE is the same size as OUTER_SIZE,
1062 : : turn into simply a cast. */
1063 : 3031 : if (tree cst_outer_num_bytes = outer_size->maybe_get_constant ())
1064 : : {
1065 : 2901 : HOST_WIDE_INT num_bytes_inner_svalue
1066 : 2901 : = int_size_in_bytes (inner_svalue->get_type ());
1067 : 2901 : if (num_bytes_inner_svalue != -1)
1068 : 2901 : if (num_bytes_inner_svalue
1069 : 2901 : == (HOST_WIDE_INT)tree_to_uhwi (cst_outer_num_bytes))
1070 : : {
1071 : 337 : if (type)
1072 : 317 : return get_or_create_cast (type, inner_svalue);
1073 : : else
1074 : : return inner_svalue;
1075 : : }
1076 : : }
1077 : :
1078 : : /* Handle zero-fill of a specific type. */
1079 : 2694 : if (tree cst = inner_svalue->maybe_get_constant ())
1080 : 2689 : if (zerop (cst) && type)
1081 : 637 : return get_or_create_cast (type, inner_svalue);
1082 : :
1083 : : return NULL;
1084 : : }
1085 : :
1086 : : /* Return the svalue * of type TYPE in which INNER_SVALUE is repeated
1087 : : enough times to be of size OUTER_SIZE, creating it if necessary.
1088 : : e.g. for filling buffers with a constant value. */
1089 : :
1090 : : const svalue *
1091 : 3035 : region_model_manager::get_or_create_repeated_svalue (tree type,
1092 : : const svalue *outer_size,
1093 : : const svalue *inner_svalue)
1094 : : {
1095 : 6070 : if (const svalue *folded
1096 : 3035 : = maybe_fold_repeated_svalue (type, outer_size, inner_svalue))
1097 : : return folded;
1098 : :
1099 : 2057 : repeated_svalue::key_t key (type, outer_size, inner_svalue);
1100 : 2057 : if (repeated_svalue **slot = m_repeated_values_map.get (key))
1101 : 1556 : return *slot;
1102 : 501 : repeated_svalue *repeated_sval
1103 : 501 : = new repeated_svalue (alloc_symbol_id (), type, outer_size, inner_svalue);
1104 : 501 : RETURN_UNKNOWN_IF_TOO_COMPLEX (repeated_sval);
1105 : 501 : m_repeated_values_map.put (key, repeated_sval);
1106 : 501 : return repeated_sval;
1107 : : }
1108 : :
1109 : : /* Attempt to get the bit_range for FIELD within a RECORD_TYPE.
1110 : : Return true and write the result to OUT if successful.
1111 : : Return false otherwise. */
1112 : :
1113 : : static bool
1114 : 816 : get_bit_range_for_field (tree field, bit_range *out)
1115 : : {
1116 : 816 : bit_size_t bit_size;
1117 : 816 : if (!int_size_in_bits (TREE_TYPE (field), &bit_size))
1118 : : return false;
1119 : 816 : int field_bit_offset = int_bit_position (field);
1120 : 816 : *out = bit_range (field_bit_offset, bit_size);
1121 : 816 : return true;
1122 : : }
1123 : :
1124 : : /* Attempt to get the byte_range for FIELD within a RECORD_TYPE.
1125 : : Return true and write the result to OUT if successful.
1126 : : Return false otherwise. */
1127 : :
1128 : : static bool
1129 : 816 : get_byte_range_for_field (tree field, byte_range *out)
1130 : : {
1131 : 816 : bit_range field_bits (0, 0);
1132 : 816 : if (!get_bit_range_for_field (field, &field_bits))
1133 : : return false;
1134 : 816 : return field_bits.as_byte_range (out);
1135 : : }
1136 : :
1137 : : /* Attempt to determine if there is a specific field within RECORD_TYPE
1138 : : at BYTES. If so, return it, and write the location of BYTES relative
1139 : : to the field to *OUT_RANGE_WITHIN_FIELD.
1140 : : Otherwise, return NULL_TREE.
1141 : : For example, given:
1142 : : struct foo { uint32 a; uint32; b};
1143 : : and
1144 : : bytes = {bytes 6-7} (of foo)
1145 : : we have bytes 3-4 of field b. */
1146 : :
1147 : : static tree
1148 : 816 : get_field_at_byte_range (tree record_type, const byte_range &bytes,
1149 : : byte_range *out_range_within_field)
1150 : : {
1151 : 816 : bit_offset_t bit_offset = bytes.m_start_byte_offset * BITS_PER_UNIT;
1152 : :
1153 : 816 : tree field = get_field_at_bit_offset (record_type, bit_offset);
1154 : 816 : if (!field)
1155 : : return NULL_TREE;
1156 : :
1157 : 816 : byte_range field_bytes (0,0);
1158 : 816 : if (!get_byte_range_for_field (field, &field_bytes))
1159 : : return NULL_TREE;
1160 : :
1161 : : /* Is BYTES fully within field_bytes? */
1162 : 804 : byte_range bytes_within_field (0,0);
1163 : 804 : if (!field_bytes.contains_p (bytes, &bytes_within_field))
1164 : : return NULL_TREE;
1165 : :
1166 : 323 : *out_range_within_field = bytes_within_field;
1167 : 323 : return field;
1168 : : }
1169 : :
1170 : : /* Subroutine of region_model_manager::get_or_create_bits_within.
1171 : : Return a folded svalue, or NULL. */
1172 : :
1173 : : const svalue *
1174 : 25428 : region_model_manager::maybe_fold_bits_within_svalue (tree type,
1175 : : const bit_range &bits,
1176 : : const svalue *inner_svalue)
1177 : : {
1178 : 25428 : tree inner_type = inner_svalue->get_type ();
1179 : : /* Fold:
1180 : : BITS_WITHIN ((0, sizeof (VAL), VAL))
1181 : : to:
1182 : : CAST(TYPE, VAL). */
1183 : 25428 : if (bits.m_start_bit_offset == 0 && inner_type)
1184 : : {
1185 : 3510 : bit_size_t inner_type_size;
1186 : 3510 : if (int_size_in_bits (inner_type, &inner_type_size))
1187 : 3510 : if (inner_type_size == bits.m_size_in_bits)
1188 : : {
1189 : 532 : if (type)
1190 : 532 : return get_or_create_cast (type, inner_svalue);
1191 : : else
1192 : : return inner_svalue;
1193 : : }
1194 : : }
1195 : :
1196 : : /* Kind-specific folding. */
1197 : 49792 : if (const svalue *sval
1198 : 24896 : = inner_svalue->maybe_fold_bits_within (type, bits, this))
1199 : : return sval;
1200 : :
1201 : 1602 : byte_range bytes (0,0);
1202 : 1602 : if (bits.as_byte_range (&bytes) && inner_type)
1203 : 1402 : switch (TREE_CODE (inner_type))
1204 : : {
1205 : : default:
1206 : : break;
1207 : 411 : case ARRAY_TYPE:
1208 : 411 : {
1209 : : /* Fold:
1210 : : BITS_WITHIN (range, KIND(REG))
1211 : : to:
1212 : : BITS_WITHIN (range - offsetof(ELEMENT), KIND(REG.ELEMENT))
1213 : : if range1 is a byte-range fully within one ELEMENT. */
1214 : 411 : tree element_type = TREE_TYPE (inner_type);
1215 : 411 : HOST_WIDE_INT element_byte_size
1216 : 411 : = int_size_in_bytes (element_type);
1217 : 411 : if (element_byte_size > 0)
1218 : : {
1219 : 411 : HOST_WIDE_INT start_idx
1220 : 411 : = (bytes.get_start_byte_offset ().to_shwi ()
1221 : 411 : / element_byte_size);
1222 : 411 : HOST_WIDE_INT last_idx
1223 : 411 : = (bytes.get_last_byte_offset ().to_shwi ()
1224 : 411 : / element_byte_size);
1225 : 411 : if (start_idx == last_idx)
1226 : : {
1227 : 452 : if (const initial_svalue *initial_sval
1228 : 226 : = inner_svalue->dyn_cast_initial_svalue ())
1229 : : {
1230 : 167 : bit_offset_t start_of_element
1231 : 167 : = start_idx * element_byte_size * BITS_PER_UNIT;
1232 : 167 : bit_range bits_within_element
1233 : 167 : (bits.m_start_bit_offset - start_of_element,
1234 : 167 : bits.m_size_in_bits);
1235 : 167 : const svalue *idx_sval
1236 : 167 : = get_or_create_int_cst (integer_type_node, start_idx);
1237 : 167 : const region *element_reg =
1238 : 167 : get_element_region (initial_sval->get_region (),
1239 : : element_type, idx_sval);
1240 : 167 : const svalue *element_reg_sval
1241 : 167 : = get_or_create_initial_value (element_reg);
1242 : 167 : return get_or_create_bits_within (type,
1243 : : bits_within_element,
1244 : : element_reg_sval);
1245 : : }
1246 : : }
1247 : : }
1248 : : }
1249 : : break;
1250 : 816 : case RECORD_TYPE:
1251 : 816 : {
1252 : : /* Fold:
1253 : : BYTES_WITHIN (range, KIND(REG))
1254 : : to:
1255 : : BYTES_WITHIN (range - offsetof(FIELD), KIND(REG.FIELD))
1256 : : if range1 is fully within FIELD. */
1257 : 816 : byte_range bytes_within_field (0, 0);
1258 : 816 : if (tree field = get_field_at_byte_range (inner_type, bytes,
1259 : : &bytes_within_field))
1260 : : {
1261 : 646 : if (const initial_svalue *initial_sval
1262 : 323 : = inner_svalue->dyn_cast_initial_svalue ())
1263 : : {
1264 : 184 : const region *field_reg =
1265 : 184 : get_field_region (initial_sval->get_region (), field);
1266 : 184 : const svalue *initial_reg_sval
1267 : 184 : = get_or_create_initial_value (field_reg);
1268 : 184 : return get_or_create_bits_within
1269 : 184 : (type,
1270 : 368 : bytes_within_field.as_bit_range (),
1271 : : initial_reg_sval);
1272 : : }
1273 : : }
1274 : : }
1275 : 632 : break;
1276 : : }
1277 : : return NULL;
1278 : : }
1279 : :
1280 : : /* Return the svalue * of type TYPE for extracting BITS from INNER_SVALUE,
1281 : : creating it if necessary. */
1282 : :
1283 : : const svalue *
1284 : 25428 : region_model_manager::get_or_create_bits_within (tree type,
1285 : : const bit_range &bits,
1286 : : const svalue *inner_svalue)
1287 : : {
1288 : 50856 : if (const svalue *folded
1289 : 25428 : = maybe_fold_bits_within_svalue (type, bits, inner_svalue))
1290 : : return folded;
1291 : :
1292 : 1251 : bits_within_svalue::key_t key (type, bits, inner_svalue);
1293 : 1251 : if (bits_within_svalue **slot = m_bits_within_values_map.get (key))
1294 : 578 : return *slot;
1295 : 673 : bits_within_svalue *bits_within_sval
1296 : 673 : = new bits_within_svalue (alloc_symbol_id (), type, bits, inner_svalue);
1297 : 673 : RETURN_UNKNOWN_IF_TOO_COMPLEX (bits_within_sval);
1298 : 673 : m_bits_within_values_map.put (key, bits_within_sval);
1299 : 673 : return bits_within_sval;
1300 : : }
1301 : :
1302 : : /* Return the svalue * that decorates ARG as being unmergeable,
1303 : : creating it if necessary. */
1304 : :
1305 : : const svalue *
1306 : 936 : region_model_manager::get_or_create_unmergeable (const svalue *arg)
1307 : : {
1308 : 936 : if (arg->get_kind () == SK_UNMERGEABLE)
1309 : : return arg;
1310 : :
1311 : 936 : if (unmergeable_svalue **slot = m_unmergeable_values_map.get (arg))
1312 : 734 : return *slot;
1313 : 202 : unmergeable_svalue *unmergeable_sval
1314 : 202 : = new unmergeable_svalue (alloc_symbol_id (), arg);
1315 : 202 : RETURN_UNKNOWN_IF_TOO_COMPLEX (unmergeable_sval);
1316 : 202 : m_unmergeable_values_map.put (arg, unmergeable_sval);
1317 : 202 : return unmergeable_sval;
1318 : : }
1319 : :
1320 : : /* Return the svalue * of type TYPE for the merger of value BASE_SVAL
1321 : : and ITER_SVAL at POINT, creating it if necessary. */
1322 : :
1323 : : const svalue *
1324 : 4871 : region_model_manager::
1325 : : get_or_create_widening_svalue (tree type,
1326 : : const function_point &point,
1327 : : const svalue *base_sval,
1328 : : const svalue *iter_sval)
1329 : : {
1330 : 4871 : gcc_assert (base_sval->get_kind () != SK_WIDENING);
1331 : 4871 : gcc_assert (iter_sval->get_kind () != SK_WIDENING);
1332 : 4871 : widening_svalue::key_t key (type, point, base_sval, iter_sval);
1333 : 4871 : if (widening_svalue **slot = m_widening_values_map.get (key))
1334 : 2388 : return *slot;
1335 : 2483 : widening_svalue *widening_sval
1336 : : = new widening_svalue (alloc_symbol_id (), type, point, base_sval,
1337 : 2483 : iter_sval);
1338 : 2483 : RETURN_UNKNOWN_IF_TOO_COMPLEX (widening_sval);
1339 : 2483 : m_widening_values_map.put (key, widening_sval);
1340 : 2483 : return widening_sval;
1341 : : }
1342 : :
1343 : : /* Return the svalue * of type TYPE for the compound values in MAP,
1344 : : creating it if necessary. */
1345 : :
1346 : : const svalue *
1347 : 4227 : region_model_manager::get_or_create_compound_svalue (tree type,
1348 : : const binding_map &map)
1349 : : {
1350 : 4227 : compound_svalue::key_t tmp_key (type, &map);
1351 : 4227 : if (compound_svalue **slot = m_compound_values_map.get (tmp_key))
1352 : 3570 : return *slot;
1353 : 657 : compound_svalue *compound_sval
1354 : 657 : = new compound_svalue (alloc_symbol_id (), type, map);
1355 : 657 : RETURN_UNKNOWN_IF_TOO_COMPLEX (compound_sval);
1356 : : /* Use make_key rather than reusing the key, so that we use a
1357 : : ptr to compound_sval's binding_map, rather than the MAP param. */
1358 : 657 : m_compound_values_map.put (compound_sval->make_key (), compound_sval);
1359 : 657 : return compound_sval;
1360 : : }
1361 : :
1362 : : /* class conjured_purge. */
1363 : :
1364 : : /* Purge state relating to SVAL. */
1365 : :
1366 : : void
1367 : 38543 : conjured_purge::purge (const conjured_svalue *sval) const
1368 : : {
1369 : 38543 : m_model->purge_state_involving (sval, m_ctxt);
1370 : 38543 : }
1371 : :
1372 : : /* Return the svalue * of type TYPE for the value conjured for ID_REG
1373 : : at STMT (using IDX for any further disambiguation),
1374 : : creating it if necessary.
1375 : : Use P to purge existing state from the svalue, for the case where a
1376 : : conjured_svalue would be reused along an execution path. */
1377 : :
1378 : : const svalue *
1379 : 66942 : region_model_manager::get_or_create_conjured_svalue (tree type,
1380 : : const gimple *stmt,
1381 : : const region *id_reg,
1382 : : const conjured_purge &p,
1383 : : unsigned idx)
1384 : : {
1385 : 66942 : conjured_svalue::key_t key (type, stmt, id_reg, idx);
1386 : 66942 : if (conjured_svalue **slot = m_conjured_values_map.get (key))
1387 : : {
1388 : 38543 : const conjured_svalue *sval = *slot;
1389 : : /* We're reusing an existing conjured_svalue, perhaps from a different
1390 : : state within this analysis, or perhaps from an earlier state on this
1391 : : execution path. For the latter, purge any state involving the "new"
1392 : : svalue from the current program_state. */
1393 : 38543 : p.purge (sval);
1394 : 38543 : return sval;
1395 : : }
1396 : 28399 : conjured_svalue *conjured_sval
1397 : 28399 : = new conjured_svalue (alloc_symbol_id (), type, stmt, id_reg, idx);
1398 : 28399 : RETURN_UNKNOWN_IF_TOO_COMPLEX (conjured_sval);
1399 : 28303 : m_conjured_values_map.put (key, conjured_sval);
1400 : 28303 : return conjured_sval;
1401 : : }
1402 : :
1403 : : /* Subroutine of region_model_manager::get_or_create_asm_output_svalue.
1404 : : Return a folded svalue, or NULL. */
1405 : :
1406 : : const svalue *
1407 : 403 : region_model_manager::
1408 : : maybe_fold_asm_output_svalue (tree type,
1409 : : const vec<const svalue *> &inputs)
1410 : : {
1411 : : /* Unknown inputs should lead to unknown results. */
1412 : 1833 : for (const auto &iter : inputs)
1413 : 681 : if (iter->get_kind () == SK_UNKNOWN)
1414 : 9 : return get_or_create_unknown_svalue (type);
1415 : :
1416 : : return NULL;
1417 : : }
1418 : :
1419 : : /* Return the svalue * of type TYPE for OUTPUT_IDX of the deterministic
1420 : : asm stmt ASM_STMT, given INPUTS as inputs. */
1421 : :
1422 : : const svalue *
1423 : 301 : region_model_manager::
1424 : : get_or_create_asm_output_svalue (tree type,
1425 : : const gasm *asm_stmt,
1426 : : unsigned output_idx,
1427 : : const vec<const svalue *> &inputs)
1428 : : {
1429 : 301 : gcc_assert (inputs.length () <= asm_output_svalue::MAX_INPUTS);
1430 : :
1431 : 602 : if (const svalue *folded
1432 : 301 : = maybe_fold_asm_output_svalue (type, inputs))
1433 : : return folded;
1434 : :
1435 : 292 : const char *asm_string = gimple_asm_string (asm_stmt);
1436 : 292 : const unsigned noutputs = gimple_asm_noutputs (asm_stmt);
1437 : :
1438 : 292 : asm_output_svalue::key_t key (type, asm_string, output_idx, inputs);
1439 : 292 : if (asm_output_svalue **slot = m_asm_output_values_map.get (key))
1440 : 120 : return *slot;
1441 : 172 : asm_output_svalue *asm_output_sval
1442 : : = new asm_output_svalue (alloc_symbol_id (), type, asm_string, output_idx,
1443 : 172 : noutputs, inputs);
1444 : 172 : RETURN_UNKNOWN_IF_TOO_COMPLEX (asm_output_sval);
1445 : 167 : m_asm_output_values_map.put (key, asm_output_sval);
1446 : 167 : return asm_output_sval;
1447 : : }
1448 : :
1449 : : /* Return the svalue * of type TYPE for OUTPUT_IDX of a deterministic
1450 : : asm stmt with string ASM_STRING with NUM_OUTPUTS outputs, given
1451 : : INPUTS as inputs. */
1452 : :
1453 : : const svalue *
1454 : 102 : region_model_manager::
1455 : : get_or_create_asm_output_svalue (tree type,
1456 : : const char *asm_string,
1457 : : unsigned output_idx,
1458 : : unsigned num_outputs,
1459 : : const vec<const svalue *> &inputs)
1460 : : {
1461 : 102 : gcc_assert (inputs.length () <= asm_output_svalue::MAX_INPUTS);
1462 : :
1463 : 204 : if (const svalue *folded
1464 : 102 : = maybe_fold_asm_output_svalue (type, inputs))
1465 : : return folded;
1466 : :
1467 : 102 : asm_output_svalue::key_t key (type, asm_string, output_idx, inputs);
1468 : 102 : if (asm_output_svalue **slot = m_asm_output_values_map.get (key))
1469 : 82 : return *slot;
1470 : 20 : asm_output_svalue *asm_output_sval
1471 : : = new asm_output_svalue (alloc_symbol_id (), type, asm_string, output_idx,
1472 : 20 : num_outputs, inputs);
1473 : 20 : RETURN_UNKNOWN_IF_TOO_COMPLEX (asm_output_sval);
1474 : 20 : m_asm_output_values_map.put (key, asm_output_sval);
1475 : 20 : return asm_output_sval;
1476 : : }
1477 : :
1478 : : /* Return the svalue * of type TYPE for the result of a call to FNDECL
1479 : : with __attribute__((const)), given INPUTS as inputs. */
1480 : :
1481 : : const svalue *
1482 : 1098 : region_model_manager::
1483 : : get_or_create_const_fn_result_svalue (tree type,
1484 : : tree fndecl,
1485 : : const vec<const svalue *> &inputs)
1486 : : {
1487 : 1098 : gcc_assert (fndecl);
1488 : 1098 : gcc_assert (DECL_P (fndecl));
1489 : 1098 : gcc_assert (TREE_READONLY (fndecl));
1490 : 1098 : gcc_assert (inputs.length () <= const_fn_result_svalue::MAX_INPUTS);
1491 : :
1492 : 1098 : const_fn_result_svalue::key_t key (type, fndecl, inputs);
1493 : 1098 : if (const_fn_result_svalue **slot = m_const_fn_result_values_map.get (key))
1494 : 843 : return *slot;
1495 : 255 : const_fn_result_svalue *const_fn_result_sval
1496 : 255 : = new const_fn_result_svalue (alloc_symbol_id (), type, fndecl, inputs);
1497 : 255 : RETURN_UNKNOWN_IF_TOO_COMPLEX (const_fn_result_sval);
1498 : 255 : m_const_fn_result_values_map.put (key, const_fn_result_sval);
1499 : 255 : return const_fn_result_sval;
1500 : : }
1501 : :
1502 : : /* Given DATA_CST (a STRING_CST or RAW_DATA_CST) and BYTE_OFFSET_CST a constant,
1503 : : attempt to get the character at that offset, returning either
1504 : : the svalue for the character constant, or NULL if unsuccessful. */
1505 : :
1506 : : const svalue *
1507 : 513 : region_model_manager::maybe_get_char_from_cst (tree data_cst,
1508 : : tree byte_offset_cst)
1509 : : {
1510 : 513 : switch (TREE_CODE (data_cst))
1511 : : {
1512 : 0 : default: gcc_unreachable ();
1513 : 447 : case STRING_CST:
1514 : 447 : return maybe_get_char_from_string_cst (data_cst, byte_offset_cst);
1515 : 66 : case RAW_DATA_CST:
1516 : 66 : return maybe_get_char_from_raw_data_cst (data_cst, byte_offset_cst);
1517 : : }
1518 : : }
1519 : :
1520 : : /* Get a tree for the size of STRING_CST, or NULL_TREE.
1521 : : Note that this may be larger than TREE_STRING_LENGTH (implying
1522 : : a run of trailing zero bytes from TREE_STRING_LENGTH up to this
1523 : : higher limit). */
1524 : :
1525 : : tree
1526 : 1145 : get_string_cst_size (const_tree string_cst)
1527 : : {
1528 : 1145 : gcc_assert (TREE_CODE (string_cst) == STRING_CST);
1529 : 1145 : gcc_assert (TREE_CODE (TREE_TYPE (string_cst)) == ARRAY_TYPE);
1530 : :
1531 : 1145 : return TYPE_SIZE_UNIT (TREE_TYPE (string_cst));
1532 : : }
1533 : :
1534 : : /* Given STRING_CST, a STRING_CST and BYTE_OFFSET_CST a constant,
1535 : : attempt to get the character at that offset, returning either
1536 : : the svalue for the character constant, or NULL if unsuccessful. */
1537 : :
1538 : : const svalue *
1539 : 840 : region_model_manager::maybe_get_char_from_string_cst (tree string_cst,
1540 : : tree byte_offset_cst)
1541 : : {
1542 : 840 : gcc_assert (TREE_CODE (string_cst) == STRING_CST);
1543 : :
1544 : : /* Adapted from fold_read_from_constant_string. */
1545 : 840 : scalar_int_mode char_mode;
1546 : 840 : if (TREE_CODE (byte_offset_cst) == INTEGER_CST
1547 : 1680 : && is_int_mode (TYPE_MODE (TREE_TYPE (TREE_TYPE (string_cst))),
1548 : : &char_mode)
1549 : 1680 : && GET_MODE_SIZE (char_mode) == 1)
1550 : : {
1551 : : /* If we're beyond the string_cst, the read is unsuccessful. */
1552 : 840 : if (compare_constants (byte_offset_cst,
1553 : : GE_EXPR,
1554 : 840 : get_string_cst_size (string_cst)).is_true ())
1555 : : return NULL;
1556 : :
1557 : 790 : int char_val;
1558 : 1580 : if (compare_tree_int (byte_offset_cst,
1559 : 790 : TREE_STRING_LENGTH (string_cst)) < 0)
1560 : : /* We're within the area defined by TREE_STRING_POINTER. */
1561 : 788 : char_val = (TREE_STRING_POINTER (string_cst)
1562 : 788 : [TREE_INT_CST_LOW (byte_offset_cst)]);
1563 : : else
1564 : : /* We're in the padding area of trailing zeroes. */
1565 : : char_val = 0;
1566 : 790 : tree char_cst
1567 : 790 : = build_int_cst_type (TREE_TYPE (TREE_TYPE (string_cst)), char_val);
1568 : 790 : return get_or_create_constant_svalue (char_cst);
1569 : : }
1570 : : return NULL;
1571 : : }
1572 : :
1573 : : /* Given RAW_DATA_CST, a RAW_DATA_CST and BYTE_OFFSET_CST a constant,
1574 : : attempt to get the character at that offset, returning either
1575 : : the svalue for the character constant, or NULL if unsuccessful. */
1576 : :
1577 : : const svalue *
1578 : 66 : region_model_manager::maybe_get_char_from_raw_data_cst (tree raw_data_cst,
1579 : : tree byte_offset_cst)
1580 : : {
1581 : 66 : gcc_assert (TREE_CODE (raw_data_cst) == RAW_DATA_CST);
1582 : 66 : gcc_assert (TREE_CODE (byte_offset_cst) == INTEGER_CST);
1583 : :
1584 : 66 : offset_int o = (wi::to_offset (byte_offset_cst));
1585 : 66 : if (o >= 0 && o < RAW_DATA_LENGTH (raw_data_cst))
1586 : 54 : return get_or_create_int_cst
1587 : 54 : (TREE_TYPE (raw_data_cst),
1588 : 108 : RAW_DATA_UCHAR_ELT (raw_data_cst, o.to_uhwi ()));
1589 : : return nullptr;
1590 : : }
1591 : :
1592 : : /* region consolidation. */
1593 : :
1594 : : /* Return the region for FNDECL, creating it if necessary. */
1595 : :
1596 : : const function_region *
1597 : 892291 : region_model_manager::get_region_for_fndecl (tree fndecl)
1598 : : {
1599 : 892291 : gcc_assert (TREE_CODE (fndecl) == FUNCTION_DECL);
1600 : :
1601 : 892291 : function_region **slot = m_fndecls_map.get (fndecl);
1602 : 892291 : if (slot)
1603 : 883092 : return *slot;
1604 : 9199 : function_region *reg
1605 : 9199 : = new function_region (alloc_symbol_id (), &m_code_region, fndecl);
1606 : 9199 : m_fndecls_map.put (fndecl, reg);
1607 : 9199 : return reg;
1608 : : }
1609 : :
1610 : : /* Return the region for LABEL, creating it if necessary. */
1611 : :
1612 : : const label_region *
1613 : 401 : region_model_manager::get_region_for_label (tree label)
1614 : : {
1615 : 401 : gcc_assert (TREE_CODE (label) == LABEL_DECL);
1616 : :
1617 : 401 : label_region **slot = m_labels_map.get (label);
1618 : 401 : if (slot)
1619 : 355 : return *slot;
1620 : :
1621 : 46 : tree fndecl = DECL_CONTEXT (label);
1622 : 46 : gcc_assert (fndecl && TREE_CODE (fndecl) == FUNCTION_DECL);
1623 : :
1624 : 46 : const function_region *func_reg = get_region_for_fndecl (fndecl);
1625 : 46 : label_region *reg
1626 : 46 : = new label_region (alloc_symbol_id (), func_reg, label);
1627 : 46 : m_labels_map.put (label, reg);
1628 : 46 : return reg;
1629 : : }
1630 : :
1631 : : /* Return the region for EXPR, creating it if necessary. */
1632 : :
1633 : : const decl_region *
1634 : 58592 : region_model_manager::get_region_for_global (tree expr)
1635 : : {
1636 : 58592 : gcc_assert (VAR_P (expr));
1637 : :
1638 : 58592 : decl_region **slot = m_globals_map.get (expr);
1639 : 58592 : if (slot)
1640 : 52208 : return *slot;
1641 : 6384 : decl_region *reg
1642 : 6384 : = new decl_region (alloc_symbol_id (), &m_globals_region, expr);
1643 : 6384 : m_globals_map.put (expr, reg);
1644 : 6384 : return reg;
1645 : : }
1646 : :
1647 : : /* Return the region for an unknown access of type REGION_TYPE,
1648 : : creating it if necessary.
1649 : : This is a symbolic_region, where the pointer is an unknown_svalue
1650 : : of type ®ION_TYPE. */
1651 : :
1652 : : const region *
1653 : 14965 : region_model_manager::get_unknown_symbolic_region (tree region_type)
1654 : : {
1655 : 14965 : tree ptr_type = region_type ? build_pointer_type (region_type) : NULL_TREE;
1656 : 14965 : const svalue *unknown_ptr = get_or_create_unknown_svalue (ptr_type);
1657 : 14965 : return get_symbolic_region (unknown_ptr);
1658 : : }
1659 : :
1660 : : /* Return the region that describes accessing field FIELD of PARENT,
1661 : : creating it if necessary. */
1662 : :
1663 : : const region *
1664 : 60260 : region_model_manager::get_field_region (const region *parent, tree field)
1665 : : {
1666 : 60260 : gcc_assert (TREE_CODE (field) == FIELD_DECL);
1667 : :
1668 : : /* (*UNKNOWN_PTR).field is (*UNKNOWN_PTR_OF_&FIELD_TYPE). */
1669 : 60260 : if (parent->symbolic_for_unknown_ptr_p ())
1670 : 4635 : return get_unknown_symbolic_region (TREE_TYPE (field));
1671 : :
1672 : 55625 : field_region::key_t key (parent, field);
1673 : 103328 : if (field_region *reg = m_field_regions.get (key))
1674 : : return reg;
1675 : :
1676 : 7922 : field_region *field_reg
1677 : 7922 : = new field_region (alloc_symbol_id (), parent, field);
1678 : 7922 : m_field_regions.put (key, field_reg);
1679 : 7922 : return field_reg;
1680 : : }
1681 : :
1682 : : /* Return the region that describes accessing the element of type
1683 : : ELEMENT_TYPE at index INDEX of PARENT, creating it if necessary. */
1684 : :
1685 : : const region *
1686 : 16663 : region_model_manager::get_element_region (const region *parent,
1687 : : tree element_type,
1688 : : const svalue *index)
1689 : : {
1690 : : /* (UNKNOWN_PTR[IDX]) is (UNKNOWN_PTR). */
1691 : 16663 : if (parent->symbolic_for_unknown_ptr_p ())
1692 : 60 : return get_unknown_symbolic_region (element_type);
1693 : :
1694 : 16603 : element_region::key_t key (parent, element_type, index);
1695 : 29364 : if (element_region *reg = m_element_regions.get (key))
1696 : : return reg;
1697 : :
1698 : 3842 : element_region *element_reg
1699 : 3842 : = new element_region (alloc_symbol_id (), parent, element_type, index);
1700 : 3842 : m_element_regions.put (key, element_reg);
1701 : 3842 : return element_reg;
1702 : : }
1703 : :
1704 : : /* Return the region that describes accessing the subregion of type
1705 : : ELEMENT_TYPE at offset BYTE_OFFSET within PARENT, creating it if
1706 : : necessary. */
1707 : :
1708 : : const region *
1709 : 101142 : region_model_manager::get_offset_region (const region *parent,
1710 : : tree type,
1711 : : const svalue *byte_offset)
1712 : : {
1713 : : /* (UNKNOWN_PTR + OFFSET) is (UNKNOWN_PTR). */
1714 : 101640 : if (parent->symbolic_for_unknown_ptr_p ())
1715 : 9896 : return get_unknown_symbolic_region (type);
1716 : :
1717 : : /* If BYTE_OFFSET is zero, return PARENT. */
1718 : 91744 : if (tree cst_offset = byte_offset->maybe_get_constant ())
1719 : 81498 : if (zerop (cst_offset))
1720 : 73029 : return get_cast_region (parent, type);
1721 : :
1722 : : /* Fold OFFSET_REGION(OFFSET_REGION(REG, X), Y)
1723 : : to OFFSET_REGION(REG, (X + Y)). */
1724 : 37430 : if (const offset_region *parent_offset_reg
1725 : 18715 : = parent->dyn_cast_offset_region ())
1726 : : {
1727 : 498 : const svalue *sval_x = parent_offset_reg->get_byte_offset ();
1728 : 498 : const svalue *sval_sum
1729 : 498 : = get_or_create_binop (byte_offset->get_type (),
1730 : : PLUS_EXPR, sval_x, byte_offset);
1731 : 498 : return get_offset_region (parent->get_parent_region (), type, sval_sum);
1732 : : }
1733 : :
1734 : 18217 : offset_region::key_t key (parent, type, byte_offset);
1735 : 32691 : if (offset_region *reg = m_offset_regions.get (key))
1736 : : return reg;
1737 : :
1738 : 3743 : offset_region *offset_reg
1739 : 3743 : = new offset_region (alloc_symbol_id (), parent, type, byte_offset);
1740 : 3743 : m_offset_regions.put (key, offset_reg);
1741 : 3743 : return offset_reg;
1742 : : }
1743 : :
1744 : : /* Return the region that describes accessing the subregion of type
1745 : : TYPE of size BYTE_SIZE_SVAL within PARENT, creating it if necessary. */
1746 : :
1747 : : const region *
1748 : 8802 : region_model_manager::get_sized_region (const region *parent,
1749 : : tree type,
1750 : : const svalue *byte_size_sval)
1751 : : {
1752 : 8802 : if (parent->symbolic_for_unknown_ptr_p ())
1753 : 320 : return get_unknown_symbolic_region (type);
1754 : :
1755 : 8482 : if (byte_size_sval->get_type () != size_type_node)
1756 : 2109 : byte_size_sval = get_or_create_cast (size_type_node, byte_size_sval);
1757 : :
1758 : : /* If PARENT is already that size, return it. */
1759 : 8482 : const svalue *parent_byte_size_sval = parent->get_byte_size_sval (this);
1760 : 8482 : if (tree parent_size_cst = parent_byte_size_sval->maybe_get_constant ())
1761 : 2648 : if (tree size_cst = byte_size_sval->maybe_get_constant ())
1762 : : {
1763 : 2064 : tree comparison
1764 : 2064 : = fold_binary (EQ_EXPR, boolean_type_node, parent_size_cst, size_cst);
1765 : 2064 : if (comparison == boolean_true_node)
1766 : : return parent;
1767 : : }
1768 : :
1769 : 7339 : sized_region::key_t key (parent, type, byte_size_sval);
1770 : 11550 : if (sized_region *reg = m_sized_regions.get (key))
1771 : : return reg;
1772 : :
1773 : 3128 : sized_region *sized_reg
1774 : 3128 : = new sized_region (alloc_symbol_id (), parent, type, byte_size_sval);
1775 : 3128 : m_sized_regions.put (key, sized_reg);
1776 : 3128 : return sized_reg;
1777 : : }
1778 : :
1779 : : /* Return the region that describes accessing PARENT_REGION as if
1780 : : it were of type TYPE, creating it if necessary. */
1781 : :
1782 : : const region *
1783 : 75555 : region_model_manager::get_cast_region (const region *original_region,
1784 : : tree type)
1785 : : {
1786 : : /* If types match, return ORIGINAL_REGION. */
1787 : 75555 : if (type == original_region->get_type ())
1788 : : return original_region;
1789 : :
1790 : 21029 : if (original_region->symbolic_for_unknown_ptr_p ())
1791 : 54 : return get_unknown_symbolic_region (type);
1792 : :
1793 : 20975 : cast_region::key_t key (original_region, type);
1794 : 39319 : if (cast_region *reg = m_cast_regions.get (key))
1795 : : return reg;
1796 : :
1797 : 2631 : cast_region *cast_reg
1798 : 2631 : = new cast_region (alloc_symbol_id (), original_region, type);
1799 : 2631 : m_cast_regions.put (key, cast_reg);
1800 : 2631 : return cast_reg;
1801 : : }
1802 : :
1803 : : /* Return the frame_region for call to FUN from CALLING_FRAME, creating it
1804 : : if necessary. CALLING_FRAME may be NULL. */
1805 : :
1806 : : const frame_region *
1807 : 33992 : region_model_manager::get_frame_region (const frame_region *calling_frame,
1808 : : const function &fun)
1809 : : {
1810 : 33992 : int index = calling_frame ? calling_frame->get_index () + 1 : 0;
1811 : :
1812 : 33992 : frame_region::key_t key (calling_frame, fun);
1813 : 53575 : if (frame_region *reg = m_frame_regions.get (key))
1814 : : return reg;
1815 : :
1816 : 14409 : frame_region *frame_reg
1817 : : = new frame_region (alloc_symbol_id (), &m_stack_region, calling_frame,
1818 : 14409 : fun, index);
1819 : 14409 : m_frame_regions.put (key, frame_reg);
1820 : 14409 : return frame_reg;
1821 : : }
1822 : :
1823 : : /* Return the region that describes dereferencing SVAL, creating it
1824 : : if necessary. */
1825 : :
1826 : : const region *
1827 : 91624 : region_model_manager::get_symbolic_region (const svalue *sval)
1828 : : {
1829 : 91624 : symbolic_region::key_t key (&m_root_region, sval);
1830 : 174808 : if (symbolic_region *reg = m_symbolic_regions.get (key))
1831 : : return reg;
1832 : :
1833 : 8440 : symbolic_region *symbolic_reg
1834 : 8440 : = new symbolic_region (alloc_symbol_id (), &m_root_region, sval);
1835 : 8440 : m_symbolic_regions.put (key, symbolic_reg);
1836 : 8440 : return symbolic_reg;
1837 : : }
1838 : :
1839 : : /* Return the region that describes accessing STRING_CST, creating it
1840 : : if necessary. */
1841 : :
1842 : : const string_region *
1843 : 17341 : region_model_manager::get_region_for_string (tree string_cst)
1844 : : {
1845 : 17341 : gcc_assert (TREE_CODE (string_cst) == STRING_CST);
1846 : :
1847 : 17341 : string_region **slot = m_string_map.get (string_cst);
1848 : 17341 : if (slot)
1849 : 13585 : return *slot;
1850 : 3756 : string_region *reg
1851 : 3756 : = new string_region (alloc_symbol_id (), &m_root_region, string_cst);
1852 : 3756 : m_string_map.put (string_cst, reg);
1853 : 3756 : return reg;
1854 : : }
1855 : :
1856 : : /* Return the region that describes accessing BITS within PARENT as TYPE,
1857 : : creating it if necessary. */
1858 : :
1859 : : const region *
1860 : 242 : region_model_manager::get_bit_range (const region *parent, tree type,
1861 : : const bit_range &bits)
1862 : : {
1863 : 242 : gcc_assert (parent);
1864 : :
1865 : 242 : if (parent->symbolic_for_unknown_ptr_p ())
1866 : 0 : return get_unknown_symbolic_region (type);
1867 : :
1868 : 242 : bit_range_region::key_t key (parent, type, bits);
1869 : 317 : if (bit_range_region *reg = m_bit_range_regions.get (key))
1870 : : return reg;
1871 : :
1872 : 167 : bit_range_region *bit_range_reg
1873 : 167 : = new bit_range_region (alloc_symbol_id (), parent, type, bits);
1874 : 167 : m_bit_range_regions.put (key, bit_range_reg);
1875 : 167 : return bit_range_reg;
1876 : : }
1877 : :
1878 : : /* Return the region that describes accessing the IDX-th variadic argument
1879 : : within PARENT_FRAME, creating it if necessary. */
1880 : :
1881 : : const var_arg_region *
1882 : 1121 : region_model_manager::get_var_arg_region (const frame_region *parent_frame,
1883 : : unsigned idx)
1884 : : {
1885 : 1121 : gcc_assert (parent_frame);
1886 : :
1887 : 1121 : var_arg_region::key_t key (parent_frame, idx);
1888 : 1763 : if (var_arg_region *reg = m_var_arg_regions.get (key))
1889 : : return reg;
1890 : :
1891 : 479 : var_arg_region *var_arg_reg
1892 : 479 : = new var_arg_region (alloc_symbol_id (), parent_frame, idx);
1893 : 479 : m_var_arg_regions.put (key, var_arg_reg);
1894 : 479 : return var_arg_reg;
1895 : : }
1896 : :
1897 : : /* If we see a tree code we don't know how to handle, rather than
1898 : : ICE or generate bogus results, create a dummy region, and notify
1899 : : CTXT so that it can mark the new state as being not properly
1900 : : modelled. The exploded graph can then stop exploring that path,
1901 : : since any diagnostics we might issue will have questionable
1902 : : validity. */
1903 : :
1904 : : const region *
1905 : 54 : region_model_manager::
1906 : : get_region_for_unexpected_tree_code (region_model_context *ctxt,
1907 : : tree t,
1908 : : const dump_location_t &loc)
1909 : : {
1910 : 54 : tree type = TYPE_P (t) ? t : TREE_TYPE (t);
1911 : 54 : region *new_reg
1912 : 54 : = new unknown_region (alloc_symbol_id (), &m_root_region, type);
1913 : 54 : if (ctxt)
1914 : 54 : ctxt->on_unexpected_tree_code (t, loc);
1915 : 54 : return new_reg;
1916 : : }
1917 : :
1918 : : /* Return a region describing a heap-allocated block of memory.
1919 : : Reuse an existing heap_allocated_region is its id is not within
1920 : : BASE_REGS_IN_USE. */
1921 : :
1922 : : const region *
1923 : 21076 : region_model_manager::
1924 : : get_or_create_region_for_heap_alloc (const bitmap &base_regs_in_use)
1925 : : {
1926 : : /* Try to reuse an existing region, if it's unreferenced in the
1927 : : client state. */
1928 : 85632 : for (auto existing_reg : m_managed_dynamic_regions)
1929 : 44070 : if (!bitmap_bit_p (base_regs_in_use, existing_reg->get_id ()))
1930 : 19556 : if (existing_reg->get_kind () == RK_HEAP_ALLOCATED)
1931 : : return existing_reg;
1932 : :
1933 : : /* All existing ones (if any) are in use; create a new one. */
1934 : 1754 : region *reg
1935 : 1754 : = new heap_allocated_region (alloc_symbol_id (), &m_heap_region);
1936 : 1754 : m_managed_dynamic_regions.safe_push (reg);
1937 : 1754 : return reg;
1938 : : }
1939 : :
1940 : : /* Return a new region describing a block of memory allocated within FRAME. */
1941 : :
1942 : : const region *
1943 : 1105 : region_model_manager::create_region_for_alloca (const frame_region *frame)
1944 : : {
1945 : 1105 : gcc_assert (frame);
1946 : 1105 : region *reg = new alloca_region (alloc_symbol_id (), frame);
1947 : 1105 : m_managed_dynamic_regions.safe_push (reg);
1948 : 1105 : return reg;
1949 : : }
1950 : :
1951 : : /* Log OBJ to LOGGER. */
1952 : :
1953 : : template <typename T>
1954 : : static void
1955 : 110 : log_managed_object (logger *logger, const T *obj)
1956 : : {
1957 : 110 : logger->start_log_line ();
1958 : 110 : pretty_printer *pp = logger->get_printer ();
1959 : 110 : pp_string (pp, " ");
1960 : 110 : obj->dump_to_pp (pp, true);
1961 : 110 : logger->end_log_line ();
1962 : 110 : }
1963 : :
1964 : : /* Specialization for frame_region, which also logs the count of locals
1965 : : managed by the frame_region. */
1966 : :
1967 : : template <>
1968 : : void
1969 : 2 : log_managed_object (logger *logger, const frame_region *obj)
1970 : : {
1971 : 2 : logger->start_log_line ();
1972 : 2 : pretty_printer *pp = logger->get_printer ();
1973 : 2 : pp_string (pp, " ");
1974 : 2 : obj->dump_to_pp (pp, true);
1975 : 2 : pp_printf (pp, " [with %i region(s) for locals]", obj->get_num_locals ());
1976 : 2 : logger->end_log_line ();
1977 : 2 : }
1978 : :
1979 : : /* Dump the number of objects that were managed by UNIQ_MAP to LOGGER.
1980 : : If SHOW_OBJS is true, also dump the objects themselves. */
1981 : :
1982 : : template <typename K, typename T>
1983 : : static void
1984 : 42 : log_uniq_map (logger *logger, bool show_objs, const char *title,
1985 : : const hash_map<K, T*> &uniq_map)
1986 : : {
1987 : 42 : logger->log (" # %s: %li", title, (long)uniq_map.elements ());
1988 : 42 : if (!show_objs)
1989 : 0 : return;
1990 : 42 : auto_vec<const T *> vec_objs (uniq_map.elements ());
1991 : 42 : for (typename hash_map<K, T*>::iterator iter = uniq_map.begin ();
1992 : 172 : iter != uniq_map.end (); ++iter)
1993 : 88 : vec_objs.quick_push ((*iter).second);
1994 : :
1995 : 130 : vec_objs.qsort (T::cmp_ptr_ptr);
1996 : :
1997 : : unsigned i;
1998 : : const T *obj;
1999 : 144 : FOR_EACH_VEC_ELT (vec_objs, i, obj)
2000 : 88 : log_managed_object<T> (logger, obj);
2001 : 42 : }
2002 : :
2003 : : /* Dump the number of objects that were managed by MAP to LOGGER.
2004 : : If SHOW_OBJS is true, also dump the objects themselves. */
2005 : :
2006 : : template <typename T>
2007 : : static void
2008 : 22 : log_uniq_map (logger *logger, bool show_objs, const char *title,
2009 : : const consolidation_map<T> &map)
2010 : : {
2011 : 22 : logger->log (" # %s: %li", title, (long)map.elements ());
2012 : 22 : if (!show_objs)
2013 : 0 : return;
2014 : :
2015 : 22 : auto_vec<const T *> vec_objs (map.elements ());
2016 : 22 : for (typename consolidation_map<T>::iterator iter = map.begin ();
2017 : 67 : iter != map.end (); ++iter)
2018 : 23 : vec_objs.quick_push ((*iter).second);
2019 : :
2020 : 45 : vec_objs.qsort (T::cmp_ptr_ptr);
2021 : :
2022 : : unsigned i;
2023 : : const T *obj;
2024 : 52 : FOR_EACH_VEC_ELT (vec_objs, i, obj)
2025 : 23 : log_managed_object<T> (logger, obj);
2026 : 22 : }
2027 : :
2028 : : /* Dump the number of objects of each class that were managed by this
2029 : : manager to LOGGER.
2030 : : If SHOW_OBJS is true, also dump the objects themselves. */
2031 : :
2032 : : void
2033 : 2 : region_model_manager::log_stats (logger *logger, bool show_objs) const
2034 : : {
2035 : 2 : LOG_SCOPE (logger);
2036 : 2 : logger->log ("call string consolidation");
2037 : 2 : m_empty_call_string.recursive_log (logger);
2038 : 2 : logger->log ("next symbol id: %i", m_next_symbol_id);
2039 : 2 : logger->log ("svalue consolidation");
2040 : 2 : log_uniq_map (logger, show_objs, "constant_svalue", m_constants_map);
2041 : 2 : log_uniq_map (logger, show_objs, "unknown_svalue", m_unknowns_map);
2042 : 2 : if (m_unknown_NULL)
2043 : 1 : log_managed_object (logger, m_unknown_NULL);
2044 : 2 : log_uniq_map (logger, show_objs, "poisoned_svalue", m_poisoned_values_map);
2045 : 2 : log_uniq_map (logger, show_objs, "setjmp_svalue", m_setjmp_values_map);
2046 : 2 : log_uniq_map (logger, show_objs, "initial_svalue", m_initial_values_map);
2047 : 2 : log_uniq_map (logger, show_objs, "region_svalue", m_pointer_values_map);
2048 : 2 : log_uniq_map (logger, show_objs, "unaryop_svalue", m_unaryop_values_map);
2049 : 2 : log_uniq_map (logger, show_objs, "binop_svalue", m_binop_values_map);
2050 : 2 : log_uniq_map (logger, show_objs, "sub_svalue", m_sub_values_map);
2051 : 2 : log_uniq_map (logger, show_objs, "repeated_svalue", m_repeated_values_map);
2052 : 2 : log_uniq_map (logger, show_objs, "bits_within_svalue",
2053 : 2 : m_bits_within_values_map);
2054 : 2 : log_uniq_map (logger, show_objs, "unmergeable_svalue",
2055 : 2 : m_unmergeable_values_map);
2056 : 2 : log_uniq_map (logger, show_objs, "widening_svalue", m_widening_values_map);
2057 : 2 : log_uniq_map (logger, show_objs, "compound_svalue", m_compound_values_map);
2058 : 2 : log_uniq_map (logger, show_objs, "conjured_svalue", m_conjured_values_map);
2059 : 2 : log_uniq_map (logger, show_objs, "asm_output_svalue",
2060 : 2 : m_asm_output_values_map);
2061 : 2 : log_uniq_map (logger, show_objs, "const_fn_result_svalue",
2062 : 2 : m_const_fn_result_values_map);
2063 : :
2064 : 2 : logger->log ("max accepted svalue num_nodes: %i",
2065 : 2 : m_max_complexity.m_num_nodes);
2066 : 2 : logger->log ("max accepted svalue max_depth: %i",
2067 : 2 : m_max_complexity.m_max_depth);
2068 : :
2069 : 2 : logger->log ("region consolidation");
2070 : 2 : log_uniq_map (logger, show_objs, "function_region", m_fndecls_map);
2071 : 2 : log_uniq_map (logger, show_objs, "label_region", m_labels_map);
2072 : 2 : log_uniq_map (logger, show_objs, "decl_region for globals", m_globals_map);
2073 : 2 : log_uniq_map (logger, show_objs, "field_region", m_field_regions);
2074 : 2 : log_uniq_map (logger, show_objs, "element_region", m_element_regions);
2075 : 2 : log_uniq_map (logger, show_objs, "offset_region", m_offset_regions);
2076 : 2 : log_uniq_map (logger, show_objs, "sized_region", m_sized_regions);
2077 : 2 : log_uniq_map (logger, show_objs, "cast_region", m_cast_regions);
2078 : 2 : log_uniq_map (logger, show_objs, "frame_region", m_frame_regions);
2079 : 2 : log_uniq_map (logger, show_objs, "symbolic_region", m_symbolic_regions);
2080 : 2 : log_uniq_map (logger, show_objs, "string_region", m_string_map);
2081 : 2 : log_uniq_map (logger, show_objs, "bit_range_region", m_bit_range_regions);
2082 : 2 : log_uniq_map (logger, show_objs, "var_arg_region", m_var_arg_regions);
2083 : 2 : logger->log (" # managed dynamic regions: %i",
2084 : : m_managed_dynamic_regions.length ());
2085 : 2 : m_store_mgr.log_stats (logger, show_objs);
2086 : 2 : m_range_mgr->log_stats (logger, show_objs);
2087 : 2 : }
2088 : :
2089 : : /* Dump the number of objects of each class that were managed by this
2090 : : manager to LOGGER.
2091 : : If SHOW_OBJS is true, also dump the objects themselves.
2092 : : This is here so it can use log_uniq_map. */
2093 : :
2094 : : void
2095 : 2 : store_manager::log_stats (logger *logger, bool show_objs) const
2096 : : {
2097 : 2 : LOG_SCOPE (logger);
2098 : 2 : log_uniq_map (logger, show_objs, "concrete_binding",
2099 : 2 : m_concrete_binding_key_mgr);
2100 : 2 : log_uniq_map (logger, show_objs, "symbolic_binding",
2101 : 2 : m_symbolic_binding_key_mgr);
2102 : 2 : }
2103 : :
2104 : : /* Emit a warning showing DECL_REG->tracked_p () for use in DejaGnu tests
2105 : : (using -fdump-analyzer-untracked). */
2106 : :
2107 : : static void
2108 : 163 : dump_untracked_region (const decl_region *decl_reg)
2109 : : {
2110 : 163 : tree decl = decl_reg->get_decl ();
2111 : 163 : if (TREE_CODE (decl) != VAR_DECL)
2112 : : return;
2113 : : /* For now, don't emit the status of decls in the constant pool, to avoid
2114 : : differences in DejaGnu test results between targets that use these vs
2115 : : those that don't.
2116 : : (Eventually these decls should probably be untracked and we should test
2117 : : for that, but that's not stage 4 material). */
2118 : 56 : if (DECL_IN_CONSTANT_POOL (decl))
2119 : : return;
2120 : 85 : warning_at (DECL_SOURCE_LOCATION (decl), 0,
2121 : : "track %qD: %s",
2122 : 56 : decl, (decl_reg->tracked_p () ? "yes" : "no"));
2123 : : }
2124 : :
2125 : : /* Implementation of -fdump-analyzer-untracked. */
2126 : :
2127 : : void
2128 : 23 : region_model_manager::dump_untracked_regions () const
2129 : : {
2130 : 74 : for (auto iter : m_globals_map)
2131 : : {
2132 : 51 : const decl_region *decl_reg = iter.second;
2133 : 51 : dump_untracked_region (decl_reg);
2134 : : }
2135 : 75 : for (auto frame_iter : m_frame_regions)
2136 : : {
2137 : 52 : const frame_region *frame_reg = frame_iter.second;
2138 : 52 : frame_reg->dump_untracked_regions ();
2139 : : }
2140 : 23 : }
2141 : :
2142 : : void
2143 : 52 : frame_region::dump_untracked_regions () const
2144 : : {
2145 : 164 : for (auto iter : m_locals)
2146 : : {
2147 : 112 : const decl_region *decl_reg = iter.second;
2148 : 112 : dump_untracked_region (decl_reg);
2149 : : }
2150 : 52 : }
2151 : :
2152 : : } // namespace ana
2153 : :
2154 : : #endif /* #if ENABLE_ANALYZER */
|