Add Darwin (Mac OS X kernel) native support.
authorshebs <shebs@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 12 Apr 2001 02:13:00 +0000 (02:13 +0000)
committershebs <shebs@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 12 Apr 2001 02:13:00 +0000 (02:13 +0000)
        * config.gcc (powerpc-*-darwin*): Add native bits.
        * config/darwin.c: New file, generic Darwin support functions.
        * config/darwin.h: New file, generic Darwin definitions.
        * config/darwin-protos.h: New file, generic Darwin prototypes.
        * rs6000/darwin.h: New file, Darwin for PowerPC.
        * rs6000/t-darwin: New file, Darwin makefile fragment.
        * rs6000/rs6000.h (OBJECT_MACHO): New macro.
        (TARGET_MACHO): Ditto.
        (rs6000_abi): Add ABI_DARWIN.
        (RS6000_REG_SAVE): Add ABI_DARWIN case.
        (RS6000_SAVE_AREA): Ditto.
        (FP_ARG_MAX_REG): Ditto.
        (RETURN_ADDRESS_OFFSET): Ditto.
        * rs6000/rs6000.c (rs6000_legitimize_address): Add TARGET_MACHO
        cases.
        (rs6000_emit_move): Add ABI_DARWIN cases.
        (print_operand): Ditto.
        (first_reg_to_save): Ditto.
        (rs6000_stack_info): Ditto, also align stack by 16 instead of 8.
        (debug_stack_info): Ditto.
        (rs6000_emit_prologue): Ditto.
        (rs6000_emit_epilogue): Ditto.
        (output_profiler_hook): Ditto.
        (output_function_profiler): Ditto.
        (rs6000_add_gc_roots): Call machopic_add_gc_roots if TARGET_MACHO.
        (output_mi_thunk): Add TARGET_MACHO case.
        (add_compiler_stub): Ditto.
        (output_compiler_stub): Ditto.
        (no_previous_def): Ditto.
        (output_call): Ditto.
        (machopic_output_stub): Ditto.
        (rs6000_machopic_legitimize_pic_address): Ditto.
        (toc_section): Ditto.
        * rs6000/rs6000.md (addsi3_high): New TARGET_MACHO pattern.
        (macho_high): Ditto.
        (macho_low): Ditto.
        (movsi_low): Ditto.
        (load_macho_picbase): Ditto.
        (call): Add TARGET_MACHO case to modify function.
        (call_value): Ditto.
        (call_nonlocal_sysv): Add ABI_DARWIN case.
        (call_value_nonlocal_sysv): Ditto.
        * rs6000/rs6000-protos.h (rs6000_machopic_legitimize_pic_address):
        Add prototype.
        (machopic_output_stub): Ditto.
        * ginclude/stddef.h: Test _BSD_WCHAR_T_DEFINED_.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@41277 138bc75d-0d04-0410-961f-82ee72b054a4

12 files changed:
gcc/ChangeLog
gcc/config.gcc
gcc/config/darwin-protos.h [new file with mode: 0644]
gcc/config/darwin.c [new file with mode: 0644]
gcc/config/darwin.h [new file with mode: 0644]
gcc/config/rs6000/darwin.h [new file with mode: 0644]
gcc/config/rs6000/rs6000-protos.h
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.h
gcc/config/rs6000/rs6000.md
gcc/config/rs6000/t-darwin [new file with mode: 0644]
gcc/ginclude/stddef.h

index 8426f00..094a788 100644 (file)
@@ -1,3 +1,53 @@
+2001-04-11  Stan Shebs  <shebs@apple.com>
+
+       Add Darwin (Mac OS X kernel) native support.
+       * config.gcc (powerpc-*-darwin*): Add native bits.
+       * config/darwin.c: New file, generic Darwin support functions.
+       * config/darwin.h: New file, generic Darwin definitions.
+       * config/darwin-protos.h: New file, generic Darwin prototypes.
+       * rs6000/darwin.h: New file, Darwin for PowerPC.
+       * rs6000/t-darwin: New file, Darwin makefile fragment.
+       * rs6000/rs6000.h (OBJECT_MACHO): New macro.
+       (TARGET_MACHO): Ditto.
+       (rs6000_abi): Add ABI_DARWIN.
+       (RS6000_REG_SAVE): Add ABI_DARWIN case.
+       (RS6000_SAVE_AREA): Ditto.
+       (FP_ARG_MAX_REG): Ditto.
+       (RETURN_ADDRESS_OFFSET): Ditto.
+       * rs6000/rs6000.c (rs6000_legitimize_address): Add TARGET_MACHO
+       cases.
+       (rs6000_emit_move): Add ABI_DARWIN cases.
+       (print_operand): Ditto.
+       (first_reg_to_save): Ditto.
+       (rs6000_stack_info): Ditto, also align stack by 16 instead of 8.
+       (debug_stack_info): Ditto.
+       (rs6000_emit_prologue): Ditto.
+       (rs6000_emit_epilogue): Ditto.
+       (output_profiler_hook): Ditto.
+       (output_function_profiler): Ditto.
+       (rs6000_add_gc_roots): Call machopic_add_gc_roots if TARGET_MACHO.
+       (output_mi_thunk): Add TARGET_MACHO case.
+       (add_compiler_stub): Ditto.
+       (output_compiler_stub): Ditto.
+       (no_previous_def): Ditto.
+       (output_call): Ditto.
+       (machopic_output_stub): Ditto.
+       (rs6000_machopic_legitimize_pic_address): Ditto.
+       (toc_section): Ditto.
+       * rs6000/rs6000.md (addsi3_high): New TARGET_MACHO pattern.
+       (macho_high): Ditto.
+       (macho_low): Ditto.
+       (movsi_low): Ditto.
+       (load_macho_picbase): Ditto.
+       (call): Add TARGET_MACHO case to modify function.
+       (call_value): Ditto.
+       (call_nonlocal_sysv): Add ABI_DARWIN case.
+       (call_value_nonlocal_sysv): Ditto.
+       * rs6000/rs6000-protos.h (rs6000_machopic_legitimize_pic_address):
+       Add prototype.
+       (machopic_output_stub): Ditto.
+       * ginclude/stddef.h: Test _BSD_WCHAR_T_DEFINED_.
+
 2001-04-11  Mark Mitchell  <mark@codesourcery.com>
 
        * dwarf2out.c (modified_type_die): Don't create new types here.
index 6fb9e99..07578f9 100644 (file)
@@ -2647,8 +2647,15 @@ powerpc-*-beos*)
        tmake_file=rs6000/t-beos
        ;;
 powerpc-*-darwin*)
+       cpu_type=rs6000
+       tm_file="${tm_file} darwin.h rs6000/darwin.h"
+       tm_p_file="${tm_p_file} darwin-protos.h"
+       tmake_file=rs6000/t-darwin
        xm_file=rs6000/xm-darwin.h
        xmake_file=rs6000/x-darwin
+       extra_objs="darwin.o"
+       # Darwin linker does collect2 functionality
+       use_collect2=no
        ;;
 powerpc-*-sysv*)
        tm_file="${tm_file} svr4.h rs6000/sysv4.h"
