OSDN Git Service

cp/:
[pf3gnuchains/gcc-fork.git] / gcc / config / darwin.c
index 93c629d..c8bb508 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
+   2005, 2006, 2007, 2008, 2009
    Free Software Foundation, Inc.
    Contributed by Apple Computer Inc.
 
@@ -8,7 +8,7 @@ This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
 any later version.
 
 GCC is distributed in the hope that it will be useful,
@@ -17,9 +17,8 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING.  If not, write to
-the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 #include "config.h"
 #include "system.h"
@@ -268,45 +267,26 @@ machopic_define_symbol (rtx mem)
   SYMBOL_REF_FLAGS (sym_ref) |= MACHO_SYMBOL_FLAG_DEFINED;
 }
 
-static GTY(()) 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 =
-      (char *) ggc_alloc_string ("<pic base>", sizeof ("<pic base>"));
-
-  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)
+machopic_gen_offset (rtx orig)
 {
-  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)
-{
-  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;
@@ -334,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;
@@ -368,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
@@ -422,7 +403,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)
@@ -529,8 +510,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 */
@@ -544,7 +524,8 @@ machopic_indirect_data_reference (rtx orig, rtx reg)
                              gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
                                       gen_rtx_HIGH (Pmode, offset))));
          emit_insn (gen_rtx_SET (Pmode, reg,
-                                 gen_rtx_LO_SUM (Pmode, hi_sum_reg, offset)));
+                                 gen_rtx_LO_SUM (Pmode, hi_sum_reg,
+                                                 copy_rtx (offset))));
 
          orig = reg;
 #else
@@ -554,8 +535,9 @@ machopic_indirect_data_reference (rtx orig, rtx reg)
          emit_insn (gen_rtx_SET (VOIDmode, reg,
                                  gen_rtx_HIGH (Pmode, offset)));
          emit_insn (gen_rtx_SET (VOIDmode, reg,
-                                 gen_rtx_LO_SUM (Pmode, reg, offset)));
-         emit_insn (gen_rtx_USE (VOIDmode, pic_offset_table_rtx));
+                                 gen_rtx_LO_SUM (Pmode, reg,
+                                                 copy_rtx (offset))));
+         emit_use (pic_offset_table_rtx);
 
          orig = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, reg);
 #endif
@@ -674,8 +656,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 +668,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)
@@ -716,7 +690,8 @@ machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
 
              emit_insn (gen_macho_high (temp_reg, asym));
              mem = gen_const_mem (GET_MODE (orig),
-                                  gen_rtx_LO_SUM (Pmode, temp_reg, asym));
+                                  gen_rtx_LO_SUM (Pmode, temp_reg,
+                                                  copy_rtx (asym)));
              emit_insn (gen_rtx_SET (VOIDmode, reg, mem));
 #else
              /* Some other CPU -- WriteMe! but right now there are no other
@@ -729,7 +704,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.  */
@@ -748,15 +723,14 @@ machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
 
              mem = gen_const_mem (GET_MODE (orig),
                                  gen_rtx_LO_SUM (Pmode,
-                                                 hi_sum_reg, offset));
+                                                 hi_sum_reg,
+                                                 copy_rtx (offset)));
              insn = emit_insn (gen_rtx_SET (VOIDmode, reg, mem));
              set_unique_reg_note (insn, REG_EQUAL, pic_ref);
 
              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,
@@ -764,7 +738,8 @@ machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
                                                                   offset))));
              emit_insn (gen_rtx_SET (VOIDmode, reg,
                                  gen_rtx_LO_SUM (Pmode, reg,
-                                          gen_rtx_CONST (Pmode, offset))));
+                                          gen_rtx_CONST (Pmode,
+                                                         copy_rtx (offset)))));
              pic_ref = gen_rtx_PLUS (Pmode,
                                      pic_offset_table_rtx, reg);
 #endif
@@ -779,16 +754,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)
@@ -803,7 +775,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;
 
