OSDN Git Service

* config/i386/i386.c (ix86_expand_prologue): Emit frame info for the
[pf3gnuchains/gcc-fork.git] / gcc / config / darwin.c
index 0057685..ba253dd 100644 (file)
@@ -1,6 +1,6 @@
 /* Functions for generic Darwin as target machine for GNU C compiler.
    Copyright (C) 1989, 1990, 1991, 1992, 1993, 2000, 2001, 2002, 2003, 2004,
-   2005, 2006, 2007, 2008, 2009, 2010
+   2005, 2006, 2007, 2008, 2009, 2010, 2011
    Free Software Foundation, Inc.
    Contributed by Apple Computer Inc.
 
@@ -41,8 +41,6 @@ along with GCC; see the file COPYING3.  If not see
 #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"
@@ -92,6 +90,9 @@ int darwin_emit_branch_islands = false;
    functions).  */
 int darwin_running_cxx;
 
+/* Some code-gen now depends on OS major version numbers (at least).  */
+int generating_for_darwin_version ;
+
 /* Section names.  */
 section * darwin_sections[NUM_DARWIN_SECTIONS];
 
@@ -147,18 +148,58 @@ output_objc_section_asm_op (const void *directive)
          objc_class_vars_section,
          objc_instance_vars_section,
          objc_module_info_section,
-         objc_symbols_section
+         objc_symbols_section,
        };
+      /* ABI=1 */
+      static const enum darwin_section_enum tomarkv1[] =
+       {
+         objc1_protocol_ext_section,
+         objc1_class_ext_section,
+         objc1_prop_list_section
+       } ;
+      /* ABI=2 */
+      static const enum darwin_section_enum tomarkv2[] =
+       {
+         objc2_message_refs_section,
+         objc2_classdefs_section,
+         objc2_metadata_section,
+         objc2_classrefs_section,
+         objc2_classlist_section,
+         objc2_categorylist_section,
+         objc2_selector_refs_section,
+         objc2_nonlazy_class_section,
+         objc2_nonlazy_category_section,
+         objc2_protocollist_section,
+         objc2_protocolrefs_section,
+         objc2_super_classrefs_section,
+         objc2_image_info_section,
+         objc2_constant_string_object_section
+       } ;
       size_t i;
 
       been_here = true;
-      for (i = 0; i < ARRAY_SIZE (tomark); i++)
-       switch_to_section (darwin_sections[tomark[i]]);
+      if (flag_objc_abi < 2)
+       {
+         for (i = 0; i < ARRAY_SIZE (tomark); i++)
+           switch_to_section (darwin_sections[tomark[i]]);
+         if (flag_objc_abi == 1)
+           for (i = 0; i < ARRAY_SIZE (tomarkv1); i++)
+             switch_to_section (darwin_sections[tomarkv1[i]]);
+       }
+      else
+       for (i = 0; i < ARRAY_SIZE (tomarkv2); i++)
+         switch_to_section (darwin_sections[tomarkv2[i]]);
+      /* Make sure we don't get varasm.c out of sync with us.  */
       switch_to_section (saved_in_section);
     }
   output_section_asm_op (directive);
 }
 
+
+/* Private flag applied to disable section-anchors in a particular section.  */
+#define SECTION_NO_ANCHOR SECTION_MACH_DEP
+
+
 /* Implement TARGET_ASM_INIT_SECTIONS.  */
 
 void
@@ -176,10 +217,6 @@ darwin_init_sections (void)
   readonly_data_section = darwin_sections[const_section];
   exception_section = darwin_sections[darwin_exception_section];
   eh_frame_section = darwin_sections[darwin_eh_frame_section];
-
-  /* Make sure that there is no conflict between the 'no anchor' section
-     flag declared in darwin.h and the section flags declared in output.h.  */
-  gcc_assert (SECTION_NO_ANCHOR > SECTION_MACH_DEP);
 }
 
 int
@@ -275,7 +312,6 @@ indirect_data (rtx sym_ref)
   return ! lprefix;
 }
 
-
 static int
 machopic_data_defined_p (rtx sym_ref)
 {
@@ -1147,19 +1183,6 @@ darwin_mark_decl_preserved (const char *name)
 }
 
 static section *
