cp-tree.h (DELTA_FROM_VTABLE_ENTRY): Remove.
* cp-tree.h (DELTA_FROM_VTABLE_ENTRY): Remove. (SET_FNADDR_FROM_VTABLE_ENTRY): Likewise. (lang_decl_flags): Add vcall_offset. (THUNK_VCALL_OFFSET): Use it. * decl.c (lang_mark_tree): Don't mark DECL_ACCESS for a thunk. * method.c (make_thunk): Create the lang_decl here, not in emit_thunk. (emit_thunk): Make generic thunks into ordinary functions once they have been fed to expand_body. * semantics.c (expand_body): Set current_function_is_thunk here. From-SVN: r33699
This commit is contained in:
parent
9d4c21486c
commit
6462c441e1
|
@ -1,3 +1,16 @@
|
|||
2000-05-04 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
* cp-tree.h (DELTA_FROM_VTABLE_ENTRY): Remove.
|
||||
(SET_FNADDR_FROM_VTABLE_ENTRY): Likewise.
|
||||
(lang_decl_flags): Add vcall_offset.
|
||||
(THUNK_VCALL_OFFSET): Use it.
|
||||
* decl.c (lang_mark_tree): Don't mark DECL_ACCESS for a thunk.
|
||||
* method.c (make_thunk): Create the lang_decl here, not in
|
||||
emit_thunk.
|
||||
(emit_thunk): Make generic thunks into ordinary functions once
|
||||
they have been fed to expand_body.
|
||||
* semantics.c (expand_body): Set current_function_is_thunk here.
|
||||
|
||||
2000-05-04 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
|
||||
|
||||
* class.c (update_vtable_entry_for_fn): Prototype.
|
||||
|
|
|
@ -1294,13 +1294,6 @@ enum languages { lang_c, lang_cplusplus, lang_java };
|
|||
((CP_TYPE_QUALS (NODE) & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE)) \
|
||||
== TYPE_QUAL_CONST)
|
||||
|
||||
#define DELTA_FROM_VTABLE_ENTRY(ENTRY) \
|
||||
(!flag_vtable_thunks ? \
|
||||
TREE_VALUE (CONSTRUCTOR_ELTS (ENTRY)) \
|
||||
: !DECL_THUNK_P (TREE_OPERAND ((ENTRY), 0)) \
|
||||
? integer_zero_node \
|
||||
: build_int_2 (THUNK_DELTA (TREE_OPERAND ((ENTRY), 0)), 0))
|
||||
|
||||
/* Virtual function addresses can be gotten from a virtual function
|
||||
table entry using this macro. */
|
||||
#define FNADDR_FROM_VTABLE_ENTRY(ENTRY) \
|
||||
|
@ -1310,8 +1303,6 @@ enum languages { lang_c, lang_cplusplus, lang_java };
|
|||
? (ENTRY) \
|
||||
: DECL_INITIAL (TREE_OPERAND ((ENTRY), 0)))
|
||||
|
||||
#define SET_FNADDR_FROM_VTABLE_ENTRY(ENTRY,VALUE) \
|
||||
(TREE_VALUE (TREE_CHAIN (TREE_CHAIN (CONSTRUCTOR_ELTS (ENTRY)))) = (VALUE))
|
||||
#define FUNCTION_ARG_CHAIN(NODE) (TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (NODE))))
|
||||
#define PROMOTES_TO_AGGR_TYPE(NODE,CODE) \
|
||||
(((CODE) == TREE_CODE (NODE) \
|
||||
|
@ -1900,6 +1891,10 @@ struct lang_decl_flags
|
|||
/* In a namespace-scope FUNCTION_DECL, this is
|
||||
GLOBAL_INIT_PRIORITY. */
|
||||
int init_priority;
|
||||
|
||||
/* In a FUNCTION_DECL for which DECL_THUNK_P holds, this is
|
||||
THUNK_VCALL_OFFSET. */
|
||||
HOST_WIDE_INT vcall_offset;
|
||||
} u2;
|
||||
};
|
||||
|
||||
|
@ -3039,7 +3034,8 @@ extern int flag_new_for_scope;
|
|||
vtable for the `this' pointer to find the vcall offset. (The vptr
|
||||
is always located at offset zero from the f `this' pointer.) If
|
||||
zero, then there is no vcall offset. */
|
||||
#define THUNK_VCALL_OFFSET(DECL) (DECL_CHECK (DECL)->decl.u2.i)
|
||||
#define THUNK_VCALL_OFFSET(DECL) \
|
||||
(DECL_LANG_SPECIFIC (DECL)->decl_flags.u2.vcall_offset)
|
||||
|
||||
/* DECL_NEEDED_P holds of a declaration when we need to emit its
|
||||
definition. This is true when the back-end tells us that
|
||||
|
|
|
@ -14731,7 +14731,9 @@ lang_mark_tree (t)
|
|||
if (ld)
|
||||
{
|
||||
ggc_mark (ld);
|
||||
if (!DECL_GLOBAL_CTOR_P (t) && !DECL_GLOBAL_DTOR_P (t))
|
||||
if (!DECL_GLOBAL_CTOR_P (t)
|
||||
&& !DECL_GLOBAL_DTOR_P (t)
|
||||
&& !DECL_THUNK_P (t))
|
||||
ggc_mark_tree (ld->decl_flags.u2.access);
|
||||
ggc_mark_tree (ld->decl_flags.context);
|
||||
if (TREE_CODE (t) != NAMESPACE_DECL)
|
||||
|
|
|
@ -2055,6 +2055,9 @@ make_thunk (function, delta, vcall_index)
|
|||
if (thunk == NULL_TREE)
|
||||
{
|
||||
thunk = build_decl (FUNCTION_DECL, thunk_id, TREE_TYPE (func_decl));
|
||||
DECL_LANG_SPECIFIC (thunk) = DECL_LANG_SPECIFIC (func_decl);
|
||||
copy_lang_decl (func_decl);
|
||||
DECL_CONTEXT (thunk) = DECL_CONTEXT (func_decl);
|
||||
TREE_READONLY (thunk) = TREE_READONLY (func_decl);
|
||||
TREE_THIS_VOLATILE (thunk) = TREE_THIS_VOLATILE (func_decl);
|
||||
comdat_linkage (thunk);
|
||||
|
@ -2063,12 +2066,22 @@ make_thunk (function, delta, vcall_index)
|
|||
THUNK_DELTA (thunk) = delta;
|
||||
THUNK_VCALL_OFFSET (thunk)
|
||||
= vcall_index * int_size_in_bytes (vtable_entry_type);
|
||||
/* The thunk itself is not a constructor or destructor, even if
|
||||
the thing it is thunking to is. */
|
||||
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_CONTEXT (thunk) = DECL_CONTEXT (func_decl);
|
||||
/* Even if this thunk is a member of a local class, we don't
|
||||
need a static chain. */
|
||||
DECL_NO_STATIC_CHAIN (thunk) = 1;
|
||||
/* The THUNK is not a pending inline, even if the FUNC_DECL is. */
|
||||
DECL_PENDING_INLINE_P (thunk) = 0;
|
||||
/* Nor has it been deferred. */
|
||||
DECL_DEFERRED_FN (thunk) = 0;
|
||||
/* So that finish_file can write out any thunks that need to be: */
|
||||
pushdecl_top_level (thunk);
|
||||
}
|
||||
|
@ -2081,15 +2094,25 @@ void
|
|||
emit_thunk (thunk_fndecl)
|
||||
tree thunk_fndecl;
|
||||
{
|
||||
tree fnaddr = DECL_INITIAL (thunk_fndecl);
|
||||
tree function = TREE_OPERAND (fnaddr, 0);
|
||||
int delta = THUNK_DELTA (thunk_fndecl);
|
||||
int vcall_offset = THUNK_VCALL_OFFSET (thunk_fndecl);
|
||||
tree fnaddr;
|
||||
tree function;
|
||||
int delta;
|
||||
int vcall_offset;
|
||||
|
||||
if (TREE_ASM_WRITTEN (thunk_fndecl))
|
||||
return;
|
||||
|
||||
TREE_ASM_WRITTEN (thunk_fndecl) = 1;
|
||||
if (TREE_CODE (DECL_INITIAL (thunk_fndecl)) != ADDR_EXPR)
|
||||
/* We already turned this thunk into an ordinary function.
|
||||
There's no need to process this thunk again. (We can't just
|
||||
clear DECL_THUNK_P because that will confuse
|
||||
FNADDR_FROM_VTABLE_ENTRY and friends.) */
|
||||
return;
|
||||
|
||||
fnaddr = DECL_INITIAL (thunk_fndecl);
|
||||
function = TREE_OPERAND (fnaddr, 0);
|
||||
delta = THUNK_DELTA (thunk_fndecl);
|
||||
vcall_offset = THUNK_VCALL_OFFSET (thunk_fndecl);
|
||||
|
||||
TREE_ADDRESSABLE (function) = 1;
|
||||
mark_used (function);
|
||||
|
@ -2097,8 +2120,14 @@ emit_thunk (thunk_fndecl)
|
|||
if (current_function_decl)
|
||||
abort ();
|
||||
|
||||
if (flag_syntax_only)
|
||||
{
|
||||
TREE_ASM_WRITTEN (thunk_fndecl) = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef ASM_OUTPUT_MI_THUNK
|
||||
if (!flag_syntax_only && vcall_offset == 0)
|
||||
if (vcall_offset == 0)
|
||||
{
|
||||
const char *fnname;
|
||||
current_function_decl = thunk_fndecl;
|
||||
|
@ -2115,6 +2144,7 @@ emit_thunk (thunk_fndecl)
|
|||
assemble_end_function (thunk_fndecl, fnname);
|
||||
current_function_decl = 0;
|
||||
cfun = 0;
|
||||
TREE_ASM_WRITTEN (thunk_fndecl) = 1;
|
||||
}
|
||||
else
|
||||
#endif /* ASM_OUTPUT_MI_THUNK */
|
||||
|
@ -2141,21 +2171,10 @@ emit_thunk (thunk_fndecl)
|
|||
a = nreverse (t);
|
||||
DECL_ARGUMENTS (thunk_fndecl) = a;
|
||||
DECL_RESULT (thunk_fndecl) = NULL_TREE;
|
||||
DECL_LANG_SPECIFIC (thunk_fndecl) = DECL_LANG_SPECIFIC (function);
|
||||
copy_lang_decl (thunk_fndecl);
|
||||
DECL_INTERFACE_KNOWN (thunk_fndecl) = 1;
|
||||
DECL_NOT_REALLY_EXTERN (thunk_fndecl) = 1;
|
||||
DECL_SAVED_FUNCTION_DATA (thunk_fndecl) = NULL;
|
||||
|
||||
/* The thunk itself is not a constructor or destructor, even if
|
||||
the thing it is thunking to is. */
|
||||
DECL_DESTRUCTOR_P (thunk_fndecl) = 0;
|
||||
DECL_CONSTRUCTOR_P (thunk_fndecl) = 0;
|
||||
|
||||
push_to_top_level ();
|
||||
start_function (NULL_TREE, thunk_fndecl, NULL_TREE, SF_PRE_PARSED);
|
||||
store_parm_decls ();
|
||||
current_function_is_thunk = 1;
|
||||
|
||||
/* Adjust the this pointer by the constant. */
|
||||
t = ssize_int (delta);
|
||||
|
@ -2199,19 +2218,12 @@ emit_thunk (thunk_fndecl)
|
|||
finish_expr_stmt (t);
|
||||
|
||||
/* The back-end expects DECL_INITIAL to contain a BLOCK, so we
|
||||
clear this here. */
|
||||
DECL_INITIAL (thunk_fndecl) = NULL_TREE;
|
||||
create one. */
|
||||
DECL_INITIAL (thunk_fndecl) = make_node (BLOCK);
|
||||
BLOCK_VARS (DECL_INITIAL (thunk_fndecl))
|
||||
= DECL_ARGUMENTS (thunk_fndecl);
|
||||
expand_body (finish_function (0));
|
||||
/* Restore the DECL_INITIAL for the THUNK_DECL. */
|
||||
DECL_INITIAL (thunk_fndecl) = fnaddr;
|
||||
pop_from_top_level ();
|
||||
|
||||
/* Don't let the backend defer this function. */
|
||||
if (DECL_DEFER_OUTPUT (thunk_fndecl))
|
||||
output_inline_function (thunk_fndecl);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2775,6 +2775,7 @@ expand_body (fn)
|
|||
|
||||
start_function (NULL_TREE, fn, NULL_TREE, SF_PRE_PARSED | SF_EXPAND);
|
||||
store_parm_decls ();
|
||||
current_function_is_thunk = DECL_THUNK_P (fn);
|
||||
|
||||
/* We don't need to redeclare __FUNCTION__, __PRETTY_FUNCTION__, or
|
||||
any of the other magic variables we set up when starting a
|
||||
|
|
Loading…
Reference in New Issue