diff options
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; } |