174 lines
4.9 KiB
C
174 lines
4.9 KiB
C
/* Representation of thunks inside symbol table.
|
|
Copyright (C) 2003-2023 Free Software Foundation, Inc.
|
|
Contributed by Jan Hubicka
|
|
|
|
This file is part of GCC.
|
|
|
|
GCC is free software; you can redistribute it and/or modify it under
|
|
the terms of the GNU General Public License as published by the Free
|
|
Software Foundation; either version 3, or (at your option) any later
|
|
version.
|
|
|
|
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with GCC; see the file COPYING3. If not see
|
|
<http://www.gnu.org/licenses/>. */
|
|
|
|
#ifndef GCC_SYMTAB_THUNKS_H
|
|
#define GCC_SYMTAB_THUNKS_H
|
|
|
|
/* This symbol annotation holds information about thunk.
|
|
|
|
Thunks are basically wrappers around methods which are introduced in case
|
|
of multiple inheritance in order to adjust the value of the "this" pointer
|
|
or of the returned value.
|
|
|
|
In the case of this-adjusting thunks, each back-end can override the
|
|
can_output_mi_thunk/output_mi_thunk target hooks to generate a minimal thunk
|
|
(with a tail call for instance) directly as assembly. For the default hook
|
|
or for the case where the can_output_mi_thunk hooks return false, the thunk
|
|
is gimplified and lowered using the regular machinery. */
|
|
|
|
struct GTY(()) thunk_info {
|
|
/* Constructor. */
|
|
thunk_info ()
|
|
: fixed_offset (0),
|
|
virtual_value (0),
|
|
indirect_offset (0),
|
|
alias (NULL),
|
|
this_adjusting (false),
|
|
virtual_offset_p (false)
|
|
{
|
|
}
|
|
/* Copy constructor. */
|
|
thunk_info (const thunk_info &t)
|
|
: fixed_offset (t.fixed_offset),
|
|
virtual_value (t.virtual_value),
|
|
indirect_offset (t.indirect_offset),
|
|
alias (t.alias),
|
|
this_adjusting (t.this_adjusting),
|
|
virtual_offset_p (t.virtual_offset_p)
|
|
{
|
|
}
|
|
|
|
/* Compare for equiality. */
|
|
bool
|
|
operator==(const thunk_info &other) const
|
|
{
|
|
return fixed_offset == other.fixed_offset
|
|
&& virtual_value == other.virtual_value
|
|
&& indirect_offset == other.indirect_offset
|
|
&& this_adjusting == other.this_adjusting
|
|
&& virtual_offset_p == other.virtual_offset_p;
|
|
}
|
|
bool
|
|
operator!=(const thunk_info &other) const
|
|
{
|
|
return !(*this == other);
|
|
}
|
|
/* Copy operator. */
|
|
thunk_info &
|
|
operator=(const thunk_info &other)
|
|
{
|
|
fixed_offset = other.fixed_offset;
|
|
virtual_value = other.virtual_value;
|
|
indirect_offset = other.indirect_offset;
|
|
alias = other.alias;
|
|
this_adjusting = other.this_adjusting;
|
|
virtual_offset_p = other.virtual_offset_p;
|
|
return *this;
|
|
}
|
|
|
|
/* Offset used to adjust "this". */
|
|
HOST_WIDE_INT fixed_offset;
|
|
|
|
/* Offset in the virtual table to get the offset to adjust "this". Valid iff
|
|
VIRTUAL_OFFSET_P is true. */
|
|
HOST_WIDE_INT virtual_value;
|
|
|
|
/* Offset from "this" to get the offset to adjust "this". Zero means: this
|
|
offset is to be ignored. */
|
|
HOST_WIDE_INT indirect_offset;
|
|
|
|
/* Thunk target, i.e. the method that this thunk wraps. Depending on the
|
|
TARGET_USE_LOCAL_THUNK_ALIAS_P macro, this may have to be a new alias. */
|
|
tree alias;
|
|
|
|
/* Nonzero for a "this" adjusting thunk and zero for a result adjusting
|
|
thunk. */
|
|
bool this_adjusting;
|
|
|
|
/* If true, this thunk is what we call a virtual thunk. In this case:
|
|
* for this-adjusting thunks, after the FIXED_OFFSET based adjustment is
|
|
done, add to the result the offset found in the vtable at:
|
|
vptr + VIRTUAL_VALUE
|
|
* for result-adjusting thunks, the FIXED_OFFSET adjustment is done after
|
|
the virtual one. */
|
|
bool virtual_offset_p;
|
|
|
|
|
|
|
|
/* Dump thunk_info. */
|
|
void dump (FILE *);
|
|
|
|
/* Stream out thunk_info. */
|
|
void stream_out (class lto_simple_output_block *);
|
|
|
|
/* Stream in trunk_info. */
|
|
void stream_in (class lto_input_block *);
|
|
|
|
hashval_t hash ();
|
|
|
|
|
|
|
|
/* Return thunk_info, if available. */
|
|
static thunk_info *get (cgraph_node *node);
|
|
|
|
/* Return thunk_info possibly creating new one. */
|
|
static thunk_info *get_create (cgraph_node *node);
|
|
|
|
/* Remove thunk_info. */
|
|
static void remove (cgraph_node *node);
|
|
|
|
/* Add unprocessed thunk. */
|
|
void register_early (cgraph_node *node);
|
|
|
|
/* Attach recorded thunks to cgraph_nodes. */
|
|
static void process_early_thunks ();
|
|
|
|
/* Release all thunk_infos. */
|
|
static void release (void);
|
|
};
|
|
|
|
bool expand_thunk (cgraph_node *, bool, bool);
|
|
|
|
/* Return thunk_info, if available. */
|
|
inline thunk_info *
|
|
thunk_info::get (cgraph_node *node)
|
|
{
|
|
if (!symtab->m_thunks)
|
|
return NULL;
|
|
return symtab->m_thunks->get (node);
|
|
}
|
|
|
|
/* Remove thunk_info association for NODE. */
|
|
inline void
|
|
thunk_info::remove (cgraph_node *node)
|
|
{
|
|
symtab->m_thunks->remove (node);
|
|
}
|
|
|
|
/* Free thunk info summaries. */
|
|
inline void
|
|
thunk_info::release ()
|
|
{
|
|
if (symtab->m_thunks)
|
|
ggc_delete (symtab->m_thunks);
|
|
symtab->m_thunks = NULL;
|
|
}
|
|
#endif /* GCC_SYMTAB_THUNKS_H */
|