X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fconfig%2Fdarwin.c;h=6c63d7a32b4b89fefdce59ed676c8e1487a01bcb;hb=b701eaf88fbfb308928262b29c5435297fe67b9d;hp=66d1ab046475c6765b36077abee83c18fb3ae4aa;hpb=e8f535c26ca1f58d34c0c329e41c0344cb31913c;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/config/darwin.c b/gcc/config/darwin.c index 66d1ab04647..6c63d7a32b4 100644 --- a/gcc/config/darwin.c +++ b/gcc/config/darwin.c @@ -1,6 +1,6 @@ /* Functions for generic Darwin as target machine for GNU C compiler. Copyright (C) 1989, 1990, 1991, 1992, 1993, 2000, 2001, 2002, 2003, 2004, - 2005, 2006, 2007 + 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. Contributed by Apple Computer Inc. @@ -46,6 +46,8 @@ along with GCC; see the file COPYING3. If not see #include "hashtab.h" #include "df.h" #include "debug.h" +#include "obstack.h" +#include "lto-streamer.h" /* Darwin supports a feature called fix-and-continue, which is used for rapid turn around debugging. When code is compiled with the @@ -188,10 +190,8 @@ machopic_symbol_defined_p (rtx sym_ref) enum machopic_addr_class machopic_classify_symbol (rtx sym_ref) { - int flags; bool function_p; - flags = SYMBOL_REF_FLAGS (sym_ref); function_p = SYMBOL_REF_FUNCTION_P (sym_ref); if (machopic_symbol_defined_p (sym_ref)) return (function_p @@ -267,44 +267,26 @@ machopic_define_symbol (rtx mem) SYMBOL_REF_FLAGS (sym_ref) |= MACHO_SYMBOL_FLAG_DEFINED; } -static GTY(()) const char * function_base; +/* Return either ORIG or: -const char * -machopic_function_base_name (void) -{ - /* if dynamic-no-pic is on, we should not get here */ - gcc_assert (!MACHO_DYNAMIC_NO_PIC_P); - - if (function_base == NULL) - function_base = ggc_alloc_string ("", sizeof ("")); - - current_function_uses_pic_offset_table = 1; - - return function_base; -} - -/* Return a SYMBOL_REF for the PIC function base. */ + (const:P (unspec:P [ORIG] UNSPEC_MACHOPIC_OFFSET)) + depending on MACHO_DYNAMIC_NO_PIC_P. */ rtx -machopic_function_base_sym (void) -{ - rtx sym_ref; - - sym_ref = gen_rtx_SYMBOL_REF (Pmode, machopic_function_base_name ()); - SYMBOL_REF_FLAGS (sym_ref) - |= (MACHO_SYMBOL_FLAG_VARIABLE | MACHO_SYMBOL_FLAG_DEFINED); - return sym_ref; -} - -/* Return either ORIG or (const:P (minus:P ORIG PIC_BASE)), depending - on whether pic_base is NULL or not. */ -static inline rtx -gen_pic_offset (rtx orig, rtx pic_base) +machopic_gen_offset (rtx orig) { - if (!pic_base) + if (MACHO_DYNAMIC_NO_PIC_P) return orig; else - return gen_rtx_CONST (Pmode, gen_rtx_MINUS (Pmode, orig, pic_base)); + { + /* Play games to avoid marking the function as needing pic if we + are being called as part of the cost-estimation process. */ + if (current_ir_type () != IR_GIMPLE || currently_expanding_to_rtl) + crtl->uses_pic_offset_table = 1; + orig = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, orig), + UNSPEC_MACHOPIC_OFFSET); + return gen_rtx_CONST (Pmode, orig); + } } static GTY(()) const char * function_base_func_name; @@ -332,7 +314,7 @@ machopic_output_function_base_name (FILE *file) /* The suffix attached to stub symbols. */ #define STUB_SUFFIX "$stub" -typedef struct machopic_indirection GTY (()) +typedef struct GTY (()) machopic_indirection { /* The SYMBOL_REF for the entity referenced. */ rtx symbol; @@ -366,7 +348,8 @@ machopic_indirection_hash (const void *slot) static int machopic_indirection_eq (const void *slot, const void *key) { - return strcmp (((const machopic_indirection *) slot)->ptr_name, key) == 0; + return strcmp (((const machopic_indirection *) slot)->ptr_name, + (const char *) key) == 0; } /* Return the name of the non-lazy pointer (if STUB_P is false) or @@ -380,7 +363,6 @@ machopic_indirection_name (rtx sym_ref, bool stub_p) size_t namelen = strlen (name); machopic_indirection *p; void ** slot; - bool saw_star = false; bool needs_quotes; const char *suffix; const char *prefix = user_label_prefix; @@ -403,7 +385,6 @@ machopic_indirection_name (rtx sym_ref, bool stub_p) if (name[0] == '*') { - saw_star = true; prefix = ""; ++name; --namelen; @@ -420,7 +401,7 @@ machopic_indirection_name (rtx sym_ref, bool stub_p) else suffix = NON_LAZY_POINTER_SUFFIX; - buffer = alloca (strlen ("&L") + buffer = XALLOCAVEC (char, strlen ("&L") + strlen (prefix) + namelen + strlen (suffix) @@ -527,8 +508,7 @@ machopic_indirect_data_reference (rtx orig, rtx reg) else if (defined) { #if defined (TARGET_TOC) || defined (HAVE_lo_sum) - rtx pic_base = machopic_function_base_sym (); - rtx offset = gen_pic_offset (orig, pic_base); + rtx offset = machopic_gen_offset (orig); #endif #if defined (TARGET_TOC) /* i.e., PowerPC */ @@ -555,7 +535,7 @@ machopic_indirect_data_reference (rtx orig, rtx reg) emit_insn (gen_rtx_SET (VOIDmode, reg, gen_rtx_LO_SUM (Pmode, reg, copy_rtx (offset)))); - emit_insn (gen_rtx_USE (VOIDmode, pic_offset_table_rtx)); + emit_use (pic_offset_table_rtx); orig = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, reg); #endif @@ -674,8 +654,6 @@ machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg) )) { /* addr(foo) = &func+(foo-func) */ - rtx pic_base; - orig = machopic_indirect_data_reference (orig, reg); if (GET_CODE (orig) == PLUS @@ -688,12 +666,6 @@ machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg) return reg; } - /* if dynamic-no-pic we don't have a pic base */ - if (MACHO_DYNAMIC_NO_PIC_P) - pic_base = NULL; - else - pic_base = machopic_function_base_sym (); - if (GET_CODE (orig) == MEM) { if (reg == 0) @@ -730,7 +702,7 @@ machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg) if (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF || GET_CODE (XEXP (orig, 0)) == LABEL_REF) { - rtx offset = gen_pic_offset (XEXP (orig, 0), pic_base); + rtx offset = machopic_gen_offset (XEXP (orig, 0)); #if defined (TARGET_TOC) /* i.e., PowerPC */ /* Generating a new reg may expose opportunities for common subexpression elimination. */ @@ -756,9 +728,7 @@ machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg) pic_ref = reg; #else - emit_insn (gen_rtx_USE (VOIDmode, - gen_rtx_REG (Pmode, - PIC_OFFSET_TABLE_REGNUM))); + emit_use (gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM)); emit_insn (gen_rtx_SET (VOIDmode, reg, gen_rtx_HIGH (Pmode, @@ -782,16 +752,13 @@ machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg) pic = reg; } #if 0 - emit_insn (gen_rtx_USE (VOIDmode, - gen_rtx_REG (Pmode, - PIC_OFFSET_TABLE_REGNUM))); + emit_use (gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM)); #endif if (reload_in_progress) df_set_regs_ever_live (REGNO (pic), true); pic_ref = gen_rtx_PLUS (Pmode, pic, - gen_pic_offset (XEXP (orig, 0), - pic_base)); + machopic_gen_offset (XEXP (orig, 0))); } #if !defined (TARGET_TOC) @@ -806,7 +773,7 @@ machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg) if (GET_CODE (orig) == SYMBOL_REF || GET_CODE (orig) == LABEL_REF) { - rtx offset = gen_pic_offset (orig, pic_base); + rtx offset = machopic_gen_offset (orig); #if defined (TARGET_TOC) /* i.e., PowerPC */ rtx hi_sum_reg; @@ -857,14 +824,13 @@ machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg) pic = reg; } #if 0 - emit_insn (gen_rtx_USE (VOIDmode, - pic_offset_table_rtx)); + emit_use (pic_offset_table_rtx); #endif if (reload_in_progress) df_set_regs_ever_live (REGNO (pic), true); pic_ref = gen_rtx_PLUS (Pmode, pic, - gen_pic_offset (orig, pic_base)); + machopic_gen_offset (orig)); } } } @@ -974,7 +940,7 @@ machopic_output_indirection (void **slot, void *data) sym_name = IDENTIFIER_POINTER (id); } - sym = alloca (strlen (sym_name) + 2); + sym = XALLOCAVEC (char, strlen (sym_name) + 2); if (sym_name[0] == '*' || sym_name[0] == '&') strcpy (sym, sym_name + 1); else if (sym_name[0] == '-' || sym_name[0] == '+') @@ -982,7 +948,7 @@ machopic_output_indirection (void **slot, void *data) else sprintf (sym, "%s%s", user_label_prefix, sym_name); - stub = alloca (strlen (ptr_name) + 2); + stub = XALLOCAVEC (char, strlen (ptr_name) + 2); if (ptr_name[0] == '*' || ptr_name[0] == '&') strcpy (stub, ptr_name + 1); else @@ -1006,6 +972,30 @@ machopic_output_indirection (void **slot, void *data) rtx init = const0_rtx; switch_to_section (darwin_sections[machopic_nl_symbol_ptr_section]); + + /* Mach-O symbols are passed around in code through indirect + references and the original symbol_ref hasn't passed through + the generic handling and reference-catching in + output_operand, so we need to manually mark weak references + as such. */ + if (SYMBOL_REF_WEAK (symbol)) + { + tree decl = SYMBOL_REF_DECL (symbol); + gcc_assert (DECL_P (decl)); + + if (decl != NULL_TREE + && DECL_EXTERNAL (decl) && TREE_PUBLIC (decl) + /* Handle only actual external-only definitions, not + e.g. extern inline code or variables for which + storage has been allocated. */ + && !TREE_STATIC (decl)) + { + fputs ("\t.weak_reference ", asm_out_file); + assemble_name (asm_out_file, sym_name); + fputc ('\n', asm_out_file); + } + } + assemble_name (asm_out_file, ptr_name); fprintf (asm_out_file, ":\n"); @@ -1044,27 +1034,12 @@ int machopic_operand_p (rtx op) { if (MACHOPIC_JUST_INDIRECT) - { - while (GET_CODE (op) == CONST) - op = XEXP (op, 0); - - if (GET_CODE (op) == SYMBOL_REF) - return machopic_symbol_defined_p (op); - else - return 0; - } - - while (GET_CODE (op) == CONST) - op = XEXP (op, 0); - - if (GET_CODE (op) == MINUS - && GET_CODE (XEXP (op, 0)) == SYMBOL_REF - && GET_CODE (XEXP (op, 1)) == SYMBOL_REF - && machopic_symbol_defined_p (XEXP (op, 0)) - && machopic_symbol_defined_p (XEXP (op, 1))) - return 1; - - return 0; + return (GET_CODE (op) == SYMBOL_REF + && machopic_symbol_defined_p (op)); + else + return (GET_CODE (op) == CONST + && GET_CODE (XEXP (op, 0)) == UNSPEC + && XINT (XEXP (op, 0), 1) == UNSPEC_MACHOPIC_OFFSET); } /* This function records whether a given name corresponds to a defined @@ -1136,6 +1111,8 @@ darwin_mergeable_string_section (tree exp, && TREE_CODE (exp) == STRING_CST && TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE && align <= 256 + && (int_size_in_bytes (TREE_TYPE (exp)) + == TREE_STRING_LENGTH (exp)) && ((size_t) TREE_STRING_LENGTH (exp) == strlen (TREE_STRING_POINTER (exp)) + 1)) return darwin_sections[cstring_section]; @@ -1198,9 +1175,8 @@ machopic_select_section (tree decl, { bool weak = (DECL_P (decl) && DECL_WEAK (decl) - && (lookup_attribute ("weak", DECL_ATTRIBUTES (decl)) - || ! lookup_attribute ("weak_import", - DECL_ATTRIBUTES (decl)))); + && !lookup_attribute ("weak_import", + DECL_ATTRIBUTES (decl))); section *base_section; switch (categorize_decl_for_section (decl, reloc)) @@ -1394,12 +1370,108 @@ darwin_globalize_label (FILE *stream, const char *name) default_globalize_label (stream, name); } +/* This routine returns non-zero if 'name' starts with the special objective-c + anonymous file-scope static name. It accommodates c++'s mangling of such + symbols (in this case the symbols will have form _ZL{d}*_OBJC_* d=digit). */ + +int +darwin_label_is_anonymous_local_objc_name (const char *name) +{ + const unsigned char *p = (const unsigned char *) name; + if (*p != '_') + return 0; + if (p[1] == 'Z' && p[2] == 'L') + { + p += 3; + while (*p >= '0' && *p <= '9') + p++; + } + return (!strncmp ((const char *)p, "_OBJC_", 6)); +} + +/* LTO support for Mach-O. */ + +/* Section names for LTO sections. */ +static unsigned int lto_section_names_offset = 0; + +/* This is the obstack which we use to allocate the many strings. */ +static struct obstack lto_section_names_obstack; + +/* Segment name for LTO sections. */ +#define LTO_SEGMENT_NAME "__GNU_LTO" + +/* Section name for LTO section names section. */ +#define LTO_NAMES_SECTION "__section_names" + +/* File to temporarily store LTO data. This is appended to asm_out_file + in darwin_end_file. */ +static FILE *lto_asm_out_file, *saved_asm_out_file; +static char *lto_asm_out_name; + +/* Prepare asm_out_file for LTO output. For darwin, this means hiding + asm_out_file and switching to an alternative output file. */ +void +darwin_asm_lto_start (void) +{ + gcc_assert (! saved_asm_out_file); + saved_asm_out_file = asm_out_file; + if (! lto_asm_out_name) + lto_asm_out_name = make_temp_file (".lto.s"); + lto_asm_out_file = fopen (lto_asm_out_name, "a"); + if (lto_asm_out_file == NULL) + fatal_error ("failed to open temporary file %s for LTO output", + lto_asm_out_name); + asm_out_file = lto_asm_out_file; +} + +/* Restore asm_out_file. */ +void +darwin_asm_lto_end (void) +{ + gcc_assert (saved_asm_out_file); + fclose (lto_asm_out_file); + asm_out_file = saved_asm_out_file; + saved_asm_out_file = NULL; +} + void darwin_asm_named_section (const char *name, - unsigned int flags ATTRIBUTE_UNUSED, + unsigned int flags, tree decl ATTRIBUTE_UNUSED) { - fprintf (asm_out_file, "\t.section %s\n", name); + /* LTO sections go in a special segment __GNU_LTO. We want to replace the + section name with something we can use to represent arbitrary-length + names (section names in Mach-O are at most 16 characters long). */ + if (strncmp (name, LTO_SECTION_NAME_PREFIX, + strlen (LTO_SECTION_NAME_PREFIX)) == 0) + { + /* We expect certain flags to be set... */ + gcc_assert ((flags & (SECTION_DEBUG | SECTION_NAMED)) + == (SECTION_DEBUG | SECTION_NAMED)); + + /* Add the section name to the things to output when we end the + current assembler output file. + This is all not very efficient, but that doesn't matter -- this + shouldn't be a hot path in the compiler... */ + obstack_1grow (<o_section_names_obstack, '\t'); + obstack_grow (<o_section_names_obstack, ".ascii ", 7); + obstack_1grow (<o_section_names_obstack, '"'); + obstack_grow (<o_section_names_obstack, name, strlen (name)); + obstack_grow (<o_section_names_obstack, "\\0\"\n", 4); + + /* Output the dummy section name. */ + fprintf (asm_out_file, "\t# %s\n", name); + fprintf (asm_out_file, "\t.section %s,__%08X,regular,debug\n", + LTO_SEGMENT_NAME, lto_section_names_offset); + + /* Update the offset for the next section name. Make sure we stay + within reasonable length. */ + lto_section_names_offset += strlen (name) + 1; + gcc_assert (lto_section_names_offset > 0 + && lto_section_names_offset < ((unsigned) 1 << 31)); + } + else + fprintf (asm_out_file, "\t.section %s\n", name); } void @@ -1428,15 +1500,15 @@ darwin_handle_kext_attribute (tree *node, tree name, /* APPLE KEXT stuff -- only applies with pure static C++ code. */ if (! TARGET_KEXTABI) { - warning (0, "%<%s%> 2.95 vtable-compatibility attribute applies " - "only when compiling a kext", IDENTIFIER_POINTER (name)); + warning (0, "%qE 2.95 vtable-compatibility attribute applies " + "only when compiling a kext", name); *no_add_attrs = true; } else if (TREE_CODE (*node) != RECORD_TYPE) { - warning (0, "%<%s%> 2.95 vtable-compatibility attribute applies " - "only to C++ classes", IDENTIFIER_POINTER (name)); + warning (0, "%qE 2.95 vtable-compatibility attribute applies " + "only to C++ classes", name); *no_add_attrs = true; } @@ -1455,8 +1527,8 @@ darwin_handle_weak_import_attribute (tree *node, tree name, { if (TREE_CODE (*node) != FUNCTION_DECL && TREE_CODE (*node) != VAR_DECL) { - warning (OPT_Wattributes, "%qs attribute ignored", - IDENTIFIER_POINTER (name)); + warning (OPT_Wattributes, "%qE attribute ignored", + name); *no_add_attrs = true; } else @@ -1592,7 +1664,8 @@ darwin_asm_output_dwarf_delta (FILE *file, int size, fprintf (file, "\n\t%s L$set$%d", directive, darwin_dwarf_label_counter++); } -/* Output labels for the start of the DWARF sections if necessary. */ +/* Output labels for the start of the DWARF sections if necessary. + Initialize the stuff we need for LTO long section names support. */ void darwin_file_start (void) { @@ -1627,6 +1700,11 @@ darwin_file_start (void) fprintf (asm_out_file, "Lsection%.*s:\n", namelen, debugnames[i] + 8); } } + + /* We fill this obstack with the complete section text for the lto section + names to write in darwin_file_end. */ + obstack_init (<o_section_names_obstack); + lto_section_names_offset = 0; } /* Output an offset in a DWARF section on Darwin. On Darwin, DWARF section @@ -1653,6 +1731,8 @@ darwin_asm_output_dwarf_offset (FILE *file, int size, const char * lab, void darwin_file_end (void) { + const char *lto_section_names; + machopic_finish (asm_out_file); if (strcmp (lang_hooks.name, "GNU C++") == 0) { @@ -1660,6 +1740,52 @@ darwin_file_end (void) switch_to_section (darwin_sections[destructor_section]); ASM_OUTPUT_ALIGN (asm_out_file, 1); } + + /* If there was LTO assembler output, append it to asm_out_file. */ + if (lto_asm_out_name) + { + int n; + char *buf, *lto_asm_txt; + + /* Shouldn't be here if we failed to switch back. */ + gcc_assert (! saved_asm_out_file); + + lto_asm_out_file = fopen (lto_asm_out_name, "r"); + if (lto_asm_out_file == NULL) + fatal_error ("failed to open temporary file %s with LTO output", + lto_asm_out_name); + fseek (lto_asm_out_file, 0, SEEK_END); + n = ftell (lto_asm_out_file); + if (n > 0) + { + fseek (lto_asm_out_file, 0, SEEK_SET); + lto_asm_txt = buf = (char *) xmalloc (n + 1); + while (fgets (lto_asm_txt, n, lto_asm_out_file)) + fputs (lto_asm_txt, asm_out_file); + } + + /* Remove the temporary file. */ + fclose (lto_asm_out_file); + unlink_if_ordinary (lto_asm_out_name); + free (lto_asm_out_name); + } + + /* Finish the LTO section names obstack. Don't output anything if + there are no recorded section names. */ + obstack_1grow (<o_section_names_obstack, '\0'); + lto_section_names = XOBFINISH (<o_section_names_obstack, const char *); + if (strlen (lto_section_names) > 0) + { + fprintf (asm_out_file, + "\t.section %s,%s,regular,debug\n", + LTO_SEGMENT_NAME, LTO_NAMES_SECTION); + fprintf (asm_out_file, + "\t# Section names in %s are offsets into this table\n", + LTO_SEGMENT_NAME); + fprintf (asm_out_file, "%s\n", lto_section_names); + } + obstack_free (<o_section_names_obstack, NULL); + fprintf (asm_out_file, "\t.subsections_via_symbols\n"); } @@ -1713,6 +1839,22 @@ darwin_kextabi_p (void) { void darwin_override_options (void) { + /* Don't emit DWARF3/4 unless specifically selected. This is a + workaround for tool bugs. */ + if (dwarf_strict < 0) + dwarf_strict = 1; + + /* Disable -freorder-blocks-and-partition for darwin_emit_unwind_label. */ + if (flag_reorder_blocks_and_partition + && (targetm.asm_out.unwind_label == darwin_emit_unwind_label)) + { + inform (input_location, + "-freorder-blocks-and-partition does not work with exceptions " + "on this architecture"); + flag_reorder_blocks_and_partition = 0; + flag_reorder_blocks = 1; + } + if (flag_mkernel || flag_apple_kext) { /* -mkernel implies -fapple-kext for C++ */ @@ -1733,4 +1875,47 @@ darwin_override_options (void) flag_var_tracking_uninit = 1; } +/* Add $LDBL128 suffix to long double builtins. */ + +static void +darwin_patch_builtin (int fncode) +{ + tree fn = built_in_decls[fncode]; + tree sym; + char *newname; + + if (!fn) + return; + + sym = DECL_ASSEMBLER_NAME (fn); + newname = ACONCAT (("_", IDENTIFIER_POINTER (sym), "$LDBL128", NULL)); + + set_user_assembler_name (fn, newname); + + fn = implicit_built_in_decls[fncode]; + if (fn) + set_user_assembler_name (fn, newname); +} + +void +darwin_patch_builtins (void) +{ + if (LONG_DOUBLE_TYPE_SIZE != 128) + return; + +#define PATCH_BUILTIN(fncode) darwin_patch_builtin (fncode); +#define PATCH_BUILTIN_NO64(fncode) \ + if (!TARGET_64BIT) \ + darwin_patch_builtin (fncode); +#define PATCH_BUILTIN_VARIADIC(fncode) \ + if (!TARGET_64BIT \ + && (strverscmp (darwin_macosx_version_min, "10.3.9") >= 0)) \ + darwin_patch_builtin (fncode); +#include "darwin-ppc-ldouble-patch.def" +#undef PATCH_BUILTIN +#undef PATCH_BUILTIN_NO64 +#undef PATCH_BUILTIN_VARIADIC +} + + #include "gt-darwin.h"