OSDN Git Service

PR target/33120
[pf3gnuchains/gcc-fork.git] / gcc / config / darwin.c
index fe33273..7794c10 100644 (file)
@@ -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, 2008
+   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 ("<pic base>", sizeof ("<pic base>"));
-
-  crtl->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;
@@ -381,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;
@@ -404,7 +385,6 @@ machopic_indirection_name (rtx sym_ref, bool stub_p)
 
   if (name[0] == '*')
     {
-      saw_star = true;
       prefix = "";
       ++name;
       --namelen;
@@ -528,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 */
@@ -675,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
@@ -689,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)
@@ -731,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.  */
@@ -787,8 +758,7 @@ machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
              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)
@@ -803,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;
 
@@ -860,7 +830,7 @@ machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
                    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));
                }
            }
        }
@@ -1064,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
@@ -1220,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))
@@ -1416,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 (&lto_section_names_obstack, '\t');
+      obstack_grow (&lto_section_names_obstack, ".ascii ", 7);
+      obstack_1grow (&lto_section_names_obstack, '"');
+      obstack_grow (&lto_section_names_obstack, name, strlen (name));
+      obstack_grow (&lto_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
@@ -1450,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;
     }
@@ -1477,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
@@ -1614,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)
 {
@@ -1649,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 (&lto_section_names_obstack);
+  lto_section_names_offset = 0;
 }
 
 /* Output an offset in a DWARF section on Darwin.  On Darwin, DWARF section
@@ -1675,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)
     {
@@ -1682,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 (&lto_section_names_obstack, '\0');
+  lto_section_names = XOBFINISH (&lto_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 (&lto_section_names_obstack, NULL);
+
   fprintf (asm_out_file, "\t.subsections_via_symbols\n");
 }
 
@@ -1735,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++ */
@@ -1797,5 +1917,41 @@ darwin_patch_builtins (void)
 #undef PATCH_BUILTIN_VARIADIC
 }
 
+void
+darwin_output_aligned_bss(FILE *fp, tree decl, const char *name,
+                         unsigned HOST_WIDE_INT size, unsigned int align)
+{
+  bool weak = (DECL_P (decl)
+              && DECL_WEAK (decl)
+              && !lookup_attribute ("weak_import",
+                                    DECL_ATTRIBUTES (decl)));
+  if (size == 0)
+    size = 1;
+  align = floor_log2 (align / BITS_PER_UNIT);
+  if (DECL_ONE_ONLY (decl) || weak) {
+    if (TREE_READONLY (decl) || TREE_CONSTANT (decl))
+      switch_to_section (darwin_sections[const_data_coal_section]);
+    else
+      switch_to_section (darwin_sections[data_coal_section]);
+    ASM_OUTPUT_ALIGN (fp, align);
+    ASM_DECLARE_OBJECT_NAME (fp, name, decl);
+    ASM_OUTPUT_SKIP (fp, size);
+    return;
+  }
+
+  fputs (".zerofill ", fp);
+  /* We uniquely name sections based upon the alignment as otherwise
+     all symbols in the section would get that alignment.  */
+  if (TREE_READONLY (decl) || TREE_CONSTANT (decl))
+    fputs ("__TEXT, ", fp);
+  else
+    fputs ("__DATA, ", fp);
+  fprintf (fp, "__bss%d, ", align);
+  assemble_name (fp, name);
+  fprintf (fp, ", "HOST_WIDE_INT_PRINT_UNSIGNED", %u\n",
+          size, align);
+  (* targetm.encode_section_info) (decl, DECL_RTL (decl), false);
+  machopic_define_symbol (DECL_RTL (decl));
+}
 
 #include "gt-darwin.h"