This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

PATCH: Darwin / Mac OS X native support, revised


This is a revised version of the patch originally submitted in
http://gcc.gnu.org/ml/gcc-patches/2001-03/msg00042.html .  (Please
see that message for general info about the patch.)

I believe that I've now accounted for all the feedback, mostly by
stripping unnecessary things (for instance, FINALIZE_PIC turns out
to have become a no-op!).  I also worked around the varasm.c tweak,
so there are now no changes to generic GCC code, and made C++ work
better.  The bootstrap on a Mac OS X final system just completed
successfully.

OK to commit?

2001-04-06  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_mi_thunk): Add TARGET_MACHO case.
        (darwin_output_function_profiler): New function.
        (rs6000_add_gc_roots): Call machopic_add_gc_roots if TARGET_MACHO.
        (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_.

Index: config.gcc
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config.gcc,v
retrieving revision 1.47
diff -c -3 -p -r1.47 config.gcc
*** config.gcc  2001/04/05 04:34:23     1.47
--- config.gcc  2001/04/06 19:44:06
*************** powerpc-*-beos*)
*** 2680,2687 ****
--- 2680,2694 ----
        xmake_file=rs6000/x-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"
Index: config/darwin-protos.h
===================================================================
RCS file: darwin-protos.h
diff -N darwin-protos.h
*** /dev/null   Tue May  5 13:32:27 1998
--- darwin-protos.h     Fri Apr  6 12:44:06 2001
***************
*** 0 ****
--- 1,59 ----
+ /* 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));
+ 
+ extern int mcount_called;     /* TRUE if we ever called "mcount"  */
+ 
+ #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 *));
Index: config/darwin.c
===================================================================
RCS file: darwin.c
diff -N darwin.c
*** /dev/null   Tue May  5 13:32:27 1998
--- darwin.c    Fri Apr  6 12:44:07 2001
***************
*** 0 ****
--- 1,1010 ----
+ /* 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.  */
+ 
+ /* This flag is set by architecture-specific code when a call to
+    mcount (for profiling) has been generated.  */
+ 
+ int mcount_called;
+ 
+ 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);
+     }
+ 
+   if (flag_pic && mcount_called)
+     machopic_output_stub (asm_out_file, "mcount", "Lmcount$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;
+ }
Index: config/darwin.h
===================================================================
RCS file: darwin.h
diff -N darwin.h
*** /dev/null   Tue May  5 13:32:27 1998
--- darwin.h    Fri Apr  6 12:44:07 2001
***************
*** 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)
+ 
Index: config/rs6000/darwin.h
===================================================================
RCS file: darwin.h
diff -N darwin.h
*** /dev/null   Tue May  5 13:32:27 1998
--- darwin.h    Fri Apr  6 12:44:08 2001
***************
*** 0 ****
--- 1,183 ----
+ /* 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 ""
+ 
+ /* Output assembler code to FILE to increment profiler label LABELNO
+    for profiling a function entry.  */
+ /* Darwin needs its own version because the mcount calling convention
+    is different.  */
+ 
+ #undef FUNCTION_PROFILER
+ #define FUNCTION_PROFILER(FILE, LABELNO)      \
+   darwin_output_function_profiler (FILE, LABELNO);
+ 
+ /* Function name to call to do profiling.  */
+ /* This is a dummy, since Darwin uses its own function.  */
+ 
+ #define RS6000_MCOUNT "never_try_to_call_me"
+ 
+ /* Since Darwin doesn't do TOCs, stub this out.  */
+ 
+ #define ASM_OUTPUT_SPECIAL_POOL_ENTRY_P(X, MODE)  0
+ 
+ #define RS6000_LAST_REG (frame_pointer_needed ? 29 : (flag_pic ? 30 : 31))
+ 
+ /* 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: config/rs6000/rs6000-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000-protos.h,v
retrieving revision 1.16
diff -c -3 -p -r1.16 rs6000-protos.h
*** rs6000-protos.h     2001/02/06 19:04:01     1.16
--- rs6000-protos.h     2001/04/06 19:44:08
*************** extern void rs6000_emit_eh_toc_restore P
*** 108,115 ****
--- 108,119 ----
  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
*************** extern void rs6000_unique_section PARAMS
*** 139,144 ****
--- 143,149 ----
  /* 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));
*************** extern void rs6000_emit_load_toc_table P
*** 172,174 ****
--- 177,181 ----
  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: config/rs6000/rs6000.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.c,v
retrieving revision 1.172
diff -c -3 -p -r1.172 rs6000.c
*** rs6000.c    2001/03/28 11:19:20     1.172
--- rs6000.c    2001/04/06 19:44:10
*************** rs6000_legitimize_address (x, oldx, mode
*** 1526,1531 ****
--- 1526,1544 ----
        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))
*************** rs6000_emit_move (dest, source, mode)
*** 1644,1650 ****
          return;
        }
  
!       if (TARGET_ELF && TARGET_NO_TOC && ! flag_pic
          && mode == Pmode
          && CONSTANT_P (operands[1])
          && GET_CODE (operands[1]) != HIGH
--- 1657,1664 ----
          return;
        }
  
!       if ((TARGET_ELF || DEFAULT_ABI == ABI_DARWIN)
!         && TARGET_NO_TOC && ! flag_pic
          && mode == Pmode
          && CONSTANT_P (operands[1])
          && GET_CODE (operands[1]) != HIGH
*************** rs6000_emit_move (dest, source, mode)
*** 1670,1675 ****
--- 1684,1696 ----
              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;
*************** rs6000_emit_move (dest, source, mode)
*** 1708,1713 ****
--- 1729,1749 ----
          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
*************** print_operand (file, x, code)
*** 4296,4301 ****
--- 4332,4338 ----
            case ABI_V4:
            case ABI_AIX_NODESC:
            case ABI_SOLARIS:
+           case ABI_DARWIN:
              break;
            }
        }
*************** first_reg_to_save ()
*** 4655,4662 ****
      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)))
        break;
  
    if (profile_flag)
--- 4692,4701 ----
      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_DARWIN
!                       && flag_pic)))))
        break;
  
    if (profile_flag)
*************** first_reg_to_save ()
*** 4665,4671 ****
         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)
        {
          int last_parm_reg, profile_first_reg;
  
--- 4704,4710 ----
         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 || DEFAULT_ABI == ABI_DARWIN)
        {
          int last_parm_reg, profile_first_reg;
  
*************** first_reg_to_save ()
*** 4683,4688 ****
--- 4722,4733 ----
             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;
*************** first_reg_to_save ()
*** 4700,4705 ****
--- 4745,4756 ----
        }
      }
  
+ #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;
  }
  
*************** first_fp_reg_to_save ()
*** 4722,4728 ****
     complicated by having two separate calling sequences, the AIX calling
     sequence and the V.4 calling sequence.
  
!    AIX stack frames look like:
                                                          32-bit  64-bit
        SP----> +---------------------------------------+
                | back chain to caller                  | 0       0
--- 4773,4779 ----
     complicated by having two separate calling sequences, the AIX calling
     sequence and the V.4 calling sequence.
  
!    AIX (and Darwin/Mac OS) stack frames look like:
                                                          32-bit  64-bit
        SP----> +---------------------------------------+
                | back chain to caller                  | 0       0
*************** rs6000_stack_info ()
*** 4821,4828 ****
    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)
        && info_ptr->first_gp_reg_save > PIC_OFFSET_TABLE_REGNUM)
      info_ptr->gp_size = reg_size * (32 - PIC_OFFSET_TABLE_REGNUM);
    else
--- 4872,4881 ----
    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))
!        || (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
*************** rs6000_stack_info ()
*** 4845,4850 ****
--- 4898,4904 ----
          && !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;
*************** rs6000_stack_info ()
*** 4886,4891 ****
--- 4940,4947 ----
                                  + 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)
*************** rs6000_stack_info ()
*** 4896,4901 ****
--- 4952,4958 ----
  
      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;
*************** rs6000_stack_info ()
*** 4942,4948 ****
  
    else
      info_ptr->push_p = (frame_pointer_needed
!                       || write_symbols != NO_DEBUG
                        || ((total_raw_size - info_ptr->fixed_size)
                            > (TARGET_32BIT ? 220 : 288)));
  
--- 4999,5005 ----
  
    else
      info_ptr->push_p = (frame_pointer_needed
!                       || (abi != ABI_DARWIN && write_symbols != NO_DEBUG)
                        || ((total_raw_size - info_ptr->fixed_size)
                            > (TARGET_32BIT ? 220 : 288)));
  
*************** debug_stack_info (info)
*** 4985,4990 ****
--- 5042,5048 ----
      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;
      }
*************** rs6000_emit_prologue ()
*** 5740,5747 ****
        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))
          {
            rtx addr, reg, mem;
            reg = gen_rtx_REG (reg_mode, info->first_gp_reg_save + i);
--- 5798,5807 ----
        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_DARWIN
!                       && flag_pic))))
          {
            rtx addr, reg, mem;
            reg = gen_rtx_REG (reg_mode, info->first_gp_reg_save + i);
*************** rs6000_emit_prologue ()
*** 5858,5863 ****
--- 5918,5935 ----
        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)));
+     }
  }
  
  
*************** rs6000_emit_epilogue (sibcall)
*** 6051,6058 ****
        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))
        {
          rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx, 
                                   GEN_INT (info->gp_save_offset 
--- 6123,6132 ----
        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_DARWIN
!                     && flag_pic))))
        {
          rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx, 
                                   GEN_INT (info->gp_save_offset 
*************** output_mi_thunk (file, thunk_fndecl, del
*** 6626,6631 ****
--- 6700,6716 ----
          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
        }
      }
  }
*************** rs6000_add_gc_roots ()
*** 7834,7837 ****
--- 7919,8291 ----
    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);
+ }
+ 
+ /* Write out a Darwin-compatible call to mcount, for profiling. */
+ 
+ void
+ darwin_output_function_profiler (file, labelno)
+      FILE *file;
+      int labelno;
+ {
+   int last_parm_reg; /* The last used parameter register.  */
+   int i, j;
+ 
+   /* Figure out last used parameter register.  The proper thing to do is
+      to walk incoming args of the function.  A function might have live
+      parameter registers even if it has no incoming args.  */
+ 
+   for (last_parm_reg = 10;
+        last_parm_reg > 2 && ! regs_ever_live [last_parm_reg];
+        last_parm_reg--)
+     ;
+ 
+   /* Save parameter registers in regs RS6000_LAST_REG-(no. of parm
+      regs used)+1 through RS6000_LAST_REG.  Don't overwrite reg 31,
+      since it might be set up as the frame pointer.  */
+   for (i = 3, j = RS6000_LAST_REG; i <= last_parm_reg; i++, j--)
+     fprintf (file, "\tmr %s,%s\n", reg_names[j], reg_names[i]);
+ 
+   /* Load location address into r3, and call mcount.  */
+   if (flag_pic)
+     {
+       if (current_function_uses_pic_offset_table) 
+       fprintf (file, "\tmr r3,r0\n");
+       else
+       fprintf (file, "\tmflr r3\n");
+  
+       fprintf (file, "\tbl Lmcount$stub\n");
+       /* Tell generic Darwin code to write a stub for mcount.  */
+       mcount_called = 1;
+     }
+   else
+     {
+       fprintf (file, "\tmflr r3\n");
+       fprintf (file, "\tbl mcount\n");
+     }
+ 
+   /* Restore parameter registers.  */
+   for (i = 3, j = RS6000_LAST_REG; i <= last_parm_reg; i++, j--)
+     fprintf (file, "\tmr %s,%s\n", reg_names[i], reg_names[j]);
+ }
+ 
+ /* 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: config/rs6000/rs6000.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.h,v
retrieving revision 1.107
diff -c -3 -p -r1.107 rs6000.h
*** rs6000.h    2001/03/28 12:22:48     1.107
--- rs6000.h    2001/04/06 19:44:11
*************** Boston, MA 02111-1307, USA.  */
*** 30,39 ****
--- 30,41 ----
  #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 ;