@@ -824,13 +796,15 @@ machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
                                                                    offset))));
              emit_insn (gen_rtx_SET (VOIDmode, reg,
                                      gen_rtx_LO_SUM (Pmode,
-                                                     hi_sum_reg, offset)));
+                                                     hi_sum_reg,
+                                                     copy_rtx (offset))));
              pic_ref = reg;
 #else
              emit_insn (gen_rtx_SET (VOIDmode, reg,
                                      gen_rtx_HIGH (Pmode, offset)));
              emit_insn (gen_rtx_SET (VOIDmode, reg,
-                                     gen_rtx_LO_SUM (Pmode, reg, offset)));
+                                     gen_rtx_LO_SUM (Pmode, reg,
+                                                     copy_rtx (offset))));
              pic_ref = gen_rtx_PLUS (Pmode,
                                      pic_offset_table_rtx, reg);
 #endif
@@ -852,14 +826,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));
                }
            }
        }
@@ -969,7 +942,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] == '+')
@@ -977,7 +950,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
@@ -1001,6 +974,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");
 
@@ -1039,27 +1036,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
@@ -1131,6 +1113,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];
@@ -1423,15 +1407,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;
     }
@@ -1450,8 +1434,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
@@ -1460,12 +1444,6 @@ darwin_handle_weak_import_attribute (tree *node, tree name,
   return NULL_TREE;
 }
 
-static void
-no_dead_strip (FILE *file, const char *lab)
-{
-  fprintf (file, ".no_dead_strip %s\n", lab);
-}
-
 /* Emit a label for an FDE, making it global and/or weak if appropriate.
    The third parameter is nonzero if this is for exception handling.
    The fourth parameter is nonzero if this is just a placeholder for an
@@ -1474,46 +1452,44 @@ no_dead_strip (FILE *file, const char *lab)
 void
 darwin_emit_unwind_label (FILE *file, tree decl, int for_eh, int empty)
 {
-  const char *base;
   char *lab;
-  bool need_quotes;
-
-  if (DECL_ASSEMBLER_NAME_SET_P (decl))
-    base = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
-  else
-    base = IDENTIFIER_POINTER (DECL_NAME (decl));
-
-  base = targetm.strip_name_encoding (base);
-  need_quotes = name_needs_quotes (base);
 
   if (! for_eh)
     return;
 
-  lab = concat (need_quotes ? "\"" : "", user_label_prefix, base, ".eh",
-               need_quotes ? "\"" : "", NULL);
+  lab = concat (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)), ".eh", NULL);
 
   if (TREE_PUBLIC (decl))
-    fprintf (file, "\t%s %s\n",
-            (DECL_VISIBILITY (decl) != VISIBILITY_HIDDEN
-             ? ".globl"
-             : ".private_extern"),
-            lab);
+    {
+      targetm.asm_out.globalize_label (file, lab);
+      if (DECL_VISIBILITY (decl) == VISIBILITY_HIDDEN)
+       {
+         fputs ("\t.private_extern ", file);
+         assemble_name (file, lab);
+         fputc ('\n', file);
+       }
+    }
 
   if (DECL_WEAK (decl))
-    fprintf (file, "\t.weak_definition %s\n", lab);
+    {
+      fputs ("\t.weak_definition ", file);
+      assemble_name (file, lab);
+      fputc ('\n', file);
+    }
 
+  assemble_name (file, lab);
   if (empty)
     {
-      fprintf (file, "%s = 0\n", lab);
+      fputs (" = 0\n", file);
 
       /* Mark the absolute .eh and .eh1 style labels as needed to
         ensure that we don't dead code strip them and keep such
         labels from another instantiation point until we can fix this
         properly with group comdat support.  */
-      no_dead_strip (file, lab);
+      darwin_mark_decl_preserved (lab);
     }
   else
-    fprintf (file, "%s:\n", lab);
+    fputs (":\n", file);
 
   free (lab);
 }
@@ -1673,7 +1649,7 @@ darwin_file_end (void)
    functions at dynamic-link time, except for vtables in kexts.  */
 
 bool
-darwin_binds_local_p (tree decl)
+darwin_binds_local_p (const_tree decl)
 {
   return default_binds_local_p_1 (decl,
                                  TARGET_KEXTABI && DARWIN_VTABLE_P (decl));
@@ -1736,4 +1712,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"