OSDN Git Service

* config/rs6000/rs6000.c (rs6000_emit_prologue): Use 5 nops,
[pf3gnuchains/gcc-fork.git] / gcc / config / darwin.c
index 579daf8..d3cafb1 100644 (file)
@@ -1,5 +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
+   Copyright (C) 1989, 1990, 1991, 1992, 1993, 2000, 2001, 2002, 2003, 2004,
+   2005
    Free Software Foundation, Inc.
    Contributed by Apple Computer Inc.
 
@@ -40,10 +41,42 @@ Boston, MA 02111-1307, USA.  */
 #include "function.h"
 #include "ggc.h"
 #include "langhooks.h"
+#include "target.h"
 #include "tm_p.h"
 #include "errors.h"
 #include "hashtab.h"
 
+/* Darwin supports a feature called fix-and-continue, which is used
+   for rapid turn around debugging.  When code is compiled with the
+   -mfix-and-continue flag, two changes are made to the generated code
+   that allow the system to do things that it would normally not be
+   able to do easily.  These changes allow gdb to load in
+   recompilation of a translation unit that has been changed into a
+   running program and replace existing functions and methods of that
+   translation unit with with versions of those functions and methods
+   from the newly compiled translation unit.  The new functions access
+   the existing static data from the old translation unit, if the data
+   existed in the unit to be replaced, and from the new translation
+   unit, for new data.
+
+   The changes are to insert 5 nops at the beginning of all functions
+   and to use indirection to get at static duration data.  The 5 nops
+   are required by consumers of the generated code.  Currently, gdb
+   uses this to patch in a jump to the overriding function, this
+   allows all uses of the old name to forward to the replacement,
+   including existing function pointers and virtual methods.  See
+   rs6000_emit_prologue for the code that handles the nop insertions.
+   The added indirection allows gdb to redirect accesses to static
+   duration data from the newly loaded translation unit to the
+   existing data, if any.  @code{static} data is special and is
+   handled by setting the second word in the .non_lazy_symbol_pointer
+   data structure to the address of the data.  See indirect_data for
+   the code that handles the extra indirection, and
+   machopic_output_indirection and its use of MACHO_SYMBOL_STATIC for
+   the code that handles @code{static} data indirection.  */
+
+
 /* Nonzero if the user passes the -mone-byte-bool switch, which forces
    sizeof(bool) to be 1. */
 const char *darwin_one_byte_bool = 0;
@@ -58,17 +91,30 @@ name_needs_quotes (const char *name)
   return 0;
 }
 