*************** extern int rs6000_debug_arg;            /* debug a
*** 861,866 ****
--- 863,872 ----
        && 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.
*************** enum rs6000_abi {
*** 1159,1165 ****
    ABI_AIX,                    /* IBM's AIX */
    ABI_AIX_NODESC,             /* AIX calling sequence minus function descriptors */
    ABI_V4,                     /* System V.4/eabi */
!   ABI_SOLARIS                 /* Solaris */
  };
  
  extern enum rs6000_abi rs6000_current_abi;    /* available for use by subtarget */
--- 1165,1172 ----
    ABI_AIX,                    /* IBM's AIX */
    ABI_AIX_NODESC,             /* AIX calling sequence minus function descriptors */
    ABI_V4,                     /* System V.4/eabi */
!   ABI_SOLARIS,                        /* Solaris */
!   ABI_DARWIN                  /* Apple's Darwin (OS X kernel) */
  };
  
  extern enum rs6000_abi rs6000_current_abi;    /* available for use by subtarget */
*************** typedef struct rs6000_stack {
*** 1210,1222 ****
  
  /* Size of the outgoing register save area */
  #define RS6000_REG_SAVE ((DEFAULT_ABI == ABI_AIX                      \
!                         || DEFAULT_ABI == ABI_AIX_NODESC)             \
                         ? (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)       \
     << (TARGET_64BIT ? 1 : 0))
  
  /* MEM representing address to save the TOC register */
