OSDN Git Service

Add ability to track uninitialized variables, and mark uninitialized
[pf3gnuchains/gcc-fork.git] / gcc / config / darwin.c
index 25fecd8..0673915 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
    Free Software Foundation, Inc.
    Contributed by Apple Computer Inc.
 
@@ -45,6 +45,7 @@ Boston, MA 02110-1301, USA.  */
 #include "tm_p.h"
 #include "toplev.h"
 #include "hashtab.h"
+#include "df.h"
 
 /* Darwin supports a feature called fix-and-continue, which is used
    for rapid turn around debugging.  When code is compiled with the
@@ -79,6 +80,9 @@ Boston, MA 02110-1301, USA.  */
 /* Section names.  */
 section * darwin_sections[NUM_DARWIN_SECTIONS];
 
+/* True if we're setting __attribute__ ((ms_struct)).  */
+int darwin_ms_struct = false;
+
 /* A get_unnamed_section callback used to switch to an ObjC section.
    DIRECTIVE is as for output_section_asm_op.  */
 
@@ -217,7 +221,8 @@ 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 we aren't generating fix-and-continue code, don't do anything
+     special.  */
   if (TARGET_FIX_AND_CONTINUE == 0)
     return 0;
 
@@ -511,7 +516,7 @@ machopic_indirect_data_reference (rtx orig, rtx reg)
        {
 #if defined (TARGET_TOC)
          /* 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
@@ -528,7 +533,9 @@ machopic_indirect_data_reference (rtx orig, rtx reg)
 #endif
 
 #if defined (TARGET_TOC) /* i.e., PowerPC */
-         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));
 
          gcc_assert (reg);
 
@@ -700,7 +707,9 @@ machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
                  || 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;
 
@@ -709,7 +718,8 @@ machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
                                   gen_rtx_LO_SUM (Pmode, temp_reg, asym));
              emit_insn (gen_rtx_SET (VOIDmode, reg, mem));
 #else
-             /* Some other CPU -- WriteMe! but right now there are no other platform that can use dynamic-no-pic  */
+             /* Some other CPU -- WriteMe! but right now there are no other
+                platforms that can use dynamic-no-pic  */
              gcc_unreachable ();
 #endif
              pic_ref = reg;
@@ -722,7 +732,9 @@ machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
 #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;
@@ -737,8 +749,7 @@ machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
                                  gen_rtx_LO_SUM (Pmode,
                                                  hi_sum_reg, offset));
              insn = emit_insn (gen_rtx_SET (VOIDmode, reg, mem));
-             REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, pic_ref,
-                                                   REG_NOTES (insn));
+             set_unique_reg_note (insn, REG_EQUAL, pic_ref);
 
              pic_ref = reg;
 #else
@@ -773,7 +784,7 @@ machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
 #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));
@@ -844,7 +855,7 @@ machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
                                          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));
@@ -1090,130 +1101,225 @@ darwin_mark_decl_preserved (const char *name)
   fputc ('\n', asm_out_file);
 }
 