-/*
- * flag_pic = 1 ... generate only indirections
- * flag_pic = 2 ... generate indirections and pure code
- */
-
+/* Return true if SYM_REF can be used without an indirection.  */
 static int
 machopic_symbol_defined_p (rtx sym_ref)
 {
-  return ((SYMBOL_REF_FLAGS (sym_ref) & MACHO_SYMBOL_FLAG_DEFINED)
-         /* Local symbols must always be defined.  */
-         || SYMBOL_REF_LOCAL_P (sym_ref));
+  if (SYMBOL_REF_FLAGS (sym_ref) & MACHO_SYMBOL_FLAG_DEFINED)
+    return true;
+
+  /* If a symbol references local and is not an extern to this
+     file, then the symbol might be able to declared as defined.  */
+  if (SYMBOL_REF_LOCAL_P (sym_ref) && ! SYMBOL_REF_EXTERNAL_P (sym_ref))
+    {
+      /* If the symbol references a variable and the variable is a
+        common symbol, then this symbol is not defined.  */
+      if (SYMBOL_REF_FLAGS (sym_ref) & MACHO_SYMBOL_FLAG_VARIABLE)
+       {
+         tree decl = SYMBOL_REF_DECL (sym_ref);
+         if (!decl)
+           return true;
+         if (DECL_COMMON (decl))
+           return false;
+       }
+      return true;
+    }
+  return false;
 }
 
 /* This module assumes that (const (symbol_ref "foo")) is a legal pic
@@ -90,12 +136,55 @@ machopic_classify_symbol (rtx sym_ref)
            ? MACHOPIC_UNDEFINED_FUNCTION : MACHOPIC_UNDEFINED_DATA);
 }
 
+#ifndef TARGET_FIX_AND_CONTINUE
+#define TARGET_FIX_AND_CONTINUE 0
+#endif
+
+/* Indicate when fix-and-continue style code generation is being used
+   and when a reference to data should be indirected so that it can be
+   rebound in a new translation unit to reference the original instance
+   of that data.  Symbol names that are for code generation local to
+   the translation unit are bound to the new translation unit;
+   currently this means symbols that begin with L or _OBJC_;
+   otherwise, we indicate that an indirect reference should be made to
+   permit the runtime to rebind new instances of the translation unit
+   to the original instance of the data.  */
+
+static int
+indirect_data (rtx sym_ref)
+{
+  int lprefix;
+  const char *name;
+
+  /* If we aren't generating fix-and-continue code, don't do anything special.  */
+  if (TARGET_FIX_AND_CONTINUE == 0)
+    return 0;
+
+  /* Otherwise, all symbol except symbols that begin with L or _OBJC_
+     are indirected.  Symbols that begin with L and _OBJC_ are always
+     bound to the current translation unit as they are used for
+     generated local data of the translation unit.  */
+
+  name = XSTR (sym_ref, 0);
+
+  lprefix = (((name[0] == '*' || name[0] == '&')
+              && (name[1] == 'L' || (name[1] == '"' && name[2] == 'L')))
+             || (strncmp (name, "_OBJC_", 6) == 0));
+
+  return ! lprefix;
+}
+
+
 static int
 machopic_data_defined_p (rtx sym_ref)
 {
+  if (indirect_data (sym_ref))
+    return 0;
+
   switch (machopic_classify_symbol (sym_ref))
     {
     case MACHOPIC_DEFINED_DATA:
+    case MACHOPIC_DEFINED_FUNCTION:
       return 1;
     default:
       return 0;
@@ -173,9 +262,8 @@ typedef struct machopic_indirection GTY (())
 {
   /* The SYMBOL_REF for the entity referenced.  */
   rtx symbol;
-  /* The IDENTIFIER_NODE giving the name of the stub or non-lazy
-     pointer.  */
-  tree ptr_name;
+  /* The name of the stub or non-lazy pointer.  */
+  const char * ptr_name;
   /* True iff this entry is for a stub (as opposed to a non-lazy
      pointer).  */
   bool stub_p;
@@ -195,7 +283,7 @@ static hashval_t
 machopic_indirection_hash (const void *slot)
 {
   const machopic_indirection *p = (const machopic_indirection *) slot;
-  return IDENTIFIER_HASH_VALUE (p->ptr_name);
+  return htab_hash_string (p->ptr_name);
 }
 
 /* Returns true if the KEY is the same as that associated with
@@ -204,7 +292,7 @@ machopic_indirection_hash (const void *slot)
 static int
 machopic_indirection_eq (const void *slot, const void *key)
 {
-  return ((const machopic_indirection *) slot)->ptr_name == (tree) key;
+  return strcmp (((const machopic_indirection *) slot)->ptr_name, key) == 0;
 }
 
 /* Return the name of the non-lazy pointer (if STUB_P is false) or
@@ -215,9 +303,9 @@ machopic_indirection_name (rtx sym_ref, bool stub_p)
 {
   char *buffer;
   const char *name = XSTR (sym_ref, 0);
-  int namelen = strlen (name);
-  tree ptr_name;
+  size_t namelen = strlen (name);
   machopic_indirection *p;
+  void ** slot;
   
   /* Construct the name of the non-lazy pointer or stub.  */
   if (stub_p)
@@ -256,32 +344,29 @@ machopic_indirection_name (rtx sym_ref, bool stub_p)
                 user_label_prefix, name);
     }
 
-  /* See if we already have it.  */
-  ptr_name = maybe_get_identifier (buffer);
-  /* If not, create a mapping from the non-lazy pointer to the
-     SYMBOL_REF.  */
-  if (!ptr_name)
+  if (!machopic_indirections)
+    machopic_indirections = htab_create_ggc (37, 
+                                            machopic_indirection_hash,
+                                            machopic_indirection_eq,
+                                            /*htab_del=*/NULL);
+  
+  slot = htab_find_slot_with_hash (machopic_indirections, buffer,
+                                  htab_hash_string (buffer), INSERT);
+  if (*slot)
+    {
+      p = (machopic_indirection *) *slot;
+    }
+  else
     {
-      void **slot;
-      ptr_name = get_identifier (buffer);
       p = (machopic_indirection *) ggc_alloc (sizeof (machopic_indirection));
       p->symbol = sym_ref;
-      p->ptr_name = ptr_name;
+      p->ptr_name = xstrdup (buffer);
       p->stub_p = stub_p;
-      p->used = 0;
-      if (!machopic_indirections)
-       machopic_indirections 
-         = htab_create_ggc (37, 
-                            machopic_indirection_hash,
-                            machopic_indirection_eq,
-                            /*htab_del=*/NULL);
-      slot = htab_find_slot_with_hash (machopic_indirections, ptr_name,
-                                      IDENTIFIER_HASH_VALUE (ptr_name),
-                                      INSERT);
-      *((machopic_indirection **) slot) = p;
+      p->used = false;
+      *slot = p;
     }
   
-  return IDENTIFIER_POINTER (ptr_name);
+  return p->ptr_name;
 }
 
 /* Return the name of the stub for the mcount function.  */
