Commit 4e7512c9 by Mark Mitchell Committed by Mark Mitchell

cp-tree.def (THUNK_DECL): Add to documentation.

	* cp-tree.def (THUNK_DECL): Add to documentation.
	* cp-tree.h (flag_huge_objects): Declare.
	* class.c (modify_vtable_entry): Tidy.
	(update_vtable_entry_for_fn): Split out from dfs_modify_vtables.
	Calculate delta appropriately for the new ABI.
	(dfs_modify_vtables): Use it.
	(modify_all_vtables): Fix thinko in code to add overriding copies
	of functions to primary vtables.
	(build_clone): Fix typo in comment.
	(clone_function_decl): Correct order of destructors in vtable.
	(build_vbase_offset_vtbl_entries): Adjust comment.
	(dfs_vcall_offset_queue_p): Remove.
	(dfs_build_vcall_offset_vtbl_entries): Update BV_VCALL_INDEX.
	(build_vcall_offset_vtbl_entries): Juse use dfs_skip_vbases.
	(build_vtable_entry): Correct check for pure virtual functions.
	Don't declare flag_huge_objects.
	* decl.c (flag_huge_objects): Remove declaration.
	* method.c (make_thunk): Tweak mangling for vcall offset thunks.
	Use int_size_in_bytes.
	(emit_thunk): Handle vcall offset thunks.