--- 1217,1230 ----
  
  /* Size of the outgoing register save area */
  #define RS6000_REG_SAVE ((DEFAULT_ABI == ABI_AIX                      \
!                         || 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 || DEFAULT_ABI == ABI_DARWIN) ?
24 : 8) \
     << (TARGET_64BIT ? 1 : 0))
  
  /* MEM representing address to save the TOC register */
*************** typedef struct rs6000_stack {
*** 1351,1357 ****
  #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)              \
                        ? FP_ARG_AIX_MAX_REG : FP_ARG_V4_MAX_REG)
  #define FP_ARG_NUM_REG (FP_ARG_MAX_REG - FP_ARG_MIN_REG + 1)
  
--- 1359,1366 ----
  #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_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)
  
*************** typedef struct rs6000_args
*** 1645,1650 ****
--- 1654,1660 ----
     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: config/rs6000/rs6000.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.md,v
retrieving revision 1.111
diff -c -3 -p -r1.111 rs6000.md
*** rs6000.md   2001/03/28 12:22:48     1.111
--- rs6000.md   2001/04/06 19:44:14
***************
*** 1449,1454 ****
--- 1449,1462 ----
     {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")
***************
*** 7347,7352 ****
--- 7355,7376 ----
      {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"
***************
*** 7406,7411 ****
--- 7430,7444 ----
    ""
    "{ 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"))]