diff --git a/gcc/config/darwin-protos.h b/gcc/config/darwin-protos.h
new file mode 100644 (file)
index 0000000..b2326c0
--- /dev/null
@@ -0,0 +1,57 @@
+/* Prototypes.
+   Copyright (C) 2001 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+extern int name_needs_quotes PARAMS ((const char *));
+
+extern void machopic_validate_stub_or_non_lazy_ptr PARAMS ((const char *, int));
+
+extern char *machopic_function_base_name PARAMS ((void));
+extern char *machopic_non_lazy_ptr_name PARAMS ((const char*));
+extern char *machopic_stub_name PARAMS ((const char*));
+
+extern void machopic_add_gc_roots PARAMS ((void));
+
+extern void machopic_picsymbol_stub_section PARAMS ((void));
+extern void machopic_symbol_stub_section PARAMS ((void));
+extern void machopic_lazy_symbol_ptr_section PARAMS ((void));
+extern void machopic_nl_symbol_ptr_section PARAMS ((void));
+
+#ifdef RTX_CODE
+
+extern int machopic_operand_p PARAMS ((rtx));
+extern enum machopic_addr_class machopic_classify_name PARAMS ((const char*));
+
+extern rtx machopic_indirect_data_reference PARAMS ((rtx, rtx));
+extern rtx machopic_indirect_call_target PARAMS ((rtx));
+extern rtx machopic_legitimize_pic_address PARAMS ((rtx, enum machine_mode, rtx));
+
+#endif /* RTX_CODE */
+
+#ifdef TREE_CODE
+
+extern enum machopic_addr_class machopic_classify_ident PARAMS ((tree));
+extern void machopic_define_ident PARAMS ((tree));
+extern void machopic_define_name PARAMS ((const char*));
+extern int machopic_name_defined_p PARAMS ((const char*));
+extern int machopic_ident_defined_p PARAMS ((tree));
+
+#endif /* TREE_CODE */
+
+extern void machopic_finish PARAMS ((FILE *));
diff --git a/gcc/config/darwin.c b/gcc/config/darwin.c
new file mode 100644 (file)
index 0000000..3e2a000
--- /dev/null
@@ -0,0 +1,1002 @@
+/* Functions for generic Darwin as target machine for GNU C compiler.
+   Copyright (C) 1989, 1990, 1991, 1992, 1993, 2000, 2001
+   Free Software Foundation, Inc.
+   Contributed by Apple Computer Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+#include "config.h"
+#include "system.h"
+#include "rtl.h"
+#include "regs.h"
+#include "hard-reg-set.h"
+#include "real.h"
+#include "insn-config.h"
+#include "conditions.h"
+#include "insn-flags.h"
+#include "output.h"
+#include "insn-attr.h"
+#include "flags.h"
+#include "tree.h"
+#include "expr.h"
+#include "reload.h"
+/* need for IDENTIFIER_GLOBAL_VALUE and IDENTIFIER_LOCAL_VALUE */
+#include "c-tree.h"
+#include "function.h"
+#include "ggc.h"
+
+#include "darwin-protos.h"
+
+extern void machopic_output_stub PARAMS ((FILE *, const char *, const char *));
+
+static int machopic_data_defined_p PARAMS ((const char *));
+static int func_name_maybe_scoped PARAMS ((const char *));
+
+/* Make everything that used to go in the text section really go there.  */
+
+int flag_no_mach_text_sections = 0;
+
+int
+name_needs_quotes (name)
+     const char *name;
+{
+  int c;
+  while ((c = *name++) != '\0')
+    if (!isalnum (c) && c != '_')
+      return 1;
+  return 0;
+}
+
+/* 
+ * flag_pic = 1 ... generate only indirections
+ * flag_pic = 2 ... generate indirections and pure code
+ */
+
+/* This module assumes that (const (symbol_ref "foo")) is a legal pic
+   reference, which will not be changed.  */
+
+static tree machopic_defined_list;
+
+enum machopic_addr_class
+machopic_classify_ident (ident)
+     tree ident;
+{
+  const char *name = IDENTIFIER_POINTER (ident);
+  int lprefix = (((name[0] == '*' || name[0] == '&')
+                 && (name[1] == 'L' || (name[1] == '"' && name[2] == 'L')))
+                || (   name[0] == '_' 
+                    && name[1] == 'O' 
+                    && name[2] == 'B' 
+                    && name[3] == 'J'
+                    && name[4] == 'C'
+                    && name[5] == '_'));
+  tree temp, decl = lookup_name_darwin (ident);
+
+  if (!decl)
+    {
+      if (lprefix)
+       {
+         const char *name = IDENTIFIER_POINTER (ident);
+         int len = strlen (name);
+
+         if ((len > 5 && !strcmp (name + len - 5, "$stub"))
+             || (len > 6 && !strcmp (name + len - 6, "$stub\"")))
+           return MACHOPIC_DEFINED_FUNCTION;
+         return MACHOPIC_DEFINED_DATA;
+       }
+
+      for (temp = machopic_defined_list;
+          temp != NULL_TREE;
+          temp = TREE_CHAIN (temp))
+       {
+         if (ident == TREE_VALUE (temp))
+           return MACHOPIC_DEFINED_DATA;
+       }
+
+      if (TREE_ASM_WRITTEN (ident))
+       return MACHOPIC_DEFINED_DATA;
+
+      return MACHOPIC_UNDEFINED;
+    }
+
+  /* variable declarations */
+  else if (TREE_CODE (decl) == VAR_DECL)
+    {
+      if ((DECL_INITIAL (decl)
+           || TREE_STATIC (decl))
+          && ! TREE_PUBLIC (decl))
+       return MACHOPIC_DEFINED_DATA;
+    }
+
+  /* function declarations */
+  else if (TREE_CODE (decl) == FUNCTION_DECL
+          && (!DECL_EXTERNAL (decl)))
+    {
+      if (TREE_STATIC (decl)
+         || TREE_ASM_WRITTEN (decl))
+       return MACHOPIC_DEFINED_FUNCTION;
+    }
+
+  for (temp = machopic_defined_list; temp != NULL_TREE; temp = TREE_CHAIN (temp))
+    {
+      if (ident == TREE_VALUE (temp))
+       {
+         if (TREE_CODE (decl) == FUNCTION_DECL)
+           return MACHOPIC_DEFINED_FUNCTION;
+         else
+           return MACHOPIC_DEFINED_DATA;
+       }
+    }
+  
+  if (TREE_CODE (decl) == FUNCTION_DECL)
+    {
+      if (lprefix)
+       return MACHOPIC_DEFINED_FUNCTION;
+      else
+       return MACHOPIC_UNDEFINED_FUNCTION;
+    }
+  else
+    {
+      if (lprefix)
+       return MACHOPIC_DEFINED_DATA;
+      else
+       return MACHOPIC_UNDEFINED_DATA;
+    }
+}
+
+     
+enum machopic_addr_class
+machopic_classify_name (name)
+     const char *name;
+{
+  return machopic_classify_ident (get_identifier (name));
+}
+
+int
+machopic_ident_defined_p (ident)
+     tree ident;
+{
+  switch (machopic_classify_ident (ident))
+    {
+    case MACHOPIC_UNDEFINED:
+    case MACHOPIC_UNDEFINED_DATA:
+    case MACHOPIC_UNDEFINED_FUNCTION:
+      return 0;
+    default:
+      return 1;
+    }
+}
+
+static int
+machopic_data_defined_p (name)
+     const char *name;
+{
+  switch (machopic_classify_ident (get_identifier (name)))
+    {
+    case MACHOPIC_DEFINED_DATA:
+      return 1;
+    default:
+      return 0;
+    }
+}
+
+int
+machopic_name_defined_p (name)
+     const char *name;
+{
+  return machopic_ident_defined_p (get_identifier (name));
+}
+
+void
+machopic_define_ident (ident)
+     tree ident;
+{
+  if (!machopic_ident_defined_p (ident))
+    machopic_defined_list = 
+      tree_cons (NULL_TREE, ident, machopic_defined_list);
+}
+
+void
+machopic_define_name (name)
+     const char *name;
+{
+  machopic_define_ident (get_identifier (name));
+}
+
+tree
+lookup_name_darwin (name)
+     tree name;
+{
+  tree val;
+
+  if (!global_bindings_p()
+      && IDENTIFIER_LOCAL_VALUE (name))
+    val = IDENTIFIER_LOCAL_VALUE (name);
+  else
+    val = IDENTIFIER_GLOBAL_VALUE (name);
+  return val;
+}
+
+/* This is a static to make inline functions work.  The rtx
+   representing the PIC base symbol always points to here. */
+
+static char function_base[32];
+
+static int current_pic_label_num;
+
+char *
+machopic_function_base_name ()
+{
+  static char *name = NULL;
+  static const char *current_name;
+
+  current_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));
+
+  if (name != current_name)
+    {
+      current_function_uses_pic_offset_table = 1;
+
+      /* Save mucho space and time.  Some of the C++ mangled names are over
+        700 characters long!  Note that we produce a label containing a '-'
+        if the function we're compiling is an Objective-C method, as evinced
+        by the incredibly scientific test below.  This is because code in
+        rs6000.c makes the same ugly test when loading the PIC reg.  */
+      ++current_pic_label_num;
+      if (*current_name == '+' || *current_name == '-')
+       sprintf (function_base, "*\"L-%d$pb\"", current_pic_label_num);
+      else
+       sprintf (function_base, "*L%d$pb", current_pic_label_num);
+
+      name = current_name;
+    }
+
+  return function_base;
+}
+
+static tree machopic_non_lazy_pointers = NULL;
+
+/* Return a non-lazy pointer name corresponding to the given name,
+   either by finding it in our list of pointer names, or by generating
+   a new one.  */
+
+char * 
+machopic_non_lazy_ptr_name (name)
+     const char *name;
+{
+  tree temp, ident = get_identifier (name);
+  
+  for (temp = machopic_non_lazy_pointers;
+       temp != NULL_TREE; 
+       temp = TREE_CHAIN (temp))
+    {
+      if (ident == TREE_VALUE (temp))
+       return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
+    }
+
+  {
+    char *buffer;
+    tree ptr_name;
+
+    buffer = alloca (strlen (name) + 20);
+
+    strcpy (buffer, "&L");
+    if (name[0] == '*')
+      strcat (buffer, name+1);
+    else
+      {
+       strcat (buffer, "_");
+       strcat (buffer, name);
+      }
+      
+    strcat (buffer, "$non_lazy_ptr");
+    ptr_name = get_identifier (buffer);
+
+    machopic_non_lazy_pointers 
+      = tree_cons (ptr_name, ident, machopic_non_lazy_pointers);
+
+    TREE_USED (machopic_non_lazy_pointers) = 0;
+
+    return IDENTIFIER_POINTER (ptr_name);
+  }
+}
+
+static tree machopic_stubs = 0;
+
+/* Make sure the GC knows about our homemade lists.  */
+
+void
+machopic_add_gc_roots ()
+{
+  ggc_add_tree_root (&machopic_defined_list, 1);
+  ggc_add_tree_root (&machopic_non_lazy_pointers, 1);
+  ggc_add_tree_root (&machopic_stubs, 1);
+}
+
+/* Return the name of the stub corresponding to the given name,
+   generating a new stub name if necessary.  */
+
+char * 
+machopic_stub_name (name)
+     const char *name;
+{
+  tree temp, ident = get_identifier (name);
+  
+  for (temp = machopic_stubs;
+       temp != NULL_TREE; 
+       temp = TREE_CHAIN (temp))
+    {
+      if (ident == TREE_VALUE (temp))
+       return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
+    }
+
+  {
+    char *buffer;
+    tree ptr_name;
+    int needs_quotes = name_needs_quotes (name);
+
+    buffer = alloca (strlen (name) + 20);
+
+    if (needs_quotes)
+      strcpy (buffer, "&\"L");
+    else
+      strcpy (buffer, "&L");
+    if (name[0] == '*')
+      {
+       strcat (buffer, name+1);
+      }
+    else
+      {
+       strcat (buffer, "_");
+       strcat (buffer, name);
+      }
+
+    if (needs_quotes)
+      strcat (buffer, "$stub\"");
+    else
+      strcat (buffer, "$stub");
+    ptr_name = get_identifier (buffer);
+
+    machopic_stubs = tree_cons (ptr_name, ident, machopic_stubs);
+    TREE_USED (machopic_stubs) = 0;
+
+    return IDENTIFIER_POINTER (ptr_name);
+  }
+}
+
+void
+machopic_validate_stub_or_non_lazy_ptr (name, validate_stub)
+     const char *name;
+     int validate_stub;
+{
+    tree temp, ident = get_identifier (name);
+
+    for (temp = (validate_stub ? machopic_stubs : machopic_non_lazy_pointers);
+         temp != NULL_TREE;
+         temp = TREE_CHAIN (temp))
+      if (ident == TREE_PURPOSE (temp))
+       {
+         /* Mark both the stub or non-lazy pointer as well as the
+            original symbol as being referenced.  */
+          TREE_USED (temp) = 1;
+         if (TREE_CODE (TREE_VALUE (temp)) == IDENTIFIER_NODE)
+           TREE_SYMBOL_REFERENCED (TREE_VALUE (temp)) = 1;
+       }
+}
+
+/* Transform ORIG, which may be any data source, to the corresponding
+   source using indirections.  */
+
+rtx
+machopic_indirect_data_reference (orig, reg)
+     rtx orig, reg;
+{
+  rtx ptr_ref = orig;
+  
+  if (! MACHOPIC_INDIRECT)
+    return orig;
+
+  if (GET_CODE (orig) == SYMBOL_REF)
+    {
+      const char *name = XSTR (orig, 0);
+
+      if (machopic_data_defined_p (name))
+       {
+         rtx pic_base = gen_rtx (SYMBOL_REF, Pmode, 
+                                 machopic_function_base_name ());
+         rtx offset = gen_rtx (CONST, Pmode,
+                               gen_rtx (MINUS, Pmode, orig, pic_base));
+
+#if defined (TARGET_TOC) /* i.e., PowerPC */
+         rtx hi_sum_reg = reg;
+
+         if (reg == NULL)
+           abort ();
+
+         emit_insn (gen_rtx (SET, Pmode, hi_sum_reg,
+                             gen_rtx (PLUS, Pmode, pic_offset_table_rtx,
+                                      gen_rtx (HIGH, Pmode, offset))));
+         emit_insn (gen_rtx (SET, Pmode, reg,
+                             gen_rtx (LO_SUM, Pmode, hi_sum_reg, offset)));
+
+         orig = reg;
+#else
+#if defined (HAVE_lo_sum)
+         if (reg == 0) abort ();
+
+         emit_insn (gen_rtx (SET, VOIDmode, reg,
+                             gen_rtx (HIGH, Pmode, offset)));
+         emit_insn (gen_rtx (SET, VOIDmode, reg,
+                             gen_rtx (LO_SUM, Pmode, reg, offset)));
+         emit_insn (gen_rtx (USE, VOIDmode,
+                             gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM)));
+
+         orig = gen_rtx (PLUS, Pmode, pic_offset_table_rtx, reg);
+#endif
+#endif
+         return orig;
+       }
+
+      ptr_ref = gen_rtx (SYMBOL_REF, Pmode,
+                         machopic_non_lazy_ptr_name (name));
+
+      ptr_ref = gen_rtx_MEM (Pmode, ptr_ref);
+      RTX_UNCHANGING_P (ptr_ref) = 1;
+
+      return ptr_ref;
+    }
+  else if (GET_CODE (orig) == CONST)
+    {
+      rtx base, result;
+
+      /* legitimize both operands of the PLUS */
+      if (GET_CODE (XEXP (orig, 0)) == PLUS)
+       {
+         base = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 0),
+                                                  reg);
+         orig = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 1),
+                                                  (base == reg ? 0 : reg));
+       }
+      else 
+       return orig;
+
+      if (MACHOPIC_PURE && GET_CODE (orig) == CONST_INT)
+        {
+         result = plus_constant_for_output (base, INTVAL (orig));
+        }
+      else
+        {
+           result = gen_rtx (PLUS, Pmode, base, orig);
+        }
+
+      if (RTX_UNCHANGING_P (base) && RTX_UNCHANGING_P (orig))
+       RTX_UNCHANGING_P (result) = 1;
+
+      if (MACHOPIC_JUST_INDIRECT && GET_CODE (base) == MEM)
+       {
+         if (reg)
+           {
+             emit_move_insn (reg, result);
+             result = reg;
+           }
+         else
+           {
+             result = force_reg (GET_MODE (result), result);
+           }
+       }
+
+      return result;
+
+    }
+  else if (GET_CODE (orig) == MEM)
+    XEXP (ptr_ref, 0) = machopic_indirect_data_reference (XEXP (orig, 0), reg);
+  /* When the target is i386, this code prevents crashes due to the
+     compiler's ignorance on how to move the PIC base register to
+     other registers.  (The reload phase sometimes introduces such
+     insns.)  */
+  else if (GET_CODE (orig) == PLUS
+          && GET_CODE (XEXP (orig, 0)) == REG
+          && REGNO (XEXP (orig, 0)) == PIC_OFFSET_TABLE_REGNUM
+#ifdef I386
+          /* Prevent the same register from being erroneously used
+             as both the base and index registers.  */
+          && GET_CODE (XEXP (orig, 1)) == CONST
+#endif
+          && reg)
+    {
+      emit_move_insn (reg, XEXP (orig, 0));
+      XEXP (ptr_ref, 0) = reg;
+    }
+  return ptr_ref;
+}
+
+/* For MACHOPIC_INDIRECT_CALL_TARGET below, we need to beware of:
+
+       extern "C" { int f(); }
+       struct X { int f(); int g(); };
+       int X::f() { ::f(); }
+       int X::g() { ::f(); f();}
+
+  This is hairy.  Both calls to "::f()" need to be indirect (i.e., to
+  appropriate symbol stubs), but since MACHOPIC_NAME_DEFINED_P calls
+  GET_IDENTIFIER which treats "f" as "X::f", and "X::f" is indeed (being)
+  defined somewhere in "X"'s inheritance hierarchy, MACHOPIC_NAME_DEFINED_P
+  returns TRUE when called with "f", which means that
+  MACHOPIC_INDIRECT_CALL_TARGET uses an "internal" call instead of an
+  indirect one as it should.
+
+  Our quick-n-dirty solution to this is to call the following
+  FUNC_NAME_MAYBE_SCOPED routine which (only for C++) checks whether
+  FNAME -- the name of the function which we're calling -- is NOT a
+  mangled C++ name, AND if the current function being compiled is a
+  method, and if so, use an "external" or "indirect" call. 
+
+  Note that this function will be called ONLY when MACHOPIC_INDIRECT_TARGET_P
+  has already indicated that the target is NOT indirect.
+
+  This conservative solution will sometimes make indirect calls where
+  it might have been possible to make direct ones.
+
+  FUNC_NAME_MAYBE_SCOPED returns 1 to indicate a "C" name (not scoped),
+  which in turns means we should create a stub for an indirect call.
+  */
+
+static int is_cplusplus = -1;
+
+static int
+func_name_maybe_scoped (fname)
+     const char *fname;
+{
+
+  if (is_cplusplus < 0)
+    is_cplusplus = (strcmp (lang_identify (), "cplusplus") == 0);
+
+  if (is_cplusplus)
+    {
+      /* If we have a method, then check whether the function we're trying to
+         call is a "C" function.  If so, we should use an indirect call.
+
+         It turns out to be hard to tell whether "we have a method", since
+         static member functions have a TREE_CODE of FUNCTION_TYPE, as do
+         namespace-level non-member functions.  So here, we always look for
+         an extern-"C"-like name, and make stubs for them no matter the
+         calling context.  This is temporary, and leaves nagging suspicion
+        that improvements should be possible here.  (I.e., I suspect that
+         it can still sometimes make stubs where it needn't.)  */
+
+      /* if (1 || TREE_CODE (TREE_TYPE (current_function_decl)) == METHOD_TYPE) */
+       {
+         /* If fname is of the form "f__1X" or "f__Fv", it's C++.  */
+         while (*fname == '_') ++fname;        /* skip leading underscores  */
+         while (*fname != 0)
+           {
+             if (fname[0] == '_' && fname[1] == '_'
+                 && (fname[2] == 'F' || (fname[2] >= '0' && fname[2] <= '9')))
+               return 0;
+             ++fname;
+           }
+         /* Not a C++ mangled name: must be "C", in which case play safe.  */
+         return 1;
+       }
+    }
+  return 0;
+}
+
+/* Transform TARGET (a MEM), which is a function call target, to the
+   corresponding symbol_stub if necessary.  Return a new MEM.  */
+
+rtx
+machopic_indirect_call_target (target)
+     rtx target;
+{
+  if (GET_CODE (target) != MEM)
+    return target;
+
+  if (MACHOPIC_INDIRECT && GET_CODE (XEXP (target, 0)) == SYMBOL_REF)
+    { 
+      enum machine_mode mode = GET_MODE (XEXP (target, 0));
+      const char *name = XSTR (XEXP (target, 0), 0);
+
+      if (!machopic_name_defined_p (name) || func_name_maybe_scoped (name)) 
+       {
+         const char *stub_name = machopic_stub_name (name);
+
+         XEXP (target, 0) = gen_rtx (SYMBOL_REF, mode, stub_name);
+         RTX_UNCHANGING_P (target) = 1;
+       } 
+    }
+
+  return target;
+}
+
+rtx
+machopic_legitimize_pic_address (orig, mode, reg)
+     rtx orig, reg;
+     enum machine_mode mode;
+{
+  rtx pic_ref = orig;
+
+  if (! MACHOPIC_PURE)
+    return orig;
+
+  /* First handle a simple SYMBOL_REF or LABEL_REF */
+  if (GET_CODE (orig) == LABEL_REF
+      || (GET_CODE (orig) == SYMBOL_REF
+         ))
+    {
+      /* addr(foo) = &func+(foo-func) */
+      rtx pic_base;
+
+      orig = machopic_indirect_data_reference (orig, reg);
+
+      if (GET_CODE (orig) == PLUS 
+         && GET_CODE (XEXP (orig, 0)) == REG)
+       {
+         if (reg == 0)
+           return force_reg (mode, orig);
+
+         emit_move_insn (reg, orig);
+         return reg;
+       }  
+
+      pic_base = gen_rtx (SYMBOL_REF, Pmode, machopic_function_base_name ());
+
+      if (GET_CODE (orig) == MEM)
+       {
+         if (reg == 0)
+           {
+             if (reload_in_progress)
+               abort ();
+             else
+               reg = gen_reg_rtx (Pmode);
+           }
+       
+#ifdef HAVE_lo_sum
+         if (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF 
+             || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
+           {
+             rtx offset = gen_rtx (CONST, Pmode,
+                                   gen_rtx (MINUS, Pmode,
+                                            XEXP (orig, 0), pic_base));
+#if defined (TARGET_TOC) /* i.e., PowerPC */
+             /* Generating a new reg may expose opportunities for
+                common subexpression elimination.  */
+              rtx hi_sum_reg =
+               (reload_in_progress ? reg : gen_reg_rtx (SImode));
+
+             emit_insn (gen_rtx (SET, Pmode, hi_sum_reg,
+                                 gen_rtx (PLUS, Pmode,
+                                          pic_offset_table_rtx,
+                                          gen_rtx (HIGH, Pmode, offset))));
+             emit_insn (gen_rtx (SET, VOIDmode, reg,
+                                 gen_rtx (MEM, GET_MODE (orig),
+                                          gen_rtx (LO_SUM, Pmode, 
+                                                   hi_sum_reg, offset))));
+             pic_ref = reg;
+
+#else
+             emit_insn (gen_rtx (USE, VOIDmode,
+                             gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM)));
+
+             emit_insn (gen_rtx (SET, VOIDmode, reg,
+                                 gen_rtx (HIGH, Pmode, 
+                                          gen_rtx (CONST, Pmode, offset))));
+             emit_insn (gen_rtx (SET, VOIDmode, reg,
+                                 gen_rtx (LO_SUM, Pmode, reg, 
+                                          gen_rtx (CONST, Pmode, offset))));
+             pic_ref = gen_rtx (PLUS, Pmode,
+                                pic_offset_table_rtx, reg);
+#endif
+           }
+         else
+#endif  /* HAVE_lo_sum */
+           {
+             rtx pic = pic_offset_table_rtx;
+             if (GET_CODE (pic) != REG)
+               {
+                 emit_move_insn (reg, pic);
+                 pic = reg;
+               }
+#if 0
+             emit_insn (gen_rtx (USE, VOIDmode,
+                                 gen_rtx (REG, Pmode, PIC_OFFSET_TABLE_REGNUM)));
+#endif
+
+             pic_ref = gen_rtx (PLUS, Pmode,
+                                pic, 
+                                gen_rtx (CONST, Pmode, 
+                                         gen_rtx (MINUS, Pmode,
+                                                  XEXP (orig, 0), 
+                                                  pic_base)));
+           }
+         
+#if !defined (TARGET_TOC)
+         RTX_UNCHANGING_P (pic_ref) = 1;
+         emit_move_insn (reg, pic_ref);
+         pic_ref = gen_rtx (MEM, GET_MODE (orig), reg);
+#endif
+       }
+      else
+       {
+
+#ifdef HAVE_lo_sum
+         if (GET_CODE (orig) == SYMBOL_REF 
+             || GET_CODE (orig) == LABEL_REF)
+           {
+             rtx offset = gen_rtx (CONST, Pmode,
+                                   gen_rtx (MINUS, Pmode, orig, pic_base));
+#if defined (TARGET_TOC) /* i.e., PowerPC */
+              rtx hi_sum_reg;
+
+             if (reg == 0)
+               {
+                 if (reload_in_progress)
+                   abort ();
+                 else
+                   reg = gen_reg_rtx (SImode);
+               }
+       
+             hi_sum_reg = reg;
+
+             emit_insn (gen_rtx (SET, Pmode, hi_sum_reg,
+                                 gen_rtx (PLUS, Pmode,
+                                          pic_offset_table_rtx,
+                                          gen_rtx (HIGH, Pmode, offset))));
+             emit_insn (gen_rtx (SET, VOIDmode, reg,
+                                 gen_rtx (LO_SUM, Pmode,
+                                          hi_sum_reg, offset)));
+             pic_ref = reg;
+#else
+             emit_insn (gen_rtx (SET, VOIDmode, reg,
+                                 gen_rtx (HIGH, Pmode, offset)));
+             emit_insn (gen_rtx (SET, VOIDmode, reg,
+                                 gen_rtx (LO_SUM, Pmode, reg, offset)));
+             pic_ref = gen_rtx (PLUS, Pmode,
+                                pic_offset_table_rtx, reg);
+#endif
+           }
+         else
+#endif  /*  HAVE_lo_sum  */
+           {
+             if (GET_CODE (orig) == REG)
+               {
+                 return orig;
+               }
+             else
+               {
+                 rtx pic = pic_offset_table_rtx;
+                 if (GET_CODE (pic) != REG)
+                   {
+                     emit_move_insn (reg, pic);
+                     pic = reg;
+                   }
+#if 0
+                 emit_insn (gen_rtx (USE, VOIDmode,
+                                     pic_offset_table_rtx));
+#endif
+                 pic_ref = gen_rtx (PLUS, Pmode,
+                                    pic,
+                                    gen_rtx (CONST, Pmode, 
+                                             gen_rtx (MINUS, Pmode,
+                                                      orig, pic_base)));
+               }
+           }
+       }
+
+      RTX_UNCHANGING_P (pic_ref) = 1;
+
+      if (GET_CODE (pic_ref) != REG)
+        {
+          if (reg != 0)
+            {
+              emit_move_insn (reg, pic_ref);
+              return reg;
+            }
+          else
+            {
+              return force_reg (mode, pic_ref);
+            }
+        }
+      else
+        {
+          return pic_ref;
+        }
+    }
+
+  else if (GET_CODE (orig) == SYMBOL_REF)
+    return orig;
+
+  else if (GET_CODE (orig) == PLUS
+          && (GET_CODE (XEXP (orig, 0)) == MEM
+              || GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
+              || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
+          && XEXP (orig, 0) != pic_offset_table_rtx
+          && GET_CODE (XEXP (orig, 1)) != REG)
+    
+    {
+      rtx base;
+      int is_complex = (GET_CODE (XEXP (orig, 0)) == MEM);
+
+      base = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
+      orig = machopic_legitimize_pic_address (XEXP (orig, 1),
+                                             Pmode, (base == reg ? 0 : reg));
+      if (GET_CODE (orig) == CONST_INT)
+       {
+         pic_ref = plus_constant_for_output (base, INTVAL (orig));
+         is_complex = 1;
+       }
+      else
+       {
+         pic_ref = gen_rtx (PLUS, Pmode, base, orig);
+       }
+
+      if (RTX_UNCHANGING_P (base) && RTX_UNCHANGING_P (orig))
+       RTX_UNCHANGING_P (pic_ref) = 1;
+
+      if (reg && is_complex)
+       {
+         emit_move_insn (reg, pic_ref);
+         pic_ref = reg;
+       }
+      /* Likewise, should we set special REG_NOTEs here?  */
+    }
+
+  else if (GET_CODE (orig) == CONST)
+    {
+      return machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
+    }
+
+  else if (GET_CODE (orig) == MEM
+          && GET_CODE (XEXP (orig, 0)) == SYMBOL_REF)
+    {
+      rtx addr = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
+
+      addr = gen_rtx (MEM, GET_MODE (orig), addr);
+      RTX_UNCHANGING_P (addr) = RTX_UNCHANGING_P (orig);
+      emit_move_insn (reg, addr);
+      pic_ref = reg;
+    }
+
+  return pic_ref;
+}
+
+
+void
+machopic_finish (asm_out_file)
+     FILE *asm_out_file;
+{
+  tree temp;
+
+  for (temp = machopic_stubs;
+       temp != NULL_TREE;
+       temp = TREE_CHAIN (temp))
+    {
+      char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
+      char *stub_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
+      char *sym;
+      char *stub;
+      tree decl = lookup_name_darwin (TREE_VALUE (temp));
+
+      if (! TREE_USED (temp))
+       continue;
+
+      /* Don't emit stubs for static inline functions which have not
+         been compiled.  */
+      if (decl
+          && TREE_CODE (decl) == FUNCTION_DECL
+          && DECL_INLINE (decl)
+          && ! TREE_PUBLIC (decl)
+          && ! TREE_ASM_WRITTEN (decl))
+       continue;
+
+      sym = alloca (strlen (sym_name) + 2);
+      if (sym_name[0] == '*' || sym_name[0] == '&')
+       strcpy (sym, sym_name + 1);
+      else if (sym_name[0] == '-' || sym_name[0] == '+')
+       strcpy (sym, sym_name);   
+      else
+       sym[0] = '_', strcpy (sym + 1, sym_name);
+
+      stub = alloca (strlen (stub_name) + 2);
+      if (stub_name[0] == '*' || stub_name[0] == '&')
+       strcpy (stub, stub_name + 1);
+      else
+       stub[0] = '_', strcpy (stub + 1, stub_name);
+
+      machopic_output_stub (asm_out_file, sym, stub);
+    }
+
+  for (temp = machopic_non_lazy_pointers;
+       temp != NULL_TREE; 
+       temp = TREE_CHAIN (temp))
+    {
+      char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
+      char *lazy_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
+#if 0
+      tree decl = lookup_name_darwin (TREE_VALUE (temp));
+#endif
+
+      if (! TREE_USED (temp))
+       continue;
+
+      if (machopic_ident_defined_p (TREE_VALUE (temp))
+#if 0 /* add back when we have private externs */
+          || (decl && DECL_PRIVATE_EXTERN (decl))
+#endif
+         )
+       {
+         data_section ();
+         assemble_align (UNITS_PER_WORD * BITS_PER_UNIT);
+         assemble_label (lazy_name);
+         assemble_integer (gen_rtx (SYMBOL_REF, Pmode, sym_name),
+                           GET_MODE_SIZE (Pmode), 1);
+       }
+      else
+       {
+         machopic_nl_symbol_ptr_section ();
+         assemble_name (asm_out_file, lazy_name); 
+         fprintf (asm_out_file, ":\n");
+
+         fprintf (asm_out_file, "\t.indirect_symbol ");
+         assemble_name (asm_out_file, sym_name); 
+         fprintf (asm_out_file, "\n");
+
+         assemble_integer (const0_rtx, GET_MODE_SIZE (Pmode), 1);
+       }
+    }
+}
+
+int 
+machopic_operand_p (op)
+     rtx op;
+{
+  if (MACHOPIC_JUST_INDIRECT)
+    {
+      while (GET_CODE (op) == CONST)
+       op = XEXP (op, 0);
+
+      if (GET_CODE (op) == SYMBOL_REF)
+       return machopic_name_defined_p (XSTR (op, 0));
+      else
+       return 0;
+    }
+
+  while (GET_CODE (op) == CONST)
+    op = XEXP (op, 0);
+
+  if (GET_CODE (op) == MINUS
+      && GET_CODE (XEXP (op, 0)) == SYMBOL_REF
+      && GET_CODE (XEXP (op, 1)) == SYMBOL_REF
+      && machopic_name_defined_p (XSTR (XEXP (op, 0), 0))
+      && machopic_name_defined_p (XSTR (XEXP (op, 1), 0)))
+      return 1;
+
+#if 0 /*def TARGET_TOC*/ /* i.e., PowerPC */
+  /* Without this statement, the compiler crashes while compiling enquire.c
+     when targetting PowerPC.  It is not known why this code is not needed
+     when targetting other processors.  */
+  else if (GET_CODE (op) == SYMBOL_REF
+          && (machopic_classify_name (XSTR (op, 0))
+              == MACHOPIC_DEFINED_FUNCTION))
+    {
+      return 1;
+    }
+#endif
+
+  return 0;
+}
diff --git a/gcc/config/darwin.h b/gcc/config/darwin.h
new file mode 100644 (file)
index 0000000..269d78c
--- /dev/null
@@ -0,0 +1,763 @@
+/* Target definitions for Darwin (Mac OS X) systems.
+   Copyright (C) 1989, 1990, 1991, 1992, 1993, 2000, 2001
+   Free Software Foundation, Inc.
+   Contributed by Apple Computer Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/* The definitions in this file are common to all processor types
+   running Darwin, which is the kernel for Mac OS X.  Darwin is
+   basically a BSD user layer laid over a Mach kernel, then evolved
+   for many years (at NeXT) in parallel with other Unix systems.  So
+   while the runtime is a somewhat idiosyncratic Mach-based thing,
+   other definitions look like they would for a BSD variant.  */
+
+/* Although NeXT ran on many different architectures, as of Jan 2001
+   the only supported Darwin targets are PowerPC and x86.  */
+
+/* Make the compiler look here for standard stuff.  */
+
+#undef STANDARD_EXEC_PREFIX
+#define STANDARD_EXEC_PREFIX "/usr/libexec/"
+
+/* Name of the command that invokes the compiler - used in g++.c.  */
+
+#undef  GCC_NAME
+#define GCC_NAME "cc"
+
+/* Never try linking with -lm - used in g++.c.  */
+
+#define NO_MATH_LIBRARY
+
+/* We have atexit.  */
+
+#define HAVE_ATEXIT
+
+/* Define an empty body for the function do_global_dtors() in libgcc2.c.  */
+
+#define DO_GLOBAL_DTORS_BODY
+
+/* The string value for __SIZE_TYPE__.  */
+
+#ifndef SIZE_TYPE
+#define SIZE_TYPE "long unsigned int"
+#endif
+
+/* Type used for ptrdiff_t, as a string used in a declaration.  */
+
+#undef  PTRDIFF_TYPE
+#define PTRDIFF_TYPE "int"
+
+/* wchar_t is int.  */
+
+#undef WCHAR_TYPE
+#define WCHAR_TYPE "int"
+#undef WCHAR_TYPE_SIZE
+#define WCHAR_TYPE_SIZE 32
+
+/* Don't default to pcc-struct-return, because gcc is the only compiler, and
+   we want to retain compatibility with older gcc versions.  */
+
+#undef DEFAULT_PCC_STRUCT_RETURN
+#define DEFAULT_PCC_STRUCT_RETURN 0
+
+/* Don't warn about MacOS-style 'APPL' four-char-constants.  */
+
+#undef WARN_FOUR_CHAR_CONSTANTS
+#define WARN_FOUR_CHAR_CONSTANTS 0
+
+/* Machine dependent cpp options.  */
+
+/* The sequence here allows us to get a more specific version number
+   glued into __APPLE_CC__.  Normally this number would be updated as
+   part of submitting to a release engineering organization.  */
+
+#ifndef APPLE_CC
+#define APPLE_CC 999
+#endif
+
+#define STRINGIFY_THIS(x) # x
+#define REALLY_STRINGIFY(x) STRINGIFY_THIS(x)
+
+#undef CPP_SPEC
+#define CPP_SPEC "-D__APPLE_CC__=" REALLY_STRINGIFY(APPLE_CC) "        \
+                 %{static:-D__STATIC__}%{!static:-D__DYNAMIC__}"
+
+/* Machine dependent libraries.  */
+
+#undef LIB_SPEC
+#define LIB_SPEC \
+     "%{!static:%{!pg:-framework System}%{pg:-framework System,_profile}}"
+
+#undef LIBGCC_SPEC
+#define LIBGCC_SPEC "%{!shared:%{static:-lcc} \
+                             %{!static:-lcc_dynamic}}"
+
+/* We specify crt0.o as -lcrt0.o so that ld will search the library path. */
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC  \
+  "%{pg:%{static:-lgcrt0.o}%{!static:-lgcrt1.o}} \
+    %{!pg:%{static:-lcrt0.o}%{!static:-lcrt1.o}}"
+
+#undef DOLLARS_IN_IDENTIFIERS
+#define DOLLARS_IN_IDENTIFIERS 2
+
+/* Allow #sccs (but don't do anything). */
+
+#define SCCS_DIRECTIVE
+
+/* We use Dbx symbol format.  */
+
+#define DBX_DEBUGGING_INFO
+
+/* When generating stabs debugging, use N_BINCL entries.  */
+
+#define DBX_USE_BINCL
+
+/* There is no limit to the length of stabs strings.  */
+
+#define DBX_CONTIN_LENGTH 0
+
+/* gdb needs a null N_SO at the end of each file for scattered loading. */
+
+#undef DBX_OUTPUT_MAIN_SOURCE_FILE_END
+#define DBX_OUTPUT_MAIN_SOURCE_FILE_END(FILE, FILENAME)                        \
+do { text_section ();                                                  \
+     fprintf (FILE,                                                    \
+             "\t.stabs \"%s\",%d,0,0,Letext\nLetext:\n", "" , N_SO);   \
+   } while (0)
+
+/* Our profiling scheme doesn't LP labels and counter words.  */
+
+#define NO_PROFILE_COUNTERS
+
+/* Don't use .gcc_compiled symbols to communicate with GDB;
+   They interfere with numerically sorted symbol lists. */
+
+#undef ASM_IDENTIFY_GCC
+#define ASM_IDENTIFY_GCC(asm_out_file)
+
+#undef INIT_SECTION_ASM_OP
+#define INIT_SECTION_ASM_OP
+
+#undef INVOKE__main
+
+#undef ASM_OUTPUT_CONSTRUCTOR
+#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME)                       \
+  do { if (flag_pic)                                            \
+        mod_init_section ();                                   \
+       else                                                    \
+        constructor_section ();                                \
+       ASM_OUTPUT_ALIGN (FILE, 1);                              \
+       fprintf (FILE, "\t.long ");                              \
+       assemble_name (FILE, NAME);                              \
+       fprintf (FILE, "\n");                                    \
+       if (!flag_pic)                                          \
+        fprintf (FILE, ".reference .constructors_used\n");     \
+      } while (0)
+
+#undef ASM_OUTPUT_DESTRUCTOR
+#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME)                        \
+  do { if (flag_pic)                                            \
+        mod_term_section ();                                   \
+       else                                                    \
+        destructor_section ();                                 \
+       ASM_OUTPUT_ALIGN (FILE, 1);                             \
+       fprintf (FILE, "\t.long ");                             \
+       assemble_name (FILE, NAME);                             \
+       fprintf (FILE, "\n");                                   \
+       if (!flag_pic)                                          \
+               fprintf (FILE, ".reference .destructors_used\n");       \
+     } while (0)
+
+
+/* Don't output a .file directive.  That is only used by the assembler for
+   error reporting.  */
+
+#undef ASM_FILE_START
+#define ASM_FILE_START(FILE)
+
+#undef ASM_FILE_END
+#define ASM_FILE_END(FILE)                                     \
+  do {                                                         \
+    extern const char *language_string;                                \
+    machopic_finish (asm_out_file);                             \
+    if (strcmp (language_string, "GNU C++") == 0)              \
+      {                                                                \
+       constructor_section ();                                 \
+       destructor_section ();                                  \
+       ASM_OUTPUT_ALIGN (FILE, 1);                             \
+      }                                                                \
+  } while (0)
+
+/* Give ObjcC methods pretty symbol names. */
+
+#undef OBJC_GEN_METHOD_LABEL
+#define OBJC_GEN_METHOD_LABEL(BUF,IS_INST,CLASS_NAME,CAT_NAME,SEL_NAME,NUM) \
+  do { if (CAT_NAME)                                                   \
+        sprintf (BUF, "%c[%s(%s) %s]", (IS_INST) ? '-' : '+',          \
+                 (CLASS_NAME), (CAT_NAME), (SEL_NAME));                \
+       else                                                            \
+        sprintf (BUF, "%c[%s %s]", (IS_INST) ? '-' : '+',              \
+                 (CLASS_NAME), (SEL_NAME));                            \
+     } while (0)
+
+/* The RTTI data (e.g., __ti4name) is common and public (and static),
+   but it does need to be referenced via indirect PIC data pointers.
+   The machopic_define_name calls are telling the machopic subsystem
+   that the name *is* defined in this module, so it doesn't need to
+   make them indirect.  */
+
+#undef ASM_DECLARE_OBJECT_NAME
+#define ASM_DECLARE_OBJECT_NAME(FILE, NAME, DECL)                      \
+  do {                                                                 \
+    char *xname = NAME;                                                 \
+    if (GET_CODE (XEXP (DECL_RTL (DECL), 0)) != SYMBOL_REF)             \
+      xname = IDENTIFIER_POINTER (DECL_NAME (DECL));                    \
+    if ((TREE_STATIC (DECL)                                             \
+        && (!DECL_COMMON (DECL) || !TREE_PUBLIC (DECL)))               \
+        || DECL_INITIAL (DECL))                                         \
+      machopic_define_name (xname);                                     \
+    ASM_OUTPUT_LABEL (FILE, xname);                                     \
+  } while (0)
+
+/* Wrap new method names in quotes so the assembler doesn't gag.
+   Make Objective-C internal symbols local.  */
+
+#undef ASM_OUTPUT_LABELREF
+#define ASM_OUTPUT_LABELREF(FILE,NAME) \
+  do {                                                                 \
+       if (NAME[0] == '&')                                             \
+         {                                                             \
+           int len = strlen (NAME);                                    \
+          if (len > 6 && !strcmp ("$stub", NAME + len - 5))            \
+            machopic_validate_stub_or_non_lazy_ptr (NAME, 1);          \
+          else if (len > 7 && !strcmp ("$stub\"", NAME + len - 6))     \
+            machopic_validate_stub_or_non_lazy_ptr (NAME, 1);          \
+          else if (len > 14 && !strcmp ("$non_lazy_ptr", NAME + len - 13)) \
+            machopic_validate_stub_or_non_lazy_ptr (NAME, 0);          \
+          fputs (&NAME[1], FILE); \
+        } \
+       else if (NAME[0] == '+' || NAME[0] == '-')   \
+         fprintf (FILE, "\"%s\"", NAME); \
+       else if (!strncmp (NAME, "_OBJC_", 6))  \
+         fprintf (FILE, "L%s", NAME);   \
+       else if (!strncmp (NAME, ".objc_class_name_", 17))              \
+        fprintf (FILE, "%s", NAME);                                    \
+       else                                                            \
+         fprintf (FILE, "_%s", NAME);                                  \
+  } while (0)
+
+#undef ALIGN_ASM_OP
+#define ALIGN_ASM_OP           ".align"
+
+#undef ASM_OUTPUT_ALIGN
+#define ASM_OUTPUT_ALIGN(FILE,LOG)     \
+  if ((LOG) != 0)                      \
+    fprintf (FILE, "\t%s %d\n", ALIGN_ASM_OP, (LOG))
+
+/* Ensure correct alignment of bss data.  */
+
+#undef ASM_OUTPUT_ALIGNED_DECL_LOCAL
+#define ASM_OUTPUT_ALIGNED_DECL_LOCAL(FILE, DECL, NAME, SIZE, ALIGN) \
+  do {  \
+    fputs (".lcomm ", (FILE));                         \
+    assemble_name ((FILE), (NAME));                    \
+    fprintf ((FILE), ",%u,%u\n", (SIZE), floor_log2 ((ALIGN) / BITS_PER_UNIT)); \
+    if ((DECL) && ((TREE_STATIC (DECL)                                             \
+        && (!DECL_COMMON (DECL) || !TREE_PUBLIC (DECL)))               \
+        || DECL_INITIAL (DECL)))                                         \
+      machopic_define_name (NAME);                                     \
+  } while (0)
+
+/* Output nothing for #ident.  */
+
+#undef ASM_OUTPUT_IDENT
+#define ASM_OUTPUT_IDENT(FILE, NAME)
+
+/* The maximum alignment which the object file format can support.
+   For Mach-O, this is 2^15.  */
+
+#undef MAX_OFILE_ALIGNMENT
+#define MAX_OFILE_ALIGNMENT 0x8000
+
+/* Create new Mach-O sections. */
+
+#undef SECTION_FUNCTION
+#define SECTION_FUNCTION(FUNCTION, SECTION, DIRECTIVE, WAS_TEXT, OBJC) \
+void                                                                   \
+FUNCTION ()                                                            \
+{                                                                      \
+  extern void text_section ();                                         \
+  extern void objc_section_init ();                                    \
+  extern int flag_no_mach_text_sections;                               \
+                                                                       \
+  if (WAS_TEXT && flag_no_mach_text_sections)                          \
+    text_section ();                                                   \
+  else if (in_section != SECTION)                                      \
+    {                                                                  \
+      if (OBJC)                                                                \
+       objc_section_init ();                                           \
+      data_section ();                                                 \
+      if (asm_out_file)                                                        \
+       fprintf (asm_out_file, "%s\n", DIRECTIVE);                      \
+      in_section = SECTION;                                            \
+    }                                                                  \
+}                                                                      \
+
+#define ALIAS_SECTION(enum_value, alias_name)                          \
+do { if (!strcmp (alias_name, name))                                   \
+       section_alias[enum_value] = (alias ? get_identifier (alias) : 0);  \
+   } while (0)
+
+/* Darwin uses many types of special sections.  */
+
+#undef EXTRA_SECTIONS
+#define EXTRA_SECTIONS                                 \
+  in_const, in_const_data, in_cstring, in_literal4, in_literal8,       \
+  in_constructor, in_destructor, in_mod_init, in_mod_term,             \
+  in_objc_class, in_objc_meta_class, in_objc_category, \
+  in_objc_class_vars, in_objc_instance_vars,           \
+  in_objc_cls_meth, in_objc_inst_meth,                 \
+  in_objc_cat_cls_meth, in_objc_cat_inst_meth,         \
+  in_objc_selector_refs,                               \
+  in_objc_selector_fixup,                              \
+  in_objc_symbols, in_objc_module_info,                        \
+  in_objc_protocol, in_objc_string_object,             \
+  in_objc_constant_string_object,                      \
+  in_objc_class_names, in_objc_meth_var_names,         \
+  in_objc_meth_var_types, in_objc_cls_refs,            \
+  in_machopic_nl_symbol_ptr,                           \
+  in_machopic_lazy_symbol_ptr,                         \
+  in_machopic_symbol_stub,                             \
+  in_machopic_picsymbol_stub,                          \
+  num_sections
+
+#undef EXTRA_SECTION_FUNCTIONS
+#define EXTRA_SECTION_FUNCTIONS                        \
+SECTION_FUNCTION (const_section,               \
+                  in_const,                    \
+                  ".const", 1, 0)              \
+SECTION_FUNCTION (const_data_section,          \
+                  in_const_data,               \
+                  ".const_data", 1, 0)         \
+SECTION_FUNCTION (cstring_section,             \
+                 in_cstring,                   \
+                 ".cstring", 1, 0)             \
+SECTION_FUNCTION (literal4_section,            \
+                 in_literal4,                  \
+                 ".literal4", 1, 0)            \
+SECTION_FUNCTION (literal8_section,            \
+                 in_literal8,                  \
+                 ".literal8", 1, 0)            \
+SECTION_FUNCTION (constructor_section,         \
+                 in_constructor,               \
+                 ".constructor", 0, 0)         \
+SECTION_FUNCTION (mod_init_section,            \
+                 in_mod_init,                  \
+                 ".mod_init_func", 0, 0)       \
+SECTION_FUNCTION (mod_term_section, \
+                 in_mod_term,                  \
+                 ".mod_term_func", 0, 0)       \
+SECTION_FUNCTION (destructor_section,          \
+                 in_destructor,                \
+                 ".destructor", 0, 0)          \
+SECTION_FUNCTION (objc_class_section,          \
+                 in_objc_class,                \
+                 ".objc_class", 0, 1)          \
+SECTION_FUNCTION (objc_meta_class_section,     \
+                 in_objc_meta_class,           \
+                 ".objc_meta_class", 0, 1)     \
+SECTION_FUNCTION (objc_category_section,       \
+                 in_objc_category,             \
+               ".objc_category", 0, 1)         \
+SECTION_FUNCTION (objc_class_vars_section,     \
+                 in_objc_class_vars,           \
+                 ".objc_class_vars", 0, 1)     \
+SECTION_FUNCTION (objc_instance_vars_section,  \
+                 in_objc_instance_vars,        \
+                 ".objc_instance_vars", 0, 1)  \
+SECTION_FUNCTION (objc_cls_meth_section,       \
+                 in_objc_cls_meth,             \
+                 ".objc_cls_meth", 0, 1)       \
+SECTION_FUNCTION (objc_inst_meth_section,      \
+                 in_objc_inst_meth,            \
+                 ".objc_inst_meth", 0, 1)      \
+SECTION_FUNCTION (objc_cat_cls_meth_section,   \
+                 in_objc_cat_cls_meth,         \
+                 ".objc_cat_cls_meth", 0, 1)   \
+SECTION_FUNCTION (objc_cat_inst_meth_section,  \
+                 in_objc_cat_inst_meth,        \
+                 ".objc_cat_inst_meth", 0, 1)  \
+SECTION_FUNCTION (objc_selector_refs_section,  \
+                 in_objc_selector_refs,        \
+                 ".objc_message_refs", 0, 1)   \
+SECTION_FUNCTION (objc_selector_fixup_section, \
+                 in_objc_selector_fixup,       \
+                 ".section __OBJC, __sel_fixup", 0, 1) \
+SECTION_FUNCTION (objc_symbols_section,                \
+                 in_objc_symbols,              \
+                 ".objc_symbols", 0, 1)        \
+SECTION_FUNCTION (objc_module_info_section,    \
+                 in_objc_module_info,          \
+                 ".objc_module_info", 0, 1)    \
+SECTION_FUNCTION (objc_protocol_section,       \
+                 in_objc_protocol,             \
+                 ".objc_protocol", 0, 1)       \
+SECTION_FUNCTION (objc_string_object_section,  \
+                 in_objc_string_object,        \
+                 ".objc_string_object", 0, 1)  \
+SECTION_FUNCTION (objc_constant_string_object_section, \
+                 in_objc_constant_string_object,       \
+                 ".section __OBJC, __cstring_object", 0, 1)    \
+SECTION_FUNCTION (objc_class_names_section,    \
+               in_objc_class_names,            \
+               ".objc_class_names", 0, 1)      \
+SECTION_FUNCTION (objc_meth_var_names_section, \
+               in_objc_meth_var_names,         \
+               ".objc_meth_var_names", 0, 1)   \
+SECTION_FUNCTION (objc_meth_var_types_section, \
+               in_objc_meth_var_types,         \
+               ".objc_meth_var_types", 0, 1)   \
+SECTION_FUNCTION (objc_cls_refs_section,       \
+               in_objc_cls_refs,               \
+               ".objc_cls_refs", 0, 1)         \
+                                               \
+SECTION_FUNCTION (machopic_lazy_symbol_ptr_section,    \
+               in_machopic_lazy_symbol_ptr,            \
+               ".lazy_symbol_pointer", 0, 0)           \
+SECTION_FUNCTION (machopic_nl_symbol_ptr_section,      \
+               in_machopic_nl_symbol_ptr,              \
+               ".non_lazy_symbol_pointer", 0, 0)       \
+SECTION_FUNCTION (machopic_symbol_stub_section,                \
+               in_machopic_symbol_stub,                \
+               ".symbol_stub", 0, 0)                   \
+SECTION_FUNCTION (machopic_picsymbol_stub_section,     \
+               in_machopic_picsymbol_stub,             \
+               ".picsymbol_stub", 0, 0)                \
+                                                       \
+void                                           \
+objc_section_init ()                           \
+{                                              \
+  static int been_here = 0;                    \
+                                               \
+  if (been_here == 0)                          \
+    {                                          \
+      been_here = 1;                           \
+          /* written, cold -> hot */           \
+      objc_cat_cls_meth_section ();            \
+      objc_cat_inst_meth_section ();           \
+      objc_string_object_section ();           \
+      objc_constant_string_object_section ();  \
+      objc_selector_refs_section ();           \
+      objc_selector_fixup_section ();          \
+      objc_cls_refs_section ();                        \
+      objc_class_section ();                   \
+      objc_meta_class_section ();              \
+          /* shared, hot -> cold */                    \
+      objc_cls_meth_section ();                        \
+      objc_inst_meth_section ();               \
+      objc_protocol_section ();                        \
+      objc_class_names_section ();             \
+      objc_meth_var_types_section ();          \
+      objc_meth_var_names_section ();          \
+      objc_category_section ();                        \
+      objc_class_vars_section ();              \
+      objc_instance_vars_section ();           \
+      objc_module_info_section ();             \
+      objc_symbols_section ();                 \
+    }                                          \
+}                                              \
+static tree section_alias[(int) num_sections]; \
+void try_section_alias ()                      \
+{                                              \
+    if (section_alias[in_section] && asm_out_file) \
+      fprintf (asm_out_file, "%s\n",           \
+              IDENTIFIER_POINTER (section_alias[in_section])); \
+}                                                      \
+void alias_section (name, alias)                       \
+     char *name, *alias;                               \
+{                                                      \
+    ALIAS_SECTION (in_data, "data");                   \
+    ALIAS_SECTION (in_text, "text");                   \
+    ALIAS_SECTION (in_const, "const");                 \
+    ALIAS_SECTION (in_const_data, "const_data");       \
+    ALIAS_SECTION (in_cstring, "cstring");             \
+    ALIAS_SECTION (in_literal4, "literal4");           \
+    ALIAS_SECTION (in_literal8, "literal8");           \
+}
+
+#undef READONLY_DATA_SECTION
+#define READONLY_DATA_SECTION const_section
+
+#undef SELECT_SECTION
+#define SELECT_SECTION(exp,reloc)                              \
+  do                                                           \
+    {                                                          \
+      if (TREE_CODE (exp) == STRING_CST)                       \
+       {                                                       \
+         if (flag_writable_strings)                            \
+           data_section ();                                    \
+         else if (TREE_STRING_LENGTH (exp) !=                  \
+                  strlen (TREE_STRING_POINTER (exp)) + 1)      \
+           readonly_data_section ();                           \
+         else                                                  \
+           cstring_section ();                                 \
+       }                                                       \
+      else if (TREE_CODE (exp) == INTEGER_CST                  \
+              || TREE_CODE (exp) == REAL_CST)                  \
+        {                                                      \
+         tree size = TYPE_SIZE (TREE_TYPE (exp));              \
+                                                               \
+         if (TREE_CODE (size) == INTEGER_CST &&                \
+             TREE_INT_CST_LOW (size) == 4 &&                   \
+             TREE_INT_CST_HIGH (size) == 0)                    \
+           literal4_section ();                                \
+         else if (TREE_CODE (size) == INTEGER_CST &&           \
+             TREE_INT_CST_LOW (size) == 8 &&                   \
+             TREE_INT_CST_HIGH (size) == 0)                    \
+           literal8_section ();                                \
+         else                                                  \
+           readonly_data_section ();                           \
+       }                                                       \
+      else if (TREE_CODE (exp) == CONSTRUCTOR                          \
+              && TREE_TYPE (exp)                                       \
+              && TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE            \
+              && TYPE_NAME (TREE_TYPE (exp)))                          \
+       {                                                               \
+         tree name = TYPE_NAME (TREE_TYPE (exp));                      \
+         if (TREE_CODE (name) == TYPE_DECL)                            \
+           name = DECL_NAME (name);                                    \
+         if (!strcmp (IDENTIFIER_POINTER (name), "NSConstantString"))  \
+           objc_constant_string_object_section ();                     \
+         else if (!strcmp (IDENTIFIER_POINTER (name), "NXConstantString")) \
+           objc_string_object_section ();                              \
+         else if (TREE_READONLY (exp) || TREE_CONSTANT (exp))          \
+           {                                                           \
+             if (TREE_SIDE_EFFECTS (exp) || flag_pic && reloc)         \
+               const_data_section ();                                  \
+             else                                                      \
+               readonly_data_section ();                               \
+            }                                                          \
+         else                                                          \
+           data_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)) \
+       {                                                               \
+         const char *name = IDENTIFIER_POINTER (DECL_NAME (exp));      \
+                                                                       \
+         if (!strncmp (name, "_OBJC_CLASS_METHODS_", 20))              \
+           objc_cls_meth_section ();                                   \
+         else if (!strncmp (name, "_OBJC_INSTANCE_METHODS_", 23))      \
+           objc_inst_meth_section ();                                  \
+         else if (!strncmp (name, "_OBJC_CATEGORY_CLASS_METHODS_", 20)) \
+           objc_cat_cls_meth_section ();                               \
+         else if (!strncmp (name, "_OBJC_CATEGORY_INSTANCE_METHODS_", 23)) \
+           objc_cat_inst_meth_section ();                              \
+         else if (!strncmp (name, "_OBJC_CLASS_VARIABLES_", 22))       \
+           objc_class_vars_section ();                                 \
+         else if (!strncmp (name, "_OBJC_INSTANCE_VARIABLES_", 25))    \
+           objc_instance_vars_section ();                              \
+         else if (!strncmp (name, "_OBJC_CLASS_PROTOCOLS_", 22))       \
+           objc_cat_cls_meth_section ();                               \
+         else if (!strncmp (name, "_OBJC_CLASS_NAME_", 17))            \
+           objc_class_names_section ();                                \
+         else if (!strncmp (name, "_OBJC_METH_VAR_NAME_", 20))         \
+           objc_meth_var_names_section ();                             \
+         else if (!strncmp (name, "_OBJC_METH_VAR_TYPE_", 20))         \
+           objc_meth_var_types_section ();                             \
+         else if (!strncmp (name, "_OBJC_CLASS_REFERENCES", 22))       \
+           objc_cls_refs_section ();                                   \
+         else if (!strncmp (name, "_OBJC_CLASS_", 12))                 \
+           objc_class_section ();                                      \
+         else if (!strncmp (name, "_OBJC_METACLASS_", 16))             \
+           objc_meta_class_section ();                                 \
+         else if (!strncmp (name, "_OBJC_CATEGORY_", 15))              \
+           objc_category_section ();                                   \
+         else if (!strncmp (name, "_OBJC_SELECTOR_REFERENCES", 25))    \
+           objc_selector_refs_section ();                              \
+         else if (!strncmp (name, "_OBJC_SELECTOR_FIXUP", 20))         \
+           objc_selector_fixup_section ();                             \
+         else if (!strncmp (name, "_OBJC_SYMBOLS", 13))                \
+           objc_symbols_section ();                                    \
+         else if (!strncmp (name, "_OBJC_MODULES", 13))                \
+           objc_module_info_section ();                                \
+         else if (!strncmp (name, "_OBJC_PROTOCOL_INSTANCE_METHODS_", 32)) \
+           objc_cat_inst_meth_section ();                              \
+         else if (!strncmp (name, "_OBJC_PROTOCOL_CLASS_METHODS_", 29)) \
+           objc_cat_cls_meth_section ();                               \
+         else if (!strncmp (name, "_OBJC_PROTOCOL_REFS_", 20))         \
+           objc_cat_cls_meth_section ();                               \
+         else if (!strncmp (name, "_OBJC_PROTOCOL_", 15))              \
+           objc_protocol_section ();                                   \
+         else if ((TREE_READONLY (exp) || TREE_CONSTANT (exp))         \
+               && !TREE_SIDE_EFFECTS (exp))                            \
+             { if (flag_pic && reloc ) const_data_section ();             \
+               else readonly_data_section (); }                        \
+         else                                                          \
+           data_section ();                                            \
+       }                                                               \
+      else if (TREE_READONLY (exp) || TREE_CONSTANT (exp))             \
+       {                                                               \
+         if (TREE_SIDE_EFFECTS (exp) || flag_pic && reloc)             \
+           const_data_section ();                                      \
+         else                                                          \
+           readonly_data_section ();                                   \
+        }                                                              \
+      else                                                             \
+        data_section ();                                               \
+      try_section_alias ();                                            \
+    }                                                                  \
+  while (0)
+
+#undef SELECT_RTX_SECTION
+#define SELECT_RTX_SECTION(mode, rtx)                                  \
+  do                                                                   \
+    {                                                                  \
+      if (GET_MODE_SIZE (mode) == 8)                                   \
+       literal8_section ();                                            \
+      else if (GET_MODE_SIZE (mode) == 4)                              \
+       literal4_section ();                                            \
+      else                                                             \
+       const_section ();                                               \
+    }                                                                  \
+  while (0)
+
+#define DECLARE_UNRESOLVED_REFERENCE(NAME)                             \
+    do { extern FILE* asm_out_file;                                    \
+        if (asm_out_file) {                                            \
+          if (flag_pic)                                                \
+            fprintf (asm_out_file, "\t.lazy_reference ");              \
+          else                                                         \
+            fprintf (asm_out_file, "\t.reference ");                   \
+          assemble_name (asm_out_file, NAME);                          \
+          fprintf (asm_out_file, "\n");                                \
+        }                                                              \
+       } while (0)
+
+#define DECLARE_CLASS_REFERENCE(NAME) \
+    do { extern FILE* asm_out_file;                                    \
+        if (asm_out_file) {                                            \
+          fprintf (asm_out_file, "\t");                                \
+          assemble_name (asm_out_file, NAME);                          \
+          fprintf (asm_out_file, "=0\n");                              \
+          assemble_global (NAME);                                      \
+        }                                                              \
+       } while (0)
+
+#undef ASM_GLOBALIZE_LABEL
+#define ASM_GLOBALIZE_LABEL(FILE,NAME) \
+ do { const char* _x = (NAME); if (!!strncmp (_x, "_OBJC_", 6)) { \
+  (fputs (".globl ", FILE), assemble_name (FILE, _x), fputs ("\n", FILE)); \
+ }} while (0)
+
+#undef ASM_GENERATE_INTERNAL_LABEL
+#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM)  \
+  sprintf (LABEL, "*%s%d", PREFIX, NUM)
+
+/* This is how to output an internal numbered label where PREFIX is
+   the class of label and NUM is the number within the class.  */
+
+#undef ASM_OUTPUT_INTERNAL_LABEL
+#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM)     \
+  fprintf (FILE, "%s%d:\n", PREFIX, NUM)
+
+/* Since we have a separate readonly data section, define this so that
+   jump tables end up in text rather than data.  */
+
+#ifndef JUMP_TABLES_IN_TEXT_SECTION
+#define JUMP_TABLES_IN_TEXT_SECTION 1
+#endif
+
+/* Symbolic names for various things we might know about a symbol.  */
+
+enum machopic_addr_class {
+  MACHOPIC_UNDEFINED,
+  MACHOPIC_DEFINED_DATA,
+  MACHOPIC_UNDEFINED_DATA,
+  MACHOPIC_DEFINED_FUNCTION,
+  MACHOPIC_UNDEFINED_FUNCTION
+};
+
+/* Macros defining the various PIC cases.  */
+
+#define MACHOPIC_INDIRECT      (flag_pic)
+#define MACHOPIC_JUST_INDIRECT (flag_pic == 1)
+#define MACHOPIC_PURE          (flag_pic == 2)
+
+#define GEN_BINDER_NAME_FOR_STUB(BUF,STUB,STUB_LENGTH)         \
+  do {                                                         \
+    const char *stub_ = (STUB);                                        \
+    char *buffer_ = (BUF);                                     \
+    strcpy (buffer_, stub_);                                   \
+    if (stub_[0] == '"')                                       \
+      {                                                                \
+       strcpy (buffer_ + (STUB_LENGTH) - 1, "_binder\"");      \
+      }                                                                \
+    else                                                       \
+      {                                                                \
+       strcpy (buffer_ + (STUB_LENGTH), "_binder");            \
+      }                                                                \
+  } while (0)
+
+#define GEN_SYMBOL_NAME_FOR_SYMBOL(BUF,SYMBOL,SYMBOL_LENGTH)   \
+  do {                                                         \
+    const char *symbol_ = (SYMBOL);                            \
+    char *buffer_ = (BUF);                                     \
+    if (name_needs_quotes (symbol_) && symbol_[0] != '"')      \
+      {                                                                \
+         sprintf (buffer_, "\"%s\"", symbol_);                 \
+      }                                                                \
+    else                                                       \
+      {                                                                \
+       strcpy (buffer_, symbol_);                              \
+      }                                                                \
+  } while (0)
+
+/* Given a symbol name string, create the lazy pointer version
+   of the symbol name.  */
+
+#define GEN_LAZY_PTR_NAME_FOR_SYMBOL(BUF,SYMBOL,SYMBOL_LENGTH) \
+  do {                                                         \
+    const char *symbol_ = (SYMBOL);                            \
+    char *buffer_ = (BUF);                                     \
+    if (symbol_[0] == '"')                                     \
+      {                                                                \
+        strcpy (buffer_, "\"L");                                       \
+        strcpy (buffer_ + 2, symbol_ + 1);                     \
+       strcpy (buffer_ + (SYMBOL_LENGTH), "$lazy_ptr\"");      \
+      }                                                                \
+    else if (name_needs_quotes (symbol_))                      \
+      {                                                                \
+        strcpy (buffer_, "\"L");                               \
+        strcpy (buffer_ + 2, symbol_);                         \
+       strcpy (buffer_ + (SYMBOL_LENGTH) + 2, "$lazy_ptr\"");  \
+      }                                                                \
+    else                                                       \
+      {                                                                \
+        strcpy (buffer_, "L");                                 \
+        strcpy (buffer_ + 1, symbol_);                         \
+       strcpy (buffer_ + (SYMBOL_LENGTH) + 1, "$lazy_ptr");    \
+      }                                                                \
+  } while (0)
+
diff --git a/gcc/config/rs6000/darwin.h b/gcc/config/rs6000/darwin.h
new file mode 100644 (file)
index 0000000..aef5d72
--- /dev/null
@@ -0,0 +1,175 @@
+/* Target definitions for PowerPC running Darwin (Mac OS X).
+   Copyright (C) 1997, 2000, 2001 Free Software Foundation, Inc.
+   Contributed by Apple Computer Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/* The "Darwin ABI" is mostly like AIX, but with some key differences.  */
+
+#define DEFAULT_ABI ABI_DARWIN
+
+/* The object file format is Mach-O.  */
+
+#define TARGET_OBJECT_FORMAT OBJECT_MACHO
+
+/* We're not ever going to do TOCs.  */
+
+#define TARGET_TOC 0
+#define TARGET_NO_TOC 1
+
+#define CPP_PREDEFINES "-D__ppc__ -D__NATURAL_ALIGNMENT__ -D__MACH__ -D__BIG_ENDIAN__ -D__APPLE__"
+
+/* We want -fPIC by default, unless we're using -static to compile for
+   the kernel or some such.  */
+
+#define CC1_SPEC "%{!static:-fPIC}"
+
+#define FIXED_R13 0
+
+#undef  TARGET_DEFAULT
+#define TARGET_DEFAULT (MASK_POWERPC | MASK_MULTIPLE | MASK_NEW_MNEMONICS \
+  | MASK_NO_FP_IN_TOC | MASK_NO_SUM_IN_TOC)
+
+/* Base register for access to local variables of the function.  */
+
+#undef  FRAME_POINTER_REGNUM
+#define FRAME_POINTER_REGNUM 30
+
+#undef  PIC_OFFSET_TABLE_REGNUM
+#define PIC_OFFSET_TABLE_REGNUM 31
+
+#undef STACK_BOUNDARY
+#define STACK_BOUNDARY 128
+
+/* Pad the outgoing args area to 16 bytes instead of the usual 8.  */
+
+#undef STARTING_FRAME_OFFSET
+#define STARTING_FRAME_OFFSET                                          \
+  (RS6000_ALIGN (current_function_outgoing_args_size, 16)              \
+   + RS6000_VARARGS_AREA                                               \
+   + RS6000_SAVE_AREA)
+
+#undef STACK_DYNAMIC_OFFSET
+#define STACK_DYNAMIC_OFFSET(FUNDECL)                                  \
+  (RS6000_ALIGN (current_function_outgoing_args_size, 16)              \
+   + (STACK_POINTER_OFFSET))
+
+/* Define cutoff for using external functions to save floating point.
+   Currently on Darwin, always use inline stores.  */
+
+#undef FP_SAVE_INLINE
+#define FP_SAVE_INLINE(FIRST_REG) ((FIRST_REG) < 64)
+
+/* Always use the "debug" register names, they're what the assembler
+   wants to see.  */
+
+#undef REGISTER_NAMES
+#define REGISTER_NAMES DEBUG_REGISTER_NAMES
+
+/* This outputs NAME to FILE.  */
+
+#undef  RS6000_OUTPUT_BASENAME
+#define RS6000_OUTPUT_BASENAME(FILE, NAME)     \
+    assemble_name (FILE, NAME);
+
+/* Output before instructions.  */
+/* This is how to output the definition of a user-level label named NAME,
+   such as the label on a static function or variable NAME.  */
+
+#define ASM_OUTPUT_LABEL(FILE,NAME)    \
+  do { assemble_name (FILE, NAME); fputs (":\n", FILE); } while (0)
+
+/* This is how to output a command to make the user-level label named NAME
+   defined for reference from other files.  */
+
+#undef ASM_GLOBALIZE_LABEL
+#define ASM_GLOBALIZE_LABEL(FILE,NAME) \
+  do { fputs ("\t.globl ", FILE);      \
+       RS6000_OUTPUT_BASENAME (FILE, NAME); putc ('\n', FILE);} while (0)
+
+/* This is how to output an internal label prefix.  rs6000.c uses this
+   when generating traceback tables.  */
+/* Not really used for Darwin?  */
+
+#undef ASM_OUTPUT_INTERNAL_LABEL_PREFIX
+#define ASM_OUTPUT_INTERNAL_LABEL_PREFIX(FILE,PREFIX)  \
+  fprintf (FILE, "%s", PREFIX)
+
+#undef TEXT_SECTION_ASM_OP
+#define TEXT_SECTION_ASM_OP ".text"
+
+/* Output before writable data.  */
+
+#undef DATA_SECTION_ASM_OP
+#define DATA_SECTION_ASM_OP ".data"
+
+/* This says how to output an assembler line to define a global common
+   symbol.  */
+/* ? */
+#undef  ASM_OUTPUT_ALIGNED_COMMON
+#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED)   \
+  do { fputs (".comm ", (FILE));                       \
+       RS6000_OUTPUT_BASENAME ((FILE), (NAME));                \
+       fprintf ((FILE), ",%d\n", (SIZE)); } while (0)
+
+#define ASM_OUTPUT_SKIP(FILE,SIZE)  \
+  fprintf (FILE, "\t.space %d\n", SIZE)
+
+/* FP save and restore routines.  */
+#define        SAVE_FP_PREFIX "._savef"
+#define SAVE_FP_SUFFIX ""
+#define        RESTORE_FP_PREFIX "._restf"
+#define RESTORE_FP_SUFFIX ""
+
+/* Generate insns to call the profiler.  */
+
+#define PROFILE_HOOK(LABEL)   output_profile_hook (LABEL)
+
+/* Function name to call to do profiling.  */
+
+#define RS6000_MCOUNT "*mcount"
+
+/* Since Darwin doesn't do TOCs, stub this out.  */
+
+#define ASM_OUTPUT_SPECIAL_POOL_ENTRY_P(X, MODE)  0
+
+/* Given an rtx X being reloaded into a reg required to be      
+   in class CLASS, return the class of reg to actually use.     
+   In general this is just CLASS; but on some machines
+   in some cases it is preferable to use a more restrictive class.
+  
+   On the RS/6000, we have to return NO_REGS when we want to reload a
+   floating-point CONST_DOUBLE to force it to be copied to memory.
+
+   Don't allow R0 when loading the address of, or otherwise furtling with,
+   a SYMBOL_REF.  */
+
+#undef PREFERRED_RELOAD_CLASS
+#define PREFERRED_RELOAD_CLASS(X,CLASS)                        \
+  (((GET_CODE (X) == CONST_DOUBLE                      \
+    && GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT)    \
+   ? NO_REGS                                           \
+   : (GET_MODE_CLASS (GET_MODE (X)) == MODE_INT        \
+      && (CLASS) == NON_SPECIAL_REGS)                  \
+   ? GENERAL_REGS                                      \
+   : (GET_CODE (X) == SYMBOL_REF || GET_CODE (X) == HIGH)      \
+   ? BASE_REGS                                         \
+   : (CLASS)))
+
+/* Fix for emit_group_load (): force large constants to be pushed via regs.  */
+#define ALWAYS_PUSH_CONSTS_USING_REGS_P                1
index 31e5716..9f8f984 100644 (file)
@@ -108,8 +108,12 @@ extern void rs6000_emit_eh_toc_restore PARAMS ((rtx));
 extern void rs6000_emit_move PARAMS ((rtx, rtx, enum machine_mode));
 extern rtx rs6000_legitimize_address PARAMS ((rtx, rtx, enum machine_mode));
 extern void rs6000_select_rtx_section PARAMS ((enum machine_mode, rtx));