@@ -289,7 +374,8 @@ machopic_indirection_name (rtx sym_ref, bool stub_p)
 const char*
 machopic_mcount_stub_name (void)
 {
-  return "&L*mcount$stub";
+  rtx symbol = gen_rtx_SYMBOL_REF (Pmode, "*mcount");
+  return machopic_indirection_name (symbol, /*stub_p=*/true);
 }
 
 /* If NAME is the name of a stub or a non-lazy pointer , mark the stub
@@ -300,18 +386,27 @@ machopic_mcount_stub_name (void)
 void
 machopic_validate_stub_or_non_lazy_ptr (const char *name)
 {
-  tree ident = get_identifier (name);
-
   machopic_indirection *p;
   
   p = ((machopic_indirection *) 
-       (htab_find_with_hash (machopic_indirections, ident,
-                            IDENTIFIER_HASH_VALUE (ident))));
-  if (p)
+       (htab_find_with_hash (machopic_indirections, name,
+                            htab_hash_string (name))));
+  if (p && ! p->used)
     {
-      p->used = 1;
-      mark_referenced (ident);
-      mark_referenced (get_identifier (XSTR (p->symbol, 0)));
+      const char *real_name;
+      tree id;
+      
+      p->used = true;
+
+      /* Do what output_addr_const will do when we actually call it.  */
+      if (SYMBOL_REF_DECL (p->symbol))
+       mark_decl_referenced (SYMBOL_REF_DECL (p->symbol));
+
+      real_name = targetm.strip_name_encoding (XSTR (p->symbol, 0));
+      
+      id = maybe_get_identifier (real_name);
+      if (id)
+       mark_referenced (id);
     }
 }
 
@@ -333,12 +428,8 @@ machopic_indirect_data_reference (rtx orig, rtx reg)
       if (defined && MACHO_DYNAMIC_NO_PIC_P)
        {
 #if defined (TARGET_TOC)
-         emit_insn (GET_MODE (orig) == DImode
-                    ? gen_macho_high_di (reg, orig)
-                    : gen_macho_high (reg, orig));
-         emit_insn (GET_MODE (orig) == DImode
-                    ? gen_macho_low_di (reg, reg, orig)
-                    : gen_macho_low (reg, reg, orig));
+         emit_insn (gen_macho_high (reg, orig));
+         emit_insn (gen_macho_low (reg, reg, orig));
 #else
           /* some other cpu -- writeme!  */
           abort ();
@@ -382,13 +473,14 @@ machopic_indirect_data_reference (rtx orig, rtx reg)
          return orig;
        }
 
-      ptr_ref = (gen_rtx_SYMBOL_REF 
+      ptr_ref = (gen_rtx_SYMBOL_REF
                 (Pmode, 
                  machopic_indirection_name (orig, /*stub_p=*/false)));
 
       SYMBOL_REF_DECL (ptr_ref) = SYMBOL_REF_DECL (orig);
 
       ptr_ref = gen_const_mem (Pmode, ptr_ref);
+      machopic_define_symbol (ptr_ref);
 
       return ptr_ref;
     }
@@ -533,9 +625,7 @@ machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
              rtx asym = XEXP (orig, 0);
              rtx mem;
 
-             emit_insn (mode == DImode
-                        ? gen_macho_high_di (temp_reg, asym)
-                        : gen_macho_high (temp_reg, asym));
+             emit_insn (gen_macho_high (temp_reg, asym));
              mem = gen_const_mem (GET_MODE (orig),
                                   gen_rtx_LO_SUM (Pmode, temp_reg, asym));
              emit_insn (gen_rtx_SET (VOIDmode, reg, mem));
