1 | /* Representation of thunks inside symbol table. |
2 | Copyright (C) 2003-2023 Free Software Foundation, Inc. |
3 | Contributed by Jan Hubicka |
4 | |
5 | This file is part of GCC. |
6 | |
7 | GCC is free software; you can redistribute it and/or modify it under |
8 | the terms of the GNU General Public License as published by the Free |
9 | Software Foundation; either version 3, or (at your option) any later |
10 | version. |
11 | |
12 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY |
13 | WARRANTY; without even the implied warranty of MERCHANTABILITY or |
14 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
15 | 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_SYMTAB_THUNKS_H |
22 | #define GCC_SYMTAB_THUNKS_H |
23 | |
24 | /* This symbol annotation holds information about thunk. |
25 | |
26 | Thunks are basically wrappers around methods which are introduced in case |
27 | of multiple inheritance in order to adjust the value of the "this" pointer |
28 | or of the returned value. |
29 | |
30 | In the case of this-adjusting thunks, each back-end can override the |
31 | can_output_mi_thunk/output_mi_thunk target hooks to generate a minimal thunk |
32 | (with a tail call for instance) directly as assembly. For the default hook |
33 | or for the case where the can_output_mi_thunk hooks return false, the thunk |
34 | is gimplified and lowered using the regular machinery. */ |
35 | |
36 | struct GTY(()) thunk_info { |
37 | /* Constructor. */ |
38 | thunk_info () |
39 | : fixed_offset (0), |
40 | virtual_value (0), |
41 | indirect_offset (0), |
42 | alias (NULL), |
43 | this_adjusting (false), |
44 | virtual_offset_p (false) |
45 | { |
46 | } |
47 | /* Copy constructor. */ |
48 | thunk_info (const thunk_info &t) |
49 | : fixed_offset (t.fixed_offset), |
50 | virtual_value (t.virtual_value), |
51 | indirect_offset (t.indirect_offset), |
52 | alias (t.alias), |
53 | this_adjusting (t.this_adjusting), |
54 | virtual_offset_p (t.virtual_offset_p) |
55 | { |
56 | } |
57 | |
58 | /* Compare for equiality. */ |
59 | bool |
60 | operator==(const thunk_info &other) const |
61 | { |
62 | return fixed_offset == other.fixed_offset |
63 | && virtual_value == other.virtual_value |
64 | && indirect_offset == other.indirect_offset |
65 | && this_adjusting == other.this_adjusting |
66 | && virtual_offset_p == other.virtual_offset_p; |
67 | } |
68 | bool |
69 | operator!=(const thunk_info &other) const |
70 | { |
71 | return !(*this == other); |
72 | } |
73 | /* Copy operator. */ |
74 | thunk_info & |
75 | operator=(const thunk_info &other) |
76 | { |
77 | fixed_offset = other.fixed_offset; |
78 | virtual_value = other.virtual_value; |
79 | indirect_offset = other.indirect_offset; |
80 | alias = other.alias; |
81 | this_adjusting = other.this_adjusting; |
82 | virtual_offset_p = other.virtual_offset_p; |
83 | return *this; |
84 | } |
85 | |
86 | /* Offset used to adjust "this". */ |
87 | HOST_WIDE_INT fixed_offset; |
88 | |
89 | /* Offset in the virtual table to get the offset to adjust "this". Valid iff |
90 | VIRTUAL_OFFSET_P is true. */ |
91 | HOST_WIDE_INT virtual_value; |
92 | |
93 | /* Offset from "this" to get the offset to adjust "this". Zero means: this |
94 | offset is to be ignored. */ |
95 | HOST_WIDE_INT indirect_offset; |
96 | |
97 | /* Thunk target, i.e. the method that this thunk wraps. Depending on the |
98 | TARGET_USE_LOCAL_THUNK_ALIAS_P macro, this may have to be a new alias. */ |
99 | tree alias; |
100 | |
101 | /* Nonzero for a "this" adjusting thunk and zero for a result adjusting |
102 | thunk. */ |
103 | bool this_adjusting; |
104 | |
105 | /* If true, this thunk is what we call a virtual thunk. In this case: |
106 | * for this-adjusting thunks, after the FIXED_OFFSET based adjustment is |
107 | done, add to the result the offset found in the vtable at: |
108 | vptr + VIRTUAL_VALUE |
109 | * for result-adjusting thunks, the FIXED_OFFSET adjustment is done after |
110 | the virtual one. */ |
111 | bool virtual_offset_p; |
112 | |
113 | |
114 | |
115 | /* Dump thunk_info. */ |
116 | void dump (FILE *); |
117 | |
118 | /* Stream out thunk_info. */ |
119 | void stream_out (class lto_simple_output_block *); |
120 | |
121 | /* Stream in trunk_info. */ |
122 | void stream_in (class lto_input_block *); |
123 | |
124 | hashval_t hash (); |
125 | |
126 | |
127 | |
128 | /* Return thunk_info, if available. */ |
129 | static thunk_info *get (cgraph_node *node); |
130 | |
131 | /* Return thunk_info possibly creating new one. */ |
132 | static thunk_info *get_create (cgraph_node *node); |
133 | |
134 | /* Remove thunk_info. */ |
135 | static void remove (cgraph_node *node); |
136 | |
137 | /* Add unprocessed thunk. */ |
138 | void register_early (cgraph_node *node); |
139 | |
140 | /* Attach recorded thunks to cgraph_nodes. */ |
141 | static void process_early_thunks (); |
142 | |
143 | /* Release all thunk_infos. */ |
144 | static void release (void); |
145 | }; |
146 | |
147 | bool expand_thunk (cgraph_node *, bool, bool); |
148 | |
149 | /* Return thunk_info, if available. */ |
150 | inline thunk_info * |
151 | thunk_info::get (cgraph_node *node) |
152 | { |
153 | if (!symtab->m_thunks) |
154 | return NULL; |
155 | return symtab->m_thunks->get (node); |
156 | } |
157 | |
158 | /* Remove thunk_info association for NODE. */ |
159 | inline void |
160 | thunk_info::remove (cgraph_node *node) |
161 | { |
162 | symtab->m_thunks->remove (node); |
163 | } |
164 | |
165 | /* Free thunk info summaries. */ |
166 | inline void |
167 | thunk_info::release () |
168 | { |
169 | if (symtab->m_thunks) |
170 | ggc_delete (ptr: symtab->m_thunks); |
171 | symtab->m_thunks = NULL; |
172 | } |
173 | #endif /* GCC_SYMTAB_THUNKS_H */ |
174 | |