-section *
-machopic_select_section (tree exp, int reloc,
-                        unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
+static section *
+darwin_text_section (int reloc, int weak)
 {
-  section *base_section;
-  bool weak_p = (DECL_P (exp) && DECL_WEAK (exp)
-                && (lookup_attribute ("weak", DECL_ATTRIBUTES (exp))
-                    || ! lookup_attribute ("weak_import",
-                                           DECL_ATTRIBUTES (exp))));
-
-  if (TREE_CODE (exp) == FUNCTION_DECL)
-    {
-      if (reloc == 1)
-       base_section = (weak_p
-                       ? darwin_sections[text_unlikely_coal_section]
-                       : unlikely_text_section ());
-      else
-       base_section = weak_p ? darwin_sections[text_coal_section] : text_section;
-    }
-  else if (decl_readonly_section_1 (exp, reloc, MACHOPIC_INDIRECT))
-    base_section = weak_p ? darwin_sections[const_coal_section] : darwin_sections[const_section];
-  else if (TREE_READONLY (exp) || TREE_CONSTANT (exp))
-    base_section = weak_p ? darwin_sections[const_data_coal_section] : darwin_sections[const_data_section];
+  if (reloc)
+    return (weak
+           ? darwin_sections[text_unlikely_coal_section]
+           : unlikely_text_section ());
   else
-    base_section = weak_p ? darwin_sections[data_coal_section] : data_section;
+    return (weak
+           ? darwin_sections[text_coal_section]
+           : text_section);
+}
 
-  if (TREE_CODE (exp) == STRING_CST
+static section *
+darwin_rodata_section (int weak)
+{
+  return (weak
+         ? darwin_sections[const_coal_section]
+         : darwin_sections[const_section]);
+}
+
+static section *
+darwin_mergeable_string_section (tree exp,
+                                unsigned HOST_WIDE_INT align)
+{
+  if (flag_merge_constants
+      && TREE_CODE (exp) == STRING_CST
+      && TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE
+      && align <= 256
       && ((size_t) TREE_STRING_LENGTH (exp)
          == strlen (TREE_STRING_POINTER (exp)) + 1))
     return darwin_sections[cstring_section];
-  else if ((TREE_CODE (exp) == INTEGER_CST || TREE_CODE (exp) == REAL_CST)
-          && flag_merge_constants)
+
+  return readonly_data_section;
+}
+
+#ifndef HAVE_GAS_LITERAL16
+#define HAVE_GAS_LITERAL16 0
+#endif
+
+static section *
+darwin_mergeable_constant_section (tree exp,
+                                  unsigned HOST_WIDE_INT align)
+{
+  enum machine_mode mode = DECL_MODE (exp);
+  unsigned int modesize = GET_MODE_BITSIZE (mode);
+
+  if (flag_merge_constants
+      && mode != VOIDmode
+      && mode != BLKmode
+      && modesize <= align
+      && align >= 8
+      && align <= 256
+      && (align & (align -1)) == 0)
     {
       tree size = TYPE_SIZE_UNIT (TREE_TYPE (exp));
 
-      if (TREE_CODE (size) == INTEGER_CST &&
-         TREE_INT_CST_LOW (size) == 4 &&
-         TREE_INT_CST_HIGH (size) == 0)
-       return darwin_sections[literal4_section];
-      else if (TREE_CODE (size) == INTEGER_CST &&
-              TREE_INT_CST_LOW (size) == 8 &&
-              TREE_INT_CST_HIGH (size) == 0)
-       return darwin_sections[literal8_section];
+      if (TREE_CODE (size) == INTEGER_CST
+         && TREE_INT_CST_LOW (size) == 4
+         && TREE_INT_CST_HIGH (size) == 0)
+        return darwin_sections[literal4_section];
+      else if (TREE_CODE (size) == INTEGER_CST
+              && TREE_INT_CST_LOW (size) == 8
+              && TREE_INT_CST_HIGH (size) == 0)
+        return darwin_sections[literal8_section];
+      else if (HAVE_GAS_LITERAL16
+              && TARGET_64BIT
+               && TREE_CODE (size) == INTEGER_CST
+               && TREE_INT_CST_LOW (size) == 16
+               && TREE_INT_CST_HIGH (size) == 0)
+        return darwin_sections[literal16_section];
       else
-       return base_section;
+        return readonly_data_section;
     }
-  else if (TREE_CODE (exp) == CONSTRUCTOR
-          && TREE_TYPE (exp)
-          && TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE
-          && TYPE_NAME (TREE_TYPE (exp)))
+
+  return readonly_data_section;
+}
+
+int
+machopic_reloc_rw_mask (void)
+{
+  return MACHOPIC_INDIRECT ? 3 : 0;
+}
+
+section *
+machopic_select_section (tree decl,
+                        int reloc,
+                        unsigned HOST_WIDE_INT align)
+{
+  bool weak = (DECL_P (decl)
+              && DECL_WEAK (decl)
+              && (lookup_attribute ("weak", DECL_ATTRIBUTES (decl))
+                  || ! lookup_attribute ("weak_import",
+                                         DECL_ATTRIBUTES (decl))));
+  section *base_section;
+
+  switch (categorize_decl_for_section (decl, reloc))
     {
-      tree name = TYPE_NAME (TREE_TYPE (exp));
+    case SECCAT_TEXT:
+      base_section = darwin_text_section (reloc, weak);
+      break;
+
+    case SECCAT_RODATA:
+    case SECCAT_SRODATA:
+      base_section = darwin_rodata_section (weak);
+      break;
+
+    case SECCAT_RODATA_MERGE_STR:
+      base_section = darwin_mergeable_string_section (decl, align);
+      break;
+
+    case SECCAT_RODATA_MERGE_STR_INIT:
+      base_section = darwin_mergeable_string_section (DECL_INITIAL (decl), align);
+      break;
+
+    case SECCAT_RODATA_MERGE_CONST:
+      base_section =  darwin_mergeable_constant_section (decl, align);
+      break;
+
+    case SECCAT_DATA:
+    case SECCAT_DATA_REL:
+    case SECCAT_DATA_REL_LOCAL:
+    case SECCAT_DATA_REL_RO:
+    case SECCAT_DATA_REL_RO_LOCAL:
+    case SECCAT_SDATA:
+    case SECCAT_TDATA:
+    case SECCAT_BSS:
+    case SECCAT_SBSS:
+    case SECCAT_TBSS:
+      if (TREE_READONLY (decl) || TREE_CONSTANT (decl))
+       base_section = weak ? darwin_sections[const_data_coal_section]
+                           : darwin_sections[const_data_section];
+      else
+       base_section = weak ? darwin_sections[data_coal_section] : data_section;
+      break;
+
+    default:
+      gcc_unreachable ();
+    }
+
+  /* Darwin weird special cases.  */
+  if (TREE_CODE (decl) == CONSTRUCTOR
+      && TREE_TYPE (decl)
+      && TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
+      && TYPE_NAME (TREE_TYPE (decl)))
+    {
+      tree name = TYPE_NAME (TREE_TYPE (decl));
       if (TREE_CODE (name) == TYPE_DECL)
-       name = DECL_NAME (name);
+        name = DECL_NAME (name);
 
       if (!strcmp (IDENTIFIER_POINTER (name), "__builtin_ObjCString"))
-       {
-         if (flag_next_runtime)
-           return darwin_sections[objc_constant_string_object_section];
-         else
-           return darwin_sections[objc_string_object_section];
-       }
+        {
+          if (flag_next_runtime)
+            return darwin_sections[objc_constant_string_object_section];
+          else
+            return darwin_sections[objc_string_object_section];
+        }
       else
-       return base_section;
+        return base_section;
     }
-  else if (TREE_CODE (exp) == VAR_DECL &&
-          DECL_NAME (exp) &&
-          TREE_CODE (DECL_NAME (exp)) == IDENTIFIER_NODE &&
-          IDENTIFIER_POINTER (DECL_NAME (exp)) &&
-          !strncmp (IDENTIFIER_POINTER (DECL_NAME (exp)), "_OBJC_", 6))
+  else if (TREE_CODE (decl) == VAR_DECL
+          && DECL_NAME (decl)
+          && TREE_CODE (DECL_NAME (decl)) == IDENTIFIER_NODE
+          && IDENTIFIER_POINTER (DECL_NAME (decl))
+          && !strncmp (IDENTIFIER_POINTER (DECL_NAME (decl)), "_OBJC_", 6))
     {
-      const char *name = IDENTIFIER_POINTER (DECL_NAME (exp));
+      const char *name = IDENTIFIER_POINTER (DECL_NAME (decl));
 
       if (!strncmp (name, "_OBJC_CLASS_METHODS_", 20))
-       return darwin_sections[objc_cls_meth_section];
+        return darwin_sections[objc_cls_meth_section];
       else if (!strncmp (name, "_OBJC_INSTANCE_METHODS_", 23))
-       return darwin_sections[objc_inst_meth_section];
+        return darwin_sections[objc_inst_meth_section];
       else if (!strncmp (name, "_OBJC_CATEGORY_CLASS_METHODS_", 20))
-       return darwin_sections[objc_cat_cls_meth_section];
+        return darwin_sections[objc_cat_cls_meth_section];
       else if (!strncmp (name, "_OBJC_CATEGORY_INSTANCE_METHODS_", 23))
-       return darwin_sections[objc_cat_inst_meth_section];
+        return darwin_sections[objc_cat_inst_meth_section];
       else if (!strncmp (name, "_OBJC_CLASS_VARIABLES_", 22))
-       return darwin_sections[objc_class_vars_section];
+        return darwin_sections[objc_class_vars_section];
       else if (!strncmp (name, "_OBJC_INSTANCE_VARIABLES_", 25))
-       return darwin_sections[objc_instance_vars_section];
+        return darwin_sections[objc_instance_vars_section];
       else if (!strncmp (name, "_OBJC_CLASS_PROTOCOLS_", 22))
-       return darwin_sections[objc_cat_cls_meth_section];
+        return darwin_sections[objc_cat_cls_meth_section];
       else if (!strncmp (name, "_OBJC_CLASS_NAME_", 17))
-       return darwin_sections[objc_class_names_section];
+        return darwin_sections[objc_class_names_section];
       else if (!strncmp (name, "_OBJC_METH_VAR_NAME_", 20))
-       return darwin_sections[objc_meth_var_names_section];
+        return darwin_sections[objc_meth_var_names_section];
       else if (!strncmp (name, "_OBJC_METH_VAR_TYPE_", 20))
-       return darwin_sections[objc_meth_var_types_section];
+        return darwin_sections[objc_meth_var_types_section];
       else if (!strncmp (name, "_OBJC_CLASS_REFERENCES", 22))
-       return darwin_sections[objc_cls_refs_section];
+        return darwin_sections[objc_cls_refs_section];
       else if (!strncmp (name, "_OBJC_CLASS_", 12))
-       return darwin_sections[objc_class_section];
+        return darwin_sections[objc_class_section];
       else if (!strncmp (name, "_OBJC_METACLASS_", 16))
-       return darwin_sections[objc_meta_class_section];
+        return darwin_sections[objc_meta_class_section];
       else if (!strncmp (name, "_OBJC_CATEGORY_", 15))
-       return darwin_sections[objc_category_section];
+        return darwin_sections[objc_category_section];
       else if (!strncmp (name, "_OBJC_SELECTOR_REFERENCES", 25))
-       return darwin_sections[objc_selector_refs_section];
+        return darwin_sections[objc_selector_refs_section];
       else if (!strncmp (name, "_OBJC_SELECTOR_FIXUP", 20))
-       return darwin_sections[objc_selector_fixup_section];
+        return darwin_sections[objc_selector_fixup_section];
       else if (!strncmp (name, "_OBJC_SYMBOLS", 13))
-       return darwin_sections[objc_symbols_section];
+        return darwin_sections[objc_symbols_section];
       else if (!strncmp (name, "_OBJC_MODULES", 13))
-       return darwin_sections[objc_module_info_section];
+        return darwin_sections[objc_module_info_section];
       else if (!strncmp (name, "_OBJC_IMAGE_INFO", 16))
-       return darwin_sections[objc_image_info_section];
+        return darwin_sections[objc_image_info_section];
       else if (!strncmp (name, "_OBJC_PROTOCOL_INSTANCE_METHODS_", 32))
-       return darwin_sections[objc_cat_inst_meth_section];
+        return darwin_sections[objc_cat_inst_meth_section];
       else if (!strncmp (name, "_OBJC_PROTOCOL_CLASS_METHODS_", 29))
-       return darwin_sections[objc_cat_cls_meth_section];
+        return darwin_sections[objc_cat_cls_meth_section];
       else if (!strncmp (name, "_OBJC_PROTOCOL_REFS_", 20))
-       return darwin_sections[objc_cat_cls_meth_section];
+        return darwin_sections[objc_cat_cls_meth_section];
       else if (!strncmp (name, "_OBJC_PROTOCOL_", 15))
-       return darwin_sections[objc_protocol_section];
+        return darwin_sections[objc_protocol_section];
       else
-       return base_section;
+        return base_section;
     }
-  else
-    return base_section;
+
+  return base_section;
 }
 
 /* This can be called with address expressions as "rtx".
@@ -1231,6 +1337,13 @@ machopic_select_rtx_section (enum machine_mode mode, rtx x,
           && (GET_CODE (x) == CONST_INT
               || GET_CODE (x) == CONST_DOUBLE))
     return darwin_sections[literal4_section];
+  else if (HAVE_GAS_LITERAL16
+          && TARGET_64BIT
+          && GET_MODE_SIZE (mode) == 16
+          && (GET_CODE (x) == CONST_INT
+              || GET_CODE (x) == CONST_DOUBLE
+              || GET_CODE (x) == CONST_VECTOR))
+    return darwin_sections[literal16_section];
   else if (MACHOPIC_INDIRECT
           && (GET_CODE (x) == SYMBOL_REF
               || GET_CODE (x) == CONST
@@ -1289,6 +1402,42 @@ darwin_unique_section (tree decl ATTRIBUTE_UNUSED, int reloc ATTRIBUTE_UNUSED)
   /* Darwin does not use unique sections.  */
 }
 
+/* Handle __attribute__ ((apple_kext_compatibility)).
+   This only applies to darwin kexts for 2.95 compatibility -- it shrinks the
+   vtable for classes with this attribute (and their descendants) by not
+   outputting the new 3.0 nondeleting destructor.  This means that such
+   objects CANNOT be allocated on the stack or as globals UNLESS they have
+   a completely empty `operator delete'.
+   Luckily, this fits in with the Darwin kext model.
+
+   This attribute also disables gcc3's potential overlaying of derived
+   class data members on the padding at the end of the base class.  */
+
+tree
+darwin_handle_kext_attribute (tree *node, tree name,
+                             tree args ATTRIBUTE_UNUSED,
+                             int flags ATTRIBUTE_UNUSED,
+                             bool *no_add_attrs)
+{
+  /* 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));
+
+      *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));
+
+      *no_add_attrs = true;
+    }
+
+  return NULL_TREE;
+}
+
 /* Handle a "weak_import" attribute; arguments as in
    struct attribute_spec.handler.  */
 
@@ -1324,35 +1473,23 @@ no_dead_strip (FILE *file, const char *lab)
 void
 darwin_emit_unwind_label (FILE *file, tree decl, int for_eh, int empty)
 {
-  tree id = DECL_ASSEMBLER_NAME (decl)
-    ? DECL_ASSEMBLER_NAME (decl)
-    : DECL_NAME (decl);
-
-  const char *prefix = user_label_prefix;
+  const char *base;
+  char *lab;
+  bool need_quotes;
 
-  const char *base = IDENTIFIER_POINTER (id);
-  unsigned int base_len = IDENTIFIER_LENGTH (id);
+  if (DECL_ASSEMBLER_NAME_SET_P (decl))
+    base = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+  else
+    base = IDENTIFIER_POINTER (DECL_NAME (decl));
 
-  const char *suffix = ".eh";
-
-  int need_quotes = name_needs_quotes (base);
-  int quotes_len = need_quotes ? 2 : 0;
-  char *lab;
+  base = targetm.strip_name_encoding (base);
+  need_quotes = name_needs_quotes (base);
 
   if (! for_eh)
-    suffix = ".eh1";
-
-  lab = XNEWVEC (char, strlen (prefix)
-                + base_len + strlen (suffix) + quotes_len + 1);
-  lab[0] = '\0';
+    return;
 
-  if (need_quotes)
-    strcat(lab, "\"");
-  strcat(lab, prefix);
-  strcat(lab, base);
-  strcat(lab, suffix);
-  if (need_quotes)
-    strcat(lab, "\"");
+  lab = concat (need_quotes ? "\"" : "", user_label_prefix, base, ".eh",
+               need_quotes ? "\"" : "", NULL);
 
   if (TREE_PUBLIC (decl))
     fprintf (file, "\t%s %s\n",
@@ -1457,6 +1594,64 @@ 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
+   responsible for parsing the DWARF and updating the offsets.  */
+
+void
+darwin_asm_output_dwarf_offset (FILE *file, int size, const char * lab,
+                               section *base)
+{
+  char sname[64];
+  int namelen;
+
+  gcc_assert (base->common.flags & SECTION_NAMED);
+  gcc_assert (strncmp (base->named.name, "__DWARF,", 8) == 0);
+  gcc_assert (strchr (base->named.name + 8, ','));
+
+  namelen = strchr (base->named.name + 8, ',') - (base->named.name + 8);
+  sprintf (sname, "*Lsection%.*s", namelen, base->named.name + 8);
+  darwin_asm_output_dwarf_delta (file, size, lab, sname);
+}
+
 void
 darwin_file_end (void)
 {
@@ -1470,13 +1665,72 @@ darwin_file_end (void)
   fprintf (asm_out_file, "\t.subsections_via_symbols\n");
 }
 
+/* TODO: Add a language hook for identifying if a decl is a vtable.  */
+#define DARWIN_VTABLE_P(DECL) 0
+
 /* Cross-module name binding.  Darwin does not support overriding
-   functions at dynamic-link time.  */
+   functions at dynamic-link time, except for vtables in kexts.  */
 
 bool
 darwin_binds_local_p (tree decl)
 {
-  return default_binds_local_p_1 (decl, 0);
+  return default_binds_local_p_1 (decl,
+                                 TARGET_KEXTABI && DARWIN_VTABLE_P (decl));
+}
+
+#if 0
+/* See TARGET_ASM_OUTPUT_ANCHOR for why we can't do this yet.  */
+/* The Darwin's implementation of TARGET_ASM_OUTPUT_ANCHOR.  Define the
+   anchor relative to ".", the current section position.  We cannot use
+   the default one because ASM_OUTPUT_DEF is wrong for Darwin.  */
+
+void
+darwin_asm_output_anchor (rtx symbol)
+{
+  fprintf (asm_out_file, "\t.set\t");
+  assemble_name (asm_out_file, XSTR (symbol, 0));
+  fprintf (asm_out_file, ", . + " HOST_WIDE_INT_PRINT_DEC "\n",
+          SYMBOL_REF_BLOCK_OFFSET (symbol));
+}
+#endif
+
+/* Set the darwin specific attributes on TYPE.  */
+void
+darwin_set_default_type_attributes (tree type)
+{
+  if (darwin_ms_struct
+      && TREE_CODE (type) == RECORD_TYPE)
+    TYPE_ATTRIBUTES (type) = tree_cons (get_identifier ("ms_struct"),
+                                        NULL_TREE,
+                                        TYPE_ATTRIBUTES (type));
+}
+
+/* True, iff we're generating code for loadable kernel extensions.  */
+
+bool
+darwin_kextabi_p (void) {
+  return flag_apple_kext;
+}
+
+void
+darwin_override_options (void)
+{
+  if (flag_mkernel || flag_apple_kext)
+    {
+      /* -mkernel implies -fapple-kext for C++ */
+      if (strcmp (lang_hooks.name, "GNU C++") == 0)
+       flag_apple_kext = 1;
+
+      flag_no_common = 1;
+
+      /* No EH in kexts.  */
+      flag_exceptions = 0;
+      /* No -fnon-call-exceptions data in kexts.  */
+      flag_non_call_exceptions = 0;
+    }
+  if (flag_var_tracking
+      && strverscmp (darwin_macosx_version_min, "10.5") >= 0)
+    flag_var_tracking_uninit = 1;
 }
 
 #include "gt-darwin.h"