+
 extern rtx rs6000_return_addr PARAMS ((int, rtx));
 extern void rs6000_output_symbol_ref PARAMS ((FILE*, rtx));
+
+extern rtx rs6000_machopic_legitimize_pic_address PARAMS ((rtx orig, enum machine_mode mode, rtx reg));
+
 #endif /* RTX_CODE */
 
 #ifdef TREE_CODE
@@ -139,6 +143,7 @@ extern void rs6000_unique_section PARAMS ((tree, int));
 /* expr.h defines ARGS_SIZE_RTX and `enum direction' */
 extern enum direction function_arg_padding PARAMS ((enum machine_mode, tree));
 #endif /* ARGS_SIZE_RTX */
+
 #endif /* TREE_CODE */
 
 extern void optimization_options PARAMS ((int, int));
@@ -172,3 +177,5 @@ extern void rs6000_emit_load_toc_table PARAMS ((int));
 extern void rs6000_aix_emit_builtin_unwind_init PARAMS ((void));
 extern void rs6000_emit_epilogue PARAMS ((int));
 extern void debug_stack_info PARAMS ((rs6000_stack_t *));
+
+extern void machopic_output_stub PARAMS ((FILE *, const char *, const char *));
index 4b24bfb..18e117e 100644 (file)
@@ -1526,6 +1526,19 @@ rs6000_legitimize_address (x, oldx, mode)
       emit_insn (gen_elf_high (reg, (x)));
       return gen_rtx_LO_SUM (Pmode, reg, (x));
     }
