OSDN Git Service

* gcc/config/m68k/m68k.c (m68k_delegitimize_address): Also expect
[pf3gnuchains/gcc-fork.git] / gcc / config / darwin.c
index 5796ace..79b4272 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
+   2005, 2006, 2007, 2008, 2009, 2010
    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"
@@ -28,7 +27,6 @@ Boston, MA 02110-1301, USA.  */
 #include "rtl.h"
 #include "regs.h"
 #include "hard-reg-set.h"
-#include "real.h"
 #include "insn-config.h"
 #include "conditions.h"
 #include "insn-flags.h"
@@ -43,8 +41,15 @@ Boston, MA 02110-1301, USA.  */
 #include "langhooks.h"
 #include "target.h"
 #include "tm_p.h"
+#include "c-tree.h"
+#include "c-lang.h"
+#include "diagnostic-core.h"
 #include "toplev.h"
 #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
@@ -76,9 +81,27 @@ Boston, MA 02110-1301, USA.  */
    of MACHO_SYMBOL_STATIC for the code that handles @code{static}
    symbol indirection.  */
 
+/* For darwin >= 9  (OSX 10.5) the linker is capable of making the necessary
+   branch islands and we no longer need to emit darwin stubs.
+   However, if we are generating code for earlier systems (or for use in the 
+   kernel) the stubs might still be required, and this will be set true.  */
+int darwin_emit_branch_islands = false;
+
+/* A flag to determine whether we are running c++ or obj-c++.  This has to be
+   settable from non-c-family contexts too (i.e. we can't use the c_dialect_
+   functions).  */
+int darwin_running_cxx;
+
 /* Section names.  */
 section * darwin_sections[NUM_DARWIN_SECTIONS];
 
+/* While we transition to using in-tests instead of ifdef'd code.  */
+#ifndef HAVE_lo_sum
+#define HAVE_lo_sum 0
+#define gen_macho_high(a,b) (a)
+#define gen_macho_low(a,b,c) (a)
+#endif
+
 /* True if we're setting __attribute__ ((ms_struct)).  */
 int darwin_ms_struct = false;
 
@@ -90,8 +113,13 @@ output_objc_section_asm_op (const void *directive)
 {
   static bool been_here = false;
 
+  /* The NeXT ObjC Runtime requires these sections to be present and in 
+     order in the object.  The code below implements this by emitting 
+     a section header for each ObjC section the first time that an ObjC
+     section is requested.  */
   if (! been_here)
     {
+      section *saved_in_section = in_section;
       static const enum darwin_section_enum tomark[] =
        {
          /* written, cold -> hot */
@@ -122,6 +150,7 @@ output_objc_section_asm_op (const void *directive)
       been_here = true;
       for (i = 0; i < ARRAY_SIZE (tomark); i++)
        switch_to_section (darwin_sections[tomark[i]]);
+      switch_to_section (saved_in_section);
     }
   output_section_asm_op (directive);
 }
@@ -150,13 +179,14 @@ name_needs_quotes (const char *name)
 {
   int c;
   while ((c = *name++) != '\0')
-    if (! ISIDNUM (c) && c != '.' && c != '$')
+    if (! ISIDNUM (c) 
+         && c != '.' && c != '$' && c != '_' )
       return 1;
   return 0;
 }
 
 /* Return true if SYM_REF can be used without an indirection.  */
-static int
+int
 machopic_symbol_defined_p (rtx sym_ref)
 {
   if (SYMBOL_REF_FLAGS (sym_ref) & MACHO_SYMBOL_FLAG_DEFINED)
@@ -187,10 +217,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
@@ -266,45 +294,26 @@ machopic_define_symbol (rtx mem)
   SYMBOL_REF_FLAGS (sym_ref) |= MACHO_SYMBOL_FLAG_DEFINED;
 }
 
-static GTY(()) char * function_base;
-
-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);
+/* Return either ORIG or:
 
-  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)
-{
-  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;
@@ -317,14 +326,24 @@ machopic_output_function_base_name (FILE *file)
 
   /* If dynamic-no-pic is on, we should not get here.  */
   gcc_assert (!MACHO_DYNAMIC_NO_PIC_P);
-  current_name =
-    IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));
-  if (function_base_func_name != current_name)
+  /* When we are generating _get_pc thunks within stubs, there is no current
+     function.  */
+  if (current_function_decl)
+    {
+      current_name =
+       IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));
+      if (function_base_func_name != current_name)
+       {
+         ++current_pic_label_num;
+         function_base_func_name = current_name;
+       }
+    }
+  else
     {
       ++current_pic_label_num;
-      function_base_func_name = current_name;
+      function_base_func_name = "L_machopic_stub_dummy";
     }
