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