+  else if (TARGET_MACHO && TARGET_32BIT && TARGET_NO_TOC
+          && ! flag_pic
+          && GET_CODE (x) != CONST_INT
+          && GET_CODE (x) != CONST_DOUBLE 
+          && CONSTANT_P (x)
+          && (TARGET_HARD_FLOAT || mode != DFmode)
+          && mode != DImode 
+          && mode != TImode)
+    {
+      rtx reg = gen_reg_rtx (Pmode);
+      emit_insn (gen_macho_high (reg, (x)));
+      return gen_rtx_LO_SUM (Pmode, reg, (x));
+    }
   else if (TARGET_TOC 
           && CONSTANT_POOL_EXPR_P (x)
           && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (x), Pmode))
@@ -1644,7 +1657,8 @@ rs6000_emit_move (dest, source, mode)
          return;
        }
 
-      if (TARGET_ELF && TARGET_NO_TOC && ! flag_pic
+      if ((TARGET_ELF || DEFAULT_ABI == ABI_DARWIN)
+         && TARGET_NO_TOC && ! flag_pic
          && mode == Pmode
          && CONSTANT_P (operands[1])
          && GET_CODE (operands[1]) != HIGH
@@ -1670,6 +1684,13 @@ rs6000_emit_move (dest, source, mode)
              operands[1] = new_ref;
            }
 
+         if (DEFAULT_ABI == ABI_DARWIN)
+           {
+             emit_insn (gen_macho_high (target, operands[1]));
+             emit_insn (gen_macho_low (operands[0], target, operands[1]));
+             return;
+           }
+
          emit_insn (gen_elf_high (target, operands[1]));
          emit_insn (gen_elf_low (operands[0], target, operands[1]));
          return;
@@ -1708,6 +1729,21 @@ rs6000_emit_move (dest, source, mode)
          if (GET_CODE (operands[1]) != LABEL_REF)
            emit_insn (gen_rtx_USE (VOIDmode, operands[1]));
 
+         /* Darwin uses a special PIC legitimizer.  */
+         if (DEFAULT_ABI == ABI_DARWIN && flag_pic)
+           {
+             rtx temp_reg = ((reload_in_progress || reload_completed)
+                             ? operands[0] : NULL);
+
+#if TARGET_MACHO
+             operands[1] =
+               rs6000_machopic_legitimize_pic_address (operands[1], mode,
+                                                                   temp_reg);
+#endif
+             emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
+             return;
+           }
+
          /* If we are to limit the number of things we put in the TOC and
             this is a symbol plus a constant we can add in one insn,
             just put the symbol in the TOC and add the constant.  Don't do
@@ -4296,6 +4332,7 @@ print_operand (file, x, code)
            case ABI_V4:
            case ABI_AIX_NODESC:
            case ABI_SOLARIS:
+           case ABI_DARWIN:
              break;
            }
        }
@@ -4655,8 +4692,10 @@ first_reg_to_save ()
     if (regs_ever_live[first_reg] 
        && (! call_used_regs[first_reg]
            || (first_reg == PIC_OFFSET_TABLE_REGNUM
-               && (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS)
-               && flag_pic == 1)))
+               && (((DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS)
+                    && flag_pic == 1)
+                   || (DEFAULT_ABI == ABI_DARWIN
+                       && flag_pic)))))
       break;
 
   if (profile_flag)
@@ -4665,7 +4704,7 @@ first_reg_to_save ()
         before/after the .__mcount call plus an additional register
         for the static chain, if needed; use registers from 30 down to 22
         to do this.  */
-      if (DEFAULT_ABI == ABI_AIX)
+      if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN)
        {
          int last_parm_reg, profile_first_reg;
 
@@ -4683,6 +4722,12 @@ first_reg_to_save ()
             Skip reg 31 which may contain the frame pointer.  */
          profile_first_reg = (33 - last_parm_reg
                               - (current_function_needs_context ? 1 : 0));
+#if TARGET_MACHO
+          /* Need to skip another reg to account for R31 being PICBASE
+             (when flag_pic is set) or R30 being used as the frame
+             pointer (when flag_pic is not set).  */
+          --profile_first_reg;
+#endif
          /* Do not save frame pointer if no parameters needs to be saved.  */
          if (profile_first_reg == 31)
            profile_first_reg = 32;
@@ -4700,6 +4745,12 @@ first_reg_to_save ()
        }
     }
 
