FreeBSD/contrib/gcc/cp/method.c
/* Return a this or result adjusting thunk to FUNCTION.  THIS_ADJUSTING
   indicates whether it is a this or result adjusting thunk.
   FIXED_OFFSET and VIRTUAL_OFFSET indicate how to do the adjustment
   (see thunk_adjust).  VIRTUAL_OFFSET can be NULL, but FIXED_OFFSET
   never is.  VIRTUAL_OFFSET is the /index/ into the vtable for this
   adjusting thunks, we scale it to a byte offset. For covariant
   thunks VIRTUAL_OFFSET is the virtual binfo.  You must post process
   the returned thunk with finish_thunk.  */
Return a this or result adjusting thunk to FUNCTION.  THIS_ADJUSTING
indicates whether it is a this or result adjusting thunk.
FIXED_OFFSET and VIRTUAL_OFFSET indicate how to do the adjustment
.  VIRTUAL_OFFSET can be NULL, but FIXED_OFFSET
never is.  VIRTUAL_OFFSET is the /index/ into the vtable for this
adjusting thunks, we scale it to a byte offset. For covariant
thunks VIRTUAL_OFFSET is the virtual binfo.  You must post process
the returned thunk with finish_thunk.
Return a this or result adjusting thunk to FUNCTION . THIS_ADJUSTING indicates whether it is a this or result adjusting thunk . FIXED_OFFSET and VIRTUAL_OFFSET indicate how to do the adjustment . VIRTUAL_OFFSET can be NULL but FIXED_OFFSET never is . VIRTUAL_OFFSET is the / index / into the vtable for this adjusting thunks we scale it to a byte offset . For covariant thunks VIRTUAL_OFFSET is the virtual binfo . You must post process the returned thunk with finish_thunk .
tree
make_thunk (tree function, bool this_adjusting,
	    tree fixed_offset, tree virtual_offset)
{
  HOST_WIDE_INT d;
  tree thunk;
  gcc_assert (TREE_CODE (function) == FUNCTION_DECL);
  gcc_assert (!DECL_THIS_THUNK_P (function));
  gcc_assert (!DECL_RESULT_THUNK_P (function) || this_adjusting);
  if (this_adjusting && virtual_offset)
    virtual_offset
      = size_binop (MULT_EXPR,
		    virtual_offset,
		    convert (ssizetype,
			     TYPE_SIZE_UNIT (vtable_entry_type)));
  d = tree_low_cst (fixed_offset, 0);
  for (thunk = DECL_THUNKS (function); thunk; thunk = TREE_CHAIN (thunk))
    if (DECL_THIS_THUNK_P (thunk) == this_adjusting
	&& THUNK_FIXED_OFFSET (thunk) == d
	&& !virtual_offset == !THUNK_VIRTUAL_OFFSET (thunk)
	&& (!virtual_offset
	    || (this_adjusting
		? tree_int_cst_equal (THUNK_VIRTUAL_OFFSET (thunk),
				      virtual_offset)
		: THUNK_VIRTUAL_OFFSET (thunk) == virtual_offset)))
      return thunk;
  gcc_assert (!TREE_ASM_WRITTEN (function));
  gcc_assert (TYPE_SIZE (DECL_CONTEXT (function))
	      && TYPE_BEING_DEFINED (DECL_CONTEXT (function)));
  thunk = build_decl (FUNCTION_DECL, NULL_TREE, TREE_TYPE (function));
  DECL_LANG_SPECIFIC (thunk) = DECL_LANG_SPECIFIC (function);
  cxx_dup_lang_specific_decl (thunk);
  DECL_THUNKS (thunk) = NULL_TREE;
  DECL_CONTEXT (thunk) = DECL_CONTEXT (function);
  TREE_READONLY (thunk) = TREE_READONLY (function);
  TREE_THIS_VOLATILE (thunk) = TREE_THIS_VOLATILE (function);
  TREE_PUBLIC (thunk) = TREE_PUBLIC (function);
  SET_DECL_THUNK_P (thunk, this_adjusting);
  THUNK_TARGET (thunk) = function;
  THUNK_FIXED_OFFSET (thunk) = d;
  THUNK_VIRTUAL_OFFSET (thunk) = virtual_offset;
  THUNK_ALIAS (thunk) = NULL_TREE;
  DECL_INTERFACE_KNOWN (thunk) = 1;
  DECL_NOT_REALLY_EXTERN (thunk) = 1;
  DECL_SAVED_FUNCTION_DATA (thunk) = NULL;
  DECL_DESTRUCTOR_P (thunk) = 0;
  DECL_CONSTRUCTOR_P (thunk) = 0;
  DECL_EXTERNAL (thunk) = 1;
  DECL_ARTIFICIAL (thunk) = 1;
  DECL_NO_STATIC_CHAIN (thunk) = 1;
  DECL_PENDING_INLINE_P (thunk) = 0;
  DECL_INLINE (thunk) = 0;
  DECL_DECLARED_INLINE_P (thunk) = 0;
  DECL_DEFERRED_FN (thunk) = 0;
  DECL_USE_TEMPLATE (thunk) = 0;
  DECL_TEMPLATE_INFO (thunk) = NULL;
  TREE_CHAIN (thunk) = DECL_THUNKS (function);
  DECL_THUNKS (function) = thunk;
  return thunk;
}
tree make_thunk ( tree function , bool this_adjusting , tree fixed_offset , tree virtual_offset ) { HOST_WIDE_INT d ; tree thunk ; gcc_assert ( TREE_CODE ( function ) == FUNCTION_DECL ) ; gcc_assert ( ! DECL_THIS_THUNK_P ( function ) ) ; gcc_assert ( ! DECL_RESULT_THUNK_P ( function ) || this_adjusting ) ; if ( this_adjusting && virtual_offset ) virtual_offset = size_binop ( MULT_EXPR , virtual_offset , convert ( ssizetype , TYPE_SIZE_UNIT ( vtable_entry_type ) ) ) ; d = tree_low_cst ( fixed_offset , 0 ) ; for ( thunk = DECL_THUNKS ( function ) ; thunk ; thunk = TREE_CHAIN ( thunk ) ) if ( DECL_THIS_THUNK_P ( thunk ) == this_adjusting && THUNK_FIXED_OFFSET ( thunk ) == d && ! virtual_offset == ! THUNK_VIRTUAL_OFFSET ( thunk ) && ( ! virtual_offset || ( this_adjusting ? tree_int_cst_equal ( THUNK_VIRTUAL_OFFSET ( thunk ) , virtual_offset ) : THUNK_VIRTUAL_OFFSET ( thunk ) == virtual_offset ) ) ) return thunk ; gcc_assert ( ! TREE_ASM_WRITTEN ( function ) ) ; gcc_assert ( TYPE_SIZE ( DECL_CONTEXT ( function ) ) && TYPE_BEING_DEFINED ( DECL_CONTEXT ( function ) ) ) ; thunk = build_decl ( FUNCTION_DECL , NULL_TREE , TREE_TYPE ( function ) ) ; DECL_LANG_SPECIFIC ( thunk ) = DECL_LANG_SPECIFIC ( function ) ; cxx_dup_lang_specific_decl ( thunk ) ; DECL_THUNKS ( thunk ) = NULL_TREE ; DECL_CONTEXT ( thunk ) = DECL_CONTEXT ( function ) ; TREE_READONLY ( thunk ) = TREE_READONLY ( function ) ; TREE_THIS_VOLATILE ( thunk ) = TREE_THIS_VOLATILE ( function ) ; TREE_PUBLIC ( thunk ) = TREE_PUBLIC ( function ) ; SET_DECL_THUNK_P ( thunk , this_adjusting ) ; THUNK_TARGET ( thunk ) = function ; THUNK_FIXED_OFFSET ( thunk ) = d ; THUNK_VIRTUAL_OFFSET ( thunk ) = virtual_offset ; THUNK_ALIAS ( thunk ) = NULL_TREE ; DECL_INTERFACE_KNOWN ( thunk ) = 1 ; DECL_NOT_REALLY_EXTERN ( thunk ) = 1 ; DECL_SAVED_FUNCTION_DATA ( thunk ) = NULL ; DECL_DESTRUCTOR_P ( thunk ) = 0 ; DECL_CONSTRUCTOR_P ( thunk ) = 0 ; DECL_EXTERNAL ( thunk ) = 1 ; DECL_ARTIFICIAL ( thunk ) = 1 ; DECL_NO_STATIC_CHAIN ( thunk ) = 1 ; DECL_PENDING_INLINE_P ( thunk ) = 0 ; DECL_INLINE ( thunk ) = 0 ; DECL_DECLARED_INLINE_P ( thunk ) = 0 ; DECL_DEFERRED_FN ( thunk ) = 0 ; DECL_USE_TEMPLATE ( thunk ) = 0 ; DECL_TEMPLATE_INFO ( thunk ) = NULL ; TREE_CHAIN ( thunk ) = DECL_THUNKS ( function ) ; DECL_THUNKS ( function ) = thunk ; return thunk ; }
Return a this or result adjusting thunk to FUNCTION.
Return a this or result adjusting thunk to FUNCTION .
/* We can have this thunks to covariant thunks, but not vice versa.  */ /* Scale the VIRTUAL_OFFSET to be in terms of bytes.  */ /* See if we already have the thunk in question.  For this_adjusting
     thunks VIRTUAL_OFFSET will be an INTEGER_CST, for covariant thunks it
     will be a BINFO.  */ /* All thunks must be created before FUNCTION is actually emitted;
     the ABI requires that all thunks be emitted together with the
     function to which they transfer control.  */ /* Likewise, we can only be adding thunks to a function declared in
     the class currently being laid out.  */ /* The thunk itself is not a constructor or destructor, even if
     the thing it is thunking to is.  */ /* Even if this thunk is a member of a local class, we don't
     need a static chain.  */ /* The THUNK is not a pending inline, even if the FUNCTION is.  */ /* Nor has it been deferred.  */ /* Nor is it a template instantiation.  */ /* Add it to the list of thunks associated with FUNCTION.  */