This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Make calls in virtual thunks local if possible
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Richard Henderson <rth at redhat dot com>, jason at redhat dot com
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Mon, 23 Jun 2003 17:20:17 +0200
- Subject: [PATCH] Make calls in virtual thunks local if possible
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
Hi!
If ASM_OUTPUT_DEF is supported, this patch creates a static alias to methods
which need thunks and makes thunks call these static aliases instead of the
real method symbols. This is possible since thunks are always emitted
together with the methods they are calling.
If a method is emitted in a linkonce section, it will emit the thunk into
the same linkonce section as well, since local symbols in linkonce sections
cannot be safely accessed from other sections.
The patch revealed a bug in x86_output_mi_thunk, which for pic hidden x86_64
functions would emit
jmp .LTHUNK0(%rip)
instead of the desired
jmp .LTHUNK0
(there was a mem around the rtl which was not supposed to be there).
Tested on gcc-3_3-rhl-branch, will bootstrap/regtest this on the trunk
tonight. Ok to commit if it passes?
2003-06-23 Jakub Jelinek <jakub@redhat.com>
* config/i386/i386.c (x86_output_mi_thunk): Don't pass MEM to %P0,
just SYMBOL_REF.
* varasm.c (resolve_unique_section): Remove prototype. No longer
static.
* tree.h (resolve_unique_section): New prototype.
cp/
* method.c (thunk_labelno): New variable.
(make_alias_for_thunk): New function.
(use_thunk): Use it if defined ASM_OUTPUT_DEF. Put the thunk
into the same section as the function it is calling.
Include gt-cp-method.h.
* Make-lang.in (gt-cp-method.h): Depend on s-gtype.
(cp/method.o): Depend on gt-cp-method.h.
* config-lang.in (gtfiles): Add $(srcdir)/cp/method.c.
--- gcc/cp/method.c.jj 2003-06-21 05:11:42.000000000 -0400
+++ gcc/cp/method.c 2003-06-23 11:08:17.000000000 -0400
@@ -351,6 +351,52 @@ thunk_adjust (tree ptr, bool this_adjust
return ptr;
}
+static GTY (()) int thunk_labelno;
+
+/* Create a static alias to function. */
+
+static tree
+make_alias_for_thunk (tree function)
+{
+ tree alias;
+ char buf[256];
+
+ ASM_GENERATE_INTERNAL_LABEL (buf, "LTHUNK", thunk_labelno);
+ thunk_labelno++;
+ alias = build_decl (FUNCTION_DECL, get_identifier (buf),
+ TREE_TYPE (function));
+ DECL_LANG_SPECIFIC (alias) = DECL_LANG_SPECIFIC (function);
+ cxx_dup_lang_specific_decl (alias);
+ DECL_CONTEXT (alias) = NULL;
+ TREE_READONLY (alias) = TREE_READONLY (function);
+ TREE_THIS_VOLATILE (alias) = TREE_THIS_VOLATILE (function);
+ TREE_PUBLIC (alias) = 0;
+ DECL_INTERFACE_KNOWN (alias) = 1;
+ DECL_NOT_REALLY_EXTERN (alias) = 1;
+ DECL_THIS_STATIC (alias) = 1;
+ DECL_SAVED_FUNCTION_DATA (alias) = NULL;
+ DECL_DESTRUCTOR_P (alias) = 0;
+ DECL_CONSTRUCTOR_P (alias) = 0;
+ DECL_CLONED_FUNCTION (alias) = NULL_TREE;
+ DECL_EXTERNAL (alias) = 0;
+ DECL_ARTIFICIAL (alias) = 1;
+ DECL_NO_STATIC_CHAIN (alias) = 1;
+ DECL_PENDING_INLINE_P (alias) = 0;
+ DECL_INLINE (alias) = 0;
+ DECL_DECLARED_INLINE_P (alias) = 0;
+ DECL_DEFERRED_FN (alias) = 0;
+ DECL_USE_TEMPLATE (alias) = 0;
+ DECL_TEMPLATE_INSTANTIATED (alias) = 0;
+ DECL_TEMPLATE_INFO (alias) = NULL;
+ TREE_ADDRESSABLE (alias) = 1;
+ TREE_USED (alias) = 1;
+ SET_DECL_ASSEMBLER_NAME (alias, DECL_NAME (alias));
+ TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (alias)) = 1;
+ if (!flag_syntax_only)
+ assemble_alias (alias, DECL_ASSEMBLER_NAME (function));
+ return alias;
+}
+
/* Emit the definition of a C++ multiple inheritance or covariant
return vtable thunk. If EMIT_P is nonzero, the thunk is emitted
immediately. */
@@ -358,7 +404,7 @@ thunk_adjust (tree ptr, bool this_adjust
void
use_thunk (tree thunk_fndecl, bool emit_p)
{
- tree function;
+ tree function, alias;
tree virtual_offset;
HOST_WIDE_INT fixed_offset, virtual_value;
bool this_adjusting = DECL_THIS_THUNK_P (thunk_fndecl);
@@ -386,6 +432,12 @@ use_thunk (tree thunk_fndecl, bool emit_
if (!emit_p)
return;
+#ifdef ASM_OUTPUT_DEF
+ alias = make_alias_for_thunk (function);
+#else
+ alias = function;
+#endif
+
fixed_offset = THUNK_FIXED_OFFSET (thunk_fndecl);
virtual_offset = THUNK_VIRTUAL_OFFSET (thunk_fndecl);
@@ -415,6 +467,21 @@ use_thunk (tree thunk_fndecl, bool emit_
push_to_top_level ();
+#ifdef ASM_OUTPUT_DEF
+ if (targetm.have_named_sections)
+ {
+ resolve_unique_section (function, 0, flag_function_sections);
+
+ if (DECL_SECTION_NAME (function) != NULL && DECL_ONE_ONLY (function))
+ {
+ resolve_unique_section (thunk_fndecl, 0, flag_function_sections);
+
+ /* Output the thunk into the same section as function. */
+ DECL_SECTION_NAME (thunk_fndecl) = DECL_SECTION_NAME (function);
+ }
+ }
+#endif
+
/* The back-end expects DECL_INITIAL to contain a BLOCK, so we
create one. */
DECL_INITIAL (thunk_fndecl) = make_node (BLOCK);
@@ -422,7 +489,7 @@ use_thunk (tree thunk_fndecl, bool emit_
if (this_adjusting
&& targetm.asm_out.can_output_mi_thunk (thunk_fndecl, fixed_offset,
- virtual_value, function))
+ virtual_value, alias))
{
const char *fnname;
current_function_decl = thunk_fndecl;
@@ -434,7 +501,7 @@ use_thunk (tree thunk_fndecl, bool emit_
assemble_start_function (thunk_fndecl, fnname);
targetm.asm_out.output_mi_thunk (asm_out_file, thunk_fndecl,
- fixed_offset, virtual_value, function);
+ fixed_offset, virtual_value, alias);
assemble_end_function (thunk_fndecl, fnname);
current_function_decl = 0;
@@ -486,7 +553,7 @@ use_thunk (tree thunk_fndecl, bool emit_
for (a = TREE_CHAIN (a); a; a = TREE_CHAIN (a))
t = tree_cons (NULL_TREE, a, t);
t = nreverse (t);
- t = build_call (function, t);
+ t = build_call (alias, t);
if (!this_adjusting)
t = thunk_adjust (t, /*this_adjusting=*/0,
fixed_offset, virtual_offset);
@@ -1054,3 +1121,5 @@ skip_artificial_parms_for (tree fn, tree
list = TREE_CHAIN (list);
return list;
}
+
+#include "gt-cp-method.h"
--- gcc/cp/Make-lang.in.jj 2003-06-21 05:11:42.000000000 -0400
+++ gcc/cp/Make-lang.in 2003-06-21 05:12:59.000000000 -0400
@@ -103,7 +103,7 @@ $(srcdir)/cp/cfns.h: $(srcdir)/cp/cfns.g
$(srcdir)/cp/cfns.gperf > $(srcdir)/cp/cfns.h
gtype-cp.h gt-cp-call.h gt-cp-decl.h gt-cp-decl2.h : s-gtype; @true
-gt-cp-pt.h gt-cp-repo.h gt-cp-parser.h : s-gtype; @true
+gt-cp-pt.h gt-cp-repo.h gt-cp-parser.h gt-cp-method.h : s-gtype; @true
gt-cp-tree.h gt-cp-mangle.h gt-cp-name-lookup.h: s-gtype; @true
#
@@ -253,7 +253,7 @@ cp/friend.o: cp/friend.c $(CXX_TREE_H) $
cp/init.o: cp/init.c $(CXX_TREE_H) $(TM_H) flags.h $(RTL_H) $(EXPR_H) toplev.h \
except.h
cp/method.o: cp/method.c $(CXX_TREE_H) $(TM_H) toplev.h $(RTL_H) $(EXPR_H) \
- $(TM_P_H) $(TARGET_H)
+ $(TM_P_H) $(TARGET_H) gt-cp-method.h
cp/cvt.o: cp/cvt.c $(CXX_TREE_H) $(TM_H) cp/decl.h flags.h toplev.h convert.h
cp/search.o: cp/search.c $(CXX_TREE_H) $(TM_H) stack.h flags.h toplev.h $(RTL_H)
cp/tree.o: cp/tree.c $(CXX_TREE_H) $(TM_H) flags.h toplev.h $(RTL_H) \
--- gcc/cp/config-lang.in.jj 2003-06-21 05:11:42.000000000 -0400
+++ gcc/cp/config-lang.in 2003-06-21 05:12:59.000000000 -0400
@@ -34,4 +34,4 @@ stagestuff="g++\$(exeext) g++-cross\$(ex
target_libs="target-libstdc++-v3 target-gperf"
-gtfiles="\$(srcdir)/cp/mangle.c \$(srcdir)/cp/name-lookup.h \$(srcdir)/cp/name-lookup.c \$(srcdir)/cp/cp-tree.h \$(srcdir)/cp/decl.h \$(srcdir)/cp/lex.h \$(srcdir)/cp/call.c \$(srcdir)/cp/decl.c \$(srcdir)/cp/decl2.c \$(srcdir)/cp/pt.c \$(srcdir)/cp/repo.c \$(srcdir)/cp/semantics.c \$(srcdir)/cp/tree.c \$(srcdir)/cp/parser.c \$(srcdir)/c-common.c \$(srcdir)/c-common.h \$(srcdir)/c-pragma.c"
+gtfiles="\$(srcdir)/cp/mangle.c \$(srcdir)/cp/name-lookup.h \$(srcdir)/cp/name-lookup.c \$(srcdir)/cp/cp-tree.h \$(srcdir)/cp/decl.h \$(srcdir)/cp/lex.h \$(srcdir)/cp/call.c \$(srcdir)/cp/decl.c \$(srcdir)/cp/decl2.c \$(srcdir)/cp/pt.c \$(srcdir)/cp/repo.c \$(srcdir)/cp/semantics.c \$(srcdir)/cp/tree.c \$(srcdir)/cp/parser.c \$(srcdir)/cp/method.c \$(srcdir)/c-common.c \$(srcdir)/c-common.h \$(srcdir)/c-pragma.c"
--- gcc/varasm.c.jj 2003-06-21 05:11:42.000000000 -0400
+++ gcc/varasm.c 2003-06-21 05:12:59.000000000 -0400
@@ -183,7 +183,6 @@ static void asm_output_aligned_bss
static bool asm_emit_uninitialised PARAMS ((tree, const char*,
unsigned HOST_WIDE_INT,
unsigned HOST_WIDE_INT));
-static void resolve_unique_section PARAMS ((tree, int, int));
static void mark_weak PARAMS ((tree));
enum in_section { no_section, in_text, in_data, in_named
@@ -460,7 +459,7 @@ named_section (decl, name, reloc)
/* If required, set DECL_SECTION_NAME to a unique name. */
-static void
+void
resolve_unique_section (decl, reloc, flag_function_or_data_sections)
tree decl;
int reloc ATTRIBUTE_UNUSED;
--- gcc/config/i386/i386.c.jj 2003-06-21 05:09:27.000000000 -0400
+++ gcc/config/i386/i386.c 2003-06-23 11:09:26.000000000 -0400
@@ -15494,15 +15494,14 @@ x86_output_mi_thunk (file, thunk, delta,
output_asm_insn ("mov{l}\t{%0, %1|%1, %0}", xops);
}
- xops[0] = DECL_RTL (function);
+ xops[0] = XEXP (DECL_RTL (function), 0);
if (TARGET_64BIT)
{
if (!flag_pic || (*targetm.binds_local_p) (function))
output_asm_insn ("jmp\t%P0", xops);
else
{
- tmp = XEXP (xops[0], 0);
- tmp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, tmp), UNSPEC_GOTPCREL);
+ tmp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, xops[0]), UNSPEC_GOTPCREL);
tmp = gen_rtx_CONST (Pmode, tmp);
tmp = gen_rtx_MEM (QImode, tmp);
xops[0] = tmp;
--- gcc/tree.h.jj 2003-06-21 05:11:41.000000000 -0400
+++ gcc/tree.h 2003-06-21 05:12:59.000000000 -0400
@@ -2907,6 +2907,7 @@ extern int supports_one_only PARAMS ((v
extern void variable_section PARAMS ((tree, int));
enum tls_model decl_tls_model PARAMS ((tree));
enum symbol_visibility decl_visibility PARAMS ((tree));
+extern void resolve_unique_section PARAMS ((tree, int, int));
/* In stmt.c */
extern void emit_nop PARAMS ((void));
Jakub