summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authoraustern <austern@138bc75d-0d04-0410-961f-82ee72b054a4>2004-03-12 17:09:03 +0000
committeraustern <austern@138bc75d-0d04-0410-961f-82ee72b054a4>2004-03-12 17:09:03 +0000
commit2f9fc8efd7791829d4e81d6945cbe12ded8f94c3 (patch)
treecaa8a2f6e25f2a2ca455a215f64f01003c8ba7c4 /gcc
parentcd5edb432360227353f9d74a01082afedd347898 (diff)
downloadgcc-2f9fc8efd7791829d4e81d6945cbe12ded8f94c3.tar.gz
Enabled linkonce support for Darwin.
* target.h (struct gcc_target): New target hook, unwind_label. * target-def.h (TARGET_ASM_EMIT_UNWIND_LABEL): New hook. * output.h (default_emit_unwind_label): New function. * default.h (TARGET_EXPLICIT_INSTANTIATIONS_ONE_ONLY): New macro. (TARGET_USES_WEAK_UNWIND_INFO): New target macro. (TARGET_SUPPORTS_HIDDEN): New target macro. * dwarf2out.c (struct dw_fde_struct): Add field for function decl that corresponds to this FDE. (FRAME_BEGIN_LABEL): Allow target to override default label. (output_call_frame_info): If FDEs are linknonce, then use extra indirection for FDE encoding, output a label for each FDE, and output an empty label for each function without an FDE. (dwarf2out_begin_prologue): Set up decl field when creating an FDE. * varasm.c (globalize_decl): Call ASM_MAKE_LABEL_LINKONCE for decls with DECL_ONE_ONLY set, if that macro is defined. (make_decl_one_only): Don't use DECL_COMMON if we're compiling for a SUPPORTS_ONE_ONLY target. * config/darwin-protos.h (darwin_unique_section): Declare. (darwin_asm_named_section): Likewise. (darwin_section_type_flags): Likewise. (darwin_non_lazy_pcrel): Likewise. (darwin_emit_unwind_label): Likewise. (darwin_make_decl_one_only): Likewise. * config/darwin.c (machopic_finish): Get rid of tweak that eliminate stubs for symbols that are defined. (darwin_encode_section_info): Don't treat weak functions as defined. (darwin_make_decl_one_only): Define. (darwin_asm_named_section): Likewise. (darwin_section_type_flags): Likewise. (darwin_unique_section): Likewise. (darwin_emit_unwind_label): Likewise. (darwin_non_lazy_pcrel): Likewise. (darwin_asm_output_dwarf_delta): Difference between two labels is local only if both labels are local. * config/darwin.h (MAKE_DECL_ONE_ONLY): Define. (ASM_MAKE_LABEL_LINKONCE): Likewise. (TARGET_SUPPORTS_HIDDEN): Likewise. (TARGET_USES_WEAK_UNWIND_INFO): Likewise. (TARGET_EXPLICIT_INSTANTIATIONS_ONE_ONLY): Likewise. (FRAME_BEGIN_LABEL): Likewise. (ASM_DECLARE_OBJECT_NAME): Make references to weak symbols indirect. (ASM_DECLARE_FUNCTION_NAME): Likewise. (darwin_eh_frame_section): Give __eh_frame section the coalesced flag. (TARGET_ASM_UNIQUE_SECTION): Define. (EH_FRAME_SECTION_NAME): Define. (EH_FRAME_SECTION_ATTR): Likewise. (ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX): Likewise. (TARGET_ASM_NAMED_SECTION): Likewise. (TARGET_SECTION_TYPE_FLAGS): Likewise. * doc/tm.texi: Document TARGET_USES_WEAK_UNWIND_INFO, TARGET_EXPLICIT_INSTANTIATIONS_ONE_ONLY, TARGET_SUPPORTS_HIDDEN, TARGET_ASM_EMIT_UNWIND_LABEL. * cp/decl2.c (maybe_make_one_only): Look at TARGET_EXPLICIT_INSTANTIATION_ONE_ONLY when deciding whether to make an explicit instantiation weak. * cp/method.c (use_thunk): Make sure we call comdat_linkage when appropriate. * cp/pt.c (do_type_instantiation): On systems where weak symbols don't go in a static archive's TOC, explicit instantiation of a class must imply *explicit* instantiation of its memeber. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@79394 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog55
-rw-r--r--gcc/config/darwin-protos.h9
-rw-r--r--gcc/config/darwin.c116
-rw-r--r--gcc/config/darwin.h80
-rw-r--r--gcc/cp/ChangeLog11
-rw-r--r--gcc/cp/decl2.c21
-rw-r--r--gcc/cp/method.c2
-rw-r--r--gcc/cp/pt.c55
-rw-r--r--gcc/defaults.h30
-rw-r--r--gcc/doc/tm.texi35
-rw-r--r--gcc/dwarf2out.c42
-rw-r--r--gcc/output.h1
-rw-r--r--gcc/target-def.h6
-rw-r--r--gcc/target.h6
-rw-r--r--gcc/varasm.c21
15 files changed, 450 insertions, 40 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 4353cf670fe..e2821e3deda 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,58 @@
+2004-03-12 Matt Austern <austern@apple.com>
+
+ * target.h (struct gcc_target): New target hook, unwind_label.
+ * target-def.h (TARGET_ASM_EMIT_UNWIND_LABEL): New hook.
+ * output.h (default_emit_unwind_label): New function.
+ * default.h (TARGET_EXPLICIT_INSTANTIATIONS_ONE_ONLY): New macro.
+ (TARGET_USES_WEAK_UNWIND_INFO): New target macro.
+ (TARGET_SUPPORTS_HIDDEN): New target macro.
+ * dwarf2out.c (struct dw_fde_struct): Add field for function decl
+ that corresponds to this FDE.
+ (FRAME_BEGIN_LABEL): Allow target to override default label.
+ (output_call_frame_info): If FDEs are linknonce, then use extra
+ indirection for FDE encoding, output a label for each FDE, and
+ output an empty label for each function without an FDE.
+ (dwarf2out_begin_prologue): Set up decl field when creating an FDE.
+ * varasm.c (globalize_decl): Call ASM_MAKE_LABEL_LINKONCE for
+ decls with DECL_ONE_ONLY set, if that macro is defined.
+ (make_decl_one_only): Don't use DECL_COMMON if we're compiling
+ for a SUPPORTS_ONE_ONLY target.
+ * config/darwin-protos.h (darwin_unique_section): Declare.
+ (darwin_asm_named_section): Likewise.
+ (darwin_section_type_flags): Likewise.
+ (darwin_non_lazy_pcrel): Likewise.
+ (darwin_emit_unwind_label): Likewise.
+ (darwin_make_decl_one_only): Likewise.
+ * config/darwin.c (machopic_finish): Get rid of tweak that
+ eliminate stubs for symbols that are defined.
+ (darwin_encode_section_info): Don't treat weak functions as defined.
+ (darwin_make_decl_one_only): Define.
+ (darwin_asm_named_section): Likewise.
+ (darwin_section_type_flags): Likewise.
+ (darwin_unique_section): Likewise.
+ (darwin_emit_unwind_label): Likewise.
+ (darwin_non_lazy_pcrel): Likewise.
+ (darwin_asm_output_dwarf_delta): Difference between two labels is
+ local only if both labels are local.
+ * config/darwin.h (MAKE_DECL_ONE_ONLY): Define.
+ (ASM_MAKE_LABEL_LINKONCE): Likewise.
+ (TARGET_SUPPORTS_HIDDEN): Likewise.
+ (TARGET_USES_WEAK_UNWIND_INFO): Likewise.
+ (TARGET_EXPLICIT_INSTANTIATIONS_ONE_ONLY): Likewise.
+ (FRAME_BEGIN_LABEL): Likewise.
+ (ASM_DECLARE_OBJECT_NAME): Make references to weak symbols indirect.
+ (ASM_DECLARE_FUNCTION_NAME): Likewise.
+ (darwin_eh_frame_section): Give __eh_frame section the coalesced flag.
+ (TARGET_ASM_UNIQUE_SECTION): Define.
+ (EH_FRAME_SECTION_NAME): Define.
+ (EH_FRAME_SECTION_ATTR): Likewise.
+ (ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX): Likewise.
+ (TARGET_ASM_NAMED_SECTION): Likewise.
+ (TARGET_SECTION_TYPE_FLAGS): Likewise.
+ * doc/tm.texi: Document TARGET_USES_WEAK_UNWIND_INFO,
+ TARGET_EXPLICIT_INSTANTIATIONS_ONE_ONLY, TARGET_SUPPORTS_HIDDEN,
+ TARGET_ASM_EMIT_UNWIND_LABEL.
+
2004-03-12 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* builtins.c (expand_builtin_mathfn): Add pow10* to the
diff --git a/gcc/config/darwin-protos.h b/gcc/config/darwin-protos.h
index 28660339488..845a8283c73 100644
--- a/gcc/config/darwin-protos.h
+++ b/gcc/config/darwin-protos.h
@@ -71,12 +71,21 @@ extern void machopic_select_section (tree, int, unsigned HOST_WIDE_INT);
extern void machopic_select_rtx_section (enum machine_mode, rtx,
unsigned HOST_WIDE_INT);
+extern void darwin_unique_section (tree decl, int reloc);
+extern void darwin_asm_named_section (const char *, unsigned int);
+extern unsigned int darwin_section_type_flags (tree, const char *, int);
+extern void darwin_non_lazy_pcrel (FILE *, rtx);
+
+extern void darwin_emit_unwind_label(FILE *, tree, int);
+
extern void darwin_pragma_ignore (struct cpp_reader *);
extern void darwin_pragma_options (struct cpp_reader *);
extern void darwin_pragma_unused (struct cpp_reader *);
extern void darwin_file_end (void);
+extern void darwin_make_decl_one_only (tree decl);
+
/* Expanded by EXTRA_SECTION_FUNCTIONS into varasm.o. */
extern void const_section (void);
extern void const_data_section (void);
diff --git a/gcc/config/darwin.c b/gcc/config/darwin.c
index 858d150d45e..dec2eb72a35 100644
--- a/gcc/config/darwin.c
+++ b/gcc/config/darwin.c
@@ -1004,6 +1004,7 @@ darwin_encode_section_info (tree decl, rtx rtl, int first ATTRIBUTE_UNUSED)
if ((TREE_CODE (decl) == FUNCTION_DECL
|| TREE_CODE (decl) == VAR_DECL)
&& !DECL_EXTERNAL (decl)
+ && (!TREE_PUBLIC (decl) || (!DECL_ONE_ONLY (decl) && !DECL_WEAK (decl)))
&& ((TREE_STATIC (decl)
&& (!DECL_COMMON (decl) || !TREE_PUBLIC (decl)))
|| (DECL_INITIAL (decl)
@@ -1124,6 +1125,20 @@ update_stubs (const char *name)
}
void
+darwin_make_decl_one_only (tree decl)
+{
+ static const char *text_section = "__TEXT,__textcoal_nt,coalesced,no_toc";
+ static const char *data_section = "__DATA,__datacoal_nt,coalesced,no_toc";
+
+ const char *sec = TREE_CODE (decl) == FUNCTION_DECL
+ ? text_section
+ : data_section;
+ TREE_PUBLIC (decl) = 1;
+ DECL_ONE_ONLY (decl) = 1;
+ DECL_SECTION_NAME (decl) = build_string (strlen (sec), sec);
+}
+
+void
machopic_select_section (tree exp, int reloc,
unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
{
@@ -1289,6 +1304,103 @@ darwin_globalize_label (FILE *stream, const char *name)
default_globalize_label (stream, name);
}
+void
+darwin_asm_named_section (const char *name, unsigned int flags ATTRIBUTE_UNUSED)
+{
+ fprintf (asm_out_file, ".section %s\n", name);
+}
+
+unsigned int
+darwin_section_type_flags (tree decl, const char *name, int reloc)
+{
+ unsigned int flags = default_section_type_flags (decl, name, reloc);
+
+ /* Weak or linkonce variables live in a writable section. */
+ if (decl != 0 && TREE_CODE (decl) != FUNCTION_DECL
+ && (DECL_WEAK (decl) || DECL_ONE_ONLY (decl)))
+ flags |= SECTION_WRITE;
+
+ return flags;
+}
+
+void
+darwin_unique_section (tree decl, int reloc ATTRIBUTE_UNUSED)
+{
+ /* Darwin does not use unique sections. However, the target's
+ unique_section hook is called for linkonce symbols. We need
+ to set an appropriate section for such symbols. */
+ if (DECL_ONE_ONLY (decl) && !DECL_SECTION_NAME (decl))
+ darwin_make_decl_one_only (decl);
+}
+
+/* Emit a label for an FDE, making it global and/or weak if appropriate.
+ The third parameter is nonzero if this is just a placeholder for an
+ FDE that we are omitting. */
+void
+darwin_emit_unwind_label(FILE *file, tree decl, int empty)
+{
+ tree id = DECL_ASSEMBLER_NAME (decl)
+ ? DECL_ASSEMBLER_NAME (decl)
+ : DECL_NAME (decl);
+
+ const char *prefix = "_";
+ const int prefix_len = 1;
+
+ const char *base = IDENTIFIER_POINTER (id);
+ unsigned int base_len = IDENTIFIER_LENGTH (id);
+
+ const char *suffix = ".eh";
+ unsigned int suffix_len = 3;
+
+ int need_quotes = name_needs_quotes (base);
+ int quotes_len = need_quotes ? 2 : 0;
+
+ char *lab = xmalloc (prefix_len + base_len + suffix_len + quotes_len + 1);
+ lab[0] = '\0';
+
+ if (need_quotes)
+ strcat(lab, "\"");
+ strcat(lab, prefix);
+ strcat(lab, base);
+ strcat(lab, suffix);
+ if (need_quotes)
+ strcat(lab, "\"");
+
+ if (TREE_PUBLIC (decl))
+ fprintf (file, "%s %s\n",
+ (DECL_VISIBILITY (decl) != VISIBILITY_HIDDEN
+ ? ".globl"
+ : ".private_extern"),
+ lab);
+
+ if (DECL_ONE_ONLY (decl) && TREE_PUBLIC (decl))
+ fprintf (file, ".weak_definition %s\n", lab);
+
+ if (empty)
+ fprintf (file, "%s = 0\n", lab);
+ else
+ fprintf (file, "%s:\n", lab);
+
+ free (lab);
+}
+
+/* Generate a PC-relative reference to a Mach-O non-lazy-symbol. */
+void
+darwin_non_lazy_pcrel (FILE *file, rtx addr)
+{
+ const char *str;
+ const char *nlp_name;
+
+ if (GET_CODE (addr) != SYMBOL_REF)
+ abort ();
+
+ str = darwin_strip_name_encoding (XSTR (addr, 0));
+ nlp_name = machopic_non_lazy_ptr_name (str);
+ fputs ("\t.long\t", file);
+ ASM_OUTPUT_LABELREF (file, nlp_name);
+ fputs ("-.", file);
+}
+
/* Emit an assembler directive to set visibility for a symbol. The
only supported visibilities are VISIBILITY_DEFAULT and
VISIBILITY_HIDDEN; the latter corresponds to Darwin's "private
@@ -1325,8 +1437,8 @@ void
darwin_asm_output_dwarf_delta (FILE *file, int size ATTRIBUTE_UNUSED,
const char *lab1, const char *lab2)
{
- const char *p = lab1 + (lab1[0] == '*');
- int islocaldiff = (p[0] == 'L');
+ int islocaldiff = (lab1[0] == '*' && lab1[1] == 'L'
+ && lab2[0] == '*' && lab2[1] == 'L');
if (islocaldiff)
fprintf (file, "\t.set L$set$%d,", darwin_dwarf_label_counter);
diff --git a/gcc/config/darwin.h b/gcc/config/darwin.h
index b5dae39e967..8a659d9ed8f 100644
--- a/gcc/config/darwin.h
+++ b/gcc/config/darwin.h
@@ -319,6 +319,47 @@ do { text_section (); \
"\t.stabs \"%s\",%d,0,0,Letext\nLetext:\n", "" , N_SO); \
} while (0)
+/* Making a symbols weak on Darwin requires more than just setting DECL_WEAK. */
+#define MAKE_DECL_ONE_ONLY(DECL) darwin_make_decl_one_only (DECL)
+
+/* Representation of linkonce symbols for the MACH-O assembler. Linkonce
+ symbols must be given a special section *and* must be preceded by a
+ special assembler directive. */
+#define ASM_MAKE_LABEL_LINKONCE(FILE, NAME) \
+ do { const char* _x = (NAME); if (!!strncmp (_x, "_OBJC_", 6)) { \
+ fputs (".weak_definition ", FILE); assemble_name (FILE, _x); \
+ fputs ("\n", FILE); }} while (0)
+
+/* We support hidden visibility */
+#undef TARGET_SUPPORTS_HIDDEN
+#define TARGET_SUPPORTS_HIDDEN 1
+
+/* The Darwin linker imposes two limitations on common symbols: they
+ can't have hidden visibility, and they can't appear in dylibs. As
+ a consequence, we should never use common symbols to represent
+ vague linkage. */
+#undef USE_COMMON_FOR_ONE_ONLY
+#define USE_COMMON_FOR_ONE_ONLY 0
+
+/* The Darwin linker doesn't like explicit template instantions to be
+ coalesced, because it doesn't want coalesced symbols to appear in
+ a static archive's table of contents. */
+#undef TARGET_EXPLICIT_INSTANTIATIONS_ONE_ONLY
+#define TARGET_EXPLICIT_INSTANTIATIONS_ONE_ONLY 0
+
+/* We make exception information linkonce. */
+#undef TARGET_USES_WEAK_UNWIND_INFO
+#define TARGET_USES_WEAK_UNWIND_INFO 1
+
+/* We need to use a nonlocal label for the start of an EH frame: the
+ Darwin linker requires that a coalesced section start with a label. */
+#undef FRAME_BEGIN_LABEL
+#define FRAME_BEGIN_LABEL "EH_frame"
+
+/* Emit a label for the FDE corresponding to DECL. EMPTY means
+ emit a label for an empty FDE. */
+#define TARGET_ASM_EMIT_UNWIND_LABEL darwin_emit_unwind_label
+
/* Our profiling scheme doesn't LP labels and counter words. */
#define NO_PROFILE_COUNTERS 1
@@ -370,10 +411,11 @@ do { text_section (); \
const char *xname = NAME; \
if (GET_CODE (XEXP (DECL_RTL (DECL), 0)) != SYMBOL_REF) \
xname = IDENTIFIER_POINTER (DECL_NAME (DECL)); \
- if ((TREE_STATIC (DECL) \
- && (!DECL_COMMON (DECL) || !TREE_PUBLIC (DECL))) \
- || DECL_INITIAL (DECL)) \
- machopic_define_name (xname); \
+ if (! DECL_ONE_ONLY (DECL) && ! DECL_WEAK (DECL)) \
+ if ((TREE_STATIC (DECL) \
+ && (!DECL_COMMON (DECL) || !TREE_PUBLIC (DECL))) \
+ || DECL_INITIAL (DECL)) \
+ machopic_define_name (xname); \
if ((TREE_STATIC (DECL) \
&& (!DECL_COMMON (DECL) || !TREE_PUBLIC (DECL))) \
|| DECL_INITIAL (DECL)) \
@@ -390,10 +432,11 @@ do { text_section (); \
const char *xname = NAME; \
if (GET_CODE (XEXP (DECL_RTL (DECL), 0)) != SYMBOL_REF) \
xname = IDENTIFIER_POINTER (DECL_NAME (DECL)); \
- if ((TREE_STATIC (DECL) \
- && (!DECL_COMMON (DECL) || !TREE_PUBLIC (DECL))) \
- || DECL_INITIAL (DECL)) \
- machopic_define_name (xname); \
+ if (! DECL_ONE_ONLY (DECL) && ! DECL_WEAK (DECL)) \
+ if ((TREE_STATIC (DECL) \
+ && (!DECL_COMMON (DECL) || !TREE_PUBLIC (DECL))) \
+ || DECL_INITIAL (DECL)) \
+ machopic_define_name (xname); \
if ((TREE_STATIC (DECL) \
&& (!DECL_COMMON (DECL) || !TREE_PUBLIC (DECL))) \
|| DECL_INITIAL (DECL)) \
@@ -646,7 +689,7 @@ SECTION_FUNCTION (darwin_exception_section, \
".section __DATA,__gcc_except_tab", 0) \
SECTION_FUNCTION (darwin_eh_frame_section, \
in_darwin_eh_frame, \
- ".section __TEXT,__eh_frame", 0) \
+ ".section " EH_FRAME_SECTION_NAME ",__eh_frame" EH_FRAME_SECTION_ATTR, 0) \
\
static void \
objc_section_init (void) \
@@ -687,6 +730,10 @@ objc_section_init (void) \
#define TARGET_ASM_SELECT_SECTION machopic_select_section
#undef TARGET_ASM_SELECT_RTX_SECTION
#define TARGET_ASM_SELECT_RTX_SECTION machopic_select_rtx_section
+#undef TARGET_ASM_UNIQUE_SECTION
+#define TARGET_ASM_UNIQUE_SECTION darwin_unique_section
+
+
#define ASM_DECLARE_UNRESOLVED_REFERENCE(FILE,NAME) \
do { \
@@ -814,6 +861,9 @@ enum machopic_addr_class {
#define TARGET_ASM_EH_FRAME_SECTION darwin_eh_frame_section
+#define EH_FRAME_SECTION_NAME "__TEXT"
+#define EH_FRAME_SECTION_ATTR ",coalesced,no_toc+strip_static_syms"
+
#undef ASM_PREFERRED_EH_DATA_FORMAT
#define ASM_PREFERRED_EH_DATA_FORMAT(CODE,GLOBAL) \
(((CODE) == 2 && (GLOBAL) == 1) \
@@ -823,8 +873,20 @@ enum machopic_addr_class {
#define ASM_OUTPUT_DWARF_DELTA(FILE,SIZE,LABEL1,LABEL2) \
darwin_asm_output_dwarf_delta (FILE, SIZE, LABEL1, LABEL2)
+#define ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX(ASM_OUT_FILE, ENCODING, SIZE, ADDR, DONE) \
+ if (ENCODING == ASM_PREFERRED_EH_DATA_FORMAT (2, 1)) { \
+ darwin_non_lazy_pcrel (ASM_OUT_FILE, ADDR); \
+ goto DONE; \
+ }
+
+
#define TARGET_TERMINATE_DW2_EH_FRAME_INFO false
+#undef TARGET_ASM_NAMED_SECTION
+#define TARGET_ASM_NAMED_SECTION darwin_asm_named_section
+#undef TARGET_SECTION_TYPE_FLAGS
+#define TARGET_SECTION_TYPE_FLAGS darwin_section_type_flags
+
#define DARWIN_REGISTER_TARGET_PRAGMAS() \
do { \
c_register_pragma (0, "mark", darwin_pragma_ignore); \
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index e543c5c6d18..fc34864146c 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,14 @@
+2004-03-12 Matt Austern <austern@apple.com>
+
+ * decl2.c (maybe_make_one_only): Look at
+ TARGET_EXPLICIT_INSTANTIATION_ONE_ONLY when deciding whether
+ to make an explicit instantiation weak.
+ * method.c (use_thunk): Make sure we call comdat_linkage
+ when appropriate.
+ * pt.c (do_type_instantiation): On systems where weak symbols
+ don't go in a static archive's TOC, explicit instantiation of a
+ class must imply *explicit* instantiation of its memeber.
+
2004-03-11 Kazu Hirata <kazu@cs.umass.edu>
* call.c, cp-tree.h, pt.c: Fix comment typos.
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 9d8043a2f46..7310d091e12 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -1399,7 +1399,9 @@ comdat_linkage (tree decl)
/* For win32 we also want to put explicit instantiations in
linkonce sections, so that they will be merged with implicit
- instantiations; otherwise we get duplicate symbol errors. */
+ instantiations; otherwise we get duplicate symbol errors.
+ For Darwin we do not want explicit instantiations to be
+ linkonce. */
void
maybe_make_one_only (tree decl)
@@ -1418,13 +1420,18 @@ maybe_make_one_only (tree decl)
to for variables so that cp_finish_decl will update their linkage,
because their DECL_INITIAL may not have been set properly yet. */
- make_decl_one_only (decl);
-
- if (TREE_CODE (decl) == VAR_DECL)
+ if (TARGET_EXPLICIT_INSTANTIATIONS_ONE_ONLY
+ || (! DECL_EXPLICIT_INSTANTIATION (decl)
+ && ! DECL_TEMPLATE_SPECIALIZATION (decl)))
{
- DECL_COMDAT (decl) = 1;
- /* Mark it needed so we don't forget to emit it. */
- mark_referenced (DECL_ASSEMBLER_NAME (decl));
+ make_decl_one_only (decl);
+
+ if (TREE_CODE (decl) == VAR_DECL)
+ {
+ DECL_COMDAT (decl) = 1;
+ /* Mark it needed so we don't forget to emit it. */
+ mark_referenced (DECL_ASSEMBLER_NAME (decl));
+ }
}
}
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index bb34d822157..10dfaca6086 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -390,6 +390,8 @@ use_thunk (tree thunk_fndecl, bool emit_p)
rewrite. */
TREE_PUBLIC (thunk_fndecl) = TREE_PUBLIC (function);
DECL_VISIBILITY (thunk_fndecl) = DECL_VISIBILITY (function);
+ if (flag_weak && TREE_PUBLIC (thunk_fndecl))
+ comdat_linkage (thunk_fndecl);
if (flag_syntax_only)
{
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index c619dc681c4..45fa0123b36 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -10661,6 +10661,7 @@ do_type_instantiation (tree t, tree storage, tsubst_flags_t complain)
int extern_p = 0;
int nomem_p = 0;
int static_p = 0;
+ int previous_instantiation_extern_p = 0;
if (TREE_CODE (t) == TYPE_DECL)
t = TREE_TYPE (t);
@@ -10722,11 +10723,16 @@ do_type_instantiation (tree t, tree storage, tsubst_flags_t complain)
No program shall explicitly instantiate any template more
than once.
- If CLASSTYPE_INTERFACE_ONLY, then the first explicit instantiation
- was `extern'. If EXTERN_P then the second is. If -frepo, chances
- are we already got marked as an explicit instantiation because of the
- repo file. All these cases are OK. */
- if (!CLASSTYPE_INTERFACE_ONLY (t) && !extern_p && !flag_use_repository
+ If PREVIOUS_INSTANTIATION_EXTERN_P, then the first explicit
+ instantiation was `extern'. If EXTERN_P then the second is.
+ If -frepo, chances are we already got marked as an explicit
+ instantiation because of the repo file. All these cases are
+ OK. */
+
+ previous_instantiation_extern_p = CLASSTYPE_INTERFACE_ONLY (t);
+
+ if (!previous_instantiation_extern_p && !extern_p
+ && !flag_use_repository
&& (complain & tf_error))
pedwarn ("duplicate explicit instantiation of `%#T'", t);
@@ -10743,6 +10749,7 @@ do_type_instantiation (tree t, tree storage, tsubst_flags_t complain)
{
tree tmp;
+ int explicitly_instantiate_members = 0;
/* In contrast to implicit instantiation, where only the
declarations, and not the definitions, of members are
@@ -10761,26 +10768,46 @@ do_type_instantiation (tree t, tree storage, tsubst_flags_t complain)
*explicit* instantiations or not. We choose to be generous,
and not set DECL_EXPLICIT_INSTANTIATION. Therefore, we allow
the explicit instantiation of a class where some of the members
- have no definition in the current translation unit. */
+ have no definition in the current translation unit. Exception:
+ on some targets (e.g. Darwin), weak symbols do not get put in
+ a static archive's TOC. The problematic case is if we're doing
+ a non-extern explicit instantiation of an extern template: we
+ have to put member functions in the TOC in that case, or we'll
+ get unresolved symbols at link time. */
+
+ explicitly_instantiate_members =
+ TARGET_EXPLICIT_INSTANTIATIONS_ONE_ONLY
+ && previous_instantiation_extern_p && ! extern_p
+ && ! TYPE_FOR_JAVA (t);
if (! static_p)
for (tmp = TYPE_METHODS (t); tmp; tmp = TREE_CHAIN (tmp))
if (TREE_CODE (tmp) == FUNCTION_DECL
&& DECL_TEMPLATE_INSTANTIATION (tmp))
{
- mark_decl_instantiated (tmp, extern_p);
- repo_template_instantiated (tmp, extern_p);
- if (! extern_p)
- instantiate_decl (tmp, /*defer_ok=*/1);
+ if (explicitly_instantiate_members)
+ do_decl_instantiation (tmp, NULL_TREE);
+ else
+ {
+ mark_decl_instantiated (tmp, extern_p);
+ repo_template_instantiated (tmp, extern_p);
+ if (! extern_p)
+ instantiate_decl (tmp, /*defer_ok=*/1);
+ }
}
for (tmp = TYPE_FIELDS (t); tmp; tmp = TREE_CHAIN (tmp))
if (TREE_CODE (tmp) == VAR_DECL && DECL_TEMPLATE_INSTANTIATION (tmp))
{
- mark_decl_instantiated (tmp, extern_p);
- repo_template_instantiated (tmp, extern_p);
- if (! extern_p)
- instantiate_decl (tmp, /*defer_ok=*/1);
+ if (explicitly_instantiate_members)
+ do_decl_instantiation (tmp, NULL_TREE);
+ else
+ {
+ mark_decl_instantiated (tmp, extern_p);
+ repo_template_instantiated (tmp, extern_p);
+ if (! extern_p)
+ instantiate_decl (tmp, /*defer_ok=*/1);
+ }
}
if (CLASSTYPE_NESTED_UTDS (t))
diff --git a/gcc/defaults.h b/gcc/defaults.h
index 7d34e3cd30b..602cbdd72a1 100644
--- a/gcc/defaults.h
+++ b/gcc/defaults.h
@@ -237,6 +237,18 @@ do { fputs (integer_asm_op (POINTER_SIZE / BITS_PER_UNIT, TRUE), FILE); \
#endif
#endif
+/* Determines whether explicit template instantiations should
+ be given link-once semantics. The C++ ABI requires this
+ macro to be nonzero; see the documentation. */
+#ifndef TARGET_EXPLICIT_INSTANTIATIONS_ONE_ONLY
+# define TARGET_EXPLICIT_INSTANTIATIONS_ONE_ONLY 1
+#endif
+
+/* This determines whether or not we need linkonce unwind information */
+#ifndef TARGET_USES_WEAK_UNWIND_INFO
+#define TARGET_USES_WEAK_UNWIND_INFO 0
+#endif
+
/* By default, there is no prefix on user-defined symbols. */
#ifndef USER_LABEL_PREFIX
#define USER_LABEL_PREFIX ""
@@ -258,6 +270,24 @@ do { fputs (integer_asm_op (POINTER_SIZE / BITS_PER_UNIT, TRUE), FILE); \
# endif
#endif
+/* This determines whether this target supports hidden visibility.
+ This is a weaker condition than HAVE_GAS_HIDDEN, which probes for
+ specific assembler syntax. */
+#ifndef TARGET_SUPPORTS_HIDDEN
+# ifdef HAVE_GAS_HIDDEN
+# define TARGET_SUPPORTS_HIDDEN 1
+# else
+# define TARGET_SUPPORTS_HIDDEN 0
+# endif
+#endif
+
+/* Determines whether we may use common symbols to represent one-only
+ semantics (a.k.a. "vague linkage"). */
+#ifndef USE_COMMON_FOR_ONE_ONLY
+# define USE_COMMON_FOR_ONE_ONLY 1
+#endif
+
+
/* If the target supports init_priority C++ attribute, give
SUPPORTS_INIT_PRIORITY a nonzero value. */
#ifndef SUPPORTS_INIT_PRIORITY
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index fe293e31eb2..1988c14ef20 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -3072,6 +3072,12 @@ for the abi and context in the @code{.unwabi} directive. If the
be updated in @var{fs}.
@end defmac
+@defmac TARGET_USES_WEAK_UNWIND_INFO
+A C expression that evaluates to true if the target requires unwind
+info to be given comdat linkage. Define it to be @code{1} if comdat
+linkage is necessary. The default is @code{0}.
+@end defmac
+
@node Stack Checking
@subsection Specifying How Stack Checking is Done
@@ -6705,6 +6711,24 @@ commands that will make the symbol(s) associated with @var{decl} have
hidden, protected or internal visibility as specified by @var{visibility}.
@end deftypefn
+@defmac TARGET_EXPLICIT_INSTANTIATIONS_ONE_ONLY
+A C expression that evaluates to true if the target's linker expects
+explicit template specializations, as well as implicit, to be given
+linkonce semantics. The default is @code{1}. The C++ ABI requires
+this macro to be nonzero. Define this macro for targets where full
+C++ ABI compliance is impossible and where explicit and implicit
+template specialization must be treated differently.
+@end defmac
+
+@defmac TARGET_SUPPORTS_HIDDEN
+A C expression that evaluates to true if the target supports hidden
+visibility. By default this expression is true if and only if
+@code{HAS_GAS_HIDDEN} is defined. Set this macro if the
+@code{HAS_GAS_HIDDEN} macro gives the wrong answer for this
+target. (For example, if the target's mechanism for supporting
+hidden visibility is not the same as GAS's.)
+@end defmac
+
@defmac ASM_OUTPUT_EXTERNAL (@var{stream}, @var{decl}, @var{name})
A C statement (sans semicolon) to output to the stdio stream
@var{stream} any text necessary for declaring the name of an external
@@ -7427,6 +7451,17 @@ If this macro is not defined, nothing special is output at the end of
the jump-table.
@end defmac
+@deftypefn {Target Hook} void TARGET_ASM_EMIT_UNWIND_LABEL (@var{stream}, @var{decl}, @var{empty})
+This target hook emits a label at the beginning of each FDE. It
+should be defined on targets where FDEs need special labels, and it
+should write the appropriate label, for the FDE associated with the
+function declaration @var{decl}, to the stdio stream @var{stream}.
+The third argument, @var{empty}, is a boolean: true if this is a
+placeholder label for an omitted FDE.
+
+The default is that FDEs are not given nonlocal labels.
+@end deftypefn
+
@node Exception Region Output
@subsection Assembler Commands for Exception Regions
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 55947932ddb..90a9caa7ebf 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -243,6 +243,7 @@ typedef struct cfa_loc GTY(())
typedef struct dw_fde_struct GTY(())
{
+ tree decl;
const char *dw_fde_begin;
const char *dw_fde_current_label;
const char *dw_fde_end;
@@ -391,7 +392,9 @@ static void def_cfa_1 (const char *, dw_cfa_location *);
#define FUNC_END_LABEL "LFE"
#endif
+#ifndef FRAME_BEGIN_LABEL
#define FRAME_BEGIN_LABEL "Lframe"
+#endif
#define CIE_AFTER_SIZE_LABEL "LSCIE"
#define CIE_END_LABEL "LECIE"
#define FDE_LABEL "LSFDE"
@@ -1942,6 +1945,22 @@ output_call_frame_info (int for_eh)
if (fde_table_in_use == 0)
return;
+ /* If we make FDEs linkonce, we may have to emit an empty label for
+ an FDE that wouldn't otherwise be emitted. We want to avoid
+ having an FDE kept around when the function it refers to is
+ discarded. (Example where this matters: a primary function
+ template in C++ requires EH information, but an explicit
+ specialization doesn't. */
+ if (TARGET_USES_WEAK_UNWIND_INFO
+ && ! flag_asynchronous_unwind_tables
+ && for_eh)
+ for (i = 0; i < fde_table_in_use; i++)
+ if ((fde_table[i].nothrow || fde_table[i].all_throwers_are_sibcalls)
+ && !fde_table[i].uses_eh_lsda
+ && ! DECL_ONE_ONLY (fde_table[i].decl))
+ (*targetm.asm_out.unwind_label) (asm_out_file, fde_table[i].decl,
+ /* empty */ 1);
+
/* If we don't have any functions we'll want to unwind out of, don't
emit any EH unwind information. Note that if exceptions aren't
enabled, we won't have collected nothrow information, and if we
@@ -1953,6 +1972,9 @@ output_call_frame_info (int for_eh)
for (i = 0; i < fde_table_in_use; i++)
if (fde_table[i].uses_eh_lsda)
any_eh_needed = any_lsda_needed = true;
+ else if (TARGET_USES_WEAK_UNWIND_INFO
+ && DECL_ONE_ONLY (fde_table[i].decl))
+ any_eh_needed = 1;
else if (! fde_table[i].nothrow
&& ! fde_table[i].all_throwers_are_sibcalls)
any_eh_needed = true;
@@ -2004,7 +2026,9 @@ output_call_frame_info (int for_eh)
P Indicates the presence of an encoding + language
personality routine in the CIE augmentation. */
- fde_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/1, /*global=*/0);
+ fde_encoding = TARGET_USES_WEAK_UNWIND_INFO
+ ? ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/2, /*global=*/1)
+ : ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/1, /*global=*/0);
per_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/2, /*global=*/1);
lsda_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/0, /*global=*/0);
@@ -2095,9 +2119,11 @@ output_call_frame_info (int for_eh)
/* Don't emit EH unwind info for leaf functions that don't need it. */
if (for_eh && !flag_asynchronous_unwind_tables && flag_exceptions
&& (fde->nothrow || fde->all_throwers_are_sibcalls)
+ && (! TARGET_USES_WEAK_UNWIND_INFO || ! DECL_ONE_ONLY (fde->decl))
&& !fde->uses_eh_lsda)
continue;
+ (*targetm.asm_out.unwind_label) (asm_out_file, fde->decl, /* empty */ 0);
(*targetm.asm_out.internal_label) (asm_out_file, FDE_LABEL, for_eh + i * 2);
ASM_GENERATE_INTERNAL_LABEL (l1, FDE_AFTER_SIZE_LABEL, for_eh + i * 2);
ASM_GENERATE_INTERNAL_LABEL (l2, FDE_END_LABEL, for_eh + i * 2);
@@ -2113,9 +2139,16 @@ output_call_frame_info (int for_eh)
if (for_eh)
{
- dw2_asm_output_encoded_addr_rtx (fde_encoding,
- gen_rtx_SYMBOL_REF (Pmode, fde->dw_fde_begin),
- "FDE initial location");
+ if (TARGET_USES_WEAK_UNWIND_INFO
+ && DECL_ONE_ONLY (fde->decl))
+ dw2_asm_output_encoded_addr_rtx (fde_encoding,
+ gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER
+ (DECL_ASSEMBLER_NAME (fde->decl))),
+ "FDE initial location");
+ else
+ dw2_asm_output_encoded_addr_rtx (fde_encoding,
+ gen_rtx_SYMBOL_REF (Pmode, fde->dw_fde_begin),
+ "FDE initial location");
dw2_asm_output_delta (size_of_encoded_value (fde_encoding),
fde->dw_fde_end, fde->dw_fde_begin,
"FDE address range");
@@ -2248,6 +2281,7 @@ dwarf2out_begin_prologue (unsigned int line ATTRIBUTE_UNUSED,
/* Add the new FDE at the end of the fde_table. */
fde = &fde_table[fde_table_in_use++];
+ fde->decl = current_function_decl;
fde->dw_fde_begin = xstrdup (label);
fde->dw_fde_current_label = NULL;
fde->dw_fde_end = NULL;
diff --git a/gcc/output.h b/gcc/output.h
index ee5668b4fee..36dab8cca82 100644
--- a/gcc/output.h
+++ b/gcc/output.h
@@ -514,6 +514,7 @@ extern const char *default_strip_name_encoding (const char *);
extern bool default_binds_local_p (tree);
extern bool default_binds_local_p_1 (tree, int);
extern void default_globalize_label (FILE *, const char *);
+extern void default_emit_unwind_label (FILE *, tree, int);
extern void default_internal_label (FILE *, const char *, unsigned long);
extern void default_file_start (void);
extern void file_end_indicate_exec_stack (void);
diff --git a/gcc/target-def.h b/gcc/target-def.h
index cfc8a19eb69..930fba64b10 100644
--- a/gcc/target-def.h
+++ b/gcc/target-def.h
@@ -57,6 +57,11 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef TARGET_ASM_GLOBALIZE_LABEL
#define TARGET_ASM_GLOBALIZE_LABEL default_globalize_label
#endif
+
+#ifndef TARGET_ASM_EMIT_UNWIND_LABEL
+#define TARGET_ASM_EMIT_UNWIND_LABEL default_emit_unwind_label
+#endif
+
#ifndef TARGET_ASM_INTERNAL_LABEL
#define TARGET_ASM_INTERNAL_LABEL default_internal_label
#endif
@@ -189,6 +194,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
TARGET_ASM_UNALIGNED_INT_OP, \
TARGET_ASM_INTEGER, \
TARGET_ASM_GLOBALIZE_LABEL, \
+ TARGET_ASM_EMIT_UNWIND_LABEL, \
TARGET_ASM_INTERNAL_LABEL, \
TARGET_ASM_ASSEMBLE_VISIBILITY, \
TARGET_ASM_FUNCTION_PROLOGUE, \
diff --git a/gcc/target.h b/gcc/target.h
index e33e815ec86..5dea29a8204 100644
--- a/gcc/target.h
+++ b/gcc/target.h
@@ -74,6 +74,12 @@ struct gcc_target
/* Output code that will globalize a label. */
void (* globalize_label) (FILE *, const char *);
+ /* Output code that will emit a label for unwind info, if this
+ target requires such labels. Second argument is the decl the
+ unwind info is associated with, third is is a boolean: true if
+ this is only a placeholder for an omitted FDE. */
+ void (* unwind_label ) (FILE *, tree, int);
+
/* Output an internal label. */
void (* internal_label) (FILE *, const char *, unsigned long);
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 061cbcac3ef..6a32ccc76d9 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -4104,6 +4104,9 @@ globalize_decl (tree decl)
}
return;
}
+#elif defined(ASM_MAKE_LABEL_LINKONCE)
+ if (DECL_ONE_ONLY (decl))
+ ASM_MAKE_LABEL_LINKONCE (asm_out_file, name);
#endif
(*targetm.asm_out.globalize_label) (asm_out_file, name);
@@ -4228,16 +4231,16 @@ make_decl_one_only (tree decl)
TREE_PUBLIC (decl) = 1;
- if (TREE_CODE (decl) == VAR_DECL
- && (DECL_INITIAL (decl) == 0 || DECL_INITIAL (decl) == error_mark_node))
- DECL_COMMON (decl) = 1;
- else if (SUPPORTS_ONE_ONLY)
+ if (SUPPORTS_ONE_ONLY)
{
#ifdef MAKE_DECL_ONE_ONLY
MAKE_DECL_ONE_ONLY (decl);
#endif
DECL_ONE_ONLY (decl) = 1;
}
+ else if (TREE_CODE (decl) == VAR_DECL
+ && (DECL_INITIAL (decl) == 0 || DECL_INITIAL (decl) == error_mark_node))
+ DECL_COMMON (decl) = 1;
else if (SUPPORTS_WEAK)
DECL_WEAK (decl) = 1;
else
@@ -4917,6 +4920,16 @@ default_globalize_label (FILE * stream, const char *name)
}
#endif /* GLOBAL_ASM_OP */
+/* Default function to output a label for unwind information. The
+ default is to do nothing. A target that needs nonlocal labels for
+ unwind information must provide its own function to do this. */
+void
+default_emit_unwind_label (FILE * stream ATTRIBUTE_UNUSED,
+ tree decl ATTRIBUTE_UNUSED,
+ int empty ATTRIBUTE_UNUSED)
+{
+}
+
/* This is how to output an internal numbered label where PREFIX is
the class of label and LABELNO is the number within the class. */