diff options
author | austern <austern@138bc75d-0d04-0410-961f-82ee72b054a4> | 2004-03-12 17:09:03 +0000 |
---|---|---|
committer | austern <austern@138bc75d-0d04-0410-961f-82ee72b054a4> | 2004-03-12 17:09:03 +0000 |
commit | 2f9fc8efd7791829d4e81d6945cbe12ded8f94c3 (patch) | |
tree | caa8a2f6e25f2a2ca455a215f64f01003c8ba7c4 /gcc | |
parent | cd5edb432360227353f9d74a01082afedd347898 (diff) | |
download | gcc-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/ChangeLog | 55 | ||||
-rw-r--r-- | gcc/config/darwin-protos.h | 9 | ||||
-rw-r--r-- | gcc/config/darwin.c | 116 | ||||
-rw-r--r-- | gcc/config/darwin.h | 80 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 21 | ||||
-rw-r--r-- | gcc/cp/method.c | 2 | ||||
-rw-r--r-- | gcc/cp/pt.c | 55 | ||||
-rw-r--r-- | gcc/defaults.h | 30 | ||||
-rw-r--r-- | gcc/doc/tm.texi | 35 | ||||
-rw-r--r-- | gcc/dwarf2out.c | 42 | ||||
-rw-r--r-- | gcc/output.h | 1 | ||||
-rw-r--r-- | gcc/target-def.h | 6 | ||||
-rw-r--r-- | gcc/target.h | 6 | ||||
-rw-r--r-- | gcc/varasm.c | 21 |
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. */ |