-  fprintf (file, "\"L%011d$pb\"", current_pic_label_num);
+  fprintf (file, "L%011d$pb", current_pic_label_num);
 }
 
 /* The suffix attached to non-lazy pointer symbols.  */
@@ -332,7 +351,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 +385,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 +400,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 +422,6 @@ machopic_indirection_name (rtx sym_ref, bool stub_p)
 
   if (name[0] == '*')
     {
-      saw_star = true;
       prefix = "";
       ++name;
       --namelen;
@@ -420,7 +438,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)
@@ -444,7 +462,7 @@ machopic_indirection_name (rtx sym_ref, bool stub_p)
     }
   else
     {
-      p = (machopic_indirection *) ggc_alloc (sizeof (machopic_indirection));
+      p = ggc_alloc_machopic_indirection ();
       p->symbol = sym_ref;
       p->ptr_name = xstrdup (buffer);
       p->stub_p = stub_p;
@@ -513,26 +531,31 @@ machopic_indirect_data_reference (rtx orig, rtx reg)
 
       if (defined && MACHO_DYNAMIC_NO_PIC_P)
        {
-#if defined (TARGET_TOC)
+         if (DARWIN_PPC)
+           {
          /* Create a new register for CSE opportunities.  */
-         rtx hi_reg = (no_new_pseudos ? reg : gen_reg_rtx (Pmode));
+         rtx hi_reg = (!can_create_pseudo_p () ? reg : gen_reg_rtx (Pmode));
          emit_insn (gen_macho_high (hi_reg, orig));
          emit_insn (gen_macho_low (reg, hi_reg, orig));
-#else
+             return reg;
+           }
+         else if (DARWIN_X86)
+           return orig;
+         else
           /* some other cpu -- writeme!  */
           gcc_unreachable ();
-#endif
-          return 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);
-#endif
+         rtx offset = NULL;
+         if (DARWIN_PPC || HAVE_lo_sum)
+           offset = machopic_gen_offset (orig);
 
-#if defined (TARGET_TOC) /* i.e., PowerPC */
-         rtx hi_sum_reg = (no_new_pseudos ? reg : gen_reg_rtx (Pmode));
+         if (DARWIN_PPC)
+           {
+         rtx hi_sum_reg = (!can_create_pseudo_p ()
+                           ? reg
+                           : gen_reg_rtx (Pmode));
 
          gcc_assert (reg);
 
@@ -540,22 +563,24 @@ 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
-#if defined (HAVE_lo_sum)
+           }
+         else if (HAVE_lo_sum)
+           {
          gcc_assert (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
-#endif
+           }
          return orig;
        }
 
@@ -568,24 +593,56 @@ machopic_indirect_data_reference (rtx orig, rtx reg)
       ptr_ref = gen_const_mem (Pmode, ptr_ref);
       machopic_define_symbol (ptr_ref);
 
+      if (DARWIN_X86 
+          && reg 
+          && MACHO_DYNAMIC_NO_PIC_P)
+       {
+           emit_insn (gen_rtx_SET (Pmode, reg, ptr_ref));
+           ptr_ref = reg;
+       }
+
       return ptr_ref;
     }
   else if (GET_CODE (orig) == CONST)
     {
-      rtx base, result;
-
-      /* legitimize both operands of the PLUS */
+      /* If "(const (plus ...", walk the PLUS and return that result.
+        PLUS processing (below) will restore the "(const ..." if
+        appropriate.  */
       if (GET_CODE (XEXP (orig, 0)) == PLUS)
+       return machopic_indirect_data_reference (XEXP (orig, 0), reg);
+      else 
+       return orig;
+    }
+  else if (GET_CODE (orig) == MEM)
+    {
+      XEXP (ptr_ref, 0) = 
+               machopic_indirect_data_reference (XEXP (orig, 0), reg);
+      return ptr_ref;
+    }
+  else if (GET_CODE (orig) == PLUS)
+    {
+      rtx base, result;
+      /* When the target is i386, this code prevents crashes due to the
+       compiler's ignorance on how to move the PIC base register to
+       other registers.  (The reload phase sometimes introduces such
+       insns.)  */
+      if (GET_CODE (XEXP (orig, 0)) == REG
+          && REGNO (XEXP (orig, 0)) == PIC_OFFSET_TABLE_REGNUM
+          /* Prevent the same register from being erroneously used
+             as both the base and index registers.  */
+          && (DARWIN_X86 && (GET_CODE (XEXP (orig, 1)) == CONST))
+          && reg)
        {
-         base = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 0),
-                                                  reg);
-         orig = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 1),
-                                                  (base == reg ? 0 : reg));
+         emit_move_insn (reg, XEXP (orig, 0));
+         XEXP (ptr_ref, 0) = reg;
+         return ptr_ref;
        }
