Line data Source code
1 : /* Operations within the code being analyzed.
2 : Copyright (C) 2019-2026 Free Software Foundation, Inc.
3 : Contributed by David Malcolm <dmalcolm@redhat.com>.
4 :
5 : This file is part of GCC.
6 :
7 : GCC is free software; you can redistribute it and/or modify it
8 : under the terms of the GNU General Public License as published by
9 : the Free Software Foundation; either version 3, or (at your option)
10 : any later version.
11 :
12 : GCC is distributed in the hope that it will be useful, but
13 : WITHOUT ANY WARRANTY; without even the implied warranty of
14 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 : General Public License for more details.
16 :
17 : You should have received a copy of the GNU General Public License
18 : along with GCC; see the file COPYING3. If not see
19 : <http://www.gnu.org/licenses/>. */
20 :
21 : #ifndef GCC_ANALYZER_OPS_H
22 : #define GCC_ANALYZER_OPS_H
23 :
24 : #include "except.h"
25 : #include "gimple-walk.h"
26 :
27 : namespace ana {
28 :
29 : class operation;
30 : class control_flow_op;
31 : class call_and_return_op;
32 : class phis_for_edge_op;
33 :
34 : class callsite_expr;
35 :
36 : struct operation_context
37 : {
38 360582 : operation_context (exploded_graph &eg,
39 : exploded_node &src_enode,
40 : const superedge &sedge)
41 360582 : : m_eg (eg),
42 360582 : m_src_enode (src_enode),
43 360582 : m_sedge (sedge)
44 : {
45 : }
46 :
47 : void DEBUG_FUNCTION dump () const;
48 :
49 : logger *get_logger () const;
50 :
51 : const extrinsic_state &get_ext_state () const;
52 :
53 : const program_point &
54 : get_initial_point () const;
55 :
56 : const program_state &
57 : get_initial_state () const;
58 :
59 : const supergraph &
60 : get_supergraph () const;
61 :
62 : program_point
63 : get_next_intraprocedural_point () const;
64 :
65 : void
66 : add_outcome (const program_point &dst_point,
67 : program_state dst_state,
68 : bool could_do_work,
69 : uncertainty_t *uncertainty,
70 : std::unique_ptr<custom_edge_info> info = nullptr);
71 :
72 : exploded_graph &m_eg;
73 : exploded_node &m_src_enode;
74 : const superedge &m_sedge;
75 : };
76 :
77 : /* Abstract base class for an operation along a superedge. */
78 :
79 0 : class operation
80 : {
81 : public:
82 : // Discriminator for concrete subclasses
83 : enum kind
84 : {
85 : asm_stmt,
86 : assignment,
87 : predict_stmt,
88 : return_stmt,
89 : resx,
90 : cond_edge,
91 : goto_edge,
92 : switch_edge,
93 : eh_dispatch_try_edge,
94 : eh_dispatch_allowed_edge,
95 : phis,
96 : call_and_return
97 : };
98 :
99 : virtual ~operation () {}
100 :
101 : void
102 : dump () const;
103 :
104 : virtual std::unique_ptr<operation>
105 : clone () const = 0;
106 :
107 : virtual void
108 : print_as_edge_label (pretty_printer *pp, bool user_facing) const = 0;
109 :
110 : virtual bool
111 : defines_ssa_name_p (const_tree ssa_name) const = 0;
112 :
113 : virtual void
114 : walk_load_store_addr_ops (void *,
115 : walk_stmt_load_store_addr_fn,
116 : walk_stmt_load_store_addr_fn,
117 : walk_stmt_load_store_addr_fn) const = 0;
118 :
119 : virtual const gimple *
120 2756 : maybe_get_stmt () const
121 : {
122 2756 : return nullptr;
123 : }
124 :
125 : virtual void
126 : execute (operation_context &op_ctxt) const = 0;
127 :
128 : virtual bool
129 0 : execute_for_feasibility (const exploded_edge &,
130 : feasibility_state &,
131 : region_model_context *,
132 : std::unique_ptr<rejected_constraint> */*out_rc*/) const
133 : {
134 : // no-op
135 0 : return true;
136 : }
137 :
138 : /* Is this op suitable for bulk-merging?
139 : It must have a single outcome, at the intraprocedural
140 : next point, with some state. */
141 : virtual bool
142 : supports_bulk_merge_p () const = 0;
143 : virtual void
144 0 : update_state_for_bulk_merger (const program_state &,
145 : program_state &) const
146 : {
147 : /* Must be implemented for any subclasses that return true
148 : for supports_bulk_merge_p. */
149 0 : gcc_unreachable ();
150 : }
151 : virtual void
152 : add_any_events_for_eedge (const exploded_edge &eedge,
153 : checker_path &out_path) const = 0;
154 :
155 : virtual const control_flow_op *
156 1444 : dyn_cast_control_flow_op () const { return nullptr; }
157 :
158 : virtual const call_and_return_op *
159 200803 : dyn_cast_call_and_return_op () const { return nullptr; }
160 :
161 : virtual const phis_for_edge_op *
162 788 : dyn_cast_phis_for_edge_op () const { return nullptr; }
163 :
164 2001 : enum kind get_kind () const { return m_kind; }
165 :
166 : protected:
167 136282 : operation (enum kind kind_)
168 136282 : : m_kind (kind_)
169 : {
170 : }
171 :
172 : static void
173 : handle_on_stmt_for_state_machines (operation_context &op_ctxt,
174 : program_state &dst_state,
175 : path_context *path_ctxt,
176 : bool &unknown_side_effects,
177 : const gimple &stmt);
178 :
179 : private:
180 : enum kind m_kind;
181 : };
182 :
183 : /* Subclass for an operation representing a specific gimple stmt
184 : that isn't control flow. */
185 :
186 : class gimple_stmt_op : public operation
187 : {
188 : public:
189 225612 : const gimple &get_stmt () const { return m_stmt; }
190 :
191 : void
192 : print_as_edge_label (pretty_printer *pp, bool user_facing) const override;
193 :
194 : bool
195 : defines_ssa_name_p (const_tree ssa_name) const final override;
196 :
197 : void
198 : walk_load_store_addr_ops (void *,
199 : walk_stmt_load_store_addr_fn,
200 : walk_stmt_load_store_addr_fn,
201 : walk_stmt_load_store_addr_fn) const final override;
202 :
203 : const gimple *
204 46855 : maybe_get_stmt () const final override
205 : {
206 46855 : return &m_stmt;
207 : }
208 :
209 : void
210 : execute (operation_context &op_ctxt) const override;
211 :
212 : void
213 : execute_on_state (operation_context &op_ctxt,
214 : program_state dst_state) const;
215 :
216 : bool
217 : execute_for_feasibility (const exploded_edge &,
218 : feasibility_state &,
219 : region_model_context *,
220 : std::unique_ptr<rejected_constraint> *out_rc) const override;
221 :
222 : virtual bool
223 : supports_bulk_merge_p () const override;
224 :
225 : void
226 : add_any_events_for_eedge (const exploded_edge &eedge,
227 : checker_path &out_path) const override;
228 :
229 : protected:
230 108970 : gimple_stmt_op (enum kind kind_, const gimple &stmt)
231 108970 : : operation (kind_), m_stmt (stmt)
232 : {}
233 :
234 : private:
235 : const gimple &m_stmt;
236 : };
237 :
238 : /* Various subclasses of gimple_stmt_op. */
239 :
240 : /* An operation subclass representing the effect of a GIMPLE_ASM stmt. */
241 :
242 : class gasm_op : public gimple_stmt_op
243 : {
244 : public:
245 210 : gasm_op (const gasm &asm_stmt)
246 210 : : gimple_stmt_op (kind::asm_stmt, asm_stmt)
247 : {
248 : }
249 :
250 : std::unique_ptr<operation>
251 0 : clone () const final override
252 : {
253 0 : return std::make_unique<gasm_op> (get_gasm ());
254 : }
255 :
256 0 : const gasm &get_gasm () const
257 : {
258 0 : return *as_a <const gasm *> (&get_stmt ());
259 : }
260 : };
261 :
262 : /* An operation subclass representing the effect of a GIMPLE_ASSIGN stmt. */
263 :
264 : class gassign_op : public gimple_stmt_op
265 : {
266 : public:
267 54554 : gassign_op (const gassign &assign_stmt)
268 54554 : : gimple_stmt_op (kind::assignment, assign_stmt)
269 : {
270 : }
271 :
272 : std::unique_ptr<operation>
273 0 : clone () const final override
274 : {
275 0 : return std::make_unique<gassign_op> (get_gassign ());
276 : }
277 :
278 0 : const gassign &get_gassign () const
279 : {
280 0 : return *as_a <const gassign *> (&get_stmt ());
281 : }
282 : };
283 :
284 : /* An operation subclass for a GIMPLE_PREDICT stmt.
285 : They have no effect on state, but can be useful for reconstructing
286 : where "return" statements were in the code the user originally wrote,
287 : to improve the reported locations in diagnostics. */
288 :
289 : class predict_op : public gimple_stmt_op
290 : {
291 : public:
292 1761 : predict_op (const gimple &predict_stmt)
293 1761 : : gimple_stmt_op (kind::predict_stmt, predict_stmt)
294 : {
295 1761 : gcc_assert (predict_stmt.code == GIMPLE_PREDICT);
296 1761 : }
297 :
298 : std::unique_ptr<operation>
299 0 : clone () const final override
300 : {
301 0 : return std::make_unique<predict_op> (get_stmt ());
302 : }
303 : };
304 :
305 : /* An operation subclass representing both:
306 : (a) the effect of a GIMPLE_RETURN stmt: copying a value into the
307 : RESULT_DECL of the current frame, and
308 : (b) a hint when reporting diagnostics that this is the return
309 : path from the function (rather than say, throwing an exception). */
310 :
311 : class greturn_op : public gimple_stmt_op
312 : {
313 : public:
314 10002 : greturn_op (const greturn &return_stmt)
315 10002 : : gimple_stmt_op (kind::return_stmt, return_stmt)
316 : {
317 : }
318 :
319 : std::unique_ptr<operation>
320 0 : clone () const final override
321 : {
322 0 : return std::make_unique<greturn_op> (get_greturn ());
323 : }
324 :
325 : void
326 : execute (operation_context &op_ctxt) const final override;
327 :
328 : bool
329 : execute_for_feasibility (const exploded_edge &,
330 : feasibility_state &,
331 : region_model_context *ctxt,
332 : std::unique_ptr<rejected_constraint> *out_rc) const override;
333 :
334 : bool
335 11286 : supports_bulk_merge_p () const final override
336 : {
337 11286 : return false;
338 : }
339 :
340 : void
341 : add_any_events_for_eedge (const exploded_edge &eedge,
342 : checker_path &out_path) const final override;
343 :
344 21501 : const greturn &get_greturn () const
345 : {
346 714 : return *as_a <const greturn *> (&get_stmt ());
347 : }
348 :
349 20787 : tree get_retval () const
350 : {
351 20787 : return gimple_return_retval (&get_greturn ());
352 : }
353 : };
354 :
355 : /* A concrete operation subclass representing the effect of a GIMPLE_CALL stmt.
356 :
357 : If the function is identified and has a known body, either simulate
358 : it interprocedurally by pushing a stack frame and transitioning to the
359 : callee, or simulate it intraprocedurally by replaying a summary of the
360 : effects of the call.
361 :
362 : If the function is identified but has an unknown body,
363 : simulate it intraprocedurally, either using a known_function
364 : subclass for precision, or following conservative rules that
365 : assume various side-effects.
366 :
367 : If the function is unidentified (for some kinds of dynamic calls),
368 : simulate it intraprocedurally, following conservative rules that
369 : assume various side-effects.
370 :
371 : In the various intraprocedural simulation cases, the exploded edge will
372 : correspond to the underlying superedge.
373 :
374 : In the interprocedural simulation case, the exploded edge will
375 : link two supernodes in different functions, and thus will require
376 : custom edge info.
377 :
378 : Various subclasses exist for handling awkward special cases,
379 : such as longjmp. */
380 :
381 : class call_and_return_op : public gimple_stmt_op
382 : {
383 : public:
384 : static std::unique_ptr<operation>
385 : make (const gcall &call_stmt);
386 :
387 : std::unique_ptr<operation>
388 0 : clone () const override
389 : {
390 0 : return std::make_unique<call_and_return_op> (get_gcall ());
391 : }
392 :
393 257103 : const gcall &get_gcall () const
394 : {
395 203309 : return *as_a <const gcall *> (&get_stmt ());
396 : }
397 :
398 : void
399 : execute (operation_context &op_ctxt) const override;
400 :
401 : bool
402 15834 : supports_bulk_merge_p () const final override
403 : {
404 15834 : return false;
405 : }
406 :
407 : void
408 : add_any_events_for_eedge (const exploded_edge &eedge,
409 : checker_path &out_path) const override;
410 :
411 : const call_and_return_op *
412 62785 : dyn_cast_call_and_return_op () const final override { return this; }
413 :
414 : tree
415 : map_expr_from_caller_to_callee (tree callee_fndecl,
416 : tree caller_expr,
417 : callsite_expr *out) const;
418 : tree
419 : map_expr_from_callee_to_caller (tree callee_fndecl,
420 : tree callee_expr,
421 : callsite_expr *out) const;
422 :
423 41878 : call_and_return_op (const gcall &call_stmt)
424 41878 : : gimple_stmt_op (kind::call_and_return, call_stmt)
425 : {
426 : }
427 :
428 : const known_function *
429 : maybe_get_known_function (const call_details &cd) const;
430 :
431 : private:
432 : cgraph_edge *
433 : get_any_cgraph_edge (operation_context &op_ctxt) const;
434 :
435 : void
436 : replay_call_summaries (operation_context &op_ctxt,
437 : function &called_fn,
438 : per_function_data &called_fn_data,
439 : region_model_context *ctxt) const;
440 :
441 : void
442 : replay_call_summary (operation_context &op_ctxt,
443 : function &called_fn,
444 : call_summary &summary,
445 : region_model_context *ctxt) const;
446 :
447 : tree
448 : get_arg_for_parm (tree callee_fndecl,
449 : tree parm,
450 : callsite_expr *out) const;
451 : tree
452 : get_parm_for_arg (tree callee_fndecl,
453 : tree arg,
454 : callsite_expr *out) const;
455 : };
456 :
457 : /* A call to one of the various __analyzer_dump* functions.
458 : These have no effect on state. */
459 :
460 : class dump_op : public call_and_return_op
461 : {
462 : public:
463 : enum dump_kind
464 : {
465 : state,
466 : sarif,
467 : dot,
468 : state_2
469 : };
470 :
471 309 : dump_op (const gcall &call_stmt, enum dump_kind dump_kind_)
472 309 : : call_and_return_op (call_stmt),
473 309 : m_dump_kind (dump_kind_)
474 : {
475 : }
476 :
477 : std::unique_ptr<operation>
478 0 : clone () const final override
479 : {
480 0 : return std::make_unique<dump_op> (get_gcall (), m_dump_kind);
481 : }
482 :
483 : void
484 : execute (operation_context &op_ctxt) const final override;
485 :
486 : private:
487 : enum dump_kind m_dump_kind;
488 : };
489 :
490 : class setjmp_op : public call_and_return_op
491 : {
492 : public:
493 29 : setjmp_op (const gcall &call_stmt)
494 29 : : call_and_return_op (call_stmt)
495 : {
496 : }
497 :
498 : std::unique_ptr<operation>
499 0 : clone () const final override
500 : {
501 0 : return std::make_unique<setjmp_op> (get_gcall ());
502 : }
503 :
504 : void
505 : execute (operation_context &op_ctxt) const final override;
506 :
507 : void
508 : add_any_events_for_eedge (const exploded_edge &eedge,
509 : checker_path &out_path) const final override;
510 : };
511 :
512 : class longjmp_op : public call_and_return_op
513 : {
514 : public:
515 41 : longjmp_op (const gcall &call_stmt)
516 41 : : call_and_return_op (call_stmt)
517 : {
518 : }
519 :
520 : std::unique_ptr<operation>
521 0 : clone () const final override
522 : {
523 0 : return std::make_unique<longjmp_op> (get_gcall ());
524 : }
525 :
526 : void
527 : execute (operation_context &op_ctxt) const final override;
528 : };
529 :
530 : class cxa_throw_op : public call_and_return_op
531 : {
532 : public:
533 112 : cxa_throw_op (const gcall &call_stmt, bool is_rethrow)
534 112 : : call_and_return_op (call_stmt),
535 112 : m_is_rethrow (is_rethrow)
536 : {
537 : }
538 :
539 : std::unique_ptr<operation>
540 0 : clone () const final override
541 : {
542 0 : return std::make_unique<cxa_throw_op> (get_gcall (), m_is_rethrow);
543 : }
544 :
545 : void
546 : execute (operation_context &op_ctxt) const final override;
547 :
548 : private:
549 : bool m_is_rethrow;
550 : };
551 :
552 : class resx_op : public gimple_stmt_op
553 : {
554 : public:
555 565 : resx_op (const gresx &resx_stmt)
556 565 : : gimple_stmt_op (kind::resx, resx_stmt)
557 : {
558 : }
559 :
560 : std::unique_ptr<operation>
561 0 : clone () const final override
562 : {
563 0 : return std::make_unique<resx_op> (get_gresx ());
564 : }
565 :
566 0 : const gresx &get_gresx () const
567 : {
568 0 : return *as_a <const gresx *> (&get_stmt ());
569 : }
570 :
571 : void
572 : execute (operation_context &op_ctxt) const final override;
573 :
574 : bool
575 47 : supports_bulk_merge_p () const final override
576 : {
577 47 : return false;
578 : }
579 :
580 : void
581 : add_any_events_for_eedge (const exploded_edge &eedge,
582 : checker_path &out_path) const final override;
583 : };
584 :
585 : /* An abstract subclass of operation representing the filtering effect on
586 : state of a gimple control-flow statement at the end of a BB, for
587 : a specific CFG out-edge from that BB. */
588 :
589 0 : class control_flow_op : public operation
590 : {
591 : public:
592 : void
593 : add_any_events_for_eedge (const exploded_edge &eedge,
594 : checker_path &out_path) const override;
595 :
596 : bool
597 27846 : defines_ssa_name_p (const_tree) const final override
598 : {
599 27846 : return false;
600 : }
601 :
602 : void
603 : walk_load_store_addr_ops (void *,
604 : walk_stmt_load_store_addr_fn,
605 : walk_stmt_load_store_addr_fn,
606 : walk_stmt_load_store_addr_fn) const final override;
607 :
608 : const gimple *
609 8196 : maybe_get_stmt () const final override
610 : {
611 8196 : return &m_ctrlflow_stmt;
612 : }
613 :
614 : virtual label_text
615 : maybe_describe_condition (bool can_colorize) const;
616 :
617 : void
618 : execute (operation_context &op_ctxt) const final override;
619 :
620 : bool
621 66 : supports_bulk_merge_p () const final override
622 : {
623 66 : return false;
624 : }
625 :
626 : bool
627 : execute_for_feasibility (const exploded_edge &,
628 : feasibility_state &,
629 : region_model_context *,
630 : std::unique_ptr<rejected_constraint> *out_rc) const override;
631 :
632 : const control_flow_op *
633 565 : dyn_cast_control_flow_op () const final override { return this; }
634 :
635 0 : ::edge get_cfg_edge () const { return m_cfg_edge; }
636 14898 : int get_flags () const { return m_cfg_edge->flags; }
637 : int back_edge_p () const { return get_flags () & EDGE_DFS_BACK; }
638 :
639 715 : const gimple &get_ctrlflow_stmt () const { return m_ctrlflow_stmt; }
640 :
641 : protected:
642 18104 : control_flow_op (enum kind kind_,
643 : ::edge cfg_edge,
644 : const gimple &ctrlflow_stmt)
645 18104 : : operation (kind_),
646 18104 : m_cfg_edge (cfg_edge),
647 17881 : m_ctrlflow_stmt (ctrlflow_stmt)
648 : {}
649 :
650 : private:
651 : virtual bool
652 : apply_constraints (const superedge *sedge,
653 : region_model &model,
654 : region_model_context *ctxt,
655 : std::unique_ptr<rejected_constraint> *out) const = 0;
656 :
657 : ::edge m_cfg_edge;
658 : const gimple &m_ctrlflow_stmt;
659 : };
660 :
661 : /* Concrete operation subclass representing filtering/applying state
662 : transitions on a specific CFG edge after a GIMPLE_COND stmt, either the
663 : "if (cond) is true" or the "if (cond) is false" branch. */
664 :
665 : class gcond_edge_op : public control_flow_op
666 : {
667 : public:
668 : gcond_edge_op (::edge cfg_edge,
669 : const gcond &cond_stmt);
670 :
671 : std::unique_ptr<operation>
672 0 : clone () const final override
673 : {
674 0 : return std::make_unique<gcond_edge_op> (get_cfg_edge (),
675 0 : get_gcond ());
676 : }
677 :
678 : void
679 : print_as_edge_label (pretty_printer *pp,
680 : bool user_facing) const final override;
681 :
682 : label_text
683 : maybe_describe_condition (bool can_colorize) const final override;
684 :
685 79176 : const gcond &get_gcond () const
686 : {
687 79176 : return *as_a <const gcond *> (&get_ctrlflow_stmt ());
688 : }
689 :
690 : private:
691 : static label_text
692 : maybe_describe_condition (bool can_colorize,
693 : tree lhs,
694 : enum tree_code op,
695 : tree rhs);
696 : static bool should_print_expr_p (tree expr);
697 :
698 : bool
699 : apply_constraints (const superedge *sedge,
700 : region_model &model,
701 : region_model_context *ctxt,
702 : std::unique_ptr<rejected_constraint> *out)
703 : const final override;
704 :
705 : bool m_true_value;
706 : };
707 :
708 : /* Concrete operation subclass representing filtering/applying state
709 : transitions on a specific CFG edge after a GIMPLE_GOTO stmt, thus
710 : handling computed gotos. */
711 :
712 : class ggoto_edge_op : public control_flow_op
713 : {
714 : public:
715 : ggoto_edge_op (::edge cfg_edge,
716 : const ggoto &goto_stmt,
717 : tree dst_label);
718 :
719 : std::unique_ptr<operation>
720 0 : clone () const final override
721 : {
722 0 : return std::make_unique<ggoto_edge_op> (get_cfg_edge (),
723 : get_ggoto (),
724 0 : m_dst_label);
725 : }
726 :
727 : void
728 : print_as_edge_label (pretty_printer *pp,
729 : bool user_facing) const final override;
730 :
731 : label_text
732 : maybe_describe_condition (bool can_colorize) const final override;
733 :
734 79 : const ggoto &get_ggoto () const
735 : {
736 79 : return *as_a <const ggoto *> (&get_ctrlflow_stmt ());
737 : }
738 :
739 : private:
740 : bool
741 : apply_constraints (const superedge *sedge,
742 : region_model &model,
743 : region_model_context *ctxt,
744 : std::unique_ptr<rejected_constraint> *out)
745 : const final override;
746 :
747 : tree m_dst_label;
748 : };
749 :
750 : /* Concrete operation subclass representing filtering/applying state
751 : transitions on a specific CFG edge after a GIMPLE_SWITCH stmt, thus
752 : handling a cluster of cases/default value. */
753 :
754 : class switch_case_op : public control_flow_op
755 : {
756 : public:
757 : switch_case_op (function &fun,
758 : ::edge cfg_edge,
759 : const gswitch &switch_stmt,
760 : bounded_ranges_manager &mgr);
761 :
762 : std::unique_ptr<operation>
763 0 : clone () const final override
764 : {
765 0 : return std::make_unique<switch_case_op> (*this);
766 : }
767 :
768 : void
769 : print_as_edge_label (pretty_printer *pp,
770 : bool user_facing) const final override;
771 :
772 : bool implicitly_created_default_p () const;
773 :
774 8072 : const gswitch &get_gswitch () const
775 : {
776 8072 : return *as_a <const gswitch *> (&get_ctrlflow_stmt ());
777 : }
778 :
779 : private:
780 : bool
781 : apply_constraints (const superedge *sedge,
782 : region_model &model,
783 : region_model_context *ctxt,
784 : std::unique_ptr<rejected_constraint> *out)
785 : const final override;
786 :
787 : std::vector<tree> m_case_labels;
788 : const bounded_ranges *m_all_cases_ranges;
789 : };
790 :
791 : /* Abstract subclass for edges from eh_dispatch statements. */
792 :
793 0 : class eh_dispatch_edge_op : public control_flow_op
794 : {
795 : public:
796 : static std::unique_ptr<eh_dispatch_edge_op>
797 : make (supernode *src,
798 : supernode *dest,
799 : ::edge cfg_edge,
800 : const geh_dispatch &geh_dispatch_stmt);
801 :
802 : const geh_dispatch &
803 : get_geh_dispatch () const
804 : {
805 : return *as_a <const geh_dispatch *> (&get_ctrlflow_stmt ());
806 : }
807 :
808 : eh_region
809 13 : get_eh_region () const { return m_eh_region; }
810 :
811 : protected:
812 : eh_dispatch_edge_op (supernode *src_snode,
813 : enum kind kind_,
814 : ::edge cfg_edge,
815 : const geh_dispatch &geh_dispatch_stmt,
816 : eh_region eh_reg);
817 :
818 230 : supernode *get_src_snode () const { return m_src_snode; }
819 :
820 : private:
821 : bool
822 : apply_constraints (const superedge *sedge,
823 : region_model &model,
824 : region_model_context *ctxt,
825 : std::unique_ptr<rejected_constraint> *out)
826 : const final override;
827 :
828 : virtual bool
829 : apply_eh_constraints (const superedge *sedge,
830 : region_model &model,
831 : region_model_context *ctxt,
832 : tree exception_type,
833 : std::unique_ptr<rejected_constraint> *out) const = 0;
834 :
835 : supernode *m_src_snode;
836 : eh_region m_eh_region;
837 : };
838 :
839 : /* Concrete operation for edges from an eh_dispatch statement
840 : for ERT_TRY regions. */
841 :
842 0 : class eh_dispatch_try_edge_op : public eh_dispatch_edge_op
843 : {
844 : public:
845 : eh_dispatch_try_edge_op (supernode *src_snode,
846 : ::edge cfg_edge,
847 : const geh_dispatch &geh_dispatch_stmt,
848 : eh_region eh_reg,
849 : eh_catch ehc);
850 :
851 : std::unique_ptr<operation>
852 0 : clone () const final override
853 : {
854 0 : return std::make_unique<eh_dispatch_try_edge_op> (*this);
855 : }
856 :
857 : void
858 : print_as_edge_label (pretty_printer *pp,
859 : bool user_facing) const final override;
860 :
861 : void
862 : add_any_events_for_eedge (const exploded_edge &eedge,
863 : checker_path &out_path) const final override;
864 :
865 : private:
866 : bool
867 : apply_eh_constraints (const superedge *sedge,
868 : region_model &model,
869 : region_model_context *ctxt,
870 : tree exception_type,
871 : std::unique_ptr<rejected_constraint> *out)
872 : const final override;
873 :
874 : eh_catch m_eh_catch;
875 : };
876 :
877 : /* Concrete operation for edges from an eh_dispatch statement
878 : for ERT_ALLOWED_EXCEPTIONS regions. */
879 :
880 0 : class eh_dispatch_allowed_edge_op : public eh_dispatch_edge_op
881 : {
882 : public:
883 : enum eh_kind
884 : {
885 : expected,
886 : unexpected
887 : };
888 :
889 : eh_dispatch_allowed_edge_op (supernode *src_snode,
890 : supernode *dst_snode,
891 : ::edge cfg_edge,
892 : const geh_dispatch &geh_dispatch_stmt,
893 : eh_region eh_reg);
894 :
895 : std::unique_ptr<operation>
896 0 : clone () const final override
897 : {
898 0 : return std::make_unique<eh_dispatch_allowed_edge_op> (*this);
899 : }
900 :
901 : void
902 : print_as_edge_label (pretty_printer *pp,
903 : bool user_facing) const final override;
904 :
905 13 : enum eh_kind get_eh_kind () const { return m_kind; }
906 :
907 : private:
908 : bool
909 : apply_eh_constraints (const superedge *sedge,
910 : region_model &model,
911 : region_model_context *ctxt,
912 : tree exception_type,
913 : std::unique_ptr<rejected_constraint> *out)
914 : const final override;
915 :
916 : enum eh_kind m_kind;
917 : };
918 :
919 : /* Concrete operation subclass representing the state transition
920 : for simultaneously handling all of the phi nodes at the entry to a BB,
921 : after following a specific CFG in-edge.
922 : Note that this covers multiple gimple stmts: all of the gphi stmts
923 : at a basic block entry (albeit for just one in-edge).
924 : This can be thought of as handling one column of the entries in the
925 : phi nodes of a BB (for a specific in-edge).
926 : We ignore MEM entries, and discard phi nodes purely affecting them. */
927 :
928 0 : class phis_for_edge_op : public operation
929 : {
930 : public:
931 : /* A "dst=src;" pair within a phi node. */
932 : struct pair
933 : {
934 : tree m_dst;
935 : tree m_src;
936 : };
937 :
938 : static std::unique_ptr<operation>
939 : maybe_make (::edge cfg_in_edge);
940 :
941 : std::unique_ptr<operation>
942 0 : clone () const final override
943 : {
944 0 : return std::make_unique<phis_for_edge_op> (*this);
945 : }
946 :
947 : phis_for_edge_op (std::vector<pair> &&pairs);
948 :
949 : const phis_for_edge_op *
950 180 : dyn_cast_phis_for_edge_op () const final override { return this; }
951 :
952 : void
953 : print_as_edge_label (pretty_printer *pp,
954 : bool user_facing) const final override;
955 :
956 : bool
957 : defines_ssa_name_p (const_tree ssa_name) const final override;
958 :
959 : void
960 : walk_load_store_addr_ops (void *,
961 : walk_stmt_load_store_addr_fn,
962 : walk_stmt_load_store_addr_fn,
963 : walk_stmt_load_store_addr_fn) const final override;
964 : void
965 : execute (operation_context &op_ctxt) const final override;
966 :
967 : bool
968 : execute_for_feasibility (const exploded_edge &,
969 : feasibility_state &,
970 : region_model_context *,
971 : std::unique_ptr<rejected_constraint> *out_rc) const override;
972 :
973 : bool
974 1136 : supports_bulk_merge_p () const final override
975 : {
976 1136 : return true;
977 : }
978 : void
979 : update_state_for_bulk_merger (const program_state &src_state,
980 : program_state &dst_state) const final override;
981 :
982 : void
983 : add_any_events_for_eedge (const exploded_edge &eedge,
984 : checker_path &out_path) const final override;
985 :
986 92 : const std::vector<pair> &get_pairs () const { return m_pairs; }
987 :
988 : private:
989 : static std::vector<pair>
990 : get_pairs_for_phi_along_in_edge (::edge cfg_in_edge);
991 :
992 : void
993 : update_state (const program_state &src_state,
994 : program_state &dst_state,
995 : region_model_context *ctxt) const;
996 :
997 : std::vector<pair> m_pairs;
998 : };
999 :
1000 : } // namespace ana
1001 :
1002 : #endif /* GCC_ANALYZER_OPS_H */
|