OSDN Git Service

* alias.c, c-common.h, c-incpath.c, c-incpath.h, expr.c,
[pf3gnuchains/gcc-fork.git] / gcc / config / darwin.c
index 429bddb..de2f6e3 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,6 +41,7 @@ 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"
@@ -89,16 +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)
-    || (SYMBOL_REF_LOCAL_P (sym_ref) && ! SYMBOL_REF_EXTERNAL_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
@@ -126,7 +142,7 @@ machopic_classify_symbol (rtx sym_ref)
 
 /* 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 refernce the original instance
+   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_;
@@ -168,6 +184,7 @@ machopic_data_defined_p (rtx sym_ref)
   switch (machopic_classify_symbol (sym_ref))
     {
     case MACHOPIC_DEFINED_DATA:
+    case MACHOPIC_DEFINED_FUNCTION:
       return 1;
     default:
       return 0;
@@ -245,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;
@@ -267,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
@@ -276,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
@@ -287,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)
@@ -328,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.  */
@@ -373,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);
     }
 }
 
@@ -406,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 ();
@@ -607,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));
@@ -739,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;
                }
@@ -850,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)
     {
@@ -871,7 +888,7 @@ 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 (! indirect_data (symbol)
           && (machopic_symbol_defined_p (symbol)
@@ -970,7 +987,7 @@ 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)
@@ -983,29 +1000,6 @@ darwin_encode_section_info (tree decl, rtx rtl, int first ATTRIBUTE_UNUSED)
     SYMBOL_REF_FLAGS (sym_ref) |= MACHO_SYMBOL_STATIC;
 }
 
-static GTY(()) tree textcoal_section = 0;
-static GTY(()) tree datacoal_section = 0;
-
-void
-darwin_make_decl_one_only (tree decl)
-{
-  tree sec = 0;
-  if (textcoal_section == 0)
-    {
-      static const char *ts = "__TEXT,__textcoal_nt,coalesced,no_toc";
-      static const char *ds = "__DATA,__datacoal_nt,coalesced,no_toc";
-      textcoal_section = build_string (strlen (ts), ts);
-      datacoal_section = build_string (strlen (ds), ds);
-    }
-
-  sec = TREE_CODE (decl) == FUNCTION_DECL
-    ? textcoal_section
-    : datacoal_section;
-  TREE_PUBLIC (decl) = 1;
-  DECL_ONE_ONLY (decl) = 1;
-  DECL_SECTION_NAME (decl) = sec;
-}
-
 void
 darwin_mark_decl_preserved (const char *name)
 {
@@ -1019,13 +1013,23 @@ 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 },
+    { text_unlikely_section, text_unlikely_coal_section },
+    { readonly_data_section, const_coal_section },
+    { const_data_section, const_data_coal_section },
+    { data_section, data_coal_section }
+  };
+
+  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)
@@ -1034,7 +1038,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 &&
@@ -1119,6 +1123,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 ();
 }
@@ -1181,41 +1207,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. 
@@ -1257,14 +1285,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)
     {
@@ -1317,7 +1345,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");
 }
 
@@ -1331,21 +1359,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