1 /* Iterator for walking a chain of inlining locations.
2 Copyright (C) 2022-2024 Free Software Foundation, Inc.
3 Contributed by David Malcolm <dmalcolm@redhat.com>.
5 This file is part of GCC.
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)
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.
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/>. */
21 #ifndef GCC_ANALYZER_INLINING_ITERATOR_H
22 #define GCC_ANALYZER_INLINING_ITERATOR_H
24 /* Iterator for walking a chain of inlining locations.
26 The fndecls and locations will be traversed from innermost to outermost.
29 inline void inner (void)
35 inner (); <-- CALLSITE
38 then the fndecl will be "inner" on the initial iteration, and "outer" on
39 the second (final) iteration.
41 Compare with lhd_print_error_function, cp_print_error_function,
42 and optrecord_json_writer::inlining_chain_to_json. */
44 class inlining_iterator
47 inlining_iterator (location_t loc
)
48 : m_abstract_origin (LOCATION_BLOCK (loc
)),
49 m_callsite (UNKNOWN_LOCATION
), m_fndecl (NULL
),
50 m_next_abstract_origin (NULL
)
55 bool done_p () const { return m_abstract_origin
== NULL
; }
59 m_abstract_origin
= m_next_abstract_origin
;
63 tree
get_fndecl () const { return m_fndecl
; }
64 location_t
get_callsite () const { return m_callsite
; }
65 tree
get_block () const { return m_abstract_origin
; }
68 void prepare_iteration ()
72 tree block
= m_abstract_origin
;
73 m_callsite
= BLOCK_SOURCE_LOCATION (block
);
75 block
= BLOCK_SUPERCONTEXT (block
);
76 while (block
&& TREE_CODE (block
) == BLOCK
77 && BLOCK_ABSTRACT_ORIGIN (block
))
79 tree ao
= BLOCK_ABSTRACT_ORIGIN (block
);
80 if (TREE_CODE (ao
) == FUNCTION_DECL
)
85 else if (TREE_CODE (ao
) != BLOCK
)
88 block
= BLOCK_SUPERCONTEXT (block
);
91 m_next_abstract_origin
= block
;
94 while (block
&& TREE_CODE (block
) == BLOCK
)
95 block
= BLOCK_SUPERCONTEXT (block
);
97 if (block
&& TREE_CODE (block
) == FUNCTION_DECL
)
99 m_next_abstract_origin
= NULL
;
103 tree m_abstract_origin
;
104 location_t m_callsite
;
106 tree m_next_abstract_origin
;
109 /* A class for fixing up fndecls and stack depths in checker_event, based
112 The early inliner runs before the analyzer, which can lead to confusing
115 Tne base fndecl and depth within a checker_event are from call strings
116 in program_points, which reflect the call strings after inlining.
117 This class lets us offset the depth and fix up the reported fndecl and
118 stack depth to better reflect the user's original code. */
123 inlining_info (location_t loc
)
125 inlining_iterator
iter (loc
);
126 m_inner_fndecl
= iter
.get_fndecl ();
128 while (!iter
.done_p ())
130 m_outer_fndecl
= iter
.get_fndecl ();
135 m_extra_frames
= num_frames
- 1;
140 tree
get_inner_fndecl () const { return m_inner_fndecl
; }
141 int get_extra_frames () const { return m_extra_frames
; }
149 #endif /* GCC_ANALYZER_INLINING_ITERATOR_H */