-darwin_text_section (int reloc, int weak)
-{
-  if (reloc)
-    return (weak
-           ? darwin_sections[text_unlikely_coal_section]
-           : unlikely_text_section ());
-  else
-    return (weak
-           ? darwin_sections[text_coal_section]
-           : text_section);
-}
-
-static section *
 darwin_rodata_section (int weak, bool zsize)
 {
   return (weak
@@ -1172,7 +1195,11 @@ static section *
 darwin_mergeable_string_section (tree exp,
                                 unsigned HOST_WIDE_INT align)
 {
-  if (flag_merge_constants
+  /* Darwin's ld expects to see non-writable string literals in the .cstring 
+     section.  Later versions of ld check and complain when CFStrings are 
+     enabled.  Therefore we shall force the strings into .cstring since we
+     don't support writable ones anyway.  */
+  if ((darwin_constant_cfstrings || flag_merge_constants)
       && TREE_CODE (exp) == STRING_CST
       && TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE
       && align <= 256
@@ -1238,12 +1265,191 @@ darwin_mergeable_constant_section (tree exp,
   return readonly_data_section;
 }
 
+section *
+darwin_tm_clone_table_section (void)
+{
+  return get_named_section (NULL,
+                           "__DATA,__tm_clone_table,regular,no_dead_strip",
+                           3);
+}
+
 int
 machopic_reloc_rw_mask (void)
 {
   return MACHOPIC_INDIRECT ? 3 : 0;
 }
 
+/* We have to deal with ObjC/C++ metadata section placement in the common
+   code, since it will also be called from LTO.
+   
+   Return metadata attributes, if present (searching for ABI=2 first)
+   Return NULL_TREE if no such attributes are found.  */
+
+static tree
+is_objc_metadata (tree decl)
+{
+  if (DECL_P (decl) 
+      && (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == CONST_DECL)
+      && DECL_ATTRIBUTES (decl))
+    {
+      tree meta = lookup_attribute ("OBJC2META", DECL_ATTRIBUTES (decl));
+      if (meta)
+       return meta;
+      meta = lookup_attribute ("OBJC1META", DECL_ATTRIBUTES (decl));
+      if (meta)
+       return meta;
+    }
+  return NULL_TREE;
+}
+
+/* Return the section required for Objective C ABI 2 metadata.  */
+static section *
+darwin_objc2_section (tree decl ATTRIBUTE_UNUSED, tree meta, section * base)
+{
+  const char *p;
+  tree ident = TREE_VALUE (meta);
+  gcc_assert (TREE_CODE (ident) == IDENTIFIER_NODE);
+  p = IDENTIFIER_POINTER (ident);
+
+  /* If we are in LTO, then we don't know the state of flag_next_runtime
+     or flag_objc_abi when the code was generated.  We set these from the
+     meta-data - which is needed to deal with const string constructors.  */
+
+  flag_next_runtime = 1;
+  flag_objc_abi = 2;
+
+  if (base == data_section)
+    base = darwin_sections[objc2_metadata_section];
+
+  /* Most of the OBJC2 META-data end up in the base section, so check it
+     first.  */
+  if      (!strncmp (p, "V2_BASE", 7))
+    return base;
+  else if (!strncmp (p, "V2_STRG", 7))
+    return darwin_sections[cstring_section];
+
+  else if (!strncmp (p, "G2_META", 7) || !strncmp (p, "G2_CLAS", 7))
+    return darwin_sections[objc2_classdefs_section];
+  else if (!strncmp (p, "V2_MREF", 7))
+    return darwin_sections[objc2_message_refs_section];
+  else if (!strncmp (p, "V2_CLRF", 7))
+    return darwin_sections[objc2_classrefs_section];
+  else if (!strncmp (p, "V2_SURF", 7))
+    return darwin_sections[objc2_super_classrefs_section];
+  else if (!strncmp (p, "V2_NLCL", 7))
+    return darwin_sections[objc2_nonlazy_class_section];
+  else if (!strncmp (p, "V2_CLAB", 7))
+    return darwin_sections[objc2_classlist_section];
+  else if (!strncmp (p, "V2_SRFS", 7))
+    return darwin_sections[objc2_selector_refs_section];
+  else if (!strncmp (p, "V2_NLCA", 7))
+    return darwin_sections[objc2_nonlazy_category_section];
+  else if (!strncmp (p, "V2_CALA", 7))
+    return darwin_sections[objc2_categorylist_section];
+
+  else if (!strncmp (p, "V2_PLST", 7))
+    return darwin_sections[objc2_protocollist_section];
+  else if (!strncmp (p, "V2_PRFS", 7))
+    return darwin_sections[objc2_protocolrefs_section];
+
+  else if (!strncmp (p, "V2_INFO", 7))
+    return darwin_sections[objc2_image_info_section];
+
+  else if (!strncmp (p, "V2_EHTY", 7))
+    return darwin_sections[data_coal_section];
+
+  else if (!strncmp (p, "V2_CSTR", 7))
+    return darwin_sections[objc2_constant_string_object_section];
+
+  /* Not recognized, default.  */
+  return base;
+}
+
+/* Return the section required for Objective C ABI 0/1 metadata.  */
+static section *
+darwin_objc1_section (tree decl ATTRIBUTE_UNUSED, tree meta, section * base)
+{
+  const char *p;
+  tree ident = TREE_VALUE (meta);
+  gcc_assert (TREE_CODE (ident) == IDENTIFIER_NODE);
+  p = IDENTIFIER_POINTER (ident);
+
+  /* If we are in LTO, then we don't know the state of flag_next_runtime
+     or flag_objc_abi when the code was generated.  We set these from the
+     meta-data - which is needed to deal with const string constructors.  */
+  flag_next_runtime = 1;
+  if (!global_options_set.x_flag_objc_abi)
+    flag_objc_abi = 1;
+
+  /* String sections first, cos there are lots of strings.  */
+  if      (!strncmp (p, "V1_STRG", 7))
+    return darwin_sections[cstring_section];
+  else if (!strncmp (p, "V1_CLSN", 7))
+    return darwin_sections[objc_class_names_section];
+  else if (!strncmp (p, "V1_METN", 7))
+    return darwin_sections[objc_meth_var_names_section];
+  else if (!strncmp (p, "V1_METT", 7))
+    return darwin_sections[objc_meth_var_types_section];
+
+  else if (!strncmp (p, "V1_CLAS", 7))
+    return darwin_sections[objc_class_section];
+  else if (!strncmp (p, "V1_META", 7))
+    return darwin_sections[objc_meta_class_section];
+  else if (!strncmp (p, "V1_CATG", 7))
+    return darwin_sections[objc_category_section];
+  else if (!strncmp (p, "V1_PROT", 7))
+    return darwin_sections[objc_protocol_section];
+
+  else if (!strncmp (p, "V1_CLCV", 7))
+    return darwin_sections[objc_class_vars_section];
+  else if (!strncmp (p, "V1_CLIV", 7))
+    return darwin_sections[objc_instance_vars_section];
+
+  else if (!strncmp (p, "V1_CLCM", 7))
+    return darwin_sections[objc_cls_meth_section];
+  else if (!strncmp (p, "V1_CLIM", 7))
+    return darwin_sections[objc_inst_meth_section];
+  else if (!strncmp (p, "V1_CACM", 7))
+    return darwin_sections[objc_cat_cls_meth_section];
+  else if (!strncmp (p, "V1_CAIM", 7))
+    return darwin_sections[objc_cat_inst_meth_section];
+  else if (!strncmp (p, "V1_PNSM", 7))
+    return darwin_sections[objc_cat_inst_meth_section];
+  else if (!strncmp (p, "V1_PCLM", 7))
+    return darwin_sections[objc_cat_cls_meth_section];
+
+  else if (!strncmp (p, "V1_CLPR", 7))
+    return darwin_sections[objc_cat_cls_meth_section];
+  else if (!strncmp (p, "V1_CAPR", 7))
+    return darwin_sections[objc_category_section]; /* ??? CHECK me.  */
+
+  else if (!strncmp (p, "V1_PRFS", 7))
+    return darwin_sections[objc_cat_cls_meth_section];
+  else if (!strncmp (p, "V1_CLRF", 7))
+    return darwin_sections[objc_cls_refs_section];
+  else if (!strncmp (p, "V1_SRFS", 7))
+    return darwin_sections[objc_selector_refs_section];
+
+  else if (!strncmp (p, "V1_MODU", 7))
+    return darwin_sections[objc_module_info_section];
+  else if (!strncmp (p, "V1_SYMT", 7))
+    return darwin_sections[objc_symbols_section];
+  else if (!strncmp (p, "V1_INFO", 7))
+    return darwin_sections[objc_image_info_section];
+
+  else if (!strncmp (p, "V1_PLST", 7))
+    return darwin_sections[objc1_prop_list_section];
+  else if (!strncmp (p, "V1_PEXT", 7))
+    return darwin_sections[objc1_protocol_ext_section];
+  else if (!strncmp (p, "V1_CEXT", 7))
+    return darwin_sections[objc1_class_ext_section];
+
+  else if (!strncmp (p, "V2_CSTR", 7))
+    return darwin_sections[objc_constant_string_object_section];
+
+  return base;
+}
+
 section *
 machopic_select_section (tree decl,
                         int reloc,
@@ -1269,17 +1475,7 @@ machopic_select_section (tree decl,
   switch (categorize_decl_for_section (decl, reloc))
     {
     case SECCAT_TEXT:
-      {
-       struct cgraph_node *node;
-       if (decl && TREE_CODE (decl) == FUNCTION_DECL
-           && (node = cgraph_get_node (decl)) != NULL)
-         base_section = darwin_function_section (decl,
-                                                 node->frequency,
-                                                 node->only_called_at_startup,
-                                                 node->only_called_at_exit);
-       if (!base_section)
-          base_section = darwin_text_section (reloc, weak);
-      }
+      gcc_unreachable ();
       break;
 
     case SECCAT_RODATA:
@@ -1352,7 +1548,25 @@ machopic_select_section (tree decl,
       gcc_unreachable ();
     }
 
-  /* Darwin weird special cases.  */
+  /* Darwin weird special cases.  
+     a) OBJC Meta-data. */
+  if (DECL_P (decl) 
+      && (TREE_CODE (decl) == VAR_DECL 
+         || TREE_CODE (decl) == CONST_DECL)
+      && DECL_ATTRIBUTES (decl))
+    {
+      tree meta = lookup_attribute ("OBJC2META", DECL_ATTRIBUTES (decl));
+      if (meta)
+       return darwin_objc2_section (decl, meta, base_section);
+      meta = lookup_attribute ("OBJC1META", DECL_ATTRIBUTES (decl));
+      if (meta)
+       return darwin_objc1_section (decl, meta, base_section);
+      meta = lookup_attribute ("OBJC1METG", DECL_ATTRIBUTES (decl));
+      if (meta)
+       return base_section; /* GNU runtime is happy with it all in one pot.  */
+    }
+
+  /* b) Constant string objects.  */
   if (TREE_CODE (decl) == CONSTRUCTOR
       && TREE_TYPE (decl)
       && TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
@@ -1362,29 +1576,53 @@ machopic_select_section (tree decl,
       if (TREE_CODE (name) == TYPE_DECL)
         name = DECL_NAME (name);
 
+      /* FIXME: This is unsatisfactory for LTO, since it relies on other
+        metadata determining the source FE.  */
       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)
+           {
+             if (flag_objc_abi == 2)
+               return darwin_sections[objc2_constant_string_object_section];
+             else
+               return darwin_sections[objc_constant_string_object_section];
+           }
+         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;
+       return base_section;
     }
+  /* c) legacy meta-data selection.  */
   else if (TREE_CODE (decl) == VAR_DECL
           && DECL_NAME (decl)
           && TREE_CODE (DECL_NAME (decl)) == IDENTIFIER_NODE
           && IDENTIFIER_POINTER (DECL_NAME (decl))
+          && flag_next_runtime
           && !strncmp (IDENTIFIER_POINTER (DECL_NAME (decl)), "_OBJC_", 6))
     {
       const char *name = IDENTIFIER_POINTER (DECL_NAME (decl));
-
+      static bool warned_objc_46 = false;
       /* We shall assert that zero-sized objects are an error in ObjC 
          meta-data.  */
       gcc_assert (tree_low_cst (DECL_SIZE_UNIT (decl), 1) != 0);
+      
+      /* ??? This mechanism for determining the metadata section is
+        broken when LTO is in use, since the frontend that generated
+        the data is not identified.  We will keep the capability for
+        the short term - in case any non-Objective-C programs are using
+        it to place data in specified sections.  */
+      if (!warned_objc_46)
+       {
+         location_t loc = DECL_SOURCE_LOCATION (decl);
+         warning_at (loc, 0, "the use of _OBJC_-prefixed variable names"
+                     " to select meta-data sections is deprecated at 4.6"
+                     " and will be removed in 4.7");
+         warned_objc_46 = true;
+       }
+      
       if (!strncmp (name, "_OBJC_CLASS_METHODS_", 20))
         return darwin_sections[objc_cls_meth_section];
       else if (!strncmp (name, "_OBJC_INSTANCE_METHODS_", 23))
@@ -1523,19 +1761,51 @@ darwin_label_is_anonymous_local_objc_name (const char *name)
   return (!strncmp ((const char *)p, "_OBJC_", 6));
 }
 
-/* LTO support for Mach-O.  */
+/* LTO support for Mach-O.
+
+   This version uses three mach-o sections to encapsulate the (unlimited
+   number of) lto sections.
+
+   __GNU_LTO, __lto_sections  contains the concatented GNU LTO section data.
+   __GNU_LTO, __section_names contains the GNU LTO section names.
+   __GNU_LTO, __section_index contains an array of values that index these.
+
+   Indexed thus:
+     <section offset from the start of __GNU_LTO, __lto_sections>,
+     <section length>
+     <name offset from the start of __GNU_LTO, __section_names,
+     <name length>.
+
+   At present, for both m32 and m64 mach-o files each of these fields is
+   represented  by a uint32_t.  This is because, AFAICT, a mach-o object
+   cannot exceed 4Gb because the section_64 offset field (see below) is 32bits.
+
+    uint32_t offset;
+   "offset  An integer specifying the offset to this section in the file."  */
+
+/* Count lto section numbers.  */
+static unsigned int lto_section_num = 0;
 
-/* Section names for LTO sections.  */
-static unsigned int lto_section_names_offset = 0;
+/* A vector of information about LTO sections, at present, we only have
+   the name.  TODO: see if we can get the data length somehow.  */
+typedef struct GTY (()) darwin_lto_section_e {
+  const char *sectname;
+} darwin_lto_section_e ;
+DEF_VEC_O(darwin_lto_section_e);
+DEF_VEC_ALLOC_O(darwin_lto_section_e, gc);
 
-/* This is the obstack which we use to allocate the many strings.  */
-static struct obstack lto_section_names_obstack;
+static GTY (()) VEC (darwin_lto_section_e, gc) * lto_section_names;
 
-/* Segment name for LTO sections.  */
+/* Segment for LTO data.  */
 #define LTO_SEGMENT_NAME "__GNU_LTO"
 
-/* Section name for LTO section names section.  */
-#define LTO_NAMES_SECTION "__section_names"
+/* Section wrapper scheme (used here to wrap the unlimited number of LTO
+   sections into three Mach-O ones).
+   NOTE: These names MUST be kept in sync with those in
+        libiberty/simple-object-mach-o.  */
+#define LTO_SECTS_SECTION "__wrapper_sects"
+#define LTO_NAMES_SECTION "__wrapper_names"
+#define LTO_INDEX_SECTION "__wrapper_index"
 
 /* File to temporarily store LTO data.  This is appended to asm_out_file
    in darwin_end_file.  */
@@ -1578,37 +1848,38 @@ darwin_asm_named_section (const char *name,
                          unsigned int flags,
                          tree decl ATTRIBUTE_UNUSED)
 {
-  /* 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).  */
+  /* LTO sections go in a special section that encapsulates the (unlimited)
+     number of GNU LTO sections within a single mach-o one.  */
   if (strncmp (name, LTO_SECTION_NAME_PREFIX,
               strlen (LTO_SECTION_NAME_PREFIX)) == 0)
     {
+      darwin_lto_section_e e;
       /* 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));
-    }
+      /* Switch to our combined section.  */
+      fprintf (asm_out_file, "\t.section %s,%s,regular,debug\n",
+              LTO_SEGMENT_NAME, LTO_SECTS_SECTION);
+      /* Output a label for the start of this sub-section.  */
+      fprintf (asm_out_file, "L_GNU_LTO%d:\t;# %s\n",
+              lto_section_num, name);
+      /* We have to jump through hoops to get the values of the intra-section
+         offsets... */
+      fprintf (asm_out_file, "\t.set L$gnu$lto$offs%d,L_GNU_LTO%d-L_GNU_LTO0\n",
+              lto_section_num, lto_section_num);
+      fprintf (asm_out_file,
+              "\t.set L$gnu$lto$size%d,L_GNU_LTO%d-L_GNU_LTO%d\n",
+              lto_section_num, lto_section_num+1, lto_section_num);
+      lto_section_num++;
+      e.sectname = xstrdup (name);
+      /* Keep the names, we'll need to make a table later.
+         TODO: check that we do not revisit sections, that would break
+         the assumption of how this is done.  */
+      if (lto_section_names == NULL)
+        lto_section_names = VEC_alloc (darwin_lto_section_e, gc, 16);
+      VEC_safe_push (darwin_lto_section_e, gc, lto_section_names, &e);
+   }
   else if (strncmp (name, "__DWARF,", 8) == 0)
     darwin_asm_dwarf_section (name, flags, decl);
   else
@@ -1686,12 +1957,37 @@ darwin_handle_weak_import_attribute (tree *node, tree name,
 void
 darwin_emit_unwind_label (FILE *file, tree decl, int for_eh, int empty)
 {
-  char *lab;
-
-  if (! for_eh)
+  char *lab ;
+  char buf[32];
+  static int invok_count = 0;
+  static tree last_fun_decl = NULL_TREE;
+  
+  /* We use the linker to emit the .eh labels for Darwin 9 and above.  */
+  if (! for_eh || generating_for_darwin_version >= 9)
     return;
 
-  lab = concat (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)), ".eh", NULL);
+  /* FIXME: This only works when the eh for all sections of a function is 
+     emitted at the same time.  If that changes, we would need to use a lookup
+     table of some form to determine what to do.  Also, we should emit the
+     unadorned label for the partition containing the public label for a
+     function.  This is of limited use, probably, since we do not currently
+     enable partitioning.  */
+  strcpy (buf, ".eh");
+  if (decl && TREE_CODE (decl) == FUNCTION_DECL) 
+    {
+      if (decl == last_fun_decl)
+        {
+         invok_count++;
+         snprintf (buf, 31, "$$part$$%d.eh", invok_count);
+       }
+      else
+       {
+         last_fun_decl = decl;
+         invok_count = 0;
+       }
+    }
+
+  lab = concat (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)), buf, NULL);
 
   if (TREE_PUBLIC (decl))
     {
@@ -1907,6 +2203,30 @@ darwin_emit_weak_or_comdat (FILE *fp, tree decl, const char *name,
     assemble_zeros (size);
 }
 
+/* Emit a chunk of data for ObjC meta-data that got placed in BSS erroneously.  */
+static void
+darwin_emit_objc_zeroed (FILE *fp, tree decl, const char *name,
+                                 unsigned HOST_WIDE_INT size, 
+                                 unsigned int align, tree meta)
+{
+  section *ocs = data_section;
+
+  if (TREE_PURPOSE (meta) == get_identifier("OBJC2META"))
+    ocs = darwin_objc2_section (decl, meta, ocs);
+  else
+    ocs = darwin_objc1_section (decl, meta, ocs);
+
+  switch_to_section (ocs);
+
+  /* We shall declare that zero-sized meta-data are not valid (yet).  */
+  gcc_assert (size);
+  fprintf (fp, "\t.align\t%d\n", floor_log2 (align / BITS_PER_UNIT));
+
+  /* ... and we let it deal with outputting one byte of zero for them too.  */ 
+  darwin_asm_declare_object_name (fp, name, decl);
+  assemble_zeros (size);
+}
+
 /* This routine emits 'local' storage:
 
    When Section Anchors are off this routine emits .zerofill commands in 
@@ -2038,6 +2358,7 @@ darwin_output_aligned_bss (FILE *fp, tree decl, const char *name,
 {
   unsigned int l2align;
   bool one, pub, weak;
+  tree meta;
 
   pub = TREE_PUBLIC (decl);
   one = DECL_ONE_ONLY (decl);
@@ -2054,6 +2375,14 @@ fprintf (fp, "# albss: %s (%lld,%d) ro %d cst %d stat %d com %d"
        pub, weak, one, (unsigned long)DECL_INITIAL (decl)); 
 #endif
 
+  /* ObjC metadata can get put in BSS because varasm.c decides it's BSS 
+     before the target has a chance to comment.  */
+  if ((meta = is_objc_metadata (decl)))
+    {
+      darwin_emit_objc_zeroed (fp, decl, name, size, DECL_ALIGN (decl), meta);
+      return;
+    }
+
   /* Check that any initializer is valid.  */
   gcc_assert ((DECL_INITIAL (decl) == NULL) 
               || (DECL_INITIAL (decl) == error_mark_node) 
@@ -2148,6 +2477,8 @@ darwin_asm_output_aligned_decl_common (FILE *fp, tree decl, const char *name,
 {
   unsigned int l2align;
   bool one, weak;
+  tree meta;
+
   /* No corresponding var.  */
   if (decl==NULL)
     {
@@ -2172,6 +2503,14 @@ fprintf (fp, "# adcom: %s (%lld,%d) ro %d cst %d stat %d com %d pub %d"
        TREE_PUBLIC (decl), weak, one, (unsigned long)DECL_INITIAL (decl)); 
 #endif
 
+  /* ObjC metadata can get put in BSS because varasm.c decides it's BSS 
+     before the target has a chance to comment.  */
+  if ((meta = is_objc_metadata (decl)))
+    {
+      darwin_emit_objc_zeroed (fp, decl, name, size, DECL_ALIGN (decl), meta);
+      return;
+    }
+
   /* We shouldn't be messing with this if the decl has a section name.  */
   gcc_assert (DECL_SECTION_NAME (decl) == NULL);
 
@@ -2218,6 +2557,7 @@ darwin_asm_output_aligned_decl_local (FILE *fp, tree decl, const char *name,
 {
   unsigned long l2align;
   bool one, weak;
+  tree meta;
 
   one = DECL_ONE_ONLY (decl);
   weak = (DECL_P (decl)
@@ -2233,6 +2573,14 @@ fprintf (fp, "# adloc: %s (%lld,%d) ro %d cst %d stat %d one %d pub %d"
        weak , (unsigned long)DECL_INITIAL (decl)); 
 #endif
 
+  /* ObjC metadata can get put in BSS because varasm.c decides it's BSS 
+     before the target has a chance to comment.  */
+  if ((meta = is_objc_metadata (decl)))
+    {
+      darwin_emit_objc_zeroed (fp, decl, name, size, DECL_ALIGN (decl), meta);
+      return;
+    }
+
   /* We shouldn't be messing with this if the decl has a section name.  */
   gcc_assert (DECL_SECTION_NAME (decl) == NULL);
 
@@ -2404,16 +2752,12 @@ 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.  */
+/* Called from the within the TARGET_ASM_FILE_START for each target.  */
 
 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;
+  /* Nothing to do.  */
 }
 
 /* Called for the TARGET_ASM_FILE_END hook.
@@ -2424,8 +2768,6 @@ darwin_file_start (void)
 void
 darwin_file_end (void)
 {
-  const char *lto_section_names;
-
   machopic_finish (asm_out_file);
   if (strcmp (lang_hooks.name, "GNU C++") == 0)
     {
@@ -2455,6 +2797,13 @@ darwin_file_end (void)
          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);
+         /* Put a termination label.  */
+         fprintf (asm_out_file, "\t.section %s,%s,regular,debug\n",
+                  LTO_SEGMENT_NAME, LTO_SECTS_SECTION);
+         fprintf (asm_out_file, "L_GNU_LTO%d:\t;# end of lto\n",
+                  lto_section_num);
+         /* Make sure our termination label stays in this section.  */
+         fputs ("\t.space\t1\n", asm_out_file);
        }
 
       /* Remove the temporary file.  */
@@ -2463,21 +2812,50 @@ darwin_file_end (void)
       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)
+  /* Output the names and indices.  */
+  if (lto_section_names && VEC_length (darwin_lto_section_e, lto_section_names))
     {
-      fprintf (asm_out_file,
-              "\t.section %s,%s,regular,debug\n",
+      int count;
+      darwin_lto_section_e *ref;
+      /* For now, we'll make the offsets 4 bytes and unaligned - we'll fix
+         the latter up ourselves.  */
+      const char *op = integer_asm_op (4,0);
+
+      /* Emit the names.  */
+      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);
+      FOR_EACH_VEC_ELT (darwin_lto_section_e, lto_section_names, count, ref)
+       {
+         fprintf (asm_out_file, "L_GNU_LTO_NAME%d:\n", count);
+         /* We have to jump through hoops to get the values of the intra-section
+            offsets... */
+         fprintf (asm_out_file,
+                  "\t.set L$gnu$lto$noff%d,L_GNU_LTO_NAME%d-L_GNU_LTO_NAME0\n",
+                  count, count);
+         fprintf (asm_out_file,
+                  "\t.set L$gnu$lto$nsiz%d,L_GNU_LTO_NAME%d-L_GNU_LTO_NAME%d\n",
+                  count, count+1, count);
+         fprintf (asm_out_file, "\t.asciz\t\"%s\"\n", ref->sectname);
+       }
+      fprintf (asm_out_file, "L_GNU_LTO_NAME%d:\t;# end\n", lto_section_num);
+      /* make sure our termination label stays in this section.  */
+      fputs ("\t.space\t1\n", asm_out_file);
+
+      /* Emit the Index.  */
+      fprintf (asm_out_file, "\t.section %s,%s,regular,debug\n",
+              LTO_SEGMENT_NAME, LTO_INDEX_SECTION);
+      fputs ("\t.align\t2\n", asm_out_file);
+      fputs ("# Section offset, Section length, Name offset, Name length\n",
+            asm_out_file);
+      FOR_EACH_VEC_ELT (darwin_lto_section_e, lto_section_names, count, ref)
+       {
+         fprintf (asm_out_file, "%s L$gnu$lto$offs%d\t;# %s\n",
+                  op, count, ref->sectname);
+         fprintf (asm_out_file, "%s L$gnu$lto$size%d\n", op, count);
+         fprintf (asm_out_file, "%s L$gnu$lto$noff%d\n", op, count);
+         fprintf (asm_out_file, "%s L$gnu$lto$nsiz%d\n", op, count);
+       }
     }
-  obstack_free (&lto_section_names_obstack, NULL);
 
   /* If we have section anchors, then we must prevent the linker from
      re-arranging data.  */
@@ -2553,21 +2931,76 @@ darwin_kextabi_p (void) {
 void
 darwin_override_options (void)
 {
-  bool darwin9plus = (darwin_macosx_version_min
-                     && strverscmp (darwin_macosx_version_min, "10.5") >= 0);
+  /* Keep track of which (major) version we're generating code for.  */
+  if (darwin_macosx_version_min)
+    {
+      if (strverscmp (darwin_macosx_version_min, "10.6") >= 0)
+       generating_for_darwin_version = 10;
+      else if (strverscmp (darwin_macosx_version_min, "10.5") >= 0)
+       generating_for_darwin_version = 9;
+
+      /* Earlier versions are not specifically accounted, until required.  */
+    }
+
+  /* In principle, this should be c-family only.  However, we really need to
+     set sensible defaults for LTO as well, since the section selection stuff
+     should check for correctness re. the ABI.  TODO: check and provide the
+     flags (runtime & ABI) from the lto wrapper).  */
+
+  /* Unless set, force ABI=2 for NeXT and m64, 0 otherwise.  */
+  if (!global_options_set.x_flag_objc_abi)
+    global_options.x_flag_objc_abi
+       = (!flag_next_runtime)
+               ? 0
+               : (TARGET_64BIT ? 2
+                               : (generating_for_darwin_version >= 9) ? 1
+                                                                      : 0);
+
+  /* Objective-C family ABI 2 is only valid for next/m64 at present.  */
+  if (global_options_set.x_flag_objc_abi && flag_next_runtime)
+    {
+      if (TARGET_64BIT && global_options.x_flag_objc_abi < 2)
+       error_at (UNKNOWN_LOCATION, "%<-fobjc-abi-version%> >= 2 must be"
+                                   " used for %<-m64%> targets with"
+                                   " %<-fnext-runtime%>");
+      if (!TARGET_64BIT && global_options.x_flag_objc_abi >= 2)
+       error_at (UNKNOWN_LOCATION, "%<-fobjc-abi-version%> >= 2 is not"
+                                   " supported on %<-m32%> targets with"
+                                   " %<-fnext-runtime%>");
+    }
 
   /* Don't emit DWARF3/4 unless specifically selected.  This is a 
      workaround for tool bugs.  */
   if (!global_options_set.x_dwarf_strict) 
     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))
+  /* Do not allow unwind tables to be generated by default for m32.  
+     fnon-call-exceptions will override this, regardless of what we do.  */
+  if (generating_for_darwin_version < 10
+      && !global_options_set.x_flag_asynchronous_unwind_tables
+      && !TARGET_64BIT)
+    global_options.x_flag_asynchronous_unwind_tables = 0;
+
+   /* Disable -freorder-blocks-and-partition when unwind tables are being
+      emitted for Darwin < 9 (OSX 10.5).
+      The strategy is, "Unless the User has specifically set/unset an unwind
+      flag we will switch off -freorder-blocks-and-partition when unwind tables
+      will be generated".  If the User specifically sets flags... we assume
+      (s)he knows why...  */
+   if (generating_for_darwin_version < 9
+       && global_options_set.x_flag_reorder_blocks_and_partition
+       && ((global_options.x_flag_exceptions           /* User, c++, java */
+           && !global_options_set.x_flag_exceptions)   /* User specified... */
+          || (global_options.x_flag_unwind_tables
+              && !global_options_set.x_flag_unwind_tables)
+          || (global_options.x_flag_non_call_exceptions
+              && !global_options_set.x_flag_non_call_exceptions)
+          || (global_options.x_flag_asynchronous_unwind_tables
+              && !global_options_set.x_flag_asynchronous_unwind_tables)))
     {
       inform (input_location,
-              "-freorder-blocks-and-partition does not work with exceptions "
-              "on this architecture");
+             "-freorder-blocks-and-partition does not work with exceptions "
+             "on this architecture");
       flag_reorder_blocks_and_partition = 0;
       flag_reorder_blocks = 1;
     }
@@ -2592,15 +3025,18 @@ darwin_override_options (void)
     }
 
   if (flag_var_tracking
-      && darwin9plus
-      && debug_info_level >= DINFO_LEVEL_NORMAL
-      && debug_hooks->var_location != do_nothing_debug_hooks.var_location)
+      && generating_for_darwin_version >= 9
+      && (flag_gtoggle ? (debug_info_level == DINFO_LEVEL_NONE)
+      : (debug_info_level >= DINFO_LEVEL_NORMAL))
+      && write_symbols == DWARF2_DEBUG)
     flag_var_tracking_uninit = 1;
 
   if (MACHO_DYNAMIC_NO_PIC_P)
     {
       if (flag_pic)
-       warning (0, "-mdynamic-no-pic overrides -fpic or -fPIC");
+       warning_at (UNKNOWN_LOCATION, 0,
+                "%<-mdynamic-no-pic%> overrides %<-fpic%>, %<-fPIC%>,"
+                " %<-fpie%> or %<-fPIE%>");
       flag_pic = 0;
     }
   else if (flag_pic == 1)
@@ -2610,7 +3046,7 @@ darwin_override_options (void)
     }
 
   /* It is assumed that branch island stubs are needed for earlier systems.  */
-  if (!darwin9plus)
+  if (generating_for_darwin_version < 9)
     darwin_emit_branch_islands = true;
   else
     emit_aligned_common = true; /* Later systems can support aligned common.  */
@@ -2619,12 +3055,13 @@ darwin_override_options (void)
   darwin_running_cxx = (strstr (lang_hooks.name, "C++") != 0);
 }
 
-/* Add $LDBL128 suffix to long double builtins.  */
+#if DARWIN_PPC
+/* Add $LDBL128 suffix to long double builtins for ppc darwin.  */
 
 static void
-darwin_patch_builtin (int fncode)
+darwin_patch_builtin (enum built_in_function fncode)
 {
-  tree fn = built_in_decls[fncode];
+  tree fn = builtin_decl_explicit (fncode);
   tree sym;
   char *newname;
 
@@ -2636,7 +3073,7 @@ darwin_patch_builtin (int fncode)
 
   set_user_assembler_name (fn, newname);
 
-  fn = implicit_built_in_decls[fncode];
+  fn = builtin_decl_implicit (fncode);
   if (fn)
     set_user_assembler_name (fn, newname);
 }
@@ -2660,6 +3097,7 @@ darwin_patch_builtins (void)
 #undef PATCH_BUILTIN_NO64
 #undef PATCH_BUILTIN_VARIADIC
 }
+#endif
 
 /*  CFStrings implementation.  */
 static GTY(()) tree cfstring_class_reference = NULL_TREE;
@@ -2669,7 +3107,7 @@ 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;
+static enum built_in_function darwin_builtin_cfstring;
 
 /* Store all constructed constant CFStrings in a hash table so that
    they get uniqued properly.  */
@@ -2699,14 +3137,14 @@ add_builtin_field_decl (tree type, const char *name, tree **chain)
   return field;
 }
 
-void
-darwin_init_cfstring_builtins (unsigned first_avail)
+tree
+darwin_init_cfstring_builtins (unsigned builtin_cfstring)
 {
   tree cfsfun, fields, pccfstring_ftype_pcchar;
   tree *chain = NULL;
 
-  DARWIN_BUILTIN_CFSTRINGMAKECONSTANTSTRING = 
-                       (enum built_in_function) first_avail;
+  darwin_builtin_cfstring = 
+    (enum built_in_function) builtin_cfstring;
   
   /* struct __builtin_CFString {
        const int *isa;         (will point at
@@ -2752,7 +3190,7 @@ darwin_init_cfstring_builtins (unsigned first_avail)
   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;
+  DECL_FUNCTION_CODE (cfsfun) = darwin_builtin_cfstring;
   lang_hooks.builtin_function (cfsfun);
 
   /* extern int __CFConstantStringClassReference[];  */
@@ -2768,6 +3206,8 @@ darwin_init_cfstring_builtins (unsigned first_avail)
   
   /* Initialize the hash table used to hold the constant CFString objects.  */
   cfstring_htab = htab_create_ggc (31, cfstring_hash, cfstring_eq, NULL);
+
+  return cfstring_type_node;
 }
 
 tree
@@ -2776,7 +3216,7 @@ darwin_fold_builtin (tree fndecl, int n_args, tree *argp,
 {
   unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
   
-  if (fcode == DARWIN_BUILTIN_CFSTRINGMAKECONSTANTSTRING)
+  if (fcode == darwin_builtin_cfstring)
     {
       if (!darwin_constant_cfstrings)
        {
@@ -2797,6 +3237,35 @@ darwin_fold_builtin (tree fndecl, int n_args, tree *argp,
   return NULL_TREE;
 }
 
+void
+darwin_rename_builtins (void)
+{
+  /* The system ___divdc3 routine in libSystem on darwin10 is not
+     accurate to 1ulp, ours is, so we avoid ever using the system name
+     for this routine and instead install a non-conflicting name that
+     is accurate.
+
+     When -ffast-math or -funsafe-math-optimizations is given, we can
+     use the faster version.  */
+  if (!flag_unsafe_math_optimizations)
+    {
+      enum built_in_function dcode
+       = (enum built_in_function)(BUILT_IN_COMPLEX_DIV_MIN
+                                  + DCmode - MIN_MODE_COMPLEX_FLOAT);
+      tree fn = builtin_decl_explicit (dcode);
+      /* Fortran and c call TARGET_INIT_BUILTINS and
+        TARGET_INIT_LIBFUNCS at different times, so we have to put a
+        call into each to ensure that at least one of them is called
+        after build_common_builtin_nodes.  A better fix is to add a
+        new hook to run after build_common_builtin_nodes runs.  */
+      if (fn)
+       set_user_assembler_name (fn, "___ieee_divdc3");
+      fn = builtin_decl_implicit (dcode);
+      if (fn)
+       set_user_assembler_name (fn, "___ieee_divdc3");
+    }
+}
+
 static hashval_t
 cfstring_hash (const void *ptr)
 {
@@ -2970,32 +3439,74 @@ section *
 darwin_function_section (tree decl, enum node_frequency freq,
                          bool startup, bool exit)
 {
+  /* Decide if we need to put this in a coalescable section.  */
+  bool weak = (decl 
+              && DECL_WEAK (decl)
+              && (!DECL_ATTRIBUTES (decl)
+                  || !lookup_attribute ("weak_import", 
+                                         DECL_ATTRIBUTES (decl))));
+
+  /* If there is a specified section name, we should not be trying to
+     override.  */
+  if (decl && DECL_SECTION_NAME (decl) != NULL_TREE)
+    return get_named_section (decl, NULL, 0);
+
+  /* Default when there is no function re-ordering.  */
+  if (!flag_reorder_functions)
+    return (weak)
+           ? darwin_sections[text_coal_section]
+           : text_section;
+
   /* Startup code should go to startup subsection unless it is
      unlikely executed (this happens especially with function splitting
-     where we can split away unnecesary parts of static constructors.  */
+     where we can split away unnecesary parts of static constructors).  */
   if (startup && freq != NODE_FREQUENCY_UNLIKELY_EXECUTED)
-    return get_named_text_section
-            (decl, "__TEXT,__startup,regular,pure_instructions", "_startup");
+    return (weak)
+           ? darwin_sections[text_startup_coal_section]
+           : darwin_sections[text_startup_section];
 
   /* Similarly for exit.  */
   if (exit && freq != NODE_FREQUENCY_UNLIKELY_EXECUTED)
-    return get_named_text_section (decl,
-                                  "__TEXT,__exit,regular,pure_instructions",
-                                  "_exit");
+    return (weak)
+           ? darwin_sections[text_exit_coal_section]
+           : darwin_sections[text_exit_section];
 
   /* Group cold functions together, similarly for hot code.  */
   switch (freq)
     {
       case NODE_FREQUENCY_UNLIKELY_EXECUTED:
-       return get_named_text_section
-                (decl,
-                 "__TEXT,__unlikely,regular,pure_instructions", "_unlikely");
+       return (weak)
+               ? darwin_sections[text_cold_coal_section]
+               : darwin_sections[text_cold_section];
+       break;
       case NODE_FREQUENCY_HOT:
-       return get_named_text_section
-                (decl, "__TEXT,__hot,regular,pure_instructions", "_hot");
+       return (weak)
+               ? darwin_sections[text_hot_coal_section]
+               : darwin_sections[text_hot_section];
+       break;
       default:
-       return NULL;
+       return (weak)
+               ? darwin_sections[text_coal_section]
+               : text_section;
+       break;
     }
 }
 
+/* When a function is partitioned between sections, we need to insert a label
+   at the start of each new chunk - so that it may become a valid 'atom' for
+   eh and debug purposes.  Without this the linker will emit warnings if one 
+   tries to add line location information (since the switched fragment will 
+   be anonymous).  */
+
+void
+darwin_function_switched_text_sections (FILE *fp, tree decl, bool new_is_cold)
+{
+  char buf[128];
+  snprintf (buf, 128, "%s%s",new_is_cold?"__cold_sect_of_":"__hot_sect_of_",
+           IDENTIFIER_POINTER (DECL_NAME (decl)));
+  /* Make sure we pick up all the relevant quotes etc.  */
+  assemble_name_raw (fp, (const char *) buf);
+  fputs (":\n", fp);
+}
+
 #include "gt-darwin.h"