+#if TARGET_MACHO
+  if (flag_pic && current_function_uses_pic_offset_table &&
+      (first_reg > PIC_OFFSET_TABLE_REGNUM))
+    return PIC_OFFSET_TABLE_REGNUM;
+#endif
+
   return first_reg;
 }
 
@@ -4722,7 +4773,7 @@ first_fp_reg_to_save ()
    complicated by having two separate calling sequences, the AIX calling
    sequence and the V.4 calling sequence.
 
-   AIX stack frames look like:
+   AIX (and Darwin/Mac OS) stack frames look like:
                                                          32-bit  64-bit
        SP----> +---------------------------------------+
                | back chain to caller                  | 0       0
@@ -4821,8 +4872,10 @@ rs6000_stack_info ()
   info_ptr->first_gp_reg_save = first_reg_to_save ();
   /* Assume that we will have to save PIC_OFFSET_TABLE_REGNUM, 
      even if it currently looks like we won't.  */
-  if (flag_pic == 1 
-      && (abi == ABI_V4 || abi == ABI_SOLARIS)
+  if (((flag_pic == 1
+       && (abi == ABI_V4 || abi == ABI_SOLARIS))
+       || (flag_pic &&
+          abi == ABI_DARWIN))
       && info_ptr->first_gp_reg_save > PIC_OFFSET_TABLE_REGNUM)
     info_ptr->gp_size = reg_size * (32 - PIC_OFFSET_TABLE_REGNUM);
   else
@@ -4845,6 +4898,7 @@ rs6000_stack_info ()
          && !FP_SAVE_INLINE (info_ptr->first_fp_reg_save))
       || (abi == ABI_V4 && current_function_calls_alloca)
       || (abi == ABI_SOLARIS && current_function_calls_alloca)