-      else
-       return orig;
 
-      if (MACHOPIC_PURE && GET_CODE (orig) == CONST_INT)
+      /* Legitimize both operands of the PLUS.  */
+      base = machopic_indirect_data_reference (XEXP (orig, 0), reg);
+      orig = machopic_indirect_data_reference (XEXP (orig, 1),
+                                              (base == reg ? 0 : reg));
+      if (MACHOPIC_INDIRECT && (GET_CODE (orig) == CONST_INT))
        result = plus_constant (base, INTVAL (orig));
       else
        result = gen_rtx_PLUS (Pmode, base, orig);
@@ -604,26 +661,6 @@ machopic_indirect_data_reference (rtx orig, rtx reg)
        }
 
       return result;
-
-    }
-  else if (GET_CODE (orig) == MEM)
-    XEXP (ptr_ref, 0) = machopic_indirect_data_reference (XEXP (orig, 0), reg);
-  /* When the target is i386, this code prevents crashes due to the
-     compiler's ignorance on how to move the PIC base register to
-     other registers.  (The reload phase sometimes introduces such
-     insns.)  */
-  else if (GET_CODE (orig) == PLUS
-          && GET_CODE (XEXP (orig, 0)) == REG
-          && REGNO (XEXP (orig, 0)) == PIC_OFFSET_TABLE_REGNUM
-#ifdef I386
-          /* Prevent the same register from being erroneously used
-             as both the base and index registers.  */
-          && GET_CODE (XEXP (orig, 1)) == CONST
-#endif
-          && reg)
-    {
-      emit_move_insn (reg, XEXP (orig, 0));
-      XEXP (ptr_ref, 0) = reg;
     }
   return ptr_ref;
 }
@@ -634,6 +671,9 @@ machopic_indirect_data_reference (rtx orig, rtx reg)
 rtx
 machopic_indirect_call_target (rtx target)
 {
+  if (! darwin_emit_branch_islands)
+    return target;
+
   if (GET_CODE (target) != MEM)
     return target;
 
@@ -670,8 +710,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
@@ -684,12 +722,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)
@@ -698,19 +730,22 @@ machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
              reg = gen_reg_rtx (Pmode);
            }
 
-#ifdef HAVE_lo_sum
+#if HAVE_lo_sum
          if (MACHO_DYNAMIC_NO_PIC_P
              && (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
                  || GET_CODE (XEXP (orig, 0)) == LABEL_REF))
            {
 #if defined (TARGET_TOC)       /* ppc  */
-             rtx temp_reg = (no_new_pseudos) ? reg : gen_reg_rtx (Pmode);
+             rtx temp_reg = (!can_create_pseudo_p ()
+                             ? reg :
+                             gen_reg_rtx (Pmode));
              rtx asym = XEXP (orig, 0);
              rtx mem;
 
              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
@@ -723,11 +758,13 @@ 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.  */
-              rtx hi_sum_reg = no_new_pseudos ? reg : gen_reg_rtx (Pmode);
+              rtx hi_sum_reg = (!can_create_pseudo_p ()
+                               ? reg
+                               : gen_reg_rtx (Pmode));
              rtx mem;
              rtx insn;
              rtx sum;
@@ -740,15 +777,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,
@@ -756,7 +792,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
@@ -771,16 +808,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)
-               regs_ever_live[REGNO (pic)] = 1;
+               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)
@@ -791,11 +825,11 @@ machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
       else
        {
 
-#ifdef HAVE_lo_sum
+#if HAVE_lo_sum
          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;
 
@@ -816,13 +850,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
@@ -844,14 +880,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)
-                   regs_ever_live[REGNO (pic)] = 1;
+                   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));
                }
            }
        }
