diff options
| author | Mark Mitchell <mark@codesourcery.com> | 2002-10-25 19:39:47 +0000 |
|---|---|---|
| committer | Mark Mitchell <mmitchel@gcc.gnu.org> | 2002-10-25 19:39:47 +0000 |
| commit | bb5e8a7ffc01267f79f7d3a70b98a29fc6eb604c (patch) | |
| tree | bc8ca7b32029d71b1854594ff6c94c1ba702f188 /gcc/cp/method.c | |
| parent | f3763a442e854320fd233fd63b7871f301f723be (diff) | |
| download | gcc-bb5e8a7ffc01267f79f7d3a70b98a29fc6eb604c.zip gcc-bb5e8a7ffc01267f79f7d3a70b98a29fc6eb604c.tar.gz gcc-bb5e8a7ffc01267f79f7d3a70b98a29fc6eb604c.tar.bz2 | |
class.c (build_vtbl_initializer): Don't use build_vtable_entry.
* class.c (build_vtbl_initializer): Don't use build_vtable_entry.
(build_vtable_entry): Remove.
* cp-tree.h (BINFO_VIRTUALS): Expand documentation.
(lang_decl): Add thunks.
(DECL_THUNKS): New macro.
* decl.c (duplicate_decls): Copy it.
* method.c (make_thunk): Simplify, and add thunks to DECL_THUNKS.
* semantics.c (emit_associated_thunks): Simplify.
* g++.dg/abi/vthunk2.C: New test.
From-SVN: r58536
Diffstat (limited to 'gcc/cp/method.c')
| -rw-r--r-- | gcc/cp/method.c | 107 |
1 files changed, 54 insertions, 53 deletions
diff --git a/gcc/cp/method.c b/gcc/cp/method.c index 60a0dce..8a905b2 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -278,10 +278,11 @@ make_thunk (function, delta, vcall_index) { tree thunk_id; tree thunk; - tree func_decl; tree vcall_offset; HOST_WIDE_INT d; + my_friendly_assert (TREE_CODE (function) == FUNCTION_DECL, 20021025); + /* Scale the VCALL_INDEX to be in terms of bytes. */ if (vcall_index) vcall_offset @@ -294,59 +295,59 @@ make_thunk (function, delta, vcall_index) d = tree_low_cst (delta, 0); - if (TREE_CODE (function) != ADDR_EXPR) - abort (); - func_decl = TREE_OPERAND (function, 0); - if (TREE_CODE (func_decl) != FUNCTION_DECL) - abort (); + /* See if we already have the thunk in question. */ + for (thunk = DECL_THUNKS (function); thunk; thunk = TREE_CHAIN (thunk)) + if (THUNK_DELTA (thunk) == d + && ((THUNK_VCALL_OFFSET (thunk) != NULL_TREE) + == (vcall_offset != NULL_TREE)) + && (THUNK_VCALL_OFFSET (thunk) + ? tree_int_cst_equal (THUNK_VCALL_OFFSET (thunk), + vcall_offset) + : true)) + return thunk; + + /* 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. */ + my_friendly_assert (!TREE_ASM_WRITTEN (function), 20021025); + + thunk_id = mangle_thunk (function, delta, vcall_offset); + thunk = build_decl (FUNCTION_DECL, thunk_id, TREE_TYPE (function)); + DECL_LANG_SPECIFIC (thunk) = DECL_LANG_SPECIFIC (function); + cxx_dup_lang_specific_decl (function); + SET_DECL_ASSEMBLER_NAME (thunk, thunk_id); + 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); + if (flag_weak) + comdat_linkage (thunk); + SET_DECL_THUNK_P (thunk); + DECL_INITIAL (thunk) = build1 (ADDR_EXPR, vfunc_ptr_type_node, function); + THUNK_DELTA (thunk) = d; + THUNK_VCALL_OFFSET (thunk) = vcall_offset; + /* 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; + /* And neither is it a clone. */ + DECL_CLONED_FUNCTION (thunk) = NULL_TREE; + DECL_EXTERNAL (thunk) = 1; + DECL_ARTIFICIAL (thunk) = 1; + /* 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 FUNCTION is. */ + DECL_PENDING_INLINE_P (thunk) = 0; + /* Nor has it been deferred. */ + DECL_DEFERRED_FN (thunk) = 0; + /* Add it to the list of thunks associated with FUNCTION. */ + TREE_CHAIN (thunk) = DECL_THUNKS (function); + DECL_THUNKS (function) = thunk; - thunk_id = mangle_thunk (TREE_OPERAND (function, 0), - delta, vcall_offset); - thunk = IDENTIFIER_GLOBAL_VALUE (thunk_id); - if (thunk && !DECL_THUNK_P (thunk)) - { - error ("implementation-reserved name `%D' used", thunk_id); - thunk = NULL_TREE; - SET_IDENTIFIER_GLOBAL_VALUE (thunk_id, thunk); - } - if (thunk == NULL_TREE) - { - thunk = build_decl (FUNCTION_DECL, thunk_id, TREE_TYPE (func_decl)); - DECL_LANG_SPECIFIC (thunk) = DECL_LANG_SPECIFIC (func_decl); - cxx_dup_lang_specific_decl (func_decl); - SET_DECL_ASSEMBLER_NAME (thunk, thunk_id); - DECL_CONTEXT (thunk) = DECL_CONTEXT (func_decl); - TREE_READONLY (thunk) = TREE_READONLY (func_decl); - TREE_THIS_VOLATILE (thunk) = TREE_THIS_VOLATILE (func_decl); - TREE_PUBLIC (thunk) = TREE_PUBLIC (func_decl); - if (flag_weak) - comdat_linkage (thunk); - SET_DECL_THUNK_P (thunk); - DECL_INITIAL (thunk) = function; - THUNK_DELTA (thunk) = d; - THUNK_VCALL_OFFSET (thunk) = vcall_offset; - /* 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; - /* And neither is it a clone. */ - DECL_CLONED_FUNCTION (thunk) = NULL_TREE; - DECL_EXTERNAL (thunk) = 1; - DECL_ARTIFICIAL (thunk) = 1; - /* 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); - SET_IDENTIFIER_GLOBAL_VALUE (thunk_id, thunk); - } return thunk; } |