+      || (DEFAULT_ABI == ABI_DARWIN && flag_pic && current_function_uses_pic_offset_table)
       || info_ptr->calls_p)
     {
       info_ptr->lr_save_p = 1;
@@ -4886,6 +4940,8 @@ rs6000_stack_info ()
                                  + info_ptr->cr_size
                                  + info_ptr->lr_size
                                  + info_ptr->toc_size, 8);
+  if (DEFAULT_ABI == ABI_DARWIN)
+    info_ptr->save_size = RS6000_ALIGN (info_ptr->save_size, 16);
 
   /* Calculate the offsets */
   switch (abi)
@@ -4896,6 +4952,7 @@ rs6000_stack_info ()
 
     case ABI_AIX:
     case ABI_AIX_NODESC:
+    case ABI_DARWIN:
       info_ptr->fp_save_offset   = - info_ptr->fp_size;
       info_ptr->gp_save_offset   = info_ptr->fp_save_offset - info_ptr->gp_size;
       info_ptr->ehrd_offset      = info_ptr->gp_save_offset - ehrd_size;
@@ -4942,7 +4999,7 @@ rs6000_stack_info ()
 
   else
     info_ptr->push_p = (frame_pointer_needed
-                       || write_symbols != NO_DEBUG
+                       || (abi != ABI_DARWIN && write_symbols != NO_DEBUG)
                        || ((total_raw_size - info_ptr->fixed_size)
                            > (TARGET_32BIT ? 220 : 288)));
 
