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