@@ -961,7 +996,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] == '+')
@@ -969,7 +1004,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
@@ -983,7 +1018,7 @@ machopic_output_indirection (void **slot, void *data)
     {
       switch_to_section (data_section);
       assemble_align (GET_MODE_ALIGNMENT (Pmode));
-      assemble_label (ptr_name);
+      assemble_label (asm_out_file, ptr_name);
       assemble_integer (gen_rtx_SYMBOL_REF (Pmode, sym_name),
                        GET_MODE_SIZE (Pmode),
                        GET_MODE_ALIGNMENT (Pmode), 1);
@@ -993,6 +1028,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");
 
@@ -1031,27 +1090,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
@@ -1089,7 +1133,7 @@ darwin_encode_section_info (tree decl, rtx rtl, int first ATTRIBUTE_UNUSED)
 void
 darwin_mark_decl_preserved (const char *name)
 {
-  fprintf (asm_out_file, ".no_dead_strip ");
+  fprintf (asm_out_file, "\t.no_dead_strip ");
   assemble_name (asm_out_file, name);
   fputc ('\n', asm_out_file);
 }
@@ -1123,6 +1167,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];
@@ -1172,6 +1218,12 @@ darwin_mergeable_constant_section (tree exp,
   return readonly_data_section;
 }
 
+int
+machopic_reloc_rw_mask (void)
+{
+  return MACHOPIC_INDIRECT ? 3 : 0;
+}
+
 section *
 machopic_select_section (tree decl,
                         int reloc,
@@ -1179,9 +1231,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))
@@ -1245,6 +1296,8 @@ machopic_select_section (tree decl,
           else
             return darwin_sections[objc_string_object_section];
         }
+      else if (!strcmp (IDENTIFIER_POINTER (name), "__builtin_CFString"))
+       return darwin_sections[cfstring_constant_object_section];
       else
         return base_section;
     }
@@ -1375,12 +1428,115 @@ 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;
+}
+
+static void
+darwin_asm_dwarf_section (const char *name, unsigned int flags, tree decl);
+
+/*  Called for the TARGET_ASM_NAMED_SECTION hook.  */
+
 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 if (strncmp (name, "__DWARF,", 8) == 0)
+    darwin_asm_dwarf_section (name, flags, decl);
+  else
+    fprintf (asm_out_file, "\t.section %s\n", name);
 }
 
 void
@@ -1409,15 +1565,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-compatability 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-compatability 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;
     }
@@ -1436,8 +1592,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
@@ -1446,12 +1602,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
@@ -1460,46 +1610,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);
 }
@@ -1530,6 +1678,20 @@ darwin_non_lazy_pcrel (FILE *file, rtx addr)
   fputs ("-.", file);
 }
 
