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 1677 : call_summary::get_state () const
34 : {
35 1677 : 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 1629 : call_summary_replay::call_summary_replay (const call_details &cd,
159 : const function &called_fn,
160 : call_summary &summary,
161 1629 : const extrinsic_state &ext_state)
162 1629 : : m_cd (cd),
163 1629 : m_summary (summary),
164 1629 : m_ext_state (ext_state)
165 : {
166 1629 : region_model_manager *mgr = cd.get_manager ();
167 :
168 : // populate params based on args
169 1629 : 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 1629 : const frame_region *summary_frame
175 1629 : = mgr->get_frame_region (nullptr, called_fn);
176 :
177 1629 : unsigned idx = 0;
178 2959 : for (tree iter_parm = DECL_ARGUMENTS (fndecl); iter_parm;
179 1330 : 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 1330 : if (idx >= cd.num_args ())
185 : break;
186 1330 : const svalue *caller_arg_sval = cd.get_arg_svalue (idx);
187 1330 : tree parm_lval = iter_parm;
188 1330 : if (tree parm_default_ssa = get_ssa_default_def (called_fn, iter_parm))
189 1319 : parm_lval = parm_default_ssa;
190 1330 : const region *summary_parm_reg
191 1330 : = summary_frame->get_region_for_local (mgr, parm_lval, cd.get_ctxt ());
192 1330 : const svalue *summary_initial_parm_reg
193 1330 : = mgr->get_or_create_initial_value (summary_parm_reg);
194 1330 : add_svalue_mapping (summary_initial_parm_reg, caller_arg_sval);
195 : }
196 :
197 : /* Handle any variadic args. */
198 : unsigned va_arg_idx = 0;
199 1635 : 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 1629 : }
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 48234 : call_summary_replay::convert_svalue_from_summary (const svalue *summary_sval)
217 : {
218 48234 : gcc_assert (summary_sval);
219 :
220 96468 : if (const svalue **slot
221 48234 : = m_map_svalue_from_summary_to_caller.get (summary_sval))
222 28270 : return *slot;
223 :
224 19964 : const svalue *caller_sval = convert_svalue_from_summary_1 (summary_sval);
225 :
226 19964 : if (caller_sval)
227 19538 : if (summary_sval->get_type () && caller_sval->get_type ())
228 18474 : gcc_assert (types_compatible_p (summary_sval->get_type (),
229 : caller_sval->get_type ()));
230 :
231 : /* Add to cache. */
232 19964 : add_svalue_mapping (summary_sval, caller_sval);
233 :
234 19964 : return caller_sval;
235 : }
236 :
237 : /* Implementation of call_summary_replay::convert_svalue_from_summary. */
238 :
239 : const svalue *
240 19964 : call_summary_replay::convert_svalue_from_summary_1 (const svalue *summary_sval)
241 : {
242 19964 : gcc_assert (summary_sval);
243 :
244 19964 : switch (summary_sval->get_kind ())
245 : {
246 0 : default:
247 0 : gcc_unreachable ();
248 2168 : case SK_REGION:
249 2168 : {
250 2168 : const region_svalue *region_summary_sval
251 2168 : = as_a <const region_svalue *> (summary_sval);
252 2168 : const region *summary_reg = region_summary_sval->get_pointee ();
253 2168 : const region *caller_reg = convert_region_from_summary (summary_reg);
254 2168 : if (!caller_reg)
255 : return nullptr;
256 2168 : region_model_manager *mgr = get_manager ();
257 2168 : const svalue *caller_ptr
258 2168 : = mgr->get_ptr_svalue (summary_sval->get_type (),
259 : caller_reg);
260 2168 : 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 4106 : case SK_INITIAL:
274 4106 : {
275 4106 : const initial_svalue *initial_summary_sval
276 4106 : = as_a <const initial_svalue *> (summary_sval);
277 : /* Params should already be in the cache, courtesy of the ctor. */
278 4106 : 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 4106 : const region *summary_reg = initial_summary_sval->get_region ();
283 4106 : const region *caller_reg = convert_region_from_summary (summary_reg);
284 4106 : if (!caller_reg)
285 : return nullptr;
286 4094 : const svalue *caller_sval
287 4094 : = m_cd.get_model ()->get_store_value (caller_reg, m_cd.get_ctxt ());
288 4094 : 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 2237 : break;
305 2237 : case SK_BINOP:
306 2237 : {
307 2237 : const binop_svalue *binop_summary_sval
308 2237 : = as_a <const binop_svalue *> (summary_sval);
309 2237 : const svalue *summary_arg0 = binop_summary_sval->get_arg0 ();
310 2237 : const svalue *caller_arg0 = convert_svalue_from_summary (summary_arg0);
311 2237 : if (!caller_arg0)
312 : return nullptr;
313 2237 : const svalue *summary_arg1 = binop_summary_sval->get_arg1 ();
314 2237 : const svalue *caller_arg1 = convert_svalue_from_summary (summary_arg1);
315 2237 : if (!caller_arg1)
316 : return nullptr;
317 2237 : region_model_manager *mgr = get_manager ();
318 2237 : return mgr->get_or_create_binop (summary_sval->get_type (),
319 : binop_summary_sval->get_op (),
320 : caller_arg0,
321 2237 : 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 38 : break;
340 38 : case SK_REPEATED:
341 38 : {
342 38 : const repeated_svalue *repeated_summary_sval
343 38 : = as_a <const repeated_svalue *> (summary_sval);
344 38 : const svalue *summary_outer_size
345 38 : = repeated_summary_sval->get_outer_size ();
346 38 : const svalue *caller_outer_size
347 38 : = convert_svalue_from_summary (summary_outer_size);
348 38 : if (!caller_outer_size)
349 : return nullptr;
350 38 : const svalue *summary_inner_sval
351 38 : = repeated_summary_sval->get_inner_svalue ();
352 38 : const svalue *caller_inner_sval
353 38 : = convert_svalue_from_summary (summary_inner_sval);
354 38 : if (!caller_inner_sval)
355 : return nullptr;
356 38 : region_model_manager *mgr = get_manager ();
357 38 : return mgr->get_or_create_repeated_svalue (summary_sval->get_type (),
358 : caller_outer_size,
359 38 : 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 218 : break;
419 218 : case SK_COMPOUND:
420 218 : {
421 218 : const compound_svalue *compound_summary_sval
422 218 : = as_a <const compound_svalue *> (summary_sval);
423 218 : region_model_manager *mgr = get_manager ();
424 218 : store_manager *store_mgr = mgr->get_store_manager ();
425 218 : binding_map caller_map (*store_mgr);
426 218 : auto_vec <const binding_key *> summary_keys;
427 716 : for (auto kv : *compound_summary_sval)
428 498 : summary_keys.safe_push (kv.m_key);
429 218 : summary_keys.qsort (binding_key::cmp_ptrs);
430 1152 : for (auto key : summary_keys)
431 : {
432 498 : gcc_assert (key->concrete_p ());
433 : /* No remapping is needed for concrete binding keys. */
434 :
435 498 : const svalue *bound_summary_sval
436 498 : = compound_summary_sval->get_map ().get (key);
437 498 : const svalue *caller_sval
438 498 : = convert_svalue_from_summary (bound_summary_sval);
439 498 : if (!caller_sval)
440 8 : caller_sval = mgr->get_or_create_unknown_svalue (NULL_TREE);
441 :
442 996 : if (const compound_svalue *inner_compound_sval
443 498 : = caller_sval->dyn_cast_compound_svalue ())
444 : {
445 0 : const concrete_binding *outer_key
446 0 : = as_a <const concrete_binding *> (key);
447 0 : for (auto inner_kv : *inner_compound_sval)
448 : {
449 : // These should already be mapped to the caller.
450 0 : const binding_key *inner_key = inner_kv.m_key;
451 0 : const svalue *inner_sval = inner_kv.m_sval;
452 0 : gcc_assert (inner_key->concrete_p ());
453 0 : const concrete_binding *concrete_key
454 0 : = as_a <const concrete_binding *> (inner_key);
455 0 : bit_offset_t effective_start
456 0 : = (concrete_key->get_start_bit_offset ()
457 0 : + outer_key->get_start_bit_offset ());
458 0 : const concrete_binding *effective_concrete_key
459 : = store_mgr->get_concrete_binding
460 0 : (effective_start,
461 : concrete_key->get_size_in_bits ());
462 0 : caller_map.put (effective_concrete_key, inner_sval);
463 : }
464 : }
465 : else
466 498 : caller_map.put (key, caller_sval);
467 : }
468 218 : return mgr->get_or_create_compound_svalue (summary_sval->get_type (),
469 : caller_map);
470 218 : }
471 26 : break;
472 26 : case SK_CONJURED:
473 26 : {
474 26 : region_model_manager *mgr = get_manager ();
475 26 : return mgr->get_or_create_unknown_svalue (summary_sval->get_type ());
476 : }
477 8 : break;
478 8 : case SK_ASM_OUTPUT:
479 8 : {
480 8 : const asm_output_svalue *asm_output_summary_sval
481 8 : = as_a <const asm_output_svalue *> (summary_sval);
482 8 : const char *asm_string = asm_output_summary_sval->get_asm_string ();
483 8 : unsigned output_idx = asm_output_summary_sval->get_output_idx ();
484 8 : unsigned num_inputs = asm_output_summary_sval->get_num_inputs ();
485 8 : unsigned num_outputs = asm_output_summary_sval->get_num_outputs ();
486 8 : auto_vec<const svalue *> inputs (num_inputs);
487 8 : for (unsigned idx = 0; idx < num_inputs; idx++)
488 : {
489 0 : const svalue *summary_input
490 0 : = asm_output_summary_sval->get_input (idx);
491 0 : const svalue *caller_input
492 0 : = convert_svalue_from_summary (summary_input);
493 0 : if (!caller_input)
494 0 : return nullptr;
495 0 : inputs.safe_push (caller_input);
496 : }
497 8 : region_model_manager *mgr = get_manager ();
498 8 : return mgr->get_or_create_asm_output_svalue (summary_sval->get_type (),
499 : asm_string,
500 : output_idx,
501 : num_outputs,
502 8 : inputs);
503 8 : }
504 2 : break;
505 2 : case SK_CONST_FN_RESULT:
506 2 : {
507 2 : const const_fn_result_svalue *const_fn_result_summary_sval
508 2 : = as_a <const const_fn_result_svalue *> (summary_sval);
509 2 : tree fndecl = const_fn_result_summary_sval->get_fndecl ();
510 2 : unsigned num_inputs = const_fn_result_summary_sval->get_num_inputs ();
511 2 : auto_vec<const svalue *> inputs (num_inputs);
512 4 : for (unsigned idx = 0; idx < num_inputs; idx++)
513 : {
514 2 : const svalue *summary_input
515 2 : = const_fn_result_summary_sval->get_input (idx);
516 2 : const svalue *caller_input
517 2 : = convert_svalue_from_summary (summary_input);
518 2 : if (!caller_input)
519 0 : return nullptr;
520 2 : inputs.safe_push (caller_input);
521 : }
522 2 : region_model_manager *mgr = get_manager ();
523 2 : return mgr->get_or_create_const_fn_result_svalue
524 2 : (summary_sval->get_type (),
525 : fndecl,
526 2 : inputs);
527 2 : }
528 : break;
529 : }
530 : }
531 :
532 : /* Try to convert SUMMARY_REG in the summary to a corresponding region
533 : in the caller, caching the result.
534 :
535 : Return nullptr if the conversion is not possible. */
536 :
537 : const region *
538 22853 : call_summary_replay::convert_region_from_summary (const region *summary_reg)
539 : {
540 22853 : gcc_assert (summary_reg);
541 :
542 45706 : if (const region **slot
543 22853 : = m_map_region_from_summary_to_caller.get (summary_reg))
544 7839 : return *slot;
545 :
546 15014 : const region *caller_reg = convert_region_from_summary_1 (summary_reg);
547 :
548 15014 : if (caller_reg)
549 14761 : if (summary_reg->get_type () && caller_reg->get_type ())
550 12858 : gcc_assert (types_compatible_p (summary_reg->get_type (),
551 : caller_reg->get_type ()));
552 :
553 : /* Add to cache. */
554 15014 : add_region_mapping (summary_reg, caller_reg);
555 :
556 15014 : return caller_reg;
557 : }
558 :
559 : /* Implementation of call_summary_replay::convert_region_from_summary. */
560 :
561 : const region *
562 15014 : call_summary_replay::convert_region_from_summary_1 (const region *summary_reg)
563 : {
564 15014 : gcc_assert (summary_reg);
565 :
566 15014 : region_model_manager *mgr = get_manager ();
567 15014 : switch (summary_reg->get_kind ())
568 : {
569 0 : default:
570 0 : gcc_unreachable ();
571 : /* Top-level regions. */
572 0 : case RK_FRAME:
573 0 : case RK_GLOBALS:
574 0 : case RK_CODE:
575 0 : case RK_STACK:
576 0 : case RK_HEAP:
577 0 : case RK_THREAD_LOCAL:
578 0 : case RK_ROOT:
579 : /* These should never be pointed to by a region_svalue. */
580 0 : gcc_unreachable ();
581 :
582 : case RK_FUNCTION:
583 : case RK_LABEL:
584 : case RK_STRING:
585 : case RK_ERRNO:
586 : case RK_UNKNOWN:
587 : case RK_PRIVATE:
588 : /* We can reuse these regions directly. */
589 : return summary_reg;
590 :
591 2693 : case RK_SYMBOLIC:
592 2693 : {
593 2693 : const symbolic_region *summary_symbolic_reg
594 2693 : = as_a <const symbolic_region *> (summary_reg);
595 2693 : const svalue *summary_ptr_sval = summary_symbolic_reg->get_pointer ();
596 2693 : const svalue *caller_ptr_sval
597 2693 : = convert_svalue_from_summary (summary_ptr_sval);
598 2693 : if (!caller_ptr_sval)
599 : return nullptr;
600 2693 : const region *caller_reg
601 2693 : = get_caller_model ()->deref_rvalue (caller_ptr_sval,
602 : NULL_TREE,
603 : get_ctxt ());
604 2693 : caller_reg = mgr->get_cast_region (caller_reg,
605 : summary_reg->get_type ());
606 2693 : return caller_reg;
607 : }
608 8098 : break;
609 :
610 8098 : case RK_DECL:
611 8098 : {
612 8098 : const decl_region *summary_decl_reg
613 8098 : = as_a <const decl_region *> (summary_reg);
614 8098 : tree decl = summary_decl_reg->get_decl ();
615 8098 : switch (TREE_CODE (decl))
616 : {
617 0 : default:
618 0 : gcc_unreachable ();
619 : case SSA_NAME:
620 : /* We don't care about writes to locals within
621 : the summary. */
622 : return nullptr;
623 6968 : case VAR_DECL:
624 : /* We don't care about writes to locals within
625 : the summary. */
626 6968 : if (is_global_var (decl))
627 : /* If it's a global, we can reuse the region directly. */
628 : return summary_reg;
629 : else
630 : /* Otherwise, we don't care about locals. */
631 : return nullptr;
632 921 : case RESULT_DECL:
633 921 : return m_cd.get_lhs_region ();
634 : case PARM_DECL:
635 : /* Writes (by value) to parms should be visible to the caller. */
636 : return nullptr;
637 : }
638 : }
639 1014 : break;
640 1014 : case RK_FIELD:
641 1014 : {
642 1014 : const field_region *summary_field_reg
643 1014 : = as_a <const field_region *> (summary_reg);
644 1014 : const region *summary_parent_reg = summary_reg->get_parent_region ();
645 1014 : const region *caller_parent_reg
646 1014 : = convert_region_from_summary (summary_parent_reg);
647 1014 : if (!caller_parent_reg)
648 : return nullptr;
649 1006 : tree field = summary_field_reg->get_field ();
650 1006 : return mgr->get_field_region (caller_parent_reg, field);
651 : }
652 22 : break;
653 22 : case RK_ELEMENT:
654 22 : {
655 22 : const element_region *summary_element_reg
656 22 : = as_a <const element_region *> (summary_reg);
657 22 : const region *summary_parent_reg = summary_reg->get_parent_region ();
658 22 : const region *caller_parent_reg
659 22 : = convert_region_from_summary (summary_parent_reg);
660 22 : if (!caller_parent_reg)
661 : return nullptr;
662 12 : const svalue *summary_index = summary_element_reg->get_index ();
663 12 : const svalue *caller_index
664 12 : = convert_svalue_from_summary (summary_index);
665 12 : if (!caller_index)
666 : return nullptr;
667 12 : return mgr->get_element_region (caller_parent_reg,
668 : summary_reg->get_type (),
669 12 : caller_index);
670 : }
671 580 : break;
672 580 : case RK_OFFSET:
673 580 : {
674 580 : const offset_region *summary_offset_reg
675 580 : = as_a <const offset_region *> (summary_reg);
676 580 : const region *summary_parent_reg = summary_reg->get_parent_region ();
677 580 : const region *caller_parent_reg
678 580 : = convert_region_from_summary (summary_parent_reg);
679 580 : if (!caller_parent_reg)
680 : return nullptr;
681 580 : const svalue *summary_byte_offset
682 580 : = summary_offset_reg->get_byte_offset ();
683 580 : const svalue *caller_byte_offset
684 580 : = convert_svalue_from_summary (summary_byte_offset);
685 580 : if (!caller_byte_offset)
686 : return nullptr;
687 580 : return mgr->get_offset_region (caller_parent_reg,
688 : summary_reg->get_type (),
689 580 : caller_byte_offset);
690 : }
691 0 : break;
692 0 : case RK_SIZED:
693 0 : {
694 0 : const sized_region *summary_sized_reg
695 0 : = as_a <const sized_region *> (summary_reg);
696 0 : const region *summary_parent_reg = summary_reg->get_parent_region ();
697 0 : const region *caller_parent_reg
698 0 : = convert_region_from_summary (summary_parent_reg);
699 0 : if (!caller_parent_reg)
700 : return nullptr;
701 0 : const svalue *summary_byte_size
702 0 : = summary_sized_reg->get_byte_size_sval (mgr);
703 0 : const svalue *caller_byte_size
704 0 : = convert_svalue_from_summary (summary_byte_size);
705 0 : if (!caller_byte_size)
706 : return nullptr;
707 0 : return mgr->get_sized_region (caller_parent_reg,
708 : summary_reg->get_type (),
709 0 : caller_byte_size);
710 : }
711 0 : break;
712 0 : case RK_CAST:
713 0 : {
714 0 : const region *summary_parent_reg = summary_reg->get_parent_region ();
715 0 : const region *caller_parent_reg
716 0 : = convert_region_from_summary (summary_parent_reg);
717 0 : if (!caller_parent_reg)
718 : return nullptr;
719 0 : return mgr->get_cast_region (caller_parent_reg,
720 0 : summary_reg->get_type ());
721 : }
722 1903 : break;
723 1903 : case RK_HEAP_ALLOCATED:
724 1903 : {
725 : /* If we have a heap-allocated region in the summary, then
726 : it was allocated within the callee.
727 : Create a new heap-allocated region to summarize this. */
728 1903 : auto_bitmap heap_regs_in_use;
729 1903 : get_caller_model ()->get_referenced_base_regions (heap_regs_in_use);
730 1903 : return mgr->get_or_create_region_for_heap_alloc (heap_regs_in_use);
731 1903 : }
732 : break;
733 : case RK_ALLOCA:
734 : return nullptr;
735 0 : case RK_BIT_RANGE:
736 0 : {
737 0 : const bit_range_region *summary_bit_range_reg
738 0 : = as_a <const bit_range_region *> (summary_reg);
739 0 : const region *summary_parent_reg = summary_reg->get_parent_region ();
740 0 : const region *caller_parent_reg
741 0 : = convert_region_from_summary (summary_parent_reg);
742 0 : if (!caller_parent_reg)
743 : return nullptr;
744 0 : const bit_range &bits = summary_bit_range_reg->get_bits ();
745 0 : return mgr->get_bit_range (caller_parent_reg,
746 : summary_reg->get_type (),
747 0 : bits);
748 : }
749 : break;
750 : case RK_VAR_ARG:
751 : return nullptr;
752 : }
753 : }
754 :
755 : /* Try to convert SUMMARY_KEY in the summary to a corresponding binding key
756 : in the caller.
757 :
758 : Return nullptr if the conversion is not possible. */
759 :
760 : const binding_key *
761 0 : call_summary_replay::convert_key_from_summary (const binding_key *summary_key)
762 : {
763 0 : if (summary_key->concrete_p ())
764 : return summary_key;
765 :
766 0 : const symbolic_binding *symbolic_key = (const symbolic_binding *)summary_key;
767 0 : const region *summary_reg = symbolic_key->get_region ();
768 0 : const region *caller_reg = convert_region_from_summary (summary_reg);
769 0 : if (!caller_reg)
770 : return nullptr;
771 0 : region_model_manager *mgr = get_manager ();
772 0 : store_manager *store_mgr = mgr->get_store_manager ();
773 0 : return store_mgr->get_symbolic_binding (caller_reg);
774 : }
775 :
776 : /* Record that SUMMARY_SVAL maps to CALLER_SVAL for this replay. */
777 :
778 : void
779 21300 : call_summary_replay::add_svalue_mapping (const svalue *summary_sval,
780 : const svalue *caller_sval)
781 : {
782 21300 : gcc_assert (summary_sval);
783 : // CALLER_SVAL can be nullptr
784 21300 : m_map_svalue_from_summary_to_caller.put (summary_sval, caller_sval);
785 21300 : }
786 :
787 : /* Record that SUMMARY_REG maps to CALLER_REG for this replay. */
788 :
789 : void
790 15014 : call_summary_replay::add_region_mapping (const region *summary_reg,
791 : const region *caller_reg)
792 : {
793 15014 : gcc_assert (summary_reg);
794 : // CALLER_REG can be nullptr
795 15014 : m_map_region_from_summary_to_caller.put (summary_reg, caller_reg);
796 15014 : }
797 :
798 : /* Dump a multiline representation of this object to PP. */
799 :
800 : void
801 0 : call_summary_replay::dump_to_pp (pretty_printer *pp, bool simple) const
802 : {
803 0 : pp_newline (pp);
804 0 : pp_string (pp, "CALL DETAILS:");
805 0 : pp_newline (pp);
806 0 : m_cd.dump_to_pp (pp, simple);
807 :
808 0 : pp_newline (pp);
809 0 : pp_string (pp, "CALLEE SUMMARY:");
810 0 : pp_newline (pp);
811 0 : m_summary.dump_to_pp (m_ext_state, pp, simple);
812 :
813 : /* Current state of caller (could be in mid-update). */
814 0 : pp_newline (pp);
815 0 : pp_string (pp, "CALLER:");
816 0 : pp_newline (pp);
817 0 : m_cd.get_model ()->dump_to_pp (pp, simple, true);
818 :
819 0 : pp_newline (pp);
820 0 : pp_string (pp, "REPLAY STATE:");
821 0 : pp_newline (pp);
822 0 : pp_string (pp, "svalue mappings from summary to caller:");
823 0 : pp_newline (pp);
824 0 : auto_vec <const svalue *> summary_svals;
825 0 : for (auto kv : m_map_svalue_from_summary_to_caller)
826 0 : summary_svals.safe_push (kv.first);
827 0 : summary_svals.qsort (svalue::cmp_ptr_ptr);
828 0 : for (auto summary_sval : summary_svals)
829 : {
830 0 : pp_string (pp, "sval in summary: ");
831 0 : summary_sval->dump_to_pp (pp, simple);
832 0 : pp_newline (pp);
833 :
834 0 : const svalue *caller_sval
835 : = *((const_cast<svalue_map_t &>
836 0 : (m_map_svalue_from_summary_to_caller)).get (summary_sval));
837 0 : pp_string (pp, " sval in caller: ");
838 0 : caller_sval->dump_to_pp (pp, simple);
839 0 : pp_newline (pp);
840 : }
841 :
842 0 : pp_newline (pp);
843 0 : pp_string (pp, "region mappings from summary to caller:");
844 0 : pp_newline (pp);
845 0 : auto_vec <const region *> summary_regs;
846 0 : for (auto kv : m_map_region_from_summary_to_caller)
847 0 : summary_regs.safe_push (kv.first);
848 0 : summary_regs.qsort (region::cmp_ptr_ptr);
849 0 : for (auto summary_reg : summary_regs)
850 : {
851 0 : pp_string (pp, "reg in summary: ");
852 0 : if (summary_reg)
853 0 : summary_reg->dump_to_pp (pp, simple);
854 : else
855 0 : pp_string (pp, "(null)");
856 0 : pp_newline (pp);
857 :
858 0 : const region *caller_reg
859 : = *((const_cast<region_map_t &>
860 0 : (m_map_region_from_summary_to_caller)).get (summary_reg));
861 0 : pp_string (pp, " reg in caller: ");
862 0 : if (caller_reg)
863 0 : caller_reg->dump_to_pp (pp, simple);
864 : else
865 0 : pp_string (pp, "(null)");
866 0 : pp_newline (pp);
867 : }
868 0 : }
869 :
870 : /* Dump a multiline representation of this object to FILE. */
871 :
872 : void
873 0 : call_summary_replay::dump (FILE *fp, bool simple) const
874 : {
875 0 : tree_dump_pretty_printer pp (fp);
876 0 : dump_to_pp (&pp, simple);
877 0 : }
878 :
879 : /* Dump a multiline representation of this object to stderr. */
880 :
881 : DEBUG_FUNCTION void
882 0 : call_summary_replay::dump (bool simple) const
883 : {
884 0 : dump (stderr, simple);
885 0 : }
886 :
887 : } // namespace ana
888 :
889 : #endif /* #if ENABLE_ANALYZER */
|