@@ -4985,6 +5042,7 @@ debug_stack_info (info)
     case ABI_NONE:      abi_string = "NONE";           break;
     case ABI_AIX:       abi_string = "AIX";            break;
     case ABI_AIX_NODESC: abi_string = "AIX";           break;
+    case ABI_DARWIN:    abi_string = "Darwin";         break;
     case ABI_V4:        abi_string = "V.4";            break;
     case ABI_SOLARIS:   abi_string = "Solaris";        break;
     }
@@ -5740,8 +5798,10 @@ rs6000_emit_prologue ()
        if ((regs_ever_live[info->first_gp_reg_save+i] 
             && ! call_used_regs[info->first_gp_reg_save+i])
            || (i+info->first_gp_reg_save == PIC_OFFSET_TABLE_REGNUM
-               && (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS)
-               && flag_pic == 1))
+               && (((DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS)
+                    && flag_pic == 1)
+                   || (DEFAULT_ABI == ABI_DARWIN
+                       && flag_pic))))
          {
            rtx addr, reg, mem;
            reg = gen_rtx_REG (reg_mode, info->first_gp_reg_save + i);
@@ -5858,6 +5918,18 @@ rs6000_emit_prologue ()
       emit_move_insn (gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM), 
                      gen_rtx_REG (Pmode, 11));
   }
+
+  if (DEFAULT_ABI == ABI_DARWIN
+      && flag_pic && current_function_uses_pic_offset_table)
+    {
+      rtx dest = gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM);
+
+      rs6000_maybe_dead (emit_insn (gen_load_macho_picbase (dest)));
+
+      rs6000_maybe_dead (
+       emit_move_insn (gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM),
+                       gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM)));
+    }
 }
 
 
@@ -6051,8 +6123,10 @@ rs6000_emit_epilogue (sibcall)
       if ((regs_ever_live[info->first_gp_reg_save+i] 
           && ! call_used_regs[info->first_gp_reg_save+i])
          || (i+info->first_gp_reg_save == PIC_OFFSET_TABLE_REGNUM
-             && (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS)
-             && flag_pic == 1))
+             && (((DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS)
+                  && flag_pic == 1)
+                 || (DEFAULT_ABI == ABI_DARWIN
+                     && flag_pic))))
        {
          rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx, 
                                   GEN_INT (info->gp_save_offset 
@@ -6626,6 +6700,17 @@ output_mi_thunk (file, thunk_fndecl, delta, function)
          if (flag_pic) fputs ("@plt", file);
          putc ('\n', file);
          break;
+
+#if TARGET_MACHO
+       case ABI_DARWIN:
+         fprintf (file, "\tb %s", prefix);
+         if (flag_pic && !machopic_name_defined_p (fname))
+           assemble_name (file, machopic_stub_name (fname));
+         else
+           assemble_name (file, fname);
+         putc ('\n', file);
+         break;
+#endif
        }
     }
 }
@@ -7226,6 +7311,28 @@ output_profile_hook (labelno)
       emit_library_call (init_one_libfunc (RS6000_MCOUNT), 0, VOIDmode, 1,
                          fun, Pmode);
     }
+  else if (DEFAULT_ABI == ABI_DARWIN)
+    {
+      char *mcount_name = RS6000_MCOUNT;
+      int caller_addr_regno = LINK_REGISTER_REGNUM;
+
+      /* Be conservative and always set this, at least for now.  */
+      current_function_uses_pic_offset_table = 1;
+
+#if TARGET_MACHO
+      /* For PIC code, set up a stub and collect the caller's address
+        from r0, which is where the prologue puts it.  */
+      if (flag_pic)
+       {
+         mcount_name = machopic_stub_name (mcount_name);
+         if (current_function_uses_pic_offset_table)
+           caller_addr_regno = 0;
+       }
+#endif
+      emit_library_call (gen_rtx_SYMBOL_REF (Pmode, mcount_name),
+                        0, VOIDmode, 1,
+                        gen_rtx_REG (Pmode, caller_addr_regno), Pmode);
+    }
 }
 
 /* Write function profiler code. */
@@ -7296,6 +7403,7 @@ output_function_profiler (file, labelno)
       break;
 
     case ABI_AIX:
+    case ABI_DARWIN:
       /* Don't do anything, done in output_profile_hook (). */
       break;
 
@@ -7834,4 +7942,325 @@ rs6000_add_gc_roots ()
   toc_hash_table = htab_create (1021, toc_hash_function, toc_hash_eq, NULL);
   ggc_add_root (&toc_hash_table, 1, sizeof (toc_hash_table), 
                toc_hash_mark_table);
+
+#if TARGET_MACHO
+  machopic_add_gc_roots ();
+#endif
+}
+
+#if TARGET_MACHO
+
+#if 0
+/* Returns 1 if OP is either a symbol reference or a sum of a symbol
+   reference and a constant.  */
+
+int
+symbolic_operand (op)
+     register rtx op;
+{
+  switch (GET_CODE (op))
+    {
+    case SYMBOL_REF:
+    case LABEL_REF:
+      return 1;
+    case CONST:
+      op = XEXP (op, 0);
+      return (GET_CODE (op) == SYMBOL_REF ||
+             (GET_CODE (XEXP (op, 0)) == SYMBOL_REF
+              || GET_CODE (XEXP (op, 0)) == LABEL_REF)
+             && GET_CODE (XEXP (op, 1)) == CONST_INT);
+    default:
+      return 0;
+    }
 }
+#endif
+
+#ifdef RS6000_LONG_BRANCH
+
+static tree stub_list = 0;
+
+/* ADD_COMPILER_STUB adds the compiler generated stub for handling 
+   procedure calls to the linked list.  */
+
+void 
+add_compiler_stub (label_name, function_name, line_number)
+     tree label_name;
+     tree function_name;
+     int line_number;
+{
+  tree stub = build_tree_list (function_name, label_name);
+  TREE_TYPE (stub) = build_int_2 (line_number, 0);
+  TREE_CHAIN (stub) = stub_list;
+  stub_list = stub;
+}
+
+#define STUB_LABEL_NAME(STUB)     TREE_VALUE (STUB)
+#define STUB_FUNCTION_NAME(STUB)  TREE_PURPOSE (STUB)
+#define STUB_LINE_NUMBER(STUB)    TREE_INT_CST_LOW (TREE_TYPE (STUB))
+
+/* OUTPUT_COMPILER_STUB outputs the compiler generated stub for handling 
+   procedure calls from the linked list and initializes the linked list.  */
+
+void output_compiler_stub ()
+{
+  char tmp_buf[256];
+  char label_buf[256];
+  char *label;
+  tree tmp_stub, stub;
+
+  if (!flag_pic)
+    for (stub = stub_list; stub; stub = TREE_CHAIN (stub))
+      {
+       fprintf (asm_out_file,
+                "%s:\n", IDENTIFIER_POINTER(STUB_LABEL_NAME(stub)));
+
+#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
+       if (write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG)
+         fprintf (asm_out_file, "\t.stabd 68,0,%d\n", STUB_LINE_NUMBER(stub));
+#endif /* DBX_DEBUGGING_INFO || XCOFF_DEBUGGING_INFO */
+
+       if (IDENTIFIER_POINTER (STUB_FUNCTION_NAME (stub))[0] == '*')
+         strcpy (label_buf,
+                 IDENTIFIER_POINTER (STUB_FUNCTION_NAME (stub))+1);
+       else
+         {
+           label_buf[0] = '_';
+           strcpy (label_buf+1,
+                   IDENTIFIER_POINTER (STUB_FUNCTION_NAME (stub)));
+         }
+
+       strcpy (tmp_buf, "lis r12,hi16(");
+       strcat (tmp_buf, label_buf);
+       strcat (tmp_buf, ")\n\tori r12,r12,lo16(");
+       strcat (tmp_buf, label_buf);
+       strcat (tmp_buf, ")\n\tmtctr r12\n\tbctr");
+       output_asm_insn (tmp_buf, 0);
+
+#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
+       if (write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG)
+         fprintf(asm_out_file, "\t.stabd 68,0,%d\n", STUB_LINE_NUMBER (stub));
+#endif /* DBX_DEBUGGING_INFO || XCOFF_DEBUGGING_INFO */
+      }
+
+  stub_list = 0;
+}
+
+/* NO_PREVIOUS_DEF checks in the link list whether the function name is
+   already there or not.  */
+
+int no_previous_def (function_name)
+     tree function_name;
+{
+  tree stub;
+  for (stub = stub_list; stub; stub = TREE_CHAIN (stub))
+    if (function_name == STUB_FUNCTION_NAME (stub))
+      return 0;
+  return 1;
+}
+
+/* GET_PREV_LABEL gets the label name from the previous definition of
+   the function.  */
+
+tree get_prev_label (function_name)
+     tree function_name;
+{
+  tree stub;
+  for (stub = stub_list; stub; stub = TREE_CHAIN (stub))
+    if (function_name == STUB_FUNCTION_NAME (stub))
+      return STUB_LABEL_NAME (stub);
+  return 0;
+}
+
+/* INSN is either a function call or a millicode call.  It may have an
+   unconditional jump in its delay slot.  
+
+   CALL_DEST is the routine we are calling.  */
+
+char *
+output_call (insn, call_dest, operand_number)
+     rtx insn;
+     rtx call_dest;
+     int operand_number;
+{
+  static char buf[256];
+  if (GET_CODE (call_dest) == SYMBOL_REF && TARGET_LONG_BRANCH && !flag_pic)
+    {
+      tree labelname;
+      tree funname = get_identifier (XSTR (call_dest, 0));
+      
+      if (no_previous_def (funname))
+       {
+         int line_number;
+         rtx label_rtx = gen_label_rtx ();
+         char *label_buf, temp_buf[256];
+         ASM_GENERATE_INTERNAL_LABEL (temp_buf, "L",
+                                      CODE_LABEL_NUMBER (label_rtx));
+         label_buf = temp_buf[0] == '*' ? temp_buf + 1 : temp_buf;
+         labelname = get_identifier (label_buf);
+         for (; insn && GET_CODE (insn) != NOTE; insn = PREV_INSN (insn));
+         if (insn)
+           line_number = NOTE_LINE_NUMBER (insn);
+         add_compiler_stub (labelname, funname, line_number);
+       }
+      else
+       labelname = get_prev_label (funname);
+
+      sprintf (buf, "jbsr %%z%d,%.246s",
+              operand_number, IDENTIFIER_POINTER (labelname));
+      return buf;
+    }
+  else
+    {
+      sprintf (buf, "bl %%z%d", operand_number);
+      return buf;
+    }
+}
+
+#endif /* RS6000_LONG_BRANCH */
+
+#define GEN_LOCAL_LABEL_FOR_SYMBOL(BUF,SYMBOL,LENGTH,N)                \
+  do {                                                         \
+    const char *symbol_ = (SYMBOL);                            \
+    char *buffer_ = (BUF);                                     \
+    if (symbol_[0] == '"')                                     \
+      {                                                                \
+        sprintf(buffer_, "\"L%d$%s", (N), symbol_+1);          \
+      }                                                                \
+    else if (name_needs_quotes(symbol_))                       \
+      {                                                                \
+        sprintf(buffer_, "\"L%d$%s\"", (N), symbol_);          \
+      }                                                                \
+    else                                                       \
+      {                                                                \
+        sprintf(buffer_, "L%d$%s", (N), symbol_);              \
+      }                                                                \
+  } while (0)
+
+
+/* Generate PIC and indirect symbol stubs.  */
+
+void
+machopic_output_stub (file, symb, stub)
+     FILE *file;
+     const char *symb, *stub;
+{
+  unsigned int length;
+  char *binder_name, *symbol_name, *lazy_ptr_name;
+  char *local_label_0, *local_label_1, *local_label_2;
+  static int label = 0;
+
+  label += 1;
+
+  length = strlen (stub);
+  binder_name = alloca (length + 32);
+  GEN_BINDER_NAME_FOR_STUB (binder_name, stub, length);
+
+  length = strlen (symb);
+  symbol_name = alloca (length + 32);
+  GEN_SYMBOL_NAME_FOR_SYMBOL (symbol_name, symb, length);
+
+  lazy_ptr_name = alloca (length + 32);
+  GEN_LAZY_PTR_NAME_FOR_SYMBOL (lazy_ptr_name, symb, length);
+
+  local_label_0 = alloca (length + 32);
+  GEN_LOCAL_LABEL_FOR_SYMBOL (local_label_0, symb, length, 0);
+
+  local_label_1 = alloca (length + 32);
+  GEN_LOCAL_LABEL_FOR_SYMBOL (local_label_1, symb, length, 1);
+
+  local_label_2 = alloca (length + 32);
+  GEN_LOCAL_LABEL_FOR_SYMBOL (local_label_2, symb, length, 2);
+
+  if (flag_pic == 2)
+    machopic_picsymbol_stub_section ();
+  else
+    machopic_symbol_stub_section ();
+
+  fprintf (file, "%s:\n", stub);
+  fprintf (file, "\t.indirect_symbol %s\n", symbol_name);
+
+  if (flag_pic == 2)
+    {
+      fprintf (file, "\tmflr r0\n");
+      fprintf (file, "\tbcl 20,31,%s\n", local_label_0);
+      fprintf (file, "%s:\n\tmflr r11\n", local_label_0);
+      fprintf (file, "\taddis r11,r11,ha16(%s-%s)\n",
+              lazy_ptr_name, local_label_0);
+      fprintf (file, "\tmtlr r0\n");
+      fprintf (file, "\tlwz r12,lo16(%s-%s)(r11)\n",
+              lazy_ptr_name, local_label_0);
+      fprintf (file, "\tmtctr r12\n");
+      fprintf (file, "\taddi r11,r11,lo16(%s-%s)\n",
+              lazy_ptr_name, local_label_0);
+      fprintf (file, "\tbctr\n");
+    }
+  else
+    fprintf (file, "non-pure not supported\n");
+  
+  machopic_lazy_symbol_ptr_section ();
+  fprintf (file, "%s:\n", lazy_ptr_name);
+  fprintf (file, "\t.indirect_symbol %s\n", symbol_name);
+  fprintf (file, "\t.long dyld_stub_binding_helper\n");
+}
+
+/* Legitimize PIC addresses.  If the address is already
+   position-independent, we return ORIG.  Newly generated
+   position-independent addresses go into a reg.  This is REG if non
+   zero, otherwise we allocate register(s) as necessary.  */
+
+#define SMALL_INT(X) ((unsigned) (INTVAL(X) + 0x4000) < 0x8000)
+
+rtx
+rs6000_machopic_legitimize_pic_address (orig, mode, reg)
+     rtx orig;
+     enum machine_mode mode;
+     rtx reg;
+{
+  rtx base, offset;
+
+  if (reg == NULL && ! reload_in_progress && ! reload_completed)
+    reg = gen_reg_rtx (Pmode);
+
+  if (GET_CODE (orig) == CONST)
+    {
+      if (GET_CODE (XEXP (orig, 0)) == PLUS
+         && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)
+       return orig;
+
+      if (GET_CODE (XEXP (orig, 0)) == PLUS)
+       {
+         base = rs6000_machopic_legitimize_pic_address (XEXP (XEXP (orig, 0), 0),
+                                                        Pmode, reg);
+         offset = rs6000_machopic_legitimize_pic_address (XEXP (XEXP (orig, 0), 1),
+                                                          Pmode, reg);
+       }
+      else
+       abort ();
+
+      if (GET_CODE (offset) == CONST_INT)
+       {
+         if (SMALL_INT (offset))
+           return plus_constant_for_output (base, INTVAL (offset));
+         else if (! reload_in_progress && ! reload_completed)
+           offset = force_reg (Pmode, offset);
+         else
+           abort ();
+       }
+      return gen_rtx (PLUS, Pmode, base, offset);
+    }
+
+  /* Fall back on generic machopic code.  */
+  return machopic_legitimize_pic_address (orig, mode, reg);
+}
+
+/* This is just a placeholder to make linking work without having to
+   add this to the generic Darwin EXTRA_SECTIONS.  If -mcall-aix is
+   ever needed for Darwin (not too likely!) this would have to get a
+   real definition.  */
+
+void
+toc_section ()
+{
+}
+
+#endif /* TARGET_MACHO */
index f0f65f5..c1b9644 100644 (file)
@@ -30,10 +30,12 @@ Boston, MA 02111-1307, USA.  */
 #define OBJECT_XCOFF 1
 #define OBJECT_ELF 2
 #define OBJECT_PEF 3
