Branch data Line data Source code
1 : : /* Classes for working with summaries of function calls.
2 : : Copyright (C) 2022 David Malcolm <dmalcolm@redhat.com>.
3 : :
4 : : This file is part of GCC.
5 : :
6 : : GCC is free software; you can redistribute it and/or modify it
7 : : under the terms of the GNU General Public License as published by
8 : : the Free Software Foundation; either version 3, or (at your option)
9 : : any later version.
10 : :
11 : : GCC is distributed in the hope that it will be useful, but
12 : : WITHOUT ANY WARRANTY; without even the implied warranty of
13 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 : : General Public License for more details.
15 : :
16 : : You should have received a copy of the GNU General Public License
17 : : along with GCC; see the file COPYING3. If not see
18 : : <http://www.gnu.org/licenses/>. */
19 : :
20 : : #include "config.h"
21 : : #define INCLUDE_MEMORY
22 : : #include "system.h"
23 : : #include "coretypes.h"
24 : : #include "tree.h"
25 : : #include "tree-dfa.h"
26 : : #include "diagnostic-core.h"
27 : : #include "diagnostic.h"
28 : : #include "tree-diagnostic.h"
29 : : #include "analyzer/analyzer.h"
30 : : #include "analyzer/region-model.h"
31 : : #include "analyzer/call-summary.h"
32 : : #include "analyzer/exploded-graph.h"
33 : :
34 : : #if ENABLE_ANALYZER
35 : :
36 : : namespace ana {
37 : :
38 : : /* class call_summary. */
39 : :
40 : : const program_state &
41 : 5019 : call_summary::get_state () const
42 : : {
43 : 5019 : return m_enode->get_state ();
44 : : }
45 : :
46 : : tree
47 : 134 : call_summary::get_fndecl () const
48 : : {
49 : 134 : return m_enode->get_point ().get_fndecl ();
50 : : }
51 : :
52 : : label_text
53 : 134 : call_summary::get_desc () const
54 : : {
55 : 134 : pretty_printer pp;
56 : 134 : pp_format_decoder (&pp) = default_tree_printer;
57 : :
58 : 134 : get_user_facing_desc (&pp);
59 : 134 : if (flag_analyzer_verbose_edges)
60 : 0 : pp_printf (&pp, " (call summary; EN: %i)", m_enode->m_index);
61 : :
62 : 134 : return label_text::take (xstrdup (pp_formatted_text (&pp)));
63 : 134 : }
64 : :
65 : : /* Generate a user-facing description of this call summary.c
66 : : This has various heuristics for distinguishing between different
67 : : summaries.
68 : : This will help with debugging, too. */
69 : :
70 : : void
71 : 134 : call_summary::get_user_facing_desc (pretty_printer *pp) const
72 : : {
73 : 134 : tree fndecl = get_fndecl ();
74 : :
75 : : /* If there are multiple summaries, try to use the return value to
76 : : distinguish between them. */
77 : 134 : if (m_per_fn_data->m_summaries.length () > 1)
78 : : {
79 : 86 : if (tree result = DECL_RESULT (fndecl))
80 : : {
81 : 86 : const region *result_reg
82 : 86 : = get_state ().m_region_model->get_lvalue (result, NULL);
83 : 86 : const svalue *result_sval
84 : 86 : = get_state ().m_region_model->get_store_value (result_reg, NULL);
85 : 86 : switch (result_sval->get_kind ())
86 : : {
87 : : default:
88 : : break;
89 : 40 : case SK_REGION:
90 : 40 : {
91 : 40 : const region_svalue *region_sval
92 : 40 : = as_a <const region_svalue *> (result_sval);
93 : 40 : const region *pointee_reg = region_sval->get_pointee ();
94 : 40 : switch (pointee_reg->get_kind ())
95 : : {
96 : : default:
97 : : break;
98 : 40 : case RK_HEAP_ALLOCATED:
99 : 40 : pp_printf (pp,
100 : : "when %qE returns pointer"
101 : : " to heap-allocated buffer",
102 : : fndecl);
103 : 40 : return;
104 : : }
105 : : }
106 : : break;
107 : 0 : case SK_CONSTANT:
108 : 0 : {
109 : 0 : const constant_svalue *constant_sval
110 : 0 : = as_a <const constant_svalue *> (result_sval);
111 : 0 : tree cst = constant_sval->get_constant ();
112 : 0 : if (POINTER_TYPE_P (TREE_TYPE (result))
113 : 0 : && zerop (cst))
114 : 0 : pp_printf (pp, "when %qE returns NULL", fndecl);
115 : : else
116 : 0 : pp_printf (pp, "when %qE returns %qE", fndecl, cst);
117 : 0 : return;
118 : : }
119 : : }
120 : : }
121 : : }
122 : :
123 : : /* Fallback. */
124 : 94 : pp_printf (pp, "when %qE returns", fndecl);
125 : : }
126 : :
127 : : /* Dump a multiline representation of this object to PP. */
128 : :
129 : : void
130 : 0 : call_summary::dump_to_pp (const extrinsic_state &ext_state,
131 : : pretty_printer *pp,
132 : : bool simple) const
133 : : {
134 : 0 : label_text desc = get_desc ();
135 : 0 : pp_printf (pp, "desc: %qs", desc.get ());
136 : 0 : pp_newline (pp);
137 : :
138 : 0 : get_state ().dump_to_pp (ext_state, simple, true, pp);
139 : 0 : }
140 : :
141 : : /* Dump a multiline representation of this object to FILE. */
142 : :
143 : : void
144 : 0 : call_summary::dump (const extrinsic_state &ext_state,
145 : : FILE *fp,
146 : : bool simple) const
147 : : {
148 : 0 : pretty_printer pp;
149 : 0 : pp_format_decoder (&pp) = default_tree_printer;
150 : 0 : pp_show_color (&pp) = pp_show_color (global_dc->printer);
151 : 0 : pp.buffer->stream = fp;
152 : 0 : dump_to_pp (ext_state, &pp, simple);
153 : 0 : pp_flush (&pp);
154 : 0 : }
155 : :
156 : : /* Dump a multiline representation of this object to stderr. */
157 : :
158 : : DEBUG_FUNCTION void
159 : 0 : call_summary::dump (const extrinsic_state &ext_state, bool simple) const
160 : : {
161 : 0 : dump (ext_state, stderr, simple);
162 : 0 : }
163 : :
164 : : /* class call_summary_replay. */
165 : :
166 : : /* call_summary_replay's ctor.
167 : : Populate the cache with params for the summary based on
168 : : arguments at the caller. */
169 : :
170 : 4827 : call_summary_replay::call_summary_replay (const call_details &cd,
171 : : const function &called_fn,
172 : : call_summary *summary,
173 : 4827 : const extrinsic_state &ext_state)
174 : 4827 : : m_cd (cd),
175 : 4827 : m_summary (summary),
176 : 4827 : m_ext_state (ext_state)
177 : : {
178 : 4827 : region_model_manager *mgr = cd.get_manager ();
179 : :
180 : : // populate params based on args
181 : 4827 : tree fndecl = called_fn.decl;
182 : :
183 : : /* Get a frame_region for use with respect to the summary.
184 : : This will be a top-level frame, since that's what's in
185 : : the summary. */
186 : 4827 : const frame_region *summary_frame
187 : 4827 : = mgr->get_frame_region (NULL, called_fn);
188 : :
189 : 4827 : unsigned idx = 0;
190 : 8665 : for (tree iter_parm = DECL_ARGUMENTS (fndecl); iter_parm;
191 : 3838 : iter_parm = DECL_CHAIN (iter_parm), ++idx)
192 : : {
193 : : /* If there's a mismatching declaration, the call stmt might
194 : : not have enough args. Handle this case by leaving the
195 : : rest of the params as uninitialized. */
196 : 3838 : if (idx >= cd.num_args ())
197 : : break;
198 : 3838 : const svalue *caller_arg_sval = cd.get_arg_svalue (idx);
199 : 3838 : tree parm_lval = iter_parm;
200 : 3838 : if (tree parm_default_ssa = get_ssa_default_def (called_fn, iter_parm))
201 : 3810 : parm_lval = parm_default_ssa;
202 : 3838 : const region *summary_parm_reg
203 : 3838 : = summary_frame->get_region_for_local (mgr, parm_lval, cd.get_ctxt ());
204 : 3838 : const svalue *summary_initial_parm_reg
205 : 3838 : = mgr->get_or_create_initial_value (summary_parm_reg);
206 : 3838 : add_svalue_mapping (summary_initial_parm_reg, caller_arg_sval);
207 : : }
208 : :
209 : : /* Handle any variadic args. */
210 : : unsigned va_arg_idx = 0;
211 : 4843 : for (; idx < cd.num_args (); idx++, va_arg_idx++)
212 : : {
213 : 16 : const svalue *caller_arg_sval = cd.get_arg_svalue (idx);
214 : 16 : const region *summary_var_arg_reg
215 : 16 : = mgr->get_var_arg_region (summary_frame, va_arg_idx);
216 : 16 : const svalue *summary_initial_var_arg_reg
217 : 16 : = mgr->get_or_create_initial_value (summary_var_arg_reg);
218 : 16 : add_svalue_mapping (summary_initial_var_arg_reg, caller_arg_sval);
219 : : }
220 : 4827 : }
221 : :
222 : : /* Try to convert SUMMARY_SVAL in the summary to a corresponding svalue
223 : : in the caller, caching the result.
224 : :
225 : : Return NULL if the conversion is not possible. */
226 : :
227 : : const svalue *
228 : 63646 : call_summary_replay::convert_svalue_from_summary (const svalue *summary_sval)
229 : : {
230 : 63646 : gcc_assert (summary_sval);
231 : :
232 : 127292 : if (const svalue **slot
233 : 63646 : = m_map_svalue_from_summary_to_caller.get (summary_sval))
234 : 35766 : return *slot;
235 : :
236 : 27880 : const svalue *caller_sval = convert_svalue_from_summary_1 (summary_sval);
237 : :
238 : 27880 : if (caller_sval)
239 : 27196 : if (summary_sval->get_type () && caller_sval->get_type ())
240 : 25513 : gcc_assert (types_compatible_p (summary_sval->get_type (),
241 : : caller_sval->get_type ()));
242 : :
243 : : /* Add to cache. */
244 : 27880 : add_svalue_mapping (summary_sval, caller_sval);
245 : :
246 : 27880 : return caller_sval;
247 : : }
248 : :
249 : : /* Implementation of call_summary_replay::convert_svalue_from_summary. */
250 : :
251 : : const svalue *
252 : 27880 : call_summary_replay::convert_svalue_from_summary_1 (const svalue *summary_sval)
253 : : {
254 : 27880 : gcc_assert (summary_sval);
255 : :
256 : 27880 : switch (summary_sval->get_kind ())
257 : : {
258 : 0 : default:
259 : 0 : gcc_unreachable ();
260 : 3246 : case SK_REGION:
261 : 3246 : {
262 : 3246 : const region_svalue *region_summary_sval
263 : 3246 : = as_a <const region_svalue *> (summary_sval);
264 : 3246 : const region *summary_reg = region_summary_sval->get_pointee ();
265 : 3246 : const region *caller_reg = convert_region_from_summary (summary_reg);
266 : 3246 : if (!caller_reg)
267 : : return NULL;
268 : 3244 : region_model_manager *mgr = get_manager ();
269 : 3244 : const svalue *caller_ptr
270 : 3244 : = mgr->get_ptr_svalue (summary_sval->get_type (),
271 : : caller_reg);
272 : 3244 : return caller_ptr;
273 : : }
274 : : break;
275 : :
276 : : case SK_CONSTANT:
277 : : case SK_PLACEHOLDER:
278 : : case SK_POISONED:
279 : : case SK_UNKNOWN:
280 : : return summary_sval;
281 : :
282 : : case SK_SETJMP:
283 : : return NULL; // TODO
284 : :
285 : 4688 : case SK_INITIAL:
286 : 4688 : {
287 : 4688 : const initial_svalue *initial_summary_sval
288 : 4688 : = as_a <const initial_svalue *> (summary_sval);
289 : : /* Params should already be in the cache, courtesy of the ctor. */
290 : 4688 : gcc_assert (!initial_summary_sval->initial_value_of_param_p ());
291 : :
292 : : /* Initial value of region within the summary is the value of the
293 : : region at the point of the call. */
294 : 4688 : const region *summary_reg = initial_summary_sval->get_region ();
295 : 4688 : const region *caller_reg = convert_region_from_summary (summary_reg);
296 : 4688 : if (!caller_reg)
297 : : return NULL;
298 : 4676 : const svalue *caller_sval
299 : 4676 : = m_cd.get_model ()->get_store_value (caller_reg, m_cd.get_ctxt ());
300 : 4676 : return caller_sval;
301 : : }
302 : 125 : break;
303 : 125 : case SK_UNARYOP:
304 : 125 : {
305 : 125 : const unaryop_svalue *unaryop_summary_sval
306 : 125 : = as_a <const unaryop_svalue *> (summary_sval);
307 : 125 : const svalue *summary_arg = unaryop_summary_sval->get_arg ();
308 : 125 : const svalue *caller_arg = convert_svalue_from_summary (summary_arg);
309 : 125 : if (!caller_arg)
310 : : return NULL;
311 : 125 : region_model_manager *mgr = get_manager ();
312 : 125 : return mgr->get_or_create_unaryop (summary_sval->get_type (),
313 : : unaryop_summary_sval->get_op (),
314 : 125 : caller_arg);
315 : : }
316 : 2880 : break;
317 : 2880 : case SK_BINOP:
318 : 2880 : {
319 : 2880 : const binop_svalue *binop_summary_sval
320 : 2880 : = as_a <const binop_svalue *> (summary_sval);
321 : 2880 : const svalue *summary_arg0 = binop_summary_sval->get_arg0 ();
322 : 2880 : const svalue *caller_arg0 = convert_svalue_from_summary (summary_arg0);
323 : 2880 : if (!caller_arg0)
324 : : return NULL;
325 : 2880 : const svalue *summary_arg1 = binop_summary_sval->get_arg1 ();
326 : 2880 : const svalue *caller_arg1 = convert_svalue_from_summary (summary_arg1);
327 : 2880 : if (!caller_arg1)
328 : : return NULL;
329 : 2880 : region_model_manager *mgr = get_manager ();
330 : 2880 : return mgr->get_or_create_binop (summary_sval->get_type (),
331 : : binop_summary_sval->get_op (),
332 : : caller_arg0,
333 : 2880 : caller_arg1);
334 : : }
335 : 0 : break;
336 : 0 : case SK_SUB:
337 : 0 : {
338 : 0 : const sub_svalue *sub_summary_sval
339 : 0 : = as_a <const sub_svalue *> (summary_sval);
340 : 0 : region_model_manager *mgr = get_manager ();
341 : 0 : const svalue *summary_parent_sval = sub_summary_sval->get_parent ();
342 : 0 : if (!summary_parent_sval)
343 : : return NULL;
344 : 0 : const region *summary_subregion = sub_summary_sval->get_subregion ();
345 : 0 : if (!summary_subregion)
346 : : return NULL;
347 : 0 : return mgr->get_or_create_sub_svalue (summary_sval->get_type (),
348 : : summary_parent_sval,
349 : 0 : summary_subregion);
350 : : }
351 : 43 : break;
352 : 43 : case SK_REPEATED:
353 : 43 : {
354 : 43 : const repeated_svalue *repeated_summary_sval
355 : 43 : = as_a <const repeated_svalue *> (summary_sval);
356 : 43 : const svalue *summary_outer_size
357 : 43 : = repeated_summary_sval->get_outer_size ();
358 : 43 : const svalue *caller_outer_size
359 : 43 : = convert_svalue_from_summary (summary_outer_size);
360 : 43 : if (!caller_outer_size)
361 : : return NULL;
362 : 43 : const svalue *summary_inner_sval
363 : 43 : = repeated_summary_sval->get_inner_svalue ();
364 : 43 : const svalue *caller_inner_sval
365 : 43 : = convert_svalue_from_summary (summary_inner_sval);
366 : 43 : if (!caller_inner_sval)
367 : : return NULL;
368 : 43 : region_model_manager *mgr = get_manager ();
369 : 43 : return mgr->get_or_create_repeated_svalue (summary_sval->get_type (),
370 : : caller_outer_size,
371 : 43 : caller_inner_sval);
372 : : }
373 : 0 : break;
374 : 0 : case SK_BITS_WITHIN:
375 : 0 : {
376 : 0 : const bits_within_svalue *bits_within_summary_sval
377 : 0 : = as_a <const bits_within_svalue *> (summary_sval);
378 : 0 : const bit_range &bits = bits_within_summary_sval->get_bits ();
379 : 0 : const svalue *summary_inner_sval
380 : 0 : = bits_within_summary_sval->get_inner_svalue ();
381 : 0 : const svalue *caller_inner_sval
382 : 0 : = convert_svalue_from_summary (summary_inner_sval);
383 : 0 : if (!caller_inner_sval)
384 : : return NULL;
385 : 0 : region_model_manager *mgr = get_manager ();
386 : 0 : return mgr->get_or_create_bits_within (summary_sval->get_type (),
387 : : bits,
388 : 0 : caller_inner_sval);
389 : : }
390 : 0 : break;
391 : 0 : case SK_UNMERGEABLE:
392 : 0 : {
393 : 0 : const unmergeable_svalue *unmergeable_summary_sval
394 : 0 : = as_a <const unmergeable_svalue *> (summary_sval);
395 : 0 : const svalue *summary_arg_sval = unmergeable_summary_sval->get_arg ();
396 : 0 : const svalue *caller_arg_sval
397 : 0 : = convert_svalue_from_summary (summary_arg_sval);
398 : 0 : if (!caller_arg_sval)
399 : : return NULL;
400 : 0 : region_model_manager *mgr = get_manager ();
401 : 0 : return mgr->get_or_create_unmergeable (caller_arg_sval);
402 : : }
403 : 672 : break;
404 : 672 : case SK_WIDENING:
405 : 672 : {
406 : 672 : const widening_svalue *widening_summary_sval
407 : 672 : = as_a <const widening_svalue *> (summary_sval);
408 : 672 : const function_point &point = widening_summary_sval->get_point ();
409 : 672 : const svalue *summary_base_sval
410 : 672 : = widening_summary_sval->get_base_svalue ();
411 : 672 : const svalue *caller_base_sval
412 : 672 : = convert_svalue_from_summary (summary_base_sval);
413 : 1342 : if (!(caller_base_sval
414 : 670 : && caller_base_sval->can_have_associated_state_p ()))
415 : 670 : return NULL;
416 : 2 : const svalue *summary_iter_sval
417 : 2 : = widening_summary_sval->get_iter_svalue ();
418 : 2 : const svalue *caller_iter_sval
419 : 2 : = convert_svalue_from_summary (summary_iter_sval);
420 : 4 : if (!(caller_iter_sval
421 : 2 : && caller_iter_sval->can_have_associated_state_p ()))
422 : 0 : return NULL;
423 : 2 : region_model_manager *mgr = get_manager ();
424 : 2 : return mgr->get_or_create_widening_svalue
425 : 2 : (summary_iter_sval->get_type (),
426 : : point,
427 : : caller_base_sval,
428 : 2 : caller_iter_sval);
429 : : }
430 : 281 : break;
431 : 281 : case SK_COMPOUND:
432 : 281 : {
433 : 281 : const compound_svalue *compound_summary_sval
434 : 281 : = as_a <const compound_svalue *> (summary_sval);
435 : 281 : region_model_manager *mgr = get_manager ();
436 : 281 : store_manager *store_mgr = mgr->get_store_manager ();
437 : 281 : binding_map caller_map;
438 : 281 : auto_vec <const binding_key *> summary_keys;
439 : 938 : for (auto kv : *compound_summary_sval)
440 : 657 : summary_keys.safe_push (kv.first);
441 : 281 : summary_keys.qsort (binding_key::cmp_ptrs);
442 : 1500 : for (auto key : summary_keys)
443 : : {
444 : 657 : gcc_assert (key->concrete_p ());
445 : : /* No remapping is needed for concrete binding keys. */
446 : :
447 : 657 : const svalue *bound_summary_sval
448 : 657 : = compound_summary_sval->get_map ().get (key);
449 : 657 : const svalue *caller_sval
450 : 657 : = convert_svalue_from_summary (bound_summary_sval);
451 : 657 : if (!caller_sval)
452 : 8 : caller_sval = mgr->get_or_create_unknown_svalue (NULL_TREE);
453 : :
454 : 1314 : if (const compound_svalue *inner_compound_sval
455 : 657 : = caller_sval->dyn_cast_compound_svalue ())
456 : : {
457 : 0 : const concrete_binding *outer_key
458 : 0 : = as_a <const concrete_binding *> (key);
459 : 0 : for (auto inner_kv : *inner_compound_sval)
460 : : {
461 : : // These should already be mapped to the caller.
462 : 0 : const binding_key *inner_key = inner_kv.first;
463 : 0 : const svalue *inner_sval = inner_kv.second;
464 : 0 : gcc_assert (inner_key->concrete_p ());
465 : 0 : const concrete_binding *concrete_key
466 : 0 : = as_a <const concrete_binding *> (inner_key);
467 : 0 : bit_offset_t effective_start
468 : 0 : = (concrete_key->get_start_bit_offset ()
469 : 0 : + outer_key->get_start_bit_offset ());
470 : 0 : const concrete_binding *effective_concrete_key
471 : : = store_mgr->get_concrete_binding
472 : 0 : (effective_start,
473 : : concrete_key->get_size_in_bits ());
474 : 0 : caller_map.put (effective_concrete_key, inner_sval);
475 : : }
476 : : }
477 : : else
478 : 657 : caller_map.put (key, caller_sval);
479 : : }
480 : 281 : return mgr->get_or_create_compound_svalue (summary_sval->get_type (),
481 : : caller_map);
482 : 281 : }
483 : 162 : break;
484 : 162 : case SK_CONJURED:
485 : 162 : {
486 : 162 : region_model_manager *mgr = get_manager ();
487 : 162 : return mgr->get_or_create_unknown_svalue (summary_sval->get_type ());
488 : : }
489 : 10 : break;
490 : 10 : case SK_ASM_OUTPUT:
491 : 10 : {
492 : 10 : const asm_output_svalue *asm_output_summary_sval
493 : 10 : = as_a <const asm_output_svalue *> (summary_sval);
494 : 10 : const char *asm_string = asm_output_summary_sval->get_asm_string ();
495 : 10 : unsigned output_idx = asm_output_summary_sval->get_output_idx ();
496 : 10 : unsigned num_inputs = asm_output_summary_sval->get_num_inputs ();
497 : 10 : unsigned num_outputs = asm_output_summary_sval->get_num_outputs ();
498 : 10 : auto_vec<const svalue *> inputs (num_inputs);
499 : 10 : for (unsigned idx = 0; idx < num_inputs; idx++)
500 : : {
501 : 0 : const svalue *summary_input
502 : 0 : = asm_output_summary_sval->get_input (idx);
503 : 0 : const svalue *caller_input
504 : 0 : = convert_svalue_from_summary (summary_input);
505 : 0 : if (!caller_input)
506 : 0 : return NULL;
507 : 0 : inputs.safe_push (caller_input);
508 : : }
509 : 10 : region_model_manager *mgr = get_manager ();
510 : 10 : return mgr->get_or_create_asm_output_svalue (summary_sval->get_type (),
511 : : asm_string,
512 : : output_idx,
513 : : num_outputs,
514 : 10 : inputs);
515 : 10 : }
516 : 2 : break;
517 : 2 : case SK_CONST_FN_RESULT:
518 : 2 : {
519 : 2 : const const_fn_result_svalue *const_fn_result_summary_sval
520 : 2 : = as_a <const const_fn_result_svalue *> (summary_sval);
521 : 2 : tree fndecl = const_fn_result_summary_sval->get_fndecl ();
522 : 2 : unsigned num_inputs = const_fn_result_summary_sval->get_num_inputs ();
523 : 2 : auto_vec<const svalue *> inputs (num_inputs);
524 : 4 : for (unsigned idx = 0; idx < num_inputs; idx++)
525 : : {
526 : 2 : const svalue *summary_input
527 : 2 : = const_fn_result_summary_sval->get_input (idx);
528 : 2 : const svalue *caller_input
529 : 2 : = convert_svalue_from_summary (summary_input);
530 : 2 : if (!caller_input)
531 : 0 : return NULL;
532 : 2 : inputs.safe_push (caller_input);
533 : : }
534 : 2 : region_model_manager *mgr = get_manager ();
535 : 2 : return mgr->get_or_create_const_fn_result_svalue
536 : 2 : (summary_sval->get_type (),
537 : : fndecl,
538 : 2 : inputs);
539 : 2 : }
540 : : break;
541 : : }
542 : : }
543 : :
544 : : /* Try to convert SUMMARY_REG in the summary to a corresponding region
545 : : in the caller, caching the result.
546 : :
547 : : Return NULL if the conversion is not possible. */
548 : :
549 : : const region *
550 : 31886 : call_summary_replay::convert_region_from_summary (const region *summary_reg)
551 : : {
552 : 31886 : gcc_assert (summary_reg);
553 : :
554 : 63772 : if (const region **slot
555 : 31886 : = m_map_region_from_summary_to_caller.get (summary_reg))
556 : 11627 : return *slot;
557 : :
558 : 20259 : const region *caller_reg = convert_region_from_summary_1 (summary_reg);
559 : :
560 : 20259 : if (caller_reg)
561 : 19942 : if (summary_reg->get_type () && caller_reg->get_type ())
562 : 16168 : gcc_assert (types_compatible_p (summary_reg->get_type (),
563 : : caller_reg->get_type ()));
564 : :
565 : : /* Add to cache. */
566 : 20259 : add_region_mapping (summary_reg, caller_reg);
567 : :
568 : 20259 : return caller_reg;
569 : : }
570 : :
571 : : /* Implementation of call_summary_replay::convert_region_from_summary. */
572 : :
573 : : const region *
574 : 20259 : call_summary_replay::convert_region_from_summary_1 (const region *summary_reg)
575 : : {
576 : 20259 : gcc_assert (summary_reg);
577 : :
578 : 20259 : region_model_manager *mgr = get_manager ();
579 : 20259 : switch (summary_reg->get_kind ())
580 : : {
581 : 0 : default:
582 : 0 : gcc_unreachable ();
583 : : /* Top-level regions. */
584 : 0 : case RK_FRAME:
585 : 0 : case RK_GLOBALS:
586 : 0 : case RK_CODE:
587 : 0 : case RK_STACK:
588 : 0 : case RK_HEAP:
589 : 0 : case RK_THREAD_LOCAL:
590 : 0 : case RK_ROOT:
591 : : /* These should never be pointed to by a region_svalue. */
592 : 0 : gcc_unreachable ();
593 : :
594 : : case RK_FUNCTION:
595 : : case RK_LABEL:
596 : : case RK_STRING:
597 : : case RK_ERRNO:
598 : : case RK_UNKNOWN:
599 : : case RK_PRIVATE:
600 : : /* We can reuse these regions directly. */
601 : : return summary_reg;
602 : :
603 : 3362 : case RK_SYMBOLIC:
604 : 3362 : {
605 : 3362 : const symbolic_region *summary_symbolic_reg
606 : 3362 : = as_a <const symbolic_region *> (summary_reg);
607 : 3362 : const svalue *summary_ptr_sval = summary_symbolic_reg->get_pointer ();
608 : 3362 : const svalue *caller_ptr_sval
609 : 3362 : = convert_svalue_from_summary (summary_ptr_sval);
610 : 3362 : if (!caller_ptr_sval)
611 : : return NULL;
612 : 3362 : const region *caller_reg
613 : 3362 : = get_caller_model ()->deref_rvalue (caller_ptr_sval,
614 : : NULL_TREE,
615 : : get_ctxt ());
616 : 3362 : caller_reg = mgr->get_cast_region (caller_reg,
617 : : summary_reg->get_type ());
618 : 3362 : return caller_reg;
619 : : }
620 : 10501 : break;
621 : :
622 : 10501 : case RK_DECL:
623 : 10501 : {
624 : 10501 : const decl_region *summary_decl_reg
625 : 10501 : = as_a <const decl_region *> (summary_reg);
626 : 10501 : tree decl = summary_decl_reg->get_decl ();
627 : 10501 : switch (TREE_CODE (decl))
628 : : {
629 : 0 : default:
630 : 0 : gcc_unreachable ();
631 : : case SSA_NAME:
632 : : /* We don't care about writes to locals within
633 : : the summary. */
634 : : return NULL;
635 : 9076 : case VAR_DECL:
636 : : /* We don't care about writes to locals within
637 : : the summary. */
638 : 9076 : if (is_global_var (decl))
639 : : /* If it's a global, we can reuse the region directly. */
640 : : return summary_reg;
641 : : else
642 : : /* Otherwise, we don't care about locals. */
643 : : return NULL;
644 : 1162 : case RESULT_DECL:
645 : 1162 : return m_cd.get_lhs_region ();
646 : : case PARM_DECL:
647 : : /* Writes (by value) to parms should be visible to the caller. */
648 : : return NULL;
649 : : }
650 : : }
651 : 834 : break;
652 : 834 : case RK_FIELD:
653 : 834 : {
654 : 834 : const field_region *summary_field_reg
655 : 834 : = as_a <const field_region *> (summary_reg);
656 : 834 : const region *summary_parent_reg = summary_reg->get_parent_region ();
657 : 834 : const region *caller_parent_reg
658 : 834 : = convert_region_from_summary (summary_parent_reg);
659 : 834 : if (!caller_parent_reg)
660 : : return NULL;
661 : 826 : tree field = summary_field_reg->get_field ();
662 : 826 : return mgr->get_field_region (caller_parent_reg, field);
663 : : }
664 : 22 : break;
665 : 22 : case RK_ELEMENT:
666 : 22 : {
667 : 22 : const element_region *summary_element_reg
668 : 22 : = as_a <const element_region *> (summary_reg);
669 : 22 : const region *summary_parent_reg = summary_reg->get_parent_region ();
670 : 22 : const region *caller_parent_reg
671 : 22 : = convert_region_from_summary (summary_parent_reg);
672 : 22 : if (!caller_parent_reg)
673 : : return NULL;
674 : 12 : const svalue *summary_index = summary_element_reg->get_index ();
675 : 12 : const svalue *caller_index
676 : 12 : = convert_svalue_from_summary (summary_index);
677 : 12 : if (!caller_index)
678 : : return NULL;
679 : 12 : return mgr->get_element_region (caller_parent_reg,
680 : : summary_reg->get_type (),
681 : 12 : caller_index);
682 : : }
683 : 684 : break;
684 : 684 : case RK_OFFSET:
685 : 684 : {
686 : 684 : const offset_region *summary_offset_reg
687 : 684 : = as_a <const offset_region *> (summary_reg);
688 : 684 : const region *summary_parent_reg = summary_reg->get_parent_region ();
689 : 684 : const region *caller_parent_reg
690 : 684 : = convert_region_from_summary (summary_parent_reg);
691 : 684 : if (!caller_parent_reg)
692 : : return NULL;
693 : 682 : const svalue *summary_byte_offset
694 : 682 : = summary_offset_reg->get_byte_offset ();
695 : 682 : const svalue *caller_byte_offset
696 : 682 : = convert_svalue_from_summary (summary_byte_offset);
697 : 682 : if (!caller_byte_offset)
698 : : return NULL;
699 : 682 : return mgr->get_offset_region (caller_parent_reg,
700 : : summary_reg->get_type (),
701 : 682 : caller_byte_offset);
702 : : }
703 : 0 : break;
704 : 0 : case RK_SIZED:
705 : 0 : {
706 : 0 : const sized_region *summary_sized_reg
707 : 0 : = as_a <const sized_region *> (summary_reg);
708 : 0 : const region *summary_parent_reg = summary_reg->get_parent_region ();
709 : 0 : const region *caller_parent_reg
710 : 0 : = convert_region_from_summary (summary_parent_reg);
711 : 0 : if (!caller_parent_reg)
712 : : return NULL;
713 : 0 : const svalue *summary_byte_size
714 : 0 : = summary_sized_reg->get_byte_size_sval (mgr);
715 : 0 : const svalue *caller_byte_size
716 : 0 : = convert_svalue_from_summary (summary_byte_size);
717 : 0 : if (!caller_byte_size)
718 : : return NULL;
719 : 0 : return mgr->get_sized_region (caller_parent_reg,
720 : : summary_reg->get_type (),
721 : 0 : caller_byte_size);
722 : : }
723 : 0 : break;
724 : 0 : case RK_CAST:
725 : 0 : {
726 : 0 : const cast_region *summary_cast_reg
727 : 0 : = as_a <const cast_region *> (summary_reg);
728 : 0 : const region *summary_original_reg
729 : 0 : = summary_cast_reg->get_original_region ();
730 : 0 : const region *caller_original_reg
731 : 0 : = convert_region_from_summary (summary_original_reg);
732 : 0 : if (!caller_original_reg)
733 : : return NULL;
734 : 0 : return mgr->get_cast_region (caller_original_reg,
735 : 0 : summary_reg->get_type ());
736 : : }
737 : 3774 : break;
738 : 3774 : case RK_HEAP_ALLOCATED:
739 : 3774 : {
740 : : /* If we have a heap-allocated region in the summary, then
741 : : it was allocated within the callee.
742 : : Create a new heap-allocated region to summarize this. */
743 : 3774 : auto_bitmap heap_regs_in_use;
744 : 3774 : get_caller_model ()->get_referenced_base_regions (heap_regs_in_use);
745 : 3774 : return mgr->get_or_create_region_for_heap_alloc (heap_regs_in_use);
746 : 3774 : }
747 : : break;
748 : : case RK_ALLOCA:
749 : : return NULL;
750 : 0 : case RK_BIT_RANGE:
751 : 0 : {
752 : 0 : const bit_range_region *summary_bit_range_reg
753 : 0 : = as_a <const bit_range_region *> (summary_reg);
754 : 0 : const region *summary_parent_reg = summary_reg->get_parent_region ();
755 : 0 : const region *caller_parent_reg
756 : 0 : = convert_region_from_summary (summary_parent_reg);
757 : 0 : if (!caller_parent_reg)
758 : : return NULL;
759 : 0 : const bit_range &bits = summary_bit_range_reg->get_bits ();
760 : 0 : return mgr->get_bit_range (caller_parent_reg,
761 : : summary_reg->get_type (),
762 : 0 : bits);
763 : : }
764 : : break;
765 : : case RK_VAR_ARG:
766 : : return NULL;
767 : : }
768 : : }
769 : :
770 : : /* Try to convert SUMMARY_KEY in the summary to a corresponding binding key
771 : : in the caller.
772 : :
773 : : Return NULL if the conversion is not possible. */
774 : :
775 : : const binding_key *
776 : 0 : call_summary_replay::convert_key_from_summary (const binding_key *summary_key)
777 : : {
778 : 0 : if (summary_key->concrete_p ())
779 : : return summary_key;
780 : :
781 : 0 : const symbolic_binding *symbolic_key = (const symbolic_binding *)summary_key;
782 : 0 : const region *summary_reg = symbolic_key->get_region ();
783 : 0 : const region *caller_reg = convert_region_from_summary (summary_reg);
784 : 0 : if (!caller_reg)
785 : : return NULL;
786 : 0 : region_model_manager *mgr = get_manager ();
787 : 0 : store_manager *store_mgr = mgr->get_store_manager ();
788 : 0 : return store_mgr->get_symbolic_binding (caller_reg);
789 : : }
790 : :
791 : : /* Record that SUMMARY_SVAL maps to CALLER_SVAL for this replay. */
792 : :
793 : : void
794 : 31734 : call_summary_replay::add_svalue_mapping (const svalue *summary_sval,
795 : : const svalue *caller_sval)
796 : : {
797 : 31734 : gcc_assert (summary_sval);
798 : : // CALLER_SVAL can be NULL
799 : 31734 : m_map_svalue_from_summary_to_caller.put (summary_sval, caller_sval);
800 : 31734 : }
801 : :
802 : : /* Record that SUMMARY_REG maps to CALLER_REG for this replay. */
803 : :
804 : : void
805 : 20259 : call_summary_replay::add_region_mapping (const region *summary_reg,
806 : : const region *caller_reg)
807 : : {
808 : 20259 : gcc_assert (summary_reg);
809 : : // CALLER_REG can be NULL
810 : 20259 : m_map_region_from_summary_to_caller.put (summary_reg, caller_reg);
811 : 20259 : }
812 : :
813 : : /* Dump a multiline representation of this object to PP. */
814 : :
815 : : void
816 : 0 : call_summary_replay::dump_to_pp (pretty_printer *pp, bool simple) const
817 : : {
818 : 0 : pp_newline (pp);
819 : 0 : pp_string (pp, "CALL DETAILS:");
820 : 0 : pp_newline (pp);
821 : 0 : m_cd.dump_to_pp (pp, simple);
822 : :
823 : 0 : pp_newline (pp);
824 : 0 : pp_string (pp, "CALLEE SUMMARY:");
825 : 0 : pp_newline (pp);
826 : 0 : m_summary->dump_to_pp (m_ext_state, pp, simple);
827 : :
828 : : /* Current state of caller (could be in mid-update). */
829 : 0 : pp_newline (pp);
830 : 0 : pp_string (pp, "CALLER:");
831 : 0 : pp_newline (pp);
832 : 0 : m_cd.get_model ()->dump_to_pp (pp, simple, true);
833 : :
834 : 0 : pp_newline (pp);
835 : 0 : pp_string (pp, "REPLAY STATE:");
836 : 0 : pp_newline (pp);
837 : 0 : pp_string (pp, "svalue mappings from summary to caller:");
838 : 0 : pp_newline (pp);
839 : 0 : auto_vec <const svalue *> summary_svals;
840 : 0 : for (auto kv : m_map_svalue_from_summary_to_caller)
841 : 0 : summary_svals.safe_push (kv.first);
842 : 0 : summary_svals.qsort (svalue::cmp_ptr_ptr);
843 : 0 : for (auto summary_sval : summary_svals)
844 : : {
845 : 0 : pp_string (pp, "sval in summary: ");
846 : 0 : summary_sval->dump_to_pp (pp, simple);
847 : 0 : pp_newline (pp);
848 : :
849 : 0 : const svalue *caller_sval
850 : : = *((const_cast<svalue_map_t &>
851 : 0 : (m_map_svalue_from_summary_to_caller)).get (summary_sval));
852 : 0 : pp_string (pp, " sval in caller: ");
853 : 0 : caller_sval->dump_to_pp (pp, simple);
854 : 0 : pp_newline (pp);
855 : : }
856 : :
857 : 0 : pp_newline (pp);
858 : 0 : pp_string (pp, "region mappings from summary to caller:");
859 : 0 : pp_newline (pp);
860 : 0 : auto_vec <const region *> summary_regs;
861 : 0 : for (auto kv : m_map_region_from_summary_to_caller)
862 : 0 : summary_regs.safe_push (kv.first);
863 : 0 : summary_regs.qsort (region::cmp_ptr_ptr);
864 : 0 : for (auto summary_reg : summary_regs)
865 : : {
866 : 0 : pp_string (pp, "reg in summary: ");
867 : 0 : if (summary_reg)
868 : 0 : summary_reg->dump_to_pp (pp, simple);
869 : : else
870 : 0 : pp_string (pp, "(null)");
871 : 0 : pp_newline (pp);
872 : :
873 : 0 : const region *caller_reg
874 : : = *((const_cast<region_map_t &>
875 : 0 : (m_map_region_from_summary_to_caller)).get (summary_reg));
876 : 0 : pp_string (pp, " reg in caller: ");
877 : 0 : if (caller_reg)
878 : 0 : caller_reg->dump_to_pp (pp, simple);
879 : : else
880 : 0 : pp_string (pp, "(null)");
881 : 0 : pp_newline (pp);
882 : : }
883 : 0 : }
884 : :
885 : : /* Dump a multiline representation of this object to FILE. */
886 : :
887 : : void
888 : 0 : call_summary_replay::dump (FILE *fp, bool simple) const
889 : : {
890 : 0 : pretty_printer pp;
891 : 0 : pp_format_decoder (&pp) = default_tree_printer;
892 : 0 : pp_show_color (&pp) = pp_show_color (global_dc->printer);
893 : 0 : pp.buffer->stream = fp;
894 : 0 : dump_to_pp (&pp, simple);
895 : 0 : pp_flush (&pp);
896 : 0 : }
897 : :
898 : : /* Dump a multiline representation of this object to stderr. */
899 : :
900 : : DEBUG_FUNCTION void
901 : 0 : call_summary_replay::dump (bool simple) const
902 : : {
903 : 0 : dump (stderr, simple);
904 : 0 : }
905 : :
906 : : } // namespace ana
907 : :
908 : : #endif /* #if ENABLE_ANALYZER */
|