Enabled linkonce support for Darwin.
authoraustern <austern@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 12 Mar 2004 17:09:03 +0000 (17:09 +0000)
committeraustern <austern@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 12 Mar 2004 17:09:03 +0000 (17:09 +0000)
* 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

17 files changed:
gcc/ChangeLog
gcc/config/darwin-protos.h
gcc/config/darwin.c
gcc/config/darwin.h
gcc/cp/ChangeLog
gcc/cp/decl2.c
gcc/cp/method.c
gcc/cp/pt.c
gcc/defaults.h
gcc/doc/tm.texi
gcc/dwarf2out.c
gcc/output.h
gcc/target-def.h
gcc/target.h
gcc/varasm.c
libffi/src/powerpc/darwin.S
libffi/src/powerpc/darwin_closure.S

index 4353cf6..e2821e3 100644 (file)
@@ -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
index 2866033..845a828 100644 (file)
@@ -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);
index 858d150..dec2eb7 100644 (file)
@@ -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);
index b5dae39..8a659d9 100644 (file)
@@ -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);       \
index e543c5c..fc34864 100644 (file)
@@ -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.
index 9d8043a..7310d09 100644 (file)
@@ -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));
+       }
     }
 }
 
index bb34d82..10dfaca 100644 (file)
@@ -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)
     {
index c619dc6..45fa012 100644 (file)
@@ -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))
index 7d34e3c..602cbdd 100644 (file)
@@ -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
index fe293e3..1988c14 100644 (file)
@@ -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
 
index 5594793..90a9caa 100644 (file)
@@ -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;
index ee5668b..36dab8c 100644 (file)
@@ -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);
index cfc8a19..930fba6 100644 (file)
@@ -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,           \
index e33e815..5dea29a 100644 (file)
@@ -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);
 
index 061cbca..6a32ccc 100644 (file)
@@ -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.  */
 
index 70c48e5..ad4824e 100644 (file)
@@ -162,8 +162,8 @@ _ffi_call_AIX:
 /* END(_ffi_call_AIX)  */
 
 .data
-.section __TEXT,__eh_frame
-Lframe1:
+.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms
+EH_frame1:
        .set    L$set$0,LECIE1-LSCIE1
        .long   L$set$0 ; Length of Common Information Entry
 LSCIE1:
@@ -173,19 +173,20 @@ LSCIE1:
        .byte   0x1     ; uleb128 0x1; CIE Code Alignment Factor
        .byte   0x7c    ; sleb128 -4; CIE Data Alignment Factor
        .byte   0x41    ; CIE RA Column
-       .byte   0x1     ; uleb128 0x1; Augmentation size
-       .byte   0x10    ; FDE Encoding (pcrel)
+       .byte   0x1     ; uleb128 0x1; Augmentation size
+       .byte   0x90    ; FDE Encoding (indirect pcrel)
        .byte   0xc     ; DW_CFA_def_cfa
        .byte   0x1     ; uleb128 0x1
        .byte   0x0     ; uleb128 0x0
        .align  2
 LECIE1:
+.globl _ffi_call_DARWIN.eh
+_ffi_call_DARWIN.eh:
 LSFDE1:
        .set    L$set$1,LEFDE1-LASFDE1
        .long   L$set$1 ; FDE Length
 LASFDE1:
-       .set    L$set$2,LASFDE1-Lframe1
-       .long   L$set$2 ; FDE CIE offset
+       .long   LASFDE1-EH_frame1 ; FDE CIE offset
        .long   LFB0-.  ; FDE initial location
        .set    L$set$3,LFE1-LFB0
        .long   L$set$3 ; FDE address range
index d8612a8..13ee81d 100644 (file)
@@ -234,8 +234,8 @@ Lfinish:
 /* END(ffi_closure_ASM)  */
 
 .data
-.section __TEXT,__eh_frame
-Lframe1:
+.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms
+EH_frame1:
        .set    L$set$0,LECIE1-LSCIE1
        .long   L$set$0 ; Length of Common Information Entry
 LSCIE1:
@@ -246,19 +246,20 @@ LSCIE1:
        .byte   0x7c    ; sleb128 -4; CIE Data Alignment Factor
        .byte   0x41    ; CIE RA Column
        .byte   0x1     ; uleb128 0x1; Augmentation size
-       .byte   0x10    ; FDE Encoding (pcrel)
+       .byte   0x90    ; FDE Encoding (indirect pcrel)
        .byte   0xc     ; DW_CFA_def_cfa
        .byte   0x1     ; uleb128 0x1
        .byte   0x0     ; uleb128 0x0
        .align  2
 LECIE1:
+.globl _ffi_closure_ASM.eh
+_ffi_closure_ASM.eh:
 LSFDE1:
        .set    L$set$1,LEFDE1-LASFDE1
        .long   L$set$1 ; FDE Length
 
 LASFDE1:
-       .set    L$set$2,LASFDE1-Lframe1
-       .long   L$set$2 ; FDE CIE offset
+       .long   LASFDE1-EH_frame1       ; FDE CIE offset
        .long   LFB1-.  ; FDE initial location
        .set    L$set$3,LFE1-LFB1
        .long   L$set$3 ; FDE address range