+/* The implementation of ASM_DECLARE_CONSTANT_NAME.  */
+
+void
+darwin_asm_declare_constant_name (FILE *file, const char *name,
+                                 const_tree exp ATTRIBUTE_UNUSED,
+                                 HOST_WIDE_INT size)
+{
+  assemble_label (file, name);
+
+  /* Darwin doesn't support zero-size objects, so give them a byte.  */
+  if ((size) == 0)
+    assemble_zeros (1);
+}
+
 /* 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
@@ -1553,6 +1715,73 @@ darwin_assemble_visibility (tree decl, int vis)
             "not supported in this configuration; ignored");
 }
 
+/* VEC Used by darwin_asm_dwarf_section.
+   Maybe a hash tab would be better here - but the intention is that this is
+   a very short list (fewer than 16 items) and each entry should (ideally, 
+   eventually) only be presented once.
+
+   A structure to hold a dwarf debug section used entry.  */
+
+typedef struct GTY(()) dwarf_sect_used_entry {
+  const char *name;
+  unsigned count;
+}
+dwarf_sect_used_entry;
+
+DEF_VEC_O(dwarf_sect_used_entry);
+DEF_VEC_ALLOC_O(dwarf_sect_used_entry, gc);
+
+/* A list of used __DWARF sections.  */
+static GTY (()) VEC (dwarf_sect_used_entry, gc) * dwarf_sect_names_table;
+
+/* This is called when we are asked to assemble a named section and the 
+   name begins with __DWARF,.  We keep a list of the section names (without
+   the __DWARF, prefix) and use this to emit our required start label on the
+   first switch to each section.  */
+
+static void
+darwin_asm_dwarf_section (const char *name, unsigned int flags,
+                         tree ARG_UNUSED (decl))
+{
+  unsigned i;
+  int namelen;
+  const char * sname;
+  dwarf_sect_used_entry *ref;
+  bool found = false;
+  gcc_assert ((flags & (SECTION_DEBUG | SECTION_NAMED))
+                   == (SECTION_DEBUG | SECTION_NAMED));
+  /* We know that the name starts with __DWARF,  */
+  sname = name + 8;
+  namelen = strchr (sname, ',') - sname;
+  gcc_assert (namelen);
+  if (dwarf_sect_names_table == NULL)
+    dwarf_sect_names_table = VEC_alloc (dwarf_sect_used_entry, gc, 16);
+  else
+    for (i = 0; 
+        VEC_iterate (dwarf_sect_used_entry, dwarf_sect_names_table, i, ref);
+        i++)
+      {
+       if (!ref)
+         break;
+       if (!strcmp (ref->name, sname))
+         {
+           found = true;
+           ref->count++;
+           break;
+         }
+      }
+
+  fprintf (asm_out_file, "\t.section %s\n", name);
+  if (!found)
+    {
+      dwarf_sect_used_entry e;
+      fprintf (asm_out_file, "Lsection%.*s:\n", namelen, sname);
+      e.count = 1;
+      e.name = xstrdup (sname);
+      VEC_safe_push (dwarf_sect_used_entry, gc, dwarf_sect_names_table, &e);
+    }
+}
+
 /* Output a difference of two labels that will be an assembly time
    constant if the two labels are local.  (.long lab1-lab2 will be
    very different if lab1 is at the boundary between two sections; it
@@ -1581,43 +1810,6 @@ 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.  */
-void
-darwin_file_start (void)
-{
-  if (write_symbols == DWARF2_DEBUG)
-    {
-      static const char * const debugnames[] =
-       {
-         DEBUG_FRAME_SECTION,
-         DEBUG_INFO_SECTION,
-         DEBUG_ABBREV_SECTION,
-         DEBUG_ARANGES_SECTION,
-         DEBUG_MACINFO_SECTION,
-         DEBUG_LINE_SECTION,
-         DEBUG_LOC_SECTION,
-         DEBUG_PUBNAMES_SECTION,
-         DEBUG_PUBTYPES_SECTION,
-         DEBUG_STR_SECTION,
-         DEBUG_RANGES_SECTION
-       };
-      size_t i;
-
-      for (i = 0; i < ARRAY_SIZE (debugnames); i++)
-       {
-         int namelen;
-
-         switch_to_section (get_section (debugnames[i], SECTION_DEBUG, NULL));
-
-         gcc_assert (strncmp (debugnames[i], "__DWARF,", 8) == 0);
-         gcc_assert (strchr (debugnames[i] + 8, ','));
-
-         namelen = strchr (debugnames[i] + 8, ',') - (debugnames[i] + 8);
-         fprintf (asm_out_file, "Lsection%.*s:\n", namelen, debugnames[i] + 8);
-       }
-    }
-}
-
 /* Output an offset in a DWARF section on Darwin.  On Darwin, DWARF section
    offsets are not represented using relocs in .o files; either the
    section never leaves the .o file, or the linker or other tool is
@@ -1639,9 +1831,28 @@ darwin_asm_output_dwarf_offset (FILE *file, int size, const char * lab,
   darwin_asm_output_dwarf_delta (file, size, lab, sname);
 }
 
+/* Called from the within the TARGET_ASM_FILE_START for each target. 
+  Initialize the stuff we need for LTO long section names support.  */
+
+void
+darwin_file_start (void)
+{
+  /* 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;
+}
+
+/* Called for the TARGET_ASM_FILE_END hook.
+   Emit the mach-o pic indirection data, the lto data and, finally a flag
+   to tell the linker that it can break the file object into sections and
+   move those around for efficiency.  */
+
 void
 darwin_file_end (void)
 {
+  const char *lto_section_names;
+
   machopic_finish (asm_out_file);
   if (strcmp (lang_hooks.name, "GNU C++") == 0)
     {
@@ -1649,6 +1860,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");
 }
 
@@ -1659,7 +1916,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));
@@ -1702,11 +1959,22 @@ darwin_kextabi_p (void) {
 void
 darwin_override_options (void)
 {
-  if (flag_apple_kext && strcmp (lang_hooks.name, "GNU C++") != 0)
+  /* 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.emit_unwind_label == darwin_emit_unwind_label))
     {
-      warning (0, "command line option %<-fapple-kext%> is only valid for C++");
-      flag_apple_kext = 0;
+      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++ */
@@ -1719,6 +1987,378 @@ darwin_override_options (void)
       flag_exceptions = 0;
       /* No -fnon-call-exceptions data in kexts.  */
       flag_non_call_exceptions = 0;
+      /* We still need to emit branch islands for kernel context.  */
+      darwin_emit_branch_islands = true;
+    }
+  if (flag_var_tracking
+      && strverscmp (darwin_macosx_version_min, "10.5") >= 0
+      && debug_info_level >= DINFO_LEVEL_NORMAL
+      && debug_hooks->var_location != do_nothing_debug_hooks.var_location)
+    flag_var_tracking_uninit = 1;
+
+  if (MACHO_DYNAMIC_NO_PIC_P)
+    {
+      if (flag_pic)
+       warning (0, "-mdynamic-no-pic overrides -fpic or -fPIC");
+      flag_pic = 0;
+    }
+  else if (flag_pic == 1)
+    {
+      /* Darwin's -fpic is -fPIC.  */
+      flag_pic = 2;
+    }
+
+  /* It is assumed that branch island stubs are needed for earlier systems.  */
+  if (darwin_macosx_version_min
+      && strverscmp (darwin_macosx_version_min, "10.5") < 0)
+    darwin_emit_branch_islands = true;
+
+  /* The c_dialect...() macros are not available to us here.  */
+  darwin_running_cxx = (strstr (lang_hooks.name, "C++") != 0);
+}
+
+/* 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
+}
+
+/*  CFStrings implementation.  */
+static GTY(()) tree cfstring_class_reference = NULL_TREE;
+static GTY(()) tree cfstring_type_node = NULL_TREE;
+static GTY(()) tree ccfstring_type_node = NULL_TREE;
+static GTY(()) tree pccfstring_type_node = NULL_TREE;
+static GTY(()) tree pcint_type_node = NULL_TREE;
+static GTY(()) tree pcchar_type_node = NULL_TREE;
+
+static enum built_in_function DARWIN_BUILTIN_CFSTRINGMAKECONSTANTSTRING;
+
+/* Store all constructed constant CFStrings in a hash table so that
+   they get uniqued properly.  */
+
+typedef struct GTY (()) cfstring_descriptor {
+  /* The string literal.  */
+  tree literal;
+  /* The resulting constant CFString.  */
+  tree constructor;
+} cfstring_descriptor;
+
+static GTY ((param_is (struct cfstring_descriptor))) htab_t cfstring_htab;
+
+static hashval_t cfstring_hash (const void *);
+static int cfstring_eq (const void *, const void *);
+
+static tree
+add_builtin_field_decl (tree type, const char *name, tree **chain)
+{
+  tree field = build_decl (BUILTINS_LOCATION, FIELD_DECL, 
+                           get_identifier (name), type);
+
+  if (*chain != NULL)
+    **chain = field;
+  *chain = &DECL_CHAIN (field);
+
+  return field;
+}
+
+void
+darwin_init_cfstring_builtins (unsigned first_avail)
+{
+  tree cfsfun, fields, pccfstring_ftype_pcchar;
+  tree *chain = NULL;
+
+  DARWIN_BUILTIN_CFSTRINGMAKECONSTANTSTRING = 
+                       (enum built_in_function) first_avail;
+  
+  /* struct __builtin_CFString {
+       const int *isa;         (will point at
+       int flags;               __CFConstantStringClassReference)
+       const char *str;
+       long length;
+     };  */
+
+  pcint_type_node = build_pointer_type 
+                  (build_qualified_type (integer_type_node, TYPE_QUAL_CONST));
+
+  pcchar_type_node = build_pointer_type 
+                  (build_qualified_type (char_type_node, TYPE_QUAL_CONST));
+
+  cfstring_type_node = (*lang_hooks.types.make_type) (RECORD_TYPE);
+
+  /* Have to build backwards for finish struct.  */
+  fields = add_builtin_field_decl (long_integer_type_node, "length", &chain);
+  add_builtin_field_decl (pcchar_type_node, "str", &chain);
+  add_builtin_field_decl (integer_type_node, "flags", &chain);
+  add_builtin_field_decl (pcint_type_node, "isa", &chain);
+  finish_builtin_struct (cfstring_type_node, "__builtin_CFString",
+                        fields, NULL_TREE);
+
+  /* const struct __builtin_CFstring *
+     __builtin___CFStringMakeConstantString (const char *); */
+
+  ccfstring_type_node = build_qualified_type 
+                       (cfstring_type_node, TYPE_QUAL_CONST);
+  pccfstring_type_node = build_pointer_type (ccfstring_type_node);
+  pccfstring_ftype_pcchar = build_function_type_list 
+                       (pccfstring_type_node, pcchar_type_node, NULL_TREE);
+
+  cfsfun  = build_decl (BUILTINS_LOCATION, FUNCTION_DECL, 
+                       get_identifier ("__builtin___CFStringMakeConstantString"),
+                       pccfstring_ftype_pcchar);
+
+  TREE_PUBLIC (cfsfun) = 1;
+  DECL_EXTERNAL (cfsfun) = 1;
+  DECL_ARTIFICIAL (cfsfun) = 1;
+  /* Make a lang-specific section - dup_lang_specific_decl makes a new node
+     in place of the existing, which may be NULL.  */
+  DECL_LANG_SPECIFIC (cfsfun) = NULL;
+  (*lang_hooks.dup_lang_specific_decl) (cfsfun);
+  DECL_BUILT_IN_CLASS (cfsfun) = BUILT_IN_MD;
+  DECL_FUNCTION_CODE (cfsfun) = DARWIN_BUILTIN_CFSTRINGMAKECONSTANTSTRING;
+  lang_hooks.builtin_function (cfsfun);
+
+  /* extern int __CFConstantStringClassReference[];  */
+  cfstring_class_reference = build_decl (BUILTINS_LOCATION, VAR_DECL,
+                get_identifier ("__CFConstantStringClassReference"),
+                build_array_type (integer_type_node, NULL_TREE));
+
+  TREE_PUBLIC (cfstring_class_reference) = 1;
+  DECL_ARTIFICIAL (cfstring_class_reference) = 1;
+  (*lang_hooks.decls.pushdecl) (cfstring_class_reference);
+  DECL_EXTERNAL (cfstring_class_reference) = 1;
+  rest_of_decl_compilation (cfstring_class_reference, 0, 0);
+  
+  /* Initialize the hash table used to hold the constant CFString objects.  */
+  cfstring_htab = htab_create_ggc (31, cfstring_hash, cfstring_eq, NULL);
+}
+
+tree
+darwin_fold_builtin (tree fndecl, int n_args, tree *argp, 
+                    bool ARG_UNUSED (ignore))
+{
+  unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
+  
+  if (fcode == DARWIN_BUILTIN_CFSTRINGMAKECONSTANTSTRING)
+    {
+      if (!darwin_constant_cfstrings)
+       {
+         error ("built-in function %qD requires the" 
+                " %<-mconstant-cfstrings%> flag", fndecl);
+         return error_mark_node;
+       }
+
+      if (n_args != 1)
+       {
+         error ("built-in function %qD takes one argument only", fndecl);
+         return error_mark_node;
+       }
+
+      return darwin_build_constant_cfstring (*argp);
+    }
+
+  return NULL_TREE;
+}
+
+static hashval_t
+cfstring_hash (const void *ptr)
+{
+  tree str = ((const struct cfstring_descriptor *)ptr)->literal;
+  const unsigned char *p = (const unsigned char *) TREE_STRING_POINTER (str);
+  int i, len = TREE_STRING_LENGTH (str);
+  hashval_t h = len;
+
+  for (i = 0; i < len; i++)
+    h = ((h * 613) + p[i]);
+
+  return h;
+}
+
+static int
+cfstring_eq (const void *ptr1, const void *ptr2)
+{
+  tree str1 = ((const struct cfstring_descriptor *)ptr1)->literal;
+  tree str2 = ((const struct cfstring_descriptor *)ptr2)->literal;
+  int len1 = TREE_STRING_LENGTH (str1);
+
+  return (len1 == TREE_STRING_LENGTH (str2)
+         && !memcmp (TREE_STRING_POINTER (str1), TREE_STRING_POINTER (str2),
+                     len1));
+}
+
+tree
+darwin_build_constant_cfstring (tree str)
+{
+  struct cfstring_descriptor *desc, key;
+  void **loc;
+  tree addr;
+
+  if (!str)
+    {
+      error ("CFString literal is missing");
+      return error_mark_node;
+    }
+
+  STRIP_NOPS (str);
+
+  if (TREE_CODE (str) == ADDR_EXPR)
+    str = TREE_OPERAND (str, 0);
+
+  if (TREE_CODE (str) != STRING_CST)
+    {
+      error ("CFString literal expression is not a string constant");
+      return error_mark_node;
+    }
+
+  /* Perhaps we already constructed a constant CFString just like this one? */
+  key.literal = str;
+  loc = htab_find_slot (cfstring_htab, &key, INSERT);
+  desc = (struct cfstring_descriptor *) *loc;
+
+  if (!desc)
+    {
+      tree var, constructor, field;
+      VEC(constructor_elt,gc) *v = NULL;
+      int length = TREE_STRING_LENGTH (str) - 1;
+
+      if (darwin_warn_nonportable_cfstrings)
+       {
+         const char *s = TREE_STRING_POINTER (str);
+         int l = 0;
+
+         for (l = 0; l < length; l++)
+           if (!s[l] || !isascii (s[l]))
+             {
+               warning (darwin_warn_nonportable_cfstrings, "%s in CFString literal",
+                        s[l] ? "non-ASCII character" : "embedded NUL");
+               break;
+             }
+       }
+
+      *loc = desc = ggc_alloc_cleared_cfstring_descriptor ();
+      desc->literal = str;
+
+      /* isa *. */
+      field = TYPE_FIELDS (ccfstring_type_node);
+      CONSTRUCTOR_APPEND_ELT(v, NULL_TREE, 
+                            build1 (ADDR_EXPR,  TREE_TYPE (field),  
+                                    cfstring_class_reference));
+      /* flags */
+      field = DECL_CHAIN (field);
+      CONSTRUCTOR_APPEND_ELT(v, NULL_TREE, 
+                            build_int_cst (TREE_TYPE (field), 0x000007c8));
+      /* string *. */
+      field = DECL_CHAIN (field);
+      CONSTRUCTOR_APPEND_ELT(v, NULL_TREE,
+                            build1 (ADDR_EXPR, TREE_TYPE (field), str));
+      /* length */
+      field = DECL_CHAIN (field);
+      CONSTRUCTOR_APPEND_ELT(v, NULL_TREE,
+                            build_int_cst (TREE_TYPE (field), length));
+
+      constructor = build_constructor (ccfstring_type_node, v);
+      TREE_READONLY (constructor) = 1;
+      TREE_CONSTANT (constructor) = 1;
+      TREE_STATIC (constructor) = 1;
+
+      /* Fromage: The C++ flavor of 'build_unary_op' expects constructor nodes
+        to have the TREE_HAS_CONSTRUCTOR (...) bit set.  However, this file is
+        being built without any knowledge of C++ tree accessors; hence, we shall
+        use the generic accessor that TREE_HAS_CONSTRUCTOR actually maps to!  */
+      if (darwin_running_cxx)
+       TREE_LANG_FLAG_4 (constructor) = 1;  /* TREE_HAS_CONSTRUCTOR  */
+
+      /* Create an anonymous global variable for this CFString.  */
+      var = build_decl (input_location, CONST_DECL, 
+                       NULL, TREE_TYPE (constructor));
+      DECL_ARTIFICIAL (var) = 1;
+      TREE_STATIC (var) = 1;
+      DECL_INITIAL (var) = constructor;
+      /* FIXME: This should use a translation_unit_decl to indicate file scope.  */
+      DECL_CONTEXT (var) = NULL_TREE;
+      desc->constructor = var;
+    }
+
+  addr = build1 (ADDR_EXPR, pccfstring_type_node, desc->constructor);
+  TREE_CONSTANT (addr) = 1;
+
+  return addr;
+}
+
+bool
+darwin_cfstring_p (tree str)
+{
+  struct cfstring_descriptor key;
+  void **loc;
+
+  if (!str)
+    return false;
+
+  STRIP_NOPS (str);
+
+  if (TREE_CODE (str) == ADDR_EXPR)
+    str = TREE_OPERAND (str, 0);
+
+  if (TREE_CODE (str) != STRING_CST)
+    return false;
+
+  key.literal = str;
+  loc = htab_find_slot (cfstring_htab, &key, NO_INSERT);
+  
+  if (loc)
+    return true;
+
+  return false;
+}
+
+void
+darwin_enter_string_into_cfstring_table (tree str)
+{
+  struct cfstring_descriptor key;
+  void **loc;
+
+  key.literal = str;
+  loc = htab_find_slot (cfstring_htab, &key, INSERT);
+
+  if (!*loc)
+    {
+      *loc = ggc_alloc_cleared_cfstring_descriptor ();
+      ((struct cfstring_descriptor *)*loc)->literal = str;
     }
 }