@@ -665,7 +755,8 @@ machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
          else
 #endif  /*  HAVE_lo_sum  */
            {
-             if (GET_CODE (orig) == REG)
+             if (REG_P (orig)
+                 || GET_CODE (orig) == SUBREG)
                {
                  return orig;
                }
@@ -776,7 +867,7 @@ machopic_output_indirection (void **slot, void *data)
 
   symbol = p->symbol;
   sym_name = XSTR (symbol, 0);
-  ptr_name = IDENTIFIER_POINTER (p->ptr_name);
+  ptr_name = p->ptr_name;
   
   if (p->stub_p)
     {
@@ -797,9 +888,11 @@ machopic_output_indirection (void **slot, void *data)
       else
        sprintf (stub, "%s%s", user_label_prefix, ptr_name);
 
-      machopic_output_stub (asm_out_file, sym, stub);    
+      machopic_output_stub (asm_out_file, sym, stub);
     }
-  else if (machopic_symbol_defined_p (symbol))
+  else if (! indirect_data (symbol)
+          && (machopic_symbol_defined_p (symbol)
+              || SYMBOL_REF_LOCAL_P (symbol)))
     {
       data_section ();
       assemble_align (GET_MODE_ALIGNMENT (Pmode));
@@ -810,6 +903,8 @@ machopic_output_indirection (void **slot, void *data)
     }
   else
     {
+      rtx init = const0_rtx;
+
       machopic_nl_symbol_ptr_section ();
       assemble_name (asm_out_file, ptr_name);
       fprintf (asm_out_file, ":\n");
@@ -818,7 +913,18 @@ machopic_output_indirection (void **slot, void *data)
       assemble_name (asm_out_file, sym_name);
       fprintf (asm_out_file, "\n");
       
-      assemble_integer (const0_rtx, GET_MODE_SIZE (Pmode),
+      /* Variables that are marked with MACHO_SYMBOL_STATIC need to
+        have their symbol name instead of 0 in the second entry of
+        the non-lazy symbol pointer data structure when they are
+        defined.  This allows the runtime to rebind newer instances
+        of the translation unit with the original instance of the
+        data.  */
+
+      if ((SYMBOL_REF_FLAGS (symbol) & MACHO_SYMBOL_STATIC)
+         && machopic_symbol_defined_p (symbol))
+       init = gen_rtx_SYMBOL_REF (Pmode, sym_name);
+
+      assemble_integer (init, GET_MODE_SIZE (Pmode),
                        GET_MODE_ALIGNMENT (Pmode), 1);
     }
   
@@ -829,7 +935,7 @@ void
 machopic_finish (FILE *asm_out_file)
 {
   if (machopic_indirections)
-    htab_traverse_noresize (machopic_indirections, 
+    htab_traverse_noresize (machopic_indirections,
                            machopic_output_indirection,
                            asm_out_file);
 }
@@ -881,26 +987,17 @@ darwin_encode_section_info (tree decl, rtx rtl, int first ATTRIBUTE_UNUSED)
     SYMBOL_REF_FLAGS (sym_ref) |= MACHO_SYMBOL_FLAG_VARIABLE;
 
   if (!DECL_EXTERNAL (decl)
-      && (!TREE_PUBLIC (decl) || (!DECL_ONE_ONLY (decl) && !DECL_WEAK (decl)))
+      && (!TREE_PUBLIC (decl) || !DECL_WEAK (decl))
       && ((TREE_STATIC (decl)
           && (!DECL_COMMON (decl) || !TREE_PUBLIC (decl)))
          || (!DECL_COMMON (decl) && DECL_INITIAL (decl)
              && DECL_INITIAL (decl) != error_mark_node)))
     SYMBOL_REF_FLAGS (sym_ref) |= MACHO_SYMBOL_FLAG_DEFINED;
-}
 
-void
-darwin_make_decl_one_only (tree decl)
-{
-  static const char *text_section = "__TEXT,__textcoal_nt,coalesced,no_toc";
-  static const char *data_section = "__DATA,__datacoal_nt,coalesced,no_toc";
-
-  const char *sec = TREE_CODE (decl) == FUNCTION_DECL
-    ? text_section
-    : data_section;
-  TREE_PUBLIC (decl) = 1;
-  DECL_ONE_ONLY (decl) = 1;
-  DECL_SECTION_NAME (decl) = build_string (strlen (sec), sec);
+  if (TREE_CODE (decl) == VAR_DECL
+      && indirect_data (sym_ref)
+      && ! TREE_PUBLIC (decl))
+    SYMBOL_REF_FLAGS (sym_ref) |= MACHO_SYMBOL_STATIC;
 }
 
 void
@@ -916,13 +1013,28 @@ machopic_select_section (tree exp, int reloc,
                         unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
 {
   void (*base_function)(void);
-
-  if (decl_readonly_section_1 (exp, reloc, MACHOPIC_INDIRECT))
-    base_function = readonly_data_section;
+  bool weak_p = DECL_P (exp) && DECL_WEAK (exp);
+  static void (* const base_funs[][2])(void) = {
+    { text_section, text_coal_section },
+    { unlikely_text_section, text_unlikely_coal_section },
+    { readonly_data_section, const_coal_section },
+    { const_data_section, const_data_coal_section },
+    { data_section, data_coal_section }
+  };
+
+  if (reloc == 0
+      && (last_text_section == in_text_unlikely
+         || last_text_section == in_text_unlikely_coal))
+    reloc = 1;
+    
+  if (TREE_CODE (exp) == FUNCTION_DECL)
+    base_function = base_funs[reloc][weak_p];
+  else if (decl_readonly_section_1 (exp, reloc, MACHOPIC_INDIRECT))
+    base_function = base_funs[2][weak_p];
   else if (TREE_READONLY (exp) || TREE_CONSTANT (exp))
-    base_function = const_data_section;
+    base_function = base_funs[3][weak_p];
   else
-    base_function = data_section;
+    base_function = base_funs[4][weak_p];
 
   if (TREE_CODE (exp) == STRING_CST
       && ((size_t) TREE_STRING_LENGTH (exp)
@@ -931,7 +1043,7 @@ machopic_select_section (tree exp, int reloc,
   else if ((TREE_CODE (exp) == INTEGER_CST || TREE_CODE (exp) == REAL_CST)
           && flag_merge_constants)
     {
-      tree size = TYPE_SIZE (TREE_TYPE (exp));
+      tree size = TYPE_SIZE_UNIT (TREE_TYPE (exp));
 
       if (TREE_CODE (size) == INTEGER_CST &&
          TREE_INT_CST_LOW (size) == 4 &&
@@ -1016,6 +1128,28 @@ machopic_select_section (tree exp, int reloc,
       else
        base_function ();
     }
+  /* ::operator new and ::operator delete must be coalesced, even
+     if not weak.  There are 8 variants that we look for.  */
+  else if (TREE_CODE (exp) == FUNCTION_DECL
+          && ! DECL_ONE_ONLY (exp))
+    {
+      const char * name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (exp));
+      if (name[0] == '_' && name[1] == 'Z'
+         && ((name[2] == 'n' && (name[3] == 'a' || name[3] == 'w')
+              && name[4] == 'm')
+             || (name[2] == 'd' && (name[3] == 'a' || name[3] == 'l')
+                 && name[4] == 'P' && name[5] == 'v')))
+       {
+         bool delete_p = name[2] == 'd';
+         if (name[5 + delete_p] == 0
+             || strcmp (name + 5 + delete_p, "KSt9nothrow_t") == 0)
+           base_funs[reloc][1] ();
+         else
+           base_function ();
+       }
+      else
+       base_function ();
+    }
   else
     base_function ();
 }
@@ -1027,7 +1161,9 @@ void
 machopic_select_rtx_section (enum machine_mode mode, rtx x,
                             unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
 {
-  if (GET_MODE_SIZE (mode) == 8)
+  if (GET_MODE_SIZE (mode) == 8
+      && (GET_CODE (x) == CONST_INT
+         || GET_CODE (x) == CONST_DOUBLE))
     literal8_section ();
   else if (GET_MODE_SIZE (mode) == 4
           && (GET_CODE (x) == CONST_INT
@@ -1078,41 +1214,43 @@ darwin_globalize_label (FILE *stream, const char *name)
 }
 
 void
-darwin_asm_named_section (const char *name, unsigned int flags ATTRIBUTE_UNUSED)
+darwin_asm_named_section (const char *name, 
+                         unsigned int flags ATTRIBUTE_UNUSED,
+                         tree decl ATTRIBUTE_UNUSED)
 {
-  fprintf (asm_out_file, ".section %s\n", name);
+  fprintf (asm_out_file, "\t.section %s\n", name);
 }
 
-unsigned int
-darwin_section_type_flags (tree decl, const char *name, int reloc)
-{
-  unsigned int flags = default_section_type_flags (decl, name, reloc);
-  /* Weak or linkonce variables live in a writable section.  */
-  if (decl != 0 && TREE_CODE (decl) != FUNCTION_DECL
-      && (DECL_WEAK (decl) || DECL_ONE_ONLY (decl)))
-    flags |= SECTION_WRITE;
-  
-  return flags;
-}              
-
 void 
-darwin_unique_section (tree decl, int reloc ATTRIBUTE_UNUSED)
+darwin_unique_section (tree decl ATTRIBUTE_UNUSED, int reloc ATTRIBUTE_UNUSED)
 {
-  /* Darwin does not use unique sections.  However, the target's
-     unique_section hook is called for linkonce symbols.  We need
-     to set an appropriate section for such symbols. */
-  if (DECL_ONE_ONLY (decl) && !DECL_SECTION_NAME (decl))
-    darwin_make_decl_one_only (decl);
+  /* Darwin does not use unique sections.  */
 }
 
-#define HAVE_DEAD_STRIP 0
+/* Handle a "weak_import" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+tree
+darwin_handle_weak_import_attribute (tree *node, tree name,
+                                    tree ARG_UNUSED (args),
+                                    int ARG_UNUSED (flags),
+                                    bool * no_add_attrs)
+{
+  if (TREE_CODE (*node) != FUNCTION_DECL && TREE_CODE (*node) != VAR_DECL)
+    {
+      warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
+      *no_add_attrs = true;
+    }
+  else
+    declare_weak (*node);
+
+  return NULL_TREE;
+}
 
 static void
 no_dead_strip (FILE *file, const char *lab)
 {
-  if (HAVE_DEAD_STRIP)
-    fprintf (file, ".no_dead_strip %s\n", lab);
+  fprintf (file, ".no_dead_strip %s\n", lab);
 }
 
 /* Emit a label for an FDE, making it global and/or weak if appropriate. 
@@ -1154,14 +1292,14 @@ darwin_emit_unwind_label (FILE *file, tree decl, int for_eh, int empty)
     strcat(lab, "\"");
 
   if (TREE_PUBLIC (decl))
-    fprintf (file, "%s %s\n",
+    fprintf (file, "\t%s %s\n",
             (DECL_VISIBILITY (decl) != VISIBILITY_HIDDEN
              ? ".globl"
              : ".private_extern"),
             lab);
 
-  if (DECL_ONE_ONLY (decl) && TREE_PUBLIC (decl))
-    fprintf (file, ".weak_definition %s\n", lab);
+  if (DECL_WEAK (decl))
+    fprintf (file, "\t.weak_definition %s\n", lab);
 
   if (empty)
     {
@@ -1214,7 +1352,7 @@ darwin_assemble_visibility (tree decl, int vis)
       fputs ("\n", asm_out_file);
     }
   else
-    warning ("internal and protected visibility attributes not supported"
+    warning ("internal and protected visibility attributes not supported "
             "in this configuration; ignored");
 }
 
@@ -1228,21 +1366,22 @@ darwin_assemble_visibility (tree decl, int vis)
 static int darwin_dwarf_label_counter;
 
 void
-darwin_asm_output_dwarf_delta (FILE *file, int size ATTRIBUTE_UNUSED,
+darwin_asm_output_dwarf_delta (FILE *file, int size,
                               const char *lab1, const char *lab2)
 {
   int islocaldiff = (lab1[0] == '*' && lab1[1] == 'L'
                     && lab2[0] == '*' && lab2[1] == 'L');
+  const char *directive = (size == 8 ? ".quad" : ".long");
 
   if (islocaldiff)
     fprintf (file, "\t.set L$set$%d,", darwin_dwarf_label_counter);
   else
-    fprintf (file, "\t%s\t", ".long");
-  assemble_name (file, lab1);
+    fprintf (file, "\t%s\t", directive);
+  assemble_name_raw (file, lab1);
   fprintf (file, "-");
-  assemble_name (file, lab2);
+  assemble_name_raw (file, lab2);
   if (islocaldiff)
-    fprintf (file, "\n\t.long L$set$%d", darwin_dwarf_label_counter++);
+    fprintf (file, "\n\t%s L$set$%d", directive, darwin_dwarf_label_counter++);
 }
 
 void
@@ -1258,4 +1397,13 @@ darwin_file_end (void)
   fprintf (asm_out_file, "\t.subsections_via_symbols\n");
 }
 
+/* True, iff we're generating fast turn around debugging code.  When
+   true, we arrange for function prologues to start with 4 nops so
+   that gdb may insert code to redirect them, and for data to accessed
+   indirectly.  The runtime uses this indirection to forward
+   references for data to the original instance of that data.  */
+
+int darwin_fix_and_continue;
+const char *darwin_fix_and_continue_switch;
+
 #include "gt-darwin.h"