*************** operands[2] = GEN_INT (INTVAL (operands[
*** 9257,9262 ****
--- 9290,9310 ----
    "{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.
*************** operands[2] = GEN_INT (INTVAL (operands[
*** 9376,9381 ****
--- 9424,9434 ----
    ""
    "
  {
+ #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 ();
  
*************** operands[2] = GEN_INT (INTVAL (operands[
*** 9389,9394 ****
--- 9442,9448 ----
  
        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]);
  
*************** operands[2] = GEN_INT (INTVAL (operands[
*** 9419,9424 ****
--- 9473,9483 ----
    ""
    "
  {
+ #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 ();
  
*************** operands[2] = GEN_INT (INTVAL (operands[
*** 9432,9437 ****
--- 9491,9497 ----
  
        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]);
  
*************** operands[2] = GEN_INT (INTVAL (operands[
*** 9664,9669 ****
--- 9724,9730 ----
     (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"
    "*
  {
*************** operands[2] = GEN_INT (INTVAL (operands[
*** 9696,9701 ****
--- 9757,9763 ----
     (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"
    "*
  {
Index: config/rs6000/t-darwin
===================================================================
RCS file: t-darwin
diff -N t-darwin
*** /dev/null   Tue May  5 13:32:27 1998
--- t-darwin    Fri Apr  6 12:44:14 2001
***************
*** 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: ginclude/stddef.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/ginclude/stddef.h,v
retrieving revision 1.10
diff -c -3 -p -r1.10 stddef.h
*** stddef.h    2000/08/04 16:00:48     1.10
--- stddef.h    2001/04/06 19:44:15
*************** typedef long ssize_t;
*** 234,239 ****
--- 234,240 ----
  #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
*************** typedef _BSD_RUNE_T_ rune_t;
*** 285,290 ****
--- 286,292 ----
  #endif
  #ifndef __cplusplus
  typedef __WCHAR_TYPE__ wchar_t;
+ #endif
  #endif
  #endif
  #endif


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]