1 /* Representation of thunks inside symbol table. 2 Copyright (C) 2003-2022 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 (symtab->m_thunks); 171 symtab->m_thunks = NULL; 172 } 173 #endif /* GCC_SYMTAB_THUNKS_H */ 174