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 "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 : 3819 : call_summary::get_state () const
34 : : {
35 : 3819 : return m_enode->get_state ();
36 : : }
37 : :
38 : : tree
39 : 110 : call_summary::get_fndecl () const
40 : : {
41 : 110 : return m_enode->get_point ().get_fndecl ();
42 : : }
43 : :
44 : : label_text
45 : 110 : call_summary::get_desc () const
46 : : {
47 : 110 : pretty_printer pp;
48 : 110 : pp_format_decoder (&pp) = default_tree_printer;
49 : :
50 : 110 : get_user_facing_desc (&pp);
51 : 110 : if (flag_analyzer_verbose_edges)
52 : 0 : pp_printf (&pp, " (call summary; EN: %i)", m_enode->m_index);
53 : :
54 : 110 : return label_text::take (xstrdup (pp_formatted_text (&pp)));
55 : 110 : }
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 : 110 : call_summary::get_user_facing_desc (pretty_printer *pp) const
64 : : {
65 : 110 : tree fndecl = get_fndecl ();
66 : :
67 : : /* If there are multiple summaries, try to use the return value to
68 : : distinguish between them. */
69 : 110 : if (m_per_fn_data->m_summaries.length () > 1)
70 : : {
71 : 68 : if (tree result = DECL_RESULT (fndecl))
72 : : {
73 : 68 : const region *result_reg
74 : 68 : = get_state ().m_region_model->get_lvalue (result, nullptr);
75 : 68 : const svalue *result_sval
76 : 68 : = get_state ().m_region_model->get_store_value (result_reg, nullptr);
77 : 68 : switch (result_sval->get_kind ())
78 : : {
79 : : default:
80 : : break;
81 : 32 : case SK_REGION:
82 : 32 : {
83 : 32 : const region_svalue *region_sval
84 : 32 : = as_a <const region_svalue *> (result_sval);
85 : 32 : const region *pointee_reg = region_sval->get_pointee ();
86 : 32 : switch (pointee_reg->get_kind ())
87 : : {
88 : : default:
89 : : break;
90 : 32 : case RK_HEAP_ALLOCATED:
91 : 32 : pp_printf (pp,
92 : : "when %qE returns pointer"
93 : : " to heap-allocated buffer",
94 : : fndecl);
95 : 32 : 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 : 78 : 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 : 3667 : call_summary_replay::call_summary_replay (const call_details &cd,
159 : : const function &called_fn,
160 : : call_summary &summary,
161 : 3667 : const extrinsic_state &ext_state)
162 : 3667 : : m_cd (cd),
163 : 3667 : m_summary (summary),
164 : 3667 : m_ext_state (ext_state)
165 : : {
166 : 3667 : region_model_manager *mgr = cd.get_manager ();
167 : :
168 : : // populate params based on args
169 : 3667 : 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 : 3667 : const frame_region *summary_frame
175 : 3667 : = mgr->get_frame_region (nullptr, called_fn);
176 : :
177 : 3667 : unsigned idx = 0;
178 : 6760 : for (tree iter_parm = DECL_ARGUMENTS (fndecl); iter_parm;
179 : 3093 : 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 : 3093 : if (idx >= cd.num_args ())
185 : : break;
186 : 3093 : const svalue *caller_arg_sval = cd.get_arg_svalue (idx);
187 : 3093 : tree parm_lval = iter_parm;
188 : 3093 : if (tree parm_default_ssa = get_ssa_default_def (called_fn, iter_parm))
189 : 3065 : parm_lval = parm_default_ssa;
190 : 3093 : const region *summary_parm_reg
191 : 3093 : = summary_frame->get_region_for_local (mgr, parm_lval, cd.get_ctxt ());
192 : 3093 : const svalue *summary_initial_parm_reg
193 : 3093 : = mgr->get_or_create_initial_value (summary_parm_reg);
194 : 3093 : add_svalue_mapping (summary_initial_parm_reg, caller_arg_sval);
195 : : }
196 : :
197 : : /* Handle any variadic args. */
198 : : unsigned va_arg_idx = 0;
199 : 3683 : for (; idx < cd.num_args (); idx++, va_arg_idx++)
200 : : {
201 : 16 : const svalue *caller_arg_sval = cd.get_arg_svalue (idx);
202 : 16 : const region *summary_var_arg_reg
203 : 16 : = mgr->get_var_arg_region (summary_frame, va_arg_idx);
204 : 16 : const svalue *summary_initial_var_arg_reg
205 : 16 : = mgr->get_or_create_initial_value (summary_var_arg_reg);
206 : 16 : add_svalue_mapping (summary_initial_var_arg_reg, caller_arg_sval);
207 : : }
208 : 3667 : }
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 : 47149 : call_summary_replay::convert_svalue_from_summary (const svalue *summary_sval)
217 : : {
218 : 47149 : gcc_assert (summary_sval);
219 : :
220 : 94298 : if (const svalue **slot
221 : 47149 : = m_map_svalue_from_summary_to_caller.get (summary_sval))
222 : 26573 : return *slot;
223 : :
224 : 20576 : const svalue *caller_sval = convert_svalue_from_summary_1 (summary_sval);
225 : :
226 : 20576 : if (caller_sval)
227 : 20079 : if (summary_sval->get_type () && caller_sval->get_type ())
228 : 18825 : gcc_assert (types_compatible_p (summary_sval->get_type (),
229 : : caller_sval->get_type ()));
230 : :
231 : : /* Add to cache. */
232 : 20576 : add_svalue_mapping (summary_sval, caller_sval);
233 : :
234 : 20576 : return caller_sval;
235 : : }
236 : :
237 : : /* Implementation of call_summary_replay::convert_svalue_from_summary. */
238 : :
239 : : const svalue *
240 : 20576 : call_summary_replay::convert_svalue_from_summary_1 (const svalue *summary_sval)
241 : : {
242 : 20576 : gcc_assert (summary_sval);
243 : :
244 : 20576 : switch (summary_sval->get_kind ())
245 : : {
246 : 0 : default:
247 : 0 : gcc_unreachable ();
248 : 2396 : case SK_REGION:
249 : 2396 : {
250 : 2396 : const region_svalue *region_summary_sval
251 : 2396 : = as_a <const region_svalue *> (summary_sval);
252 : 2396 : const region *summary_reg = region_summary_sval->get_pointee ();
253 : 2396 : const region *caller_reg = convert_region_from_summary (summary_reg);
254 : 2396 : if (!caller_reg)
255 : : return nullptr;
256 : 2394 : region_model_manager *mgr = get_manager ();
257 : 2394 : const svalue *caller_ptr
258 : 2394 : = mgr->get_ptr_svalue (summary_sval->get_type (),
259 : : caller_reg);
260 : 2394 : 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 : 3426 : case SK_INITIAL:
274 : 3426 : {
275 : 3426 : const initial_svalue *initial_summary_sval
276 : 3426 : = as_a <const initial_svalue *> (summary_sval);
277 : : /* Params should already be in the cache, courtesy of the ctor. */
278 : 3426 : 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 : 3426 : const region *summary_reg = initial_summary_sval->get_region ();
283 : 3426 : const region *caller_reg = convert_region_from_summary (summary_reg);
284 : 3426 : if (!caller_reg)
285 : : return nullptr;
286 : 3414 : const svalue *caller_sval
287 : 3414 : = m_cd.get_model ()->get_store_value (caller_reg, m_cd.get_ctxt ());
288 : 3414 : return caller_sval;
289 : : }
290 : 111 : break;
291 : 111 : case SK_UNARYOP:
292 : 111 : {
293 : 111 : const unaryop_svalue *unaryop_summary_sval
294 : 111 : = as_a <const unaryop_svalue *> (summary_sval);
295 : 111 : const svalue *summary_arg = unaryop_summary_sval->get_arg ();
296 : 111 : const svalue *caller_arg = convert_svalue_from_summary (summary_arg);
297 : 111 : if (!caller_arg)
298 : : return nullptr;
299 : 111 : region_model_manager *mgr = get_manager ();
300 : 111 : return mgr->get_or_create_unaryop (summary_sval->get_type (),
301 : : unaryop_summary_sval->get_op (),
302 : 111 : caller_arg);
303 : : }
304 : 2114 : break;
305 : 2114 : case SK_BINOP:
306 : 2114 : {
307 : 2114 : const binop_svalue *binop_summary_sval
308 : 2114 : = as_a <const binop_svalue *> (summary_sval);
309 : 2114 : const svalue *summary_arg0 = binop_summary_sval->get_arg0 ();
310 : 2114 : const svalue *caller_arg0 = convert_svalue_from_summary (summary_arg0);
311 : 2114 : if (!caller_arg0)
312 : : return nullptr;
313 : 2114 : const svalue *summary_arg1 = binop_summary_sval->get_arg1 ();
314 : 2114 : const svalue *caller_arg1 = convert_svalue_from_summary (summary_arg1);
315 : 2114 : if (!caller_arg1)
316 : : return nullptr;
317 : 2114 : region_model_manager *mgr = get_manager ();
318 : 2114 : return mgr->get_or_create_binop (summary_sval->get_type (),
319 : : binop_summary_sval->get_op (),
320 : : caller_arg0,
321 : 2114 : 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 : 34 : break;
340 : 34 : case SK_REPEATED:
341 : 34 : {
342 : 34 : const repeated_svalue *repeated_summary_sval
343 : 34 : = as_a <const repeated_svalue *> (summary_sval);
344 : 34 : const svalue *summary_outer_size
345 : 34 : = repeated_summary_sval->get_outer_size ();
346 : 34 : const svalue *caller_outer_size
347 : 34 : = convert_svalue_from_summary (summary_outer_size);
348 : 34 : if (!caller_outer_size)
349 : : return nullptr;
350 : 34 : const svalue *summary_inner_sval
351 : 34 : = repeated_summary_sval->get_inner_svalue ();
352 : 34 : const svalue *caller_inner_sval
353 : 34 : = convert_svalue_from_summary (summary_inner_sval);
354 : 34 : if (!caller_inner_sval)
355 : : return nullptr;
356 : 34 : region_model_manager *mgr = get_manager ();
357 : 34 : return mgr->get_or_create_repeated_svalue (summary_sval->get_type (),
358 : : caller_outer_size,
359 : 34 : 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 : 485 : break;
392 : 485 : case SK_WIDENING:
393 : 485 : {
394 : 485 : const widening_svalue *widening_summary_sval
395 : 485 : = as_a <const widening_svalue *> (summary_sval);
396 : 485 : const function_point &point = widening_summary_sval->get_point ();
397 : 485 : const svalue *summary_base_sval
398 : 485 : = widening_summary_sval->get_base_svalue ();
399 : 485 : const svalue *caller_base_sval
400 : 485 : = convert_svalue_from_summary (summary_base_sval);
401 : 968 : if (!(caller_base_sval
402 : 483 : && caller_base_sval->can_have_associated_state_p ()))
403 : 483 : return nullptr;
404 : 2 : const svalue *summary_iter_sval
405 : 2 : = widening_summary_sval->get_iter_svalue ();
406 : 2 : const svalue *caller_iter_sval
407 : 2 : = convert_svalue_from_summary (summary_iter_sval);
408 : 4 : if (!(caller_iter_sval
409 : 2 : && caller_iter_sval->can_have_associated_state_p ()))
410 : 0 : return nullptr;
411 : 2 : region_model_manager *mgr = get_manager ();
412 : 2 : return mgr->get_or_create_widening_svalue
413 : 2 : (summary_iter_sval->get_type (),
414 : : point,
415 : : caller_base_sval,
416 : 2 : caller_iter_sval);
417 : : }
418 : 224 : break;
419 : 224 : case SK_COMPOUND:
420 : 224 : {
421 : 224 : const compound_svalue *compound_summary_sval
422 : 224 : = as_a <const compound_svalue *> (summary_sval);
423 : 224 : region_model_manager *mgr = get_manager ();
424 : 224 : store_manager *store_mgr = mgr->get_store_manager ();
425 : 224 : binding_map caller_map;
426 : 224 : auto_vec <const binding_key *> summary_keys;
427 : 748 : for (auto kv : *compound_summary_sval)
428 : 524 : summary_keys.safe_push (kv.first);
429 : 224 : summary_keys.qsort (binding_key::cmp_ptrs);
430 : 1196 : for (auto key : summary_keys)
431 : : {
432 : 524 : gcc_assert (key->concrete_p ());
433 : : /* No remapping is needed for concrete binding keys. */
434 : :
435 : 524 : const svalue *bound_summary_sval
436 : 524 : = compound_summary_sval->get_map ().get (key);
437 : 524 : const svalue *caller_sval
438 : 524 : = convert_svalue_from_summary (bound_summary_sval);
439 : 524 : if (!caller_sval)
440 : 8 : caller_sval = mgr->get_or_create_unknown_svalue (NULL_TREE);
441 : :
442 : 1048 : if (const compound_svalue *inner_compound_sval
443 : 524 : = 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.first;
451 : 0 : const svalue *inner_sval = inner_kv.second;
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 : 524 : caller_map.put (key, caller_sval);
467 : : }
468 : 224 : return mgr->get_or_create_compound_svalue (summary_sval->get_type (),
469 : : caller_map);
470 : 224 : }
471 : 126 : break;
472 : 126 : case SK_CONJURED:
473 : 126 : {
474 : 126 : region_model_manager *mgr = get_manager ();
475 : 126 : 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 : 23412 : call_summary_replay::convert_region_from_summary (const region *summary_reg)
539 : : {
540 : 23412 : gcc_assert (summary_reg);
541 : :
542 : 46824 : if (const region **slot
543 : 23412 : = m_map_region_from_summary_to_caller.get (summary_reg))
544 : 8508 : return *slot;
545 : :
546 : 14904 : const region *caller_reg = convert_region_from_summary_1 (summary_reg);
547 : :
548 : 14904 : if (caller_reg)
549 : 14642 : if (summary_reg->get_type () && caller_reg->get_type ())
550 : 11893 : gcc_assert (types_compatible_p (summary_reg->get_type (),
551 : : caller_reg->get_type ()));
552 : :
553 : : /* Add to cache. */
554 : 14904 : add_region_mapping (summary_reg, caller_reg);
555 : :
556 : 14904 : return caller_reg;
557 : : }
558 : :
559 : : /* Implementation of call_summary_replay::convert_region_from_summary. */
560 : :
561 : : const region *
562 : 14904 : call_summary_replay::convert_region_from_summary_1 (const region *summary_reg)
563 : : {
564 : 14904 : gcc_assert (summary_reg);
565 : :
566 : 14904 : region_model_manager *mgr = get_manager ();
567 : 14904 : 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 : 2484 : case RK_SYMBOLIC:
592 : 2484 : {
593 : 2484 : const symbolic_region *summary_symbolic_reg
594 : 2484 : = as_a <const symbolic_region *> (summary_reg);
595 : 2484 : const svalue *summary_ptr_sval = summary_symbolic_reg->get_pointer ();
596 : 2484 : const svalue *caller_ptr_sval
597 : 2484 : = convert_svalue_from_summary (summary_ptr_sval);
598 : 2484 : if (!caller_ptr_sval)
599 : : return nullptr;
600 : 2484 : const region *caller_reg
601 : 2484 : = get_caller_model ()->deref_rvalue (caller_ptr_sval,
602 : : NULL_TREE,
603 : : get_ctxt ());
604 : 2484 : caller_reg = mgr->get_cast_region (caller_reg,
605 : : summary_reg->get_type ());
606 : 2484 : return caller_reg;
607 : : }
608 : 7737 : break;
609 : :
610 : 7737 : case RK_DECL:
611 : 7737 : {
612 : 7737 : const decl_region *summary_decl_reg
613 : 7737 : = as_a <const decl_region *> (summary_reg);
614 : 7737 : tree decl = summary_decl_reg->get_decl ();
615 : 7737 : 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 : 6628 : case VAR_DECL:
624 : : /* We don't care about writes to locals within
625 : : the summary. */
626 : 6628 : 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 : 901 : case RESULT_DECL:
633 : 901 : 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 : 629 : break;
640 : 629 : case RK_FIELD:
641 : 629 : {
642 : 629 : const field_region *summary_field_reg
643 : 629 : = as_a <const field_region *> (summary_reg);
644 : 629 : const region *summary_parent_reg = summary_reg->get_parent_region ();
645 : 629 : const region *caller_parent_reg
646 : 629 : = convert_region_from_summary (summary_parent_reg);
647 : 629 : if (!caller_parent_reg)
648 : : return nullptr;
649 : 621 : tree field = summary_field_reg->get_field ();
650 : 621 : 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 : 497 : break;
672 : 497 : case RK_OFFSET:
673 : 497 : {
674 : 497 : const offset_region *summary_offset_reg
675 : 497 : = as_a <const offset_region *> (summary_reg);
676 : 497 : const region *summary_parent_reg = summary_reg->get_parent_region ();
677 : 497 : const region *caller_parent_reg
678 : 497 : = convert_region_from_summary (summary_parent_reg);
679 : 497 : if (!caller_parent_reg)
680 : : return nullptr;
681 : 495 : const svalue *summary_byte_offset
682 : 495 : = summary_offset_reg->get_byte_offset ();
683 : 495 : const svalue *caller_byte_offset
684 : 495 : = convert_svalue_from_summary (summary_byte_offset);
685 : 495 : if (!caller_byte_offset)
686 : : return nullptr;
687 : 495 : return mgr->get_offset_region (caller_parent_reg,
688 : : summary_reg->get_type (),
689 : 495 : 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 : 2749 : break;
723 : 2749 : case RK_HEAP_ALLOCATED:
724 : 2749 : {
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 : 2749 : auto_bitmap heap_regs_in_use;
729 : 2749 : get_caller_model ()->get_referenced_base_regions (heap_regs_in_use);
730 : 2749 : return mgr->get_or_create_region_for_heap_alloc (heap_regs_in_use);
731 : 2749 : }
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 : 23685 : call_summary_replay::add_svalue_mapping (const svalue *summary_sval,
780 : : const svalue *caller_sval)
781 : : {
782 : 23685 : gcc_assert (summary_sval);
783 : : // CALLER_SVAL can be nullptr
784 : 23685 : m_map_svalue_from_summary_to_caller.put (summary_sval, caller_sval);
785 : 23685 : }
786 : :
787 : : /* Record that SUMMARY_REG maps to CALLER_REG for this replay. */
788 : :
789 : : void
790 : 14904 : call_summary_replay::add_region_mapping (const region *summary_reg,
791 : : const region *caller_reg)
792 : : {
793 : 14904 : gcc_assert (summary_reg);
794 : : // CALLER_REG can be nullptr
795 : 14904 : m_map_region_from_summary_to_caller.put (summary_reg, caller_reg);
796 : 14904 : }
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 */
|