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