From 6462c441e1ae91377025ca105d91263086bc1577 Mon Sep 17 00:00:00 2001 From: Mark Mitchell Date: Fri, 5 May 2000 03:10:42 +0000 Subject: [PATCH] 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 --- gcc/cp/ChangeLog | 13 +++++++++++ gcc/cp/cp-tree.h | 16 +++++--------- gcc/cp/decl.c | 4 +++- gcc/cp/method.c | 64 ++++++++++++++++++++++++++++++++---------------------- gcc/cp/semantics.c | 1 + 5 files changed, 61 insertions(+), 37 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 42f2338..636f30e 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,16 @@ +2000-05-04 Mark Mitchell + + * 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 * class.c (update_vtable_entry_for_fn): Prototype. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 5e2b433..cb46967 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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 diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index c792e74..81203b4 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -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) diff --git a/gcc/cp/method.c b/gcc/cp/method.c index 07173d7..6491e2b 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -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); } } diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 8b9bfac..d6d493f 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -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 -- 2.7.4