From-SVN: r33185
parent 3268dc00
2000-04-15 Mark Mitchell <mark@codesourcery.com>
* cp-tree.def (THUNK_DECL): Add to documentation.
* cp-tree.h (flag_huge_objects): Declare.
* class.c (modify_vtable_entry): Tidy.
(update_vtable_entry_for_fn): Split out from dfs_modify_vtables.
Calculate delta appropriately for the new ABI.
(dfs_modify_vtables): Use it.
(modify_all_vtables): Fix thinko in code to add overriding copies
of functions to primary vtables.
(build_clone): Fix typo in comment.
(clone_function_decl): Correct order of destructors in vtable.
(build_vbase_offset_vtbl_entries): Adjust comment.
(dfs_vcall_offset_queue_p): Remove.
(dfs_build_vcall_offset_vtbl_entries): Update BV_VCALL_INDEX.
(build_vcall_offset_vtbl_entries): Juse use dfs_skip_vbases.
(build_vtable_entry): Correct check for pure virtual functions.
Don't declare flag_huge_objects.
* decl.c (flag_huge_objects): Remove declaration.
* method.c (make_thunk): Tweak mangling for vcall offset thunks.
Use int_size_in_bytes.
(emit_thunk): Handle vcall offset thunks.
Sat Apr 15 16:00:01 2000 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
* decl2.c (parse_time, varconst_time): Delete declarations.
......
......@@ -161,8 +161,10 @@ DEFTREECODE (TYPEOF_TYPE, "typeof_type", 't', 0)
/* A thunk is a stub function.
A THUNK_DECL is an alternate entry point for an ordinary
FUNCTION_DECL. It's job is to adjust the `this' poitner before
transferring control to the FUNCTION_DECL.
FUNCTION_DECL. The address of the ordinary FUNCTION_DECL is given
by the DECL_INITIAL, which is always an ADDR_EXPR whose operand is
a FUNCTION_DECL. The job of the thunk is to adjust the `this'
pointer before transferring control to the FUNCTION_DECL.
A thunk may perform either, or both, of the following operations:
......
......@@ -219,6 +219,11 @@ extern int flag_honor_std;
extern int flag_rtti;
/* Nonzero if we want to support huge (> 2^(sizeof(short)*8-1) bytes)
objects. */
extern int flag_huge_objects;
/* Nonzero if virtual base class offsets are stored in the virtual
function table. Zero if, instead, a pointer to the virtual base is
stored in the object itself. */
......@@ -1767,7 +1772,7 @@ struct lang_type
struct A {};
struct B : public A { };
struct C : virtual public B { void f(); };
struct C : virtual public B { void f(); int i; };
`A' is the primary base class for `B'. But, `B' is not a primary
base class for `C'. So, in the copy of `A' that appears in the
......
......@@ -336,10 +336,6 @@ extern int flag_no_builtin;
extern int flag_no_nonansi_builtin;
/* Nonzero if we want to support huge (> 2^(sizeof(short)*8-1) bytes)
objects. */
extern int flag_huge_objects;
/* Nonzero if we want to conserve space in the .o files. We do this
by putting uninitialized data and runtime initialized data into
.common instead of .data at the expense of not flagging multiple
......
......@@ -2036,12 +2036,12 @@ make_thunk (function, delta, vcall_index)
else
icat (-delta);
OB_PUTC ('_');
OB_PUTID (DECL_ASSEMBLER_NAME (func_decl));
if (vcall_index)
{
OB_PUTC ('_');
icat (vcall_index);
OB_PUTC ('_');
}
OB_PUTID (DECL_ASSEMBLER_NAME (func_decl));
OB_FINISH ();
thunk_id = get_identifier (obstack_base (&scratch_obstack));
......@@ -2062,7 +2062,7 @@ make_thunk (function, delta, vcall_index)
DECL_INITIAL (thunk) = function;
THUNK_DELTA (thunk) = delta;
THUNK_VCALL_OFFSET (thunk)
= vcall_index * TREE_INT_CST_LOW (TYPE_SIZE (vtable_entry_type));
= vcall_index * int_size_in_bytes (vtable_entry_type);
DECL_EXTERNAL (thunk) = 1;
DECL_ARTIFICIAL (thunk) = 1;
/* So that finish_file can write out any thunks that need to be: */
......@@ -2077,8 +2077,10 @@ void
emit_thunk (thunk_fndecl)
tree thunk_fndecl;
{
tree function = TREE_OPERAND (DECL_INITIAL (thunk_fndecl), 0);
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);
if (TREE_ASM_WRITTEN (thunk_fndecl))
return;
......@@ -2094,7 +2096,7 @@ emit_thunk (thunk_fndecl)
TREE_SET_CODE (thunk_fndecl, FUNCTION_DECL);
#ifdef ASM_OUTPUT_MI_THUNK
if (!flag_syntax_only)
if (!flag_syntax_only && vcall_offset == 0)
{
const char *fnname;
current_function_decl = thunk_fndecl;
......@@ -2112,7 +2114,8 @@ emit_thunk (thunk_fndecl)
current_function_decl = 0;
cfun = 0;
}
#else /* ASM_OUTPUT_MI_THUNK */
#endif /* ASM_OUTPUT_MI_THUNK */
else
{
/* If we don't have the necessary macro for efficient thunks, generate a
thunk function that just makes a call to the real function.
......@@ -2140,16 +2143,44 @@ emit_thunk (thunk_fndecl)
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;
start_function (NULL_TREE, thunk_fndecl, NULL_TREE,
SF_DEFAULT | SF_PRE_PARSED);
push_to_top_level ();
start_function (NULL_TREE, thunk_fndecl, NULL_TREE, SF_PRE_PARSED);
store_parm_decls ();
current_function_is_thunk = 1;
/* Build up the call to the real function. */
t = build_int_2 (delta, -1 * (delta < 0));
/* Adjust the this pointer by the constant. */
t = ssize_int (delta);
TREE_TYPE (t) = signed_type (sizetype);
t = fold (build (PLUS_EXPR, TREE_TYPE (a), a, t));
/* If there's a vcall offset, look up that value in the vtable and
adjust the `this' pointer again. */
if (vcall_offset != 0)
{
tree orig_this;
t = save_expr (t);
orig_this = t;
/* The vptr is always at offset zero in the object. */
t = build1 (NOP_EXPR,
build_pointer_type (build_pointer_type
(vtable_entry_type)),
t);
/* Form the vtable address. */
t = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (t)), t);
/* Find the entry with the vcall offset. */
t = build (PLUS_EXPR, TREE_TYPE (t), t, ssize_int (vcall_offset));
/* Calculate the offset itself. */
t = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (t)), t);
/* Adjust the `this' pointer. */
t = fold (build (PLUS_EXPR,
TREE_TYPE (orig_this),
orig_this,
t));
}
/* Build up the call to the real function. */
t = tree_cons (NULL_TREE, t, NULL_TREE);
for (a = TREE_CHAIN (a); a; a = TREE_CHAIN (a))
t = tree_cons (NULL_TREE, a, t);
......@@ -2157,13 +2188,21 @@ emit_thunk (thunk_fndecl)
t = build_call (function, t);
finish_return_stmt (t);
/* The back-end expects DECL_INITIAL to contain a BLOCK, so we
clear this here. */
DECL_INITIAL (thunk_fndecl) = NULL_TREE;
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);
}
#endif /* ASM_OUTPUT_MI_THUNK */
TREE_SET_CODE (thunk_fndecl, THUNK_DECL);
}
......
......@@ -108,10 +108,10 @@ void S4::s1 ()
S2-in-S4 secondary vtable
S4::s1 vcall offset
S1 vbase offset
S2:s0 vcall offset
S4::s1 vcall offset
S0 vbase offset
S2:s0 vcall offset
S2 offset to top
S4 RTTI
S2::s0
......@@ -151,10 +151,12 @@ int main ()
return 5;
if (*vtbl++ != (ptrdiff_t) &s1__2S4)
return 6;
// All the vcall and vbase offsets should be zero.
// The S1 vbase offset.
if (*vtbl++ != 0)
return 7;
if (*vtbl++ != 0)
// The S4::s1 vcall offset is negative; once you convert to S2, you
// have to convert to S4 to find the final overrider.
if (*vtbl++ != ((char*) &s4 - (char*) (S2*) &s4))
return 8;
if (*vtbl++ != 0)
return 9;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment