Branch data Line data Source code
1 : : /* "Supergraph" classes that combine CFGs and callgraph into one digraph.
2 : : Copyright (C) 2019-2025 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_SUPERGRAPH_H
22 : : #define GCC_ANALYZER_SUPERGRAPH_H
23 : :
24 : : #include "ordered-hash-map.h"
25 : : #include "cfg.h"
26 : : #include "basic-block.h"
27 : : #include "gimple.h"
28 : : #include "gimple-iterator.h"
29 : : #include "digraph.h"
30 : : #include "except.h"
31 : :
32 : : using namespace ana;
33 : :
34 : : namespace ana {
35 : :
36 : : /* Forward decls, using indentation to show inheritance. */
37 : :
38 : : class supergraph;
39 : : class supernode;
40 : : class superedge;
41 : : class callgraph_superedge;
42 : : class call_superedge;
43 : : class return_superedge;
44 : : class cfg_superedge;
45 : : class switch_cfg_superedge;
46 : : class eh_dispatch_cfg_superedge;
47 : : class eh_dispatch_try_cfg_superedge;
48 : : class eh_dispatch_allowed_cfg_superedge;
49 : : class supercluster;
50 : : class dot_annotator;
51 : :
52 : : class logger;
53 : :
54 : : /* An enum for discriminating between superedge subclasses. */
55 : :
56 : : enum edge_kind
57 : : {
58 : : SUPEREDGE_CFG_EDGE,
59 : : SUPEREDGE_CALL,
60 : : SUPEREDGE_RETURN,
61 : : SUPEREDGE_INTRAPROCEDURAL_CALL
62 : : };
63 : :
64 : : /* Flags for controlling the appearance of .dot dumps. */
65 : :
66 : : enum supergraph_dot_flags
67 : : {
68 : : SUPERGRAPH_DOT_SHOW_BBS = (1 << 0)
69 : : };
70 : :
71 : : /* A traits struct describing the family of node, edge and digraph
72 : : classes for supergraphs. */
73 : :
74 : : struct supergraph_traits
75 : : {
76 : : typedef supernode node_t;
77 : : typedef superedge edge_t;
78 : : typedef supergraph graph_t;
79 : : struct dump_args_t
80 : : {
81 : 12 : dump_args_t (enum supergraph_dot_flags flags,
82 : : const dot_annotator *node_annotator)
83 : 12 : : m_flags (flags),
84 : 12 : m_node_annotator (node_annotator)
85 : : {}
86 : :
87 : : enum supergraph_dot_flags m_flags;
88 : : const dot_annotator *m_node_annotator;
89 : : };
90 : : typedef supercluster cluster_t;
91 : : };
92 : :
93 : : /* A class to manage the setting and restoring of statement uids. */
94 : :
95 : 6626 : class saved_uids
96 : : {
97 : : public:
98 : : void make_uid_unique (gimple *stmt);
99 : : void restore_uids () const;
100 : :
101 : : private:
102 : : auto_vec<std::pair<gimple *, unsigned> > m_old_stmt_uids;
103 : : };
104 : :
105 : : /* A "supergraph" is a directed graph formed by joining together all CFGs,
106 : : linking them via interprocedural call and return edges.
107 : :
108 : : Basic blocks are split at callsites, so that a call statement occurs
109 : : twice: once at the end of a supernode, and a second instance at the
110 : : start of the next supernode (to handle the return). */
111 : :
112 : : class supergraph : public digraph<supergraph_traits>
113 : : {
114 : : public:
115 : : supergraph (logger *logger);
116 : : ~supergraph ();
117 : :
118 : 10088 : supernode *get_node_for_function_entry (const function &fun) const
119 : : {
120 : 20176 : return get_node_for_block (ENTRY_BLOCK_PTR_FOR_FN (&fun));
121 : : }
122 : :
123 : 150 : supernode *get_node_for_function_exit (const function &fun) const
124 : : {
125 : 300 : return get_node_for_block (EXIT_BLOCK_PTR_FOR_FN (&fun));
126 : : }
127 : :
128 : 10238 : supernode *get_node_for_block (basic_block bb) const
129 : : {
130 : 10238 : return *const_cast <bb_to_node_t &> (m_bb_to_initial_node).get (bb);
131 : : }
132 : :
133 : : /* Get the supernode containing the second half of the gcall &
134 : : at an interprocedural call, within the caller. */
135 : : supernode *get_caller_next_node (cgraph_edge *edge) const
136 : : {
137 : : return (*const_cast <cgraph_edge_to_node_t &>
138 : : (m_cgraph_edge_to_caller_next_node).get (edge));
139 : : }
140 : :
141 : : call_superedge *get_edge_for_call (cgraph_edge *edge) const
142 : : {
143 : : return (*const_cast <cgraph_edge_to_call_superedge_t &>
144 : : (m_cgraph_edge_to_call_superedge).get (edge));
145 : : }
146 : :
147 : 6690 : return_superedge *get_edge_for_return (cgraph_edge *edge) const
148 : : {
149 : 6690 : return (*const_cast <cgraph_edge_to_return_superedge_t &>
150 : 13380 : (m_cgraph_edge_to_return_superedge).get (edge));
151 : : }
152 : :
153 : 5022 : superedge *get_intraprocedural_edge_for_call (cgraph_edge *edge) const
154 : : {
155 : 5022 : return (*const_cast <cgraph_edge_to_intraproc_superedge_t &>
156 : 5022 : (m_cgraph_edge_to_intraproc_superedge).get (edge));
157 : : }
158 : :
159 : 10430 : cfg_superedge *get_edge_for_cfg_edge (edge e) const
160 : : {
161 : 10430 : return (*const_cast <cfg_edge_to_cfg_superedge_t &>
162 : 10430 : (m_cfg_edge_to_cfg_superedge).get (e));
163 : : }
164 : :
165 : 498560 : supernode *get_supernode_for_stmt (const gimple *stmt) const
166 : : {
167 : 498560 : return (*const_cast <stmt_to_node_t &>(m_stmt_to_node_t).get
168 : 498560 : (const_cast <gimple *> (stmt)));
169 : : }
170 : :
171 : : void dump_dot_to_pp (pretty_printer *pp, const dump_args_t &) const;
172 : : void dump_dot_to_file (FILE *fp, const dump_args_t &) const;
173 : : void dump_dot (const char *path, const dump_args_t &) const;
174 : :
175 : : std::unique_ptr<json::object> to_json () const;
176 : :
177 : 1117789 : int num_nodes () const { return m_nodes.length (); }
178 : : int num_edges () const { return m_edges.length (); }
179 : :
180 : 61747 : supernode *get_node_by_index (int idx) const
181 : : {
182 : 61747 : return m_nodes[idx];
183 : : }
184 : :
185 : 8365 : unsigned get_num_snodes (const function *fun) const
186 : : {
187 : 8365 : function_to_num_snodes_t &map
188 : : = const_cast <function_to_num_snodes_t &>(m_function_to_num_snodes);
189 : 8365 : return *map.get (fun);
190 : : }
191 : :
192 : : private:
193 : : supernode *add_node (function *fun, basic_block bb, gcall *returning_call,
194 : : gimple_seq phi_nodes);
195 : : cfg_superedge *add_cfg_edge (supernode *src, supernode *dest, ::edge e);
196 : : call_superedge *add_call_superedge (supernode *src, supernode *dest,
197 : : cgraph_edge *cedge);
198 : : return_superedge *add_return_superedge (supernode *src, supernode *dest,
199 : : cgraph_edge *cedge);
200 : :
201 : : /* Data. */
202 : :
203 : : typedef ordered_hash_map<basic_block, supernode *> bb_to_node_t;
204 : : bb_to_node_t m_bb_to_initial_node;
205 : : bb_to_node_t m_bb_to_final_node;
206 : :
207 : : typedef ordered_hash_map<cgraph_edge *, supernode *> cgraph_edge_to_node_t;
208 : : cgraph_edge_to_node_t m_cgraph_edge_to_caller_prev_node;
209 : : cgraph_edge_to_node_t m_cgraph_edge_to_caller_next_node;
210 : :
211 : : typedef ordered_hash_map< ::edge, cfg_superedge *>
212 : : cfg_edge_to_cfg_superedge_t;
213 : : cfg_edge_to_cfg_superedge_t m_cfg_edge_to_cfg_superedge;
214 : :
215 : : typedef ordered_hash_map<cgraph_edge *, call_superedge *>
216 : : cgraph_edge_to_call_superedge_t;
217 : : cgraph_edge_to_call_superedge_t m_cgraph_edge_to_call_superedge;
218 : :
219 : : typedef ordered_hash_map<cgraph_edge *, return_superedge *>
220 : : cgraph_edge_to_return_superedge_t;
221 : : cgraph_edge_to_return_superedge_t m_cgraph_edge_to_return_superedge;
222 : :
223 : : typedef ordered_hash_map<cgraph_edge *, superedge *>
224 : : cgraph_edge_to_intraproc_superedge_t;
225 : : cgraph_edge_to_intraproc_superedge_t m_cgraph_edge_to_intraproc_superedge;
226 : :
227 : : typedef ordered_hash_map<gimple *, supernode *> stmt_to_node_t;
228 : : stmt_to_node_t m_stmt_to_node_t;
229 : :
230 : : typedef hash_map<const function *, unsigned> function_to_num_snodes_t;
231 : : function_to_num_snodes_t m_function_to_num_snodes;
232 : :
233 : : saved_uids m_stmt_uids;
234 : : };
235 : :
236 : : /* A node within a supergraph. */
237 : :
238 : : class supernode : public dnode<supergraph_traits>
239 : : {
240 : : public:
241 : 61734 : supernode (function *fun, basic_block bb, gcall *returning_call,
242 : : gimple_seq phi_nodes, int index)
243 : 61734 : : m_fun (fun), m_bb (bb), m_returning_call (returning_call),
244 : 61734 : m_phi_nodes (phi_nodes), m_index (index)
245 : : {}
246 : :
247 : 2337445 : function *get_function () const { return m_fun; }
248 : :
249 : 175298 : bool entry_p () const
250 : : {
251 : 175298 : return m_bb == ENTRY_BLOCK_PTR_FOR_FN (m_fun);
252 : : }
253 : :
254 : 135541 : bool return_p () const
255 : : {
256 : 135541 : return m_bb == EXIT_BLOCK_PTR_FOR_FN (m_fun);
257 : : }
258 : :
259 : : void dump_dot (graphviz_out *gv, const dump_args_t &args) const override;
260 : : void dump_dot_id (pretty_printer *pp) const;
261 : :
262 : : std::unique_ptr<json::object> to_json () const;
263 : :
264 : : location_t get_start_location () const;
265 : : location_t get_end_location () const;
266 : :
267 : : /* Returns iterator at the start of the list of phi nodes, if any. */
268 : 256710 : gphi_iterator start_phis ()
269 : : {
270 : 256710 : gimple_seq *pseq = &m_phi_nodes;
271 : :
272 : : /* Adapted from gsi_start_1. */
273 : 256710 : gphi_iterator i;
274 : :
275 : 256710 : i.ptr = gimple_seq_first (*pseq);
276 : 256710 : i.seq = pseq;
277 : 256710 : i.bb = i.ptr ? gimple_bb (i.ptr) : NULL;
278 : :
279 : 256710 : return i;
280 : : }
281 : :
282 : 67 : gcall *get_returning_call () const
283 : : {
284 : 67 : return m_returning_call;
285 : : }
286 : :
287 : 493803 : gimple *get_last_stmt () const
288 : : {
289 : 493803 : if (m_stmts.length () == 0)
290 : : return NULL;
291 : 384311 : return m_stmts[m_stmts.length () - 1];
292 : : }
293 : :
294 : 1403 : gcall *get_final_call () const
295 : : {
296 : 1403 : gimple *stmt = get_last_stmt ();
297 : 1403 : if (stmt == NULL)
298 : : return NULL;
299 : 1403 : return dyn_cast<gcall *> (stmt);
300 : : }
301 : :
302 : : unsigned int get_stmt_index (const gimple *stmt) const;
303 : :
304 : : tree get_label () const;
305 : :
306 : : function * const m_fun; // alternatively could be stored as runs of indices within the supergraph
307 : : const basic_block m_bb;
308 : : gcall * const m_returning_call; // for handling the result of a returned call
309 : : gimple_seq m_phi_nodes; // ptr to that of the underlying BB, for the first supernode for the BB
310 : : auto_vec<gimple *> m_stmts;
311 : : const int m_index; /* unique within the supergraph as a whole. */
312 : : };
313 : :
314 : : /* An abstract base class encapsulating an edge within a supergraph.
315 : : Edges can be CFG edges, or calls/returns for callgraph edges. */
316 : :
317 : : class superedge : public dedge<supergraph_traits>
318 : : {
319 : : public:
320 : : virtual ~superedge () {}
321 : :
322 : : void dump (pretty_printer *pp) const;
323 : : void dump () const;
324 : : void dump_dot (graphviz_out *gv, const dump_args_t &args)
325 : : const final override;
326 : :
327 : : virtual void dump_label_to_pp (pretty_printer *pp,
328 : : bool user_facing) const = 0;
329 : :
330 : : std::unique_ptr<json::object> to_json () const;
331 : :
332 : 754893 : enum edge_kind get_kind () const { return m_kind; }
333 : :
334 : 34976 : virtual cfg_superedge *dyn_cast_cfg_superedge () { return NULL; }
335 : 15332 : virtual const cfg_superedge *dyn_cast_cfg_superedge () const { return NULL; }
336 : 129 : virtual const switch_cfg_superedge *dyn_cast_switch_cfg_superedge () const { return NULL; }
337 : 0 : virtual const eh_dispatch_cfg_superedge *dyn_cast_eh_dispatch_cfg_superedge () const { return nullptr; }
338 : 10782 : virtual const eh_dispatch_try_cfg_superedge *dyn_cast_eh_dispatch_try_cfg_superedge () const { return nullptr; }
339 : 0 : virtual const eh_dispatch_allowed_cfg_superedge *dyn_cast_eh_dispatch_allowed_cfg_superedge () const { return nullptr; }
340 : 0 : virtual callgraph_superedge *dyn_cast_callgraph_superedge () { return NULL; }
341 : 0 : virtual const callgraph_superedge *dyn_cast_callgraph_superedge () const { return NULL; }
342 : 80 : virtual call_superedge *dyn_cast_call_superedge () { return NULL; }
343 : 0 : virtual const call_superedge *dyn_cast_call_superedge () const { return NULL; }
344 : 0 : virtual return_superedge *dyn_cast_return_superedge () { return NULL; }
345 : 0 : virtual const return_superedge *dyn_cast_return_superedge () const { return NULL; }
346 : :
347 : : ::edge get_any_cfg_edge () const;
348 : : cgraph_edge *get_any_callgraph_edge () const;
349 : :
350 : : label_text get_description (bool user_facing) const;
351 : :
352 : : protected:
353 : 69809 : superedge (supernode *src, supernode *dest, enum edge_kind kind)
354 : 69809 : : dedge<supergraph_traits> (src, dest),
355 : 69809 : m_kind (kind)
356 : : {}
357 : :
358 : : public:
359 : : const enum edge_kind m_kind;
360 : : };
361 : :
362 : : /* An ID representing an expression at a callsite:
363 : : either a parameter index, or the return value (or unknown). */
364 : :
365 : : class callsite_expr
366 : : {
367 : : public:
368 : 1697 : callsite_expr () : m_val (-1) {}
369 : :
370 : 280 : static callsite_expr from_zero_based_param (int idx)
371 : : {
372 : 280 : return callsite_expr (idx + 1);
373 : : }
374 : :
375 : 69 : static callsite_expr from_return_value ()
376 : : {
377 : 69 : return callsite_expr (0);
378 : : }
379 : :
380 : 230 : bool param_p () const
381 : : {
382 : 230 : return m_val > 0;
383 : : }
384 : :
385 : 166 : bool return_value_p () const
386 : : {
387 : 166 : return m_val == 0;
388 : : }
389 : :
390 : : private:
391 : 349 : callsite_expr (int val) : m_val (val) {}
392 : :
393 : : int m_val; /* 1-based parm, 0 for return value, or -1 for "unknown". */
394 : : };
395 : :
396 : : /* A subclass of superedge with an associated callgraph edge (either a
397 : : call or a return). */
398 : :
399 : : class callgraph_superedge : public superedge
400 : : {
401 : : public:
402 : 11539 : callgraph_superedge (supernode *src, supernode *dst, enum edge_kind kind,
403 : : cgraph_edge *cedge)
404 : 11539 : : superedge (src, dst, kind),
405 : 4343 : m_cedge (cedge)
406 : : {}
407 : :
408 : : void dump_label_to_pp (pretty_printer *pp, bool user_facing) const
409 : : final override;
410 : :
411 : 0 : callgraph_superedge *dyn_cast_callgraph_superedge () final override
412 : : {
413 : 0 : return this;
414 : : }
415 : 10669 : const callgraph_superedge *dyn_cast_callgraph_superedge () const
416 : : final override
417 : : {
418 : 10669 : return this;
419 : : }
420 : :
421 : : function *get_callee_function () const;
422 : : function *get_caller_function () const;
423 : : tree get_callee_decl () const;
424 : : tree get_caller_decl () const;
425 : : const gcall &get_call_stmt () const;
426 : : tree get_arg_for_parm (tree parm, callsite_expr *out) const;
427 : : tree get_parm_for_arg (tree arg, callsite_expr *out) const;
428 : : tree map_expr_from_caller_to_callee (tree caller_expr,
429 : : callsite_expr *out) const;
430 : : tree map_expr_from_callee_to_caller (tree callee_expr,
431 : : callsite_expr *out) const;
432 : :
433 : : cgraph_edge *const m_cedge;
434 : : };
435 : :
436 : : } // namespace ana
437 : :
438 : : template <>
439 : : template <>
440 : : inline bool
441 : 9023 : is_a_helper <const callgraph_superedge *>::test (const superedge *sedge)
442 : : {
443 : 9023 : return (sedge->get_kind () == SUPEREDGE_INTRAPROCEDURAL_CALL
444 : 0 : || sedge->get_kind () == SUPEREDGE_CALL
445 : 9023 : || sedge->get_kind () == SUPEREDGE_RETURN);
446 : : }
447 : :
448 : : namespace ana {
449 : :
450 : : /* A subclass of superedge representing an interprocedural call. */
451 : :
452 : : class call_superedge : public callgraph_superedge
453 : : {
454 : : public:
455 : 3598 : call_superedge (supernode *src, supernode *dst, cgraph_edge *cedge)
456 : 3598 : : callgraph_superedge (src, dst, SUPEREDGE_CALL, cedge)
457 : : {}
458 : :
459 : 4 : call_superedge *dyn_cast_call_superedge () final override
460 : : {
461 : 4 : return this;
462 : : }
463 : 0 : const call_superedge *dyn_cast_call_superedge () const final override
464 : : {
465 : 0 : return this;
466 : : }
467 : :
468 : 6690 : return_superedge *get_edge_for_return (const supergraph &sg) const
469 : : {
470 : 6690 : return sg.get_edge_for_return (m_cedge);
471 : : }
472 : : };
473 : :
474 : : } // namespace ana
475 : :
476 : : template <>
477 : : template <>
478 : : inline bool
479 : 17704 : is_a_helper <const call_superedge *>::test (const superedge *sedge)
480 : : {
481 : 17704 : return sedge->get_kind () == SUPEREDGE_CALL;
482 : : }
483 : :
484 : : namespace ana {
485 : :
486 : : /* A subclass of superedge represesnting an interprocedural return. */
487 : :
488 : : class return_superedge : public callgraph_superedge
489 : : {
490 : : public:
491 : 3598 : return_superedge (supernode *src, supernode *dst, cgraph_edge *cedge)
492 : 3598 : : callgraph_superedge (src, dst, SUPEREDGE_RETURN, cedge)
493 : : {}
494 : :
495 : 0 : return_superedge *dyn_cast_return_superedge () final override { return this; }
496 : 0 : const return_superedge *dyn_cast_return_superedge () const final override
497 : : {
498 : 0 : return this;
499 : : }
500 : :
501 : : call_superedge *get_edge_for_call (const supergraph &sg) const
502 : : {
503 : : return sg.get_edge_for_call (m_cedge);
504 : : }
505 : : };
506 : :
507 : : } // namespace ana
508 : :
509 : : template <>
510 : : template <>
511 : : inline bool
512 : 8431 : is_a_helper <const return_superedge *>::test (const superedge *sedge)
513 : : {
514 : 8431 : return sedge->get_kind () == SUPEREDGE_RETURN;
515 : : }
516 : :
517 : : namespace ana {
518 : :
519 : : /* A subclass of superedge that corresponds to a CFG edge. */
520 : :
521 : : class cfg_superedge : public superedge
522 : : {
523 : : public:
524 : 58270 : cfg_superedge (supernode *src, supernode *dst, ::edge e)
525 : 58270 : : superedge (src, dst, SUPEREDGE_CFG_EDGE),
526 : 3223 : m_cfg_edge (e)
527 : : {}
528 : :
529 : : void dump_label_to_pp (pretty_printer *pp, bool user_facing) const override;
530 : 115735 : cfg_superedge *dyn_cast_cfg_superedge () final override { return this; }
531 : 333234 : const cfg_superedge *dyn_cast_cfg_superedge () const final override { return this; }
532 : :
533 : 71847 : ::edge get_cfg_edge () const { return m_cfg_edge; }
534 : 344162 : int get_flags () const { return m_cfg_edge->flags; }
535 : 23573 : int true_value_p () const { return get_flags () & EDGE_TRUE_VALUE; }
536 : 22611 : int false_value_p () const { return get_flags () & EDGE_FALSE_VALUE; }
537 : 106709 : int back_edge_p () const { return get_flags () & EDGE_DFS_BACK; }
538 : :
539 : : size_t get_phi_arg_idx () const;
540 : : tree get_phi_arg (const gphi *phi) const;
541 : :
542 : 478 : location_t get_goto_locus () const { return m_cfg_edge->goto_locus; }
543 : :
544 : : private:
545 : : const ::edge m_cfg_edge;
546 : : };
547 : :
548 : : } // namespace ana
549 : :
550 : : template <>
551 : : template <>
552 : : inline bool
553 : 177004 : is_a_helper <const cfg_superedge *>::test (const superedge *sedge)
554 : : {
555 : 177004 : return sedge->get_kind () == SUPEREDGE_CFG_EDGE;
556 : : }
557 : :
558 : : namespace ana {
559 : :
560 : : /* A subclass for edges from switch statements, retaining enough
561 : : information to identify the pertinent cases, and for adding labels
562 : : when rendering via graphviz. */
563 : :
564 : : class switch_cfg_superedge : public cfg_superedge {
565 : : public:
566 : : switch_cfg_superedge (supernode *src, supernode *dst, ::edge e);
567 : :
568 : 7914 : const switch_cfg_superedge *dyn_cast_switch_cfg_superedge () const
569 : : final override
570 : : {
571 : 7914 : return this;
572 : : }
573 : :
574 : : void dump_label_to_pp (pretty_printer *pp, bool user_facing) const
575 : : final override;
576 : :
577 : 3031 : gswitch *get_switch_stmt () const
578 : : {
579 : 3031 : return as_a <gswitch *> (m_src->get_last_stmt ());
580 : : }
581 : :
582 : 2974 : const vec<tree> &get_case_labels () const { return m_case_labels; }
583 : :
584 : : bool implicitly_created_default_p () const;
585 : :
586 : : private:
587 : : auto_vec<tree> m_case_labels;
588 : : };
589 : :
590 : : } // namespace ana
591 : :
592 : : template <>
593 : : template <>
594 : : inline bool
595 : 7907 : is_a_helper <const switch_cfg_superedge *>::test (const superedge *sedge)
596 : : {
597 : 7907 : return sedge->dyn_cast_switch_cfg_superedge () != NULL;
598 : : }
599 : :
600 : : namespace ana {
601 : :
602 : : /* A subclass for edges from eh_dispatch statements, retaining enough
603 : : information to identify the various types being caught, vs the
604 : : "unhandled type" case, and for adding labels when rendering
605 : : via graphviz.
606 : : This is abstract; there are concrete subclasses based on the type
607 : : of the eh_region. */
608 : :
609 : : class eh_dispatch_cfg_superedge : public cfg_superedge
610 : : {
611 : : public:
612 : : static std::unique_ptr<eh_dispatch_cfg_superedge>
613 : : make (supernode *src,
614 : : supernode *dest,
615 : : ::edge e,
616 : : const geh_dispatch *eh_dispatch_stmt);
617 : :
618 : 355 : const eh_dispatch_cfg_superedge *dyn_cast_eh_dispatch_cfg_superedge () const
619 : : final override
620 : : {
621 : 355 : return this;
622 : : }
623 : :
624 : : const geh_dispatch *
625 : : get_eh_dispatch_stmt () const
626 : : {
627 : : return m_eh_dispatch_stmt;
628 : : }
629 : :
630 : : const eh_status &get_eh_status () const;
631 : 13 : eh_region get_eh_region () const { return m_eh_region; }
632 : :
633 : : virtual bool
634 : : apply_constraints (region_model *model,
635 : : region_model_context *ctxt,
636 : : tree exception_type,
637 : : std::unique_ptr<rejected_constraint> *out) const = 0;
638 : :
639 : : protected:
640 : : eh_dispatch_cfg_superedge (supernode *src, supernode *dst, ::edge e,
641 : : const geh_dispatch *eh_dispatch_stmt,
642 : : eh_region eh_reg);
643 : :
644 : : private:
645 : : const geh_dispatch *m_eh_dispatch_stmt;
646 : : eh_region m_eh_region;
647 : : };
648 : :
649 : : } // namespace ana
650 : :
651 : : template <>
652 : : template <>
653 : : inline bool
654 : 355 : is_a_helper <const eh_dispatch_cfg_superedge *>::test (const superedge *sedge)
655 : : {
656 : 355 : return sedge->dyn_cast_eh_dispatch_cfg_superedge () != NULL;
657 : : }
658 : :
659 : : namespace ana {
660 : :
661 : : /* A concrete subclass for edges from an eh_dispatch statements
662 : : for ERT_TRY regions. */
663 : :
664 : : class eh_dispatch_try_cfg_superedge : public eh_dispatch_cfg_superedge
665 : : {
666 : : public:
667 : 180 : eh_dispatch_try_cfg_superedge (supernode *src, supernode *dst, ::edge e,
668 : : const geh_dispatch *eh_dispatch_stmt,
669 : : eh_region eh_reg,
670 : : eh_catch ehc)
671 : 180 : : eh_dispatch_cfg_superedge (src, dst, e, eh_dispatch_stmt, eh_reg),
672 : 180 : m_eh_catch (ehc)
673 : : {
674 : 180 : gcc_assert (eh_reg->type == ERT_TRY);
675 : 180 : }
676 : :
677 : : const eh_dispatch_try_cfg_superedge *
678 : 210 : dyn_cast_eh_dispatch_try_cfg_superedge () const final override
679 : : {
680 : 210 : return this;
681 : : }
682 : :
683 : : void dump_label_to_pp (pretty_printer *pp,
684 : : bool user_facing) const final override;
685 : :
686 : 387 : eh_catch get_eh_catch () const { return m_eh_catch; }
687 : :
688 : : bool
689 : : apply_constraints (region_model *model,
690 : : region_model_context *ctxt,
691 : : tree exception_type,
692 : : std::unique_ptr<rejected_constraint> *out)
693 : : const final override;
694 : :
695 : : private:
696 : : eh_catch m_eh_catch;
697 : : };
698 : :
699 : : } // namespace ana
700 : :
701 : : template <>
702 : : template <>
703 : : inline bool
704 : 144 : is_a_helper <const eh_dispatch_try_cfg_superedge *>::test (const superedge *sedge)
705 : : {
706 : 144 : return sedge->dyn_cast_eh_dispatch_try_cfg_superedge () != NULL;
707 : : }
708 : :
709 : : namespace ana {
710 : :
711 : : /* A concrete subclass for edges from an eh_dispatch statements
712 : : for ERT_ALLOWED_EXCEPTIONS regions. */
713 : :
714 : : class eh_dispatch_allowed_cfg_superedge : public eh_dispatch_cfg_superedge
715 : : {
716 : : public:
717 : : enum eh_kind
718 : : {
719 : : expected,
720 : : unexpected
721 : : };
722 : :
723 : : eh_dispatch_allowed_cfg_superedge (supernode *src, supernode *dst, ::edge e,
724 : : const geh_dispatch *eh_dispatch_stmt,
725 : : eh_region eh_reg);
726 : :
727 : : const eh_dispatch_allowed_cfg_superedge *
728 : 0 : dyn_cast_eh_dispatch_allowed_cfg_superedge () const final override
729 : : {
730 : 0 : return this;
731 : : }
732 : :
733 : : void dump_label_to_pp (pretty_printer *pp,
734 : : bool user_facing) const final override;
735 : :
736 : : bool
737 : : apply_constraints (region_model *model,
738 : : region_model_context *ctxt,
739 : : tree exception_type,
740 : : std::unique_ptr<rejected_constraint> *out)
741 : : const final override;
742 : :
743 : 13 : enum eh_kind get_eh_kind () const { return m_kind; }
744 : :
745 : : private:
746 : : enum eh_kind m_kind;
747 : : };
748 : :
749 : : } // namespace ana
750 : :
751 : : template <>
752 : : template <>
753 : : inline bool
754 : : is_a_helper <const eh_dispatch_allowed_cfg_superedge *>::test (const superedge *sedge)
755 : : {
756 : : return sedge->dyn_cast_eh_dispatch_allowed_cfg_superedge () != NULL;
757 : : }
758 : :
759 : : namespace ana {
760 : : /* Base class for adding additional content to the .dot output
761 : : for a supergraph. */
762 : :
763 : 8 : class dot_annotator
764 : : {
765 : : public:
766 : 8 : virtual ~dot_annotator () {}
767 : 0 : virtual bool add_node_annotations (graphviz_out *gv ATTRIBUTE_UNUSED,
768 : : const supernode &n ATTRIBUTE_UNUSED,
769 : : bool within_table ATTRIBUTE_UNUSED)
770 : : const
771 : : {
772 : 0 : return false;
773 : : }
774 : 0 : virtual void add_stmt_annotations (graphviz_out *gv ATTRIBUTE_UNUSED,
775 : : const gimple *stmt ATTRIBUTE_UNUSED,
776 : : bool within_row ATTRIBUTE_UNUSED)
777 : 0 : const {}
778 : 76 : virtual bool add_after_node_annotations (graphviz_out *gv ATTRIBUTE_UNUSED,
779 : : const supernode &n ATTRIBUTE_UNUSED)
780 : : const
781 : : {
782 : 76 : return false;
783 : : }
784 : : };
785 : :
786 : : extern cgraph_edge *supergraph_call_edge (function *fun, const gimple *stmt);
787 : : extern function *get_ultimate_function_for_cgraph_edge (cgraph_edge *edge);
788 : :
789 : : } // namespace ana
790 : :
791 : : #endif /* GCC_ANALYZER_SUPERGRAPH_H */
|