+#define OBJECT_MACHO 4
 
 #define TARGET_ELF (TARGET_OBJECT_FORMAT == OBJECT_ELF)
 #define TARGET_AIX (TARGET_OBJECT_FORMAT == OBJECT_XCOFF)
 #define TARGET_MACOS (TARGET_OBJECT_FORMAT == OBJECT_PEF)
+#define TARGET_MACHO (TARGET_OBJECT_FORMAT == OBJECT_MACHO)
 
 /* Print subsidiary information on the compiler version in use.  */
 #define TARGET_VERSION ;
@@ -861,6 +863,10 @@ extern int rs6000_debug_arg;               /* debug argument handling */
       && flag_pic == 1)                                                        \
     fixed_regs[PIC_OFFSET_TABLE_REGNUM]                                        \
       = call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1;                   \
+  if (DEFAULT_ABI == ABI_DARWIN && flag_pic)                           \
+    global_regs[PIC_OFFSET_TABLE_REGNUM]                               \
+      = fixed_regs[PIC_OFFSET_TABLE_REGNUM]                            \
+        = call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1;                 \
 }
 
 /* Specify the registers used for certain standard purposes.
@@ -1159,7 +1165,8 @@ enum rs6000_abi {
   ABI_AIX,                     /* IBM's AIX */
   ABI_AIX_NODESC,              /* AIX calling sequence minus function descriptors */
   ABI_V4,                      /* System V.4/eabi */
-  ABI_SOLARIS                  /* Solaris */
+  ABI_SOLARIS,                 /* Solaris */
+  ABI_DARWIN                   /* Apple's Darwin (OS X kernel) */
 };
 
 extern enum rs6000_abi rs6000_current_abi;     /* available for use by subtarget */
@@ -1210,13 +1217,14 @@ typedef struct rs6000_stack {
 
 /* Size of the outgoing register save area */
 #define RS6000_REG_SAVE ((DEFAULT_ABI == ABI_AIX                       \
-                         || DEFAULT_ABI == ABI_AIX_NODESC)             \
+                         || DEFAULT_ABI == ABI_AIX_NODESC              \
+                         || DEFAULT_ABI == ABI_DARWIN)                 \
                         ? (TARGET_64BIT ? 64 : 32)                     \
                         : 0)
 
 /* Size of the fixed area on the stack */
 #define RS6000_SAVE_AREA \
-  (((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_AIX_NODESC) ? 24 : 8)        \
+  (((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_AIX_NODESC || DEFAULT_ABI == ABI_DARWIN) ? 24 : 8)   \
    << (TARGET_64BIT ? 1 : 0))
 
 /* MEM representing address to save the TOC register */
@@ -1351,7 +1359,8 @@ typedef struct rs6000_stack {
 #define        FP_ARG_AIX_MAX_REG 45
 #define        FP_ARG_V4_MAX_REG  40
 #define        FP_ARG_MAX_REG ((DEFAULT_ABI == ABI_AIX                         \
-                        || DEFAULT_ABI == ABI_AIX_NODESC)              \
+                        || DEFAULT_ABI == ABI_AIX_NODESC               \
+                        || DEFAULT_ABI == ABI_DARWIN)                  \
                        ? FP_ARG_AIX_MAX_REG : FP_ARG_V4_MAX_REG)
 #define FP_ARG_NUM_REG (FP_ARG_MAX_REG - FP_ARG_MIN_REG + 1)
 
@@ -1645,6 +1654,7 @@ typedef struct rs6000_args
    abi's store the return address.  */
 #define RETURN_ADDRESS_OFFSET                                          \
  ((DEFAULT_ABI == ABI_AIX                                              \
+   || DEFAULT_ABI == ABI_DARWIN                                                \
    || DEFAULT_ABI == ABI_AIX_NODESC)   ? (TARGET_32BIT ? 8 : 16) :     \
   (DEFAULT_ABI == ABI_V4                                               \
    || DEFAULT_ABI == ABI_SOLARIS)      ? (TARGET_32BIT ? 4 : 8) :      \
index 833e640..6bea69b 100644 (file)
    {cau|addis} %0,%1,%v2"
   [(set_attr "length" "4,4,4,4")])
 
+(define_insn "addsi3_high"
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=b")
+        (plus:SI (match_operand:SI 1 "gpc_reg_operand" "b")
+                 (high:SI (match_operand 2 "" ""))))]
+  "TARGET_MACHO && !TARGET_64BIT"
+  "{cau|addis} %0,%1,ha16(%2)"
+  [(set_attr "length" "4")])
+
 (define_insn "*addsi3_internal2"
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
        (compare:CC (plus:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r")
     {cal|la} %0,%2@l(%1)
     {ai|addic} %0,%1,%K2")
 
+;; Mach-O PIC trickery.
+(define_insn "macho_high"
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=b*r")
+       (high:SI (match_operand 1 "" "")))]
+  "TARGET_MACHO && ! TARGET_64BIT"
+  "{liu|lis} %0,ha16(%1)")
+
+(define_insn "macho_low"
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
+       (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b,!*r")
+                  (match_operand 2 "" "")))]
+   "TARGET_MACHO && ! TARGET_64BIT"
+   "@
+    {cal %0,%a2@l(%1)|la %0,lo16(%2)(%1)}
+    {cal %0,%a2@l(%1)|addic %0,%1,lo16(%2)}")
+
 ;; Set up a register with a value from the GOT table
 
 (define_expand "movsi_got"
   ""
   "{ rs6000_emit_move (operands[0], operands[1], SImode); DONE; }")
 
+(define_insn "movsi_low"
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+        (mem:SI (lo_sum:SI (match_operand:SI 1 "register_operand" "b")
+                           (match_operand 2 "" ""))))]
+  "TARGET_MACHO && ! TARGET_64BIT"
+  "{l|lwz} %0,lo16(%2)(%1)"
+  [(set_attr "type" "load")
+   (set_attr "length" "4")])
+
 (define_insn "*movsi_internal1"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,m,r,r,r,r,r,*q,*c*l,*h")
        (match_operand:SI 1 "input_operand" "r,U,m,r,I,L,n,R,*h,r,r,0"))]
@@ -9257,6 +9290,21 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
   "{l|lwz} %0,%2-%3(%1)"
   [(set_attr "type" "load")])
 
+(define_insn "load_macho_picbase"
+  [(set (match_operand:SI 0 "register_operand" "=l")
+       (unspec:SI [(const_int 0)] 15))]
+  "(DEFAULT_ABI == ABI_DARWIN) && flag_pic"
+  "*
+{
+#if TARGET_MACHO
+  char *picbase = machopic_function_base_name ();
+  operands[1] = gen_rtx_SYMBOL_REF (Pmode, ggc_alloc_string (picbase, -1));
+#endif
+  return \"bcl 20,31,%1\\n%1:\";
+}"
+  [(set_attr "type" "branch")
+   (set_attr "length" "4")])
+
 ;; If the TOC is shared over a translation unit, as happens with all
 ;; the kinds of PIC that we support, we need to restore the TOC
 ;; pointer only when jumping over units of translation.
@@ -9376,6 +9424,11 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
   ""
   "
 {
+#if TARGET_MACHO
+  if (flag_pic)
+    operands[0] = machopic_indirect_call_target (operands[0]);
+#endif
+
   if (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != CONST_INT)
     abort ();
 
@@ -9389,6 +9442,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
 
       if (DEFAULT_ABI == ABI_V4
           || DEFAULT_ABI == ABI_AIX_NODESC
+         || DEFAULT_ABI == ABI_DARWIN
          || DEFAULT_ABI == ABI_SOLARIS)
        operands[0] = force_reg (Pmode, operands[0]);
 
@@ -9419,6 +9473,11 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
   ""
   "
 {
+#if TARGET_MACHO
+  if (flag_pic)
+    operands[1] = machopic_indirect_call_target (operands[1]);
+#endif
+
   if (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != CONST_INT)
     abort ();
 
@@ -9432,6 +9491,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
 
       if (DEFAULT_ABI == ABI_V4
          || DEFAULT_ABI == ABI_AIX_NODESC
+         || DEFAULT_ABI == ABI_DARWIN
          || DEFAULT_ABI == ABI_SOLARIS)
        operands[0] = force_reg (Pmode, operands[0]);
 
@@ -9664,6 +9724,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
    (clobber (match_scratch:SI 3 "=l,l,l,l"))]
   "DEFAULT_ABI == ABI_AIX_NODESC
    || DEFAULT_ABI == ABI_V4
+   || DEFAULT_ABI == ABI_DARWIN
    || DEFAULT_ABI == ABI_SOLARIS"
   "*
 {
@@ -9696,6 +9757,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
    (clobber (match_scratch:SI 4 "=l,l,l,l"))]
   "DEFAULT_ABI == ABI_AIX_NODESC
    || DEFAULT_ABI == ABI_V4
+   || DEFAULT_ABI == ABI_DARWIN
    || DEFAULT_ABI == ABI_SOLARIS"
   "*
 {
diff --git a/gcc/config/rs6000/t-darwin b/gcc/config/rs6000/t-darwin
new file mode 100644 (file)
index 0000000..c514fda
--- /dev/null
@@ -0,0 +1,26 @@
+# Do not build libgcc1.
+LIBGCC1 =
+CROSS_LIBGCC1 =
+
+# We want fine grained libraries, so use the new code to build the
+# floating point emulation libraries.
+FPBIT = fp-bit.c
+DPBIT = dp-bit.c
+
+dp-bit.c: $(srcdir)/config/fp-bit.c
+       cat $(srcdir)/config/fp-bit.c > dp-bit.c
+
+fp-bit.c: $(srcdir)/config/fp-bit.c
+       echo '#define FLOAT' > fp-bit.c
+       cat $(srcdir)/config/fp-bit.c >> fp-bit.c
+
+darwin.o: $(srcdir)/config/darwin.c
+       $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/darwin.c
+
+# Build the libraries for both hard and soft floating point
+
+MULTILIB_OPTIONS = msoft-float
+MULTILIB_DIRNAMES = soft-float
+
+LIBGCC = stmp-multilib
+INSTALL_LIBGCC = install-multilib
index 661d95d..081bcb2 100644 (file)
@@ -234,6 +234,7 @@ typedef long ssize_t;
 #ifndef __WCHAR_T
 #ifndef _WCHAR_T_
 #ifndef _BSD_WCHAR_T_
+#ifndef _BSD_WCHAR_T_DEFINED_    /* Darwin */
 #ifndef _WCHAR_T_DEFINED_
 #ifndef _WCHAR_T_DEFINED
 #ifndef _WCHAR_T_H
@@ -298,6 +299,7 @@ typedef __WCHAR_TYPE__ wchar_t;
 #endif
 #endif
 #endif
+#endif
 #endif /* __wchar_t__ */
 #undef __need_wchar_t
 #endif /* _STDDEF_H or __need_wchar_t.  */