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