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


This patch is the basic native support for Darwin, which is the
kernel of Mac OS X.  The patch is somewhat complicated, because
Darwin is a BSD variant built on top of Mach, with a goodly dose
of inherited NeXTisms as well.  In particular, it has a unique
architecture-independent (well, mostly :-) ) PIC strategy, mainly
implemented in the files config/darwin.[ch].

With this patch (plus an assembler tweak), mainline CVS GCC will
bootstrap, and pass nearly all of the tests that work for PowerPC
Linux.  This suffices to compile random Unix programs, but GUI code
using Apple's Cocoa or Carbon APIs will require some GCC extensions
that we expect to submit once basic support is working.

Although the patch is large, it's already been stripped down to the
minimum that still works, there are only a couple changes to generic
code (a new macro in varasm.c), and the generic rs6000.* changes are
all conditionalized in the usual ways.  To borrow a quote from
Judge Jackson :-), "I'm sure the court can find fault with every
part of my work product", but I'm willing to rewrite anything
as necessary to make it satisfactory.

Also, I don't want to pressure anybody (much :-) ), but the worldwide
OS X 1.0 release is about three weeks away, and even though Apple
makes its own version of GCC freely available, we know from experience
that people will be downloading the latest GCC and trying to build
on their new systems.  It will save wading through a bunch of mail to
get this code in sooner rather than later, and so I'd like to hear if
this patch is OK to check in.  Again, I'm completely available to
resolve any difficulties.

Stan

2001-03-01  Stan Shebs  <shebs@apple.com>

        Add Darwin (Mac OS X kernel) native support.
        * config.gcc (powerpc-*-darwin*): Add native bits.
        * varasm.c (assemble_variable): Use new macro
        ASM_DECLARE_ALL_OBJECT_NAME.
        * 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.
        (apple_output_ascii): New function.
        (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.
        (finalize_pic): 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.

        * f/com.c (lookup_name): New function, clone of C version
        for use by Darwin.

        * ginclude/stddef.h: Test _BSD_WCHAR_T_DEFINED_.


Index: gcc/config.gcc
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config.gcc,v
retrieving revision 1.32
diff -c -3 -p -r1.32 config.gcc
*** config.gcc	2001/02/26 18:15:36	1.32
--- config.gcc	2001/03/01 21:54:29
*************** powerpc-*-beos*)
*** 2689,2696 ****
--- 2689,2703 ----
  	xmake_file=rs6000/x-beos
  	;;
  powerpc-*-darwin*)
+ 	cpu_type=rs6000
+ 	tm_file=rs6000/darwin.h
+ 	tm_p_file="rs6000/rs6000-protos.h darwin-protos.h"
  	xm_file="rs6000/xm-rs6000.h rs6000/xm-darwin.h"
+ 	tmake_file=rs6000/t-darwin
  	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: gcc/varasm.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/varasm.c,v
retrieving revision 1.162
diff -c -3 -p -r1.162 varasm.c
*** varasm.c	2001/02/23 20:28:58	1.162
--- varasm.c	2001/03/01 21:54:31
*************** assemble_variable (decl, top_level, at_e
*** 1336,1341 ****
--- 1336,1345 ----
        first_global_object_name = xname;
      }
  
+ #ifdef ASM_DECLARE_ALL_OBJECT_NAME
+   ASM_DECLARE_ALL_OBJECT_NAME (asm_out_file, name, decl);
+ #endif /* ASM_DECLARE_OBJECT_NAME */
+ 
    /* Compute the alignment of this data.  */
  
    align = DECL_ALIGN (decl);
Index: gcc/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	Thu Mar  1 13:54:31 2001
***************
*** 0 ****
--- 1,61 ----
+ /* Prototypes for Darwin support functions.
+    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 int const_double_used PARAMS ((void));
+ 
+ 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: gcc/config/darwin.c
===================================================================
RCS file: darwin.c
diff -N darwin.c
*** /dev/null	Tue May  5 13:32:27 1998
--- darwin.c	Thu Mar  1 13:54:31 2001
***************
*** 0 ****
--- 1,989 ----
+ /* 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"
+ #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;
+ }
+ 
+ /* Go through all the insns looking for a double constant.  Return nonzero
+    if one is found.  */
+ 
+ int
+ const_double_used ()
+ {
+   rtx insn;
+ 
+   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+     {
+       enum rtx_code code;
+       rtx set = single_set (insn);
+ 
+       if (set)
+ 	if ((code = GET_CODE (SET_SRC (set))) == CONST_DOUBLE)
+ 	  return 1;
+     }
+   return 0;
+ }
+ 
+ /* flag_pic = 1 ... generate only indirections
+    flag_pic = 2 ... generate indirections and pure code
+    */
+ 
+ int mcount_called = 0;		/* was mcount called at any point?  */
+ 
+ static tree machopic_defined_list = 0;
+ 
+ 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 (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));
+ }
+ 
+ /* 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 (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 (!TREE_USED (temp))
+ 	continue;
+ 
+       if (machopic_ident_defined_p (TREE_VALUE (temp)))
+ 	{
+ 	  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;
+ 
+   return 0;
+ }
Index: gcc/config/darwin.h
===================================================================
RCS file: darwin.h
diff -N darwin.h
*** /dev/null	Tue May  5 13:32:27 1998
--- darwin.h	Thu Mar  1 13:54:31 2001
***************
*** 0 ****
--- 1,855 ----
+ /* 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
+ 
+ /* 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
+ 
+ /* 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
+ 
+ /* These compiler options take n arguments.  */
+ 
+ #undef	WORD_SWITCH_TAKES_ARG
+ #define WORD_SWITCH_TAKES_ARG(STR)	 	\
+   (DEFAULT_WORD_SWITCH_TAKES_ARG (STR) ? 1 :	\
+    !strcmp (STR, "read_only_relocs") ? 1 :	\
+    !strcmp (STR, "segalign") ? 1 :		\
+    !strcmp (STR, "seg1addr") ? 1 :		\
+    !strcmp (STR, "undefined") ? 1 :		\
+    !strcmp (STR, "dylib_file") ? 1 :		\
+    !strcmp (STR, "segaddr") ? 2 :		\
+    !strcmp (STR, "sectobjectsymbols") ? 2 :	\
+    !strcmp (STR, "segprot") ? 3 :		\
+    !strcmp (STR, "sectcreate") ? 3 :		\
+    !strcmp (STR, "sectalign") ? 3 :		\
+    !strcmp (STR, "segcreate") ? 3 :		\
+    !strcmp (STR, "sectorder") ? 3 :		\
+    !strcmp (STR, "siff-mask") ? 1 :		\
+    !strcmp (STR, "siff-filter") ? 1 :		\
+    !strcmp (STR, "siff-warning") ? 1 :		\
+    !strcmp (STR, "arch") ? 1 :			\
+    !strcmp (STR, "pagezero_size") ? 1 :		\
+    !strcmp (STR, "dylinker_install_name") ? 1 :	\
+    !strcmp (STR, "framework") ? 1 :		\
+    !strcmp (STR, "filelist") ? 1 :		\
+    !strcmp (STR, "image_base") ? 1 :		\
+    !strcmp (STR, "install_name") ? 1 :		\
+    !strcmp (STR, "arch_only") ? 1 :		\
+    !strcmp (STR, "compatibility_version") ? 1 :	\
+    !strcmp (STR, "current_version") ? 1 :	\
+    0)
+ 
+ #undef	WORD_SWITCH
+ #define WORD_SWITCH(STR)			\
+   (WORD_SWITCH_TAKES_ARG (STR)			\
+    || !strcmp (STR, "object")			\
+    || !strcmp (STR, "ObjC")			\
+    || !strcmp (STR, "dylinker")			\
+    || !strcmp (STR, "dynamic")			\
+    || !strcmp (STR, "static")			\
+    || !strcmp (STR, "bundle")			\
+    || !strcmp (STR, "dynamiclib")		\
+    || !strcmp (STR, "output_for_dyld")		\
+    || !strcmp (STR, "keep_private_externs")	\
+    || !strcmp (STR, "all_load"))
+ 
+ /* Machine dependent cpp options.  */
+ 
+ #undef	CPP_SPEC
+ #define CPP_SPEC "%{!traditional: -D__STDC__}			\
+     		  %{mdisable-fpregs:-D__NO_FP__}		\
+ 		  %{F*}	%{ansi} %{fno-asm} %{header-mapfile}	\
+ 		  -D__APPLE_CC__=" STRINGIFY(APPLE_CC) "	\
+ 		  %{static:-D__STATIC__}%{!static:-D__DYNAMIC__}\
+                   %{MD:-MD %M} %{MMD:-MMD %M}"
+ 
+ #define LINK_COMMAND_SPEC \
+ "%{!fsyntax-only: \
+    %{!c:%{!M:%{!MM:%{!E:%{!precomp:%{!S: \
+       %{dynamiclib:/usr/bin/libtool -arch_only ppc %{!all_load:-noall_load} %J \
+ 		%{current_version:}%{compatibility_version:}%{init*}} \
+      %{!dynamiclib:/usr/bin/ld -arch ppc %{@:-arch_multiple}} \
+ 		%{arch_errors_fatal} %l %X %{force_cpusubtype_ALL}\
+ 		%{@:-o %f%g-ppc.out}%{!@:%{o}%{!o:%{dynamiclib:-o a.out}}} \
+ 		%{static}%{!static:-dynamic} \
+ 		%{bundle:-bundle %{!dynamiclib:%{image_base}}} \
+ 		%{A} %{d} %{e*} %{m} %{N} %{n} %{p} \
+ 		%{r} %{s} %{Si}%{Sn} %{T*} %{t} %{u*} %{X} %{x} %{z} %{y*} \
+ 		%{!A:%{!nostdlib:%{!nostartfiles:%S}}} \
+ 		%{L*} %o %{!nostdlib:%G %L %{!A:%E}} \
+ 		%{.C:\\| /usr/bin/c++filt}%{.M:\\| /usr/bin/c++filt} \
+ 		%{.cc:\\| /usr/bin/c++filt} \
+ 		%{!.C:%{!.M:%{!.cc:%{ObjC++:\\| /usr/bin/c++filt}}}}}}}}}}}"
+ 
+ /* Machine dependent ld options.  */
+ 
+ #undef	LINK_SPEC
+ #define LINK_SPEC "%{Z} %{M} %{F*} \
+ %{execute*} %{preload*} %{fvmlib*} \
+ %{segalign*} %{seg1addr*} %{segaddr*} %{segprot*} \
+ %{pagezero_size*} %{undefined*} %{dylib_file*} \
+ %{umbrella*} %{segs_read_*} %{seg_addr_table*} \
+ %{seglinkedit*} %{noseglinkedit*} %{read_only_relocs} \
+ %{sectcreate*} %{sectalign*} %{sectobjectsymbols}\
+ %{segcreate*} %{Mach*} %{whyload} %{w} \
+ %{sectorder*} %{whatsloaded} %{ObjC} %{all_load} %{object} \
+ %{dylinker} %{dylinker_install_name*} %{output_for_dyld} \
+ %{keep_private_externs} %{prebind} %{noprebind}"
+ 
+ /* 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:%{!dynamiclib:-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  \
+ "%{!dynamiclib:%{bundle:%{!static:-lbundle1.o}} \
+    %{!bundle:%{pg:%{static:-lgcrt0.o} \
+ 		  %{!static:%{object:-lgcrt0.o} \
+ 			    %{!object:%{preload:-lgcrt0.o} \
+ 				      %{!preload:-lgcrt1.o}}}} \
+ 	    %{!pg:%{static:-lcrt0.o} \
+ 		  %{!static:%{object:-lcrt0.o} \
+ 			    %{!object:%{preload:-lcrt0.o} \
+ 				      %{!preload:-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.  */
+ 
+ #undef	SDB_DEBUGGING_INFO
+ #undef	XCOFF_DEBUGGING_INFO
+ #define DBX_DEBUGGING_INFO
+ 
+ /* This saves a fair amount of space. */
+ 
+ #undef	DBX_CONTIN_LENGTH
+ #define DBX_CONTIN_LENGTH 0
+ 
+ /* These come from bsd386.h, but are specific to sequent, so make sure
+    they don't bite us.  */
+ 
+ #undef	DBX_NO_XREFS
+ #undef	DBX_CONTIN_LENGTH
+ 
+ /* 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)
+ 
+ /* 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
+ 
+ #define ASM_OUTPUT_ZEROFILL(FILE, NAME, SIZE, ALIGNMENT)  	\
+ do { fputs (".zerofill __DATA, __common, ", (FILE));		\
+         assemble_name ((FILE), (NAME));				\
+         fprintf ((FILE), ", %u, %u\n", (SIZE), (ALIGNMENT)); 	\
+ 	in_section = no_section;				\
+       } while (0)
+ 
+ #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));                    \
+     ASM_OUTPUT_LABEL (FILE, xname);                                     \
+   } while (0)
+ 
+ #undef ASM_DECLARE_ALL_OBJECT_NAME
+ #define ASM_DECLARE_ALL_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);                                     \
+   } 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_LOCAL
+ #define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGN) \
+ ( fputs (".lcomm ", (FILE)),				\
+   assemble_name ((FILE), (NAME)),			\
+   fprintf ((FILE), ",%u,%u\n", (SIZE), floor_log2 ((ALIGN) / BITS_PER_UNIT)))
+ 
+ /* 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: gcc/config/rs6000/darwin.h
===================================================================
RCS file: darwin.h
diff -N darwin.h
*** /dev/null	Tue May  5 13:32:27 1998
--- darwin.h	Thu Mar  1 13:54:32 2001
***************
*** 0 ****
--- 1,198 ----
+ /* 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
+ 
+ /* As with the ABI, the debug info most resembles what XCOFF uses.  */
+ 
+ #define XCOFF_DEBUGGING_INFO
+ 
+ #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
+ 
+ #include "rs6000/rs6000.h"
+ 
+ /* Bring in generic Darwin definitions.  */
+ /* Important to bring in after rs6000.h, since we want Darwinisms to
+    trump generic PowerPCisms.  */
+ 
+ #include <darwin.h>
+ 
+ #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.  */
+ 
+ #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"
+ 
+ /* Call the generic Mach-O PIC function to dump out the last bits of
+    PIC support code.  */
+ 
+ #define FINALIZE_PIC finalize_pic ()
+ 
+ /* 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: gcc/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/03/01 21:54:32
*************** extern rtx rs6000_legitimize_address PAR
*** 110,115 ****
--- 110,118 ----
  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_emit_load_toc_table P
*** 172,174 ****
--- 175,179 ----
  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: gcc/config/rs6000/rs6000.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.c,v
retrieving revision 1.169
diff -c -3 -p -r1.169 rs6000.c
*** rs6000.c	2001/02/21 01:50:36	1.169
--- rs6000.c	2001/03/01 21:54:34
*************** rs6000_legitimize_address (x, oldx, mode
*** 1515,1521 ****
        return gen_rtx_PLUS (Pmode, XEXP (x, 0),
  			   force_reg (Pmode, force_operand (XEXP (x, 1), 0)));
      }
!   else if (TARGET_ELF && TARGET_32BIT && TARGET_NO_TOC && ! flag_pic
  	   && GET_CODE (x) != CONST_INT
  	   && GET_CODE (x) != CONST_DOUBLE 
  	   && CONSTANT_P (x)
--- 1515,1522 ----
        return gen_rtx_PLUS (Pmode, XEXP (x, 0),
  			   force_reg (Pmode, force_operand (XEXP (x, 1), 0)));
      }
!   else if ((TARGET_ELF || TARGET_MACHO) && TARGET_32BIT && TARGET_NO_TOC
! 	   && ! flag_pic
  	   && GET_CODE (x) != CONST_INT
  	   && GET_CODE (x) != CONST_DOUBLE 
  	   && CONSTANT_P (x)
*************** rs6000_legitimize_address (x, oldx, mode
*** 1527,1532 ****
--- 1528,1546 ----
        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)
*** 1645,1651 ****
  	  return;
  	}
  
!       if (TARGET_ELF && TARGET_NO_TOC && ! flag_pic
  	  && mode == Pmode
  	  && CONSTANT_P (operands[1])
  	  && GET_CODE (operands[1]) != HIGH
--- 1659,1666 ----
  	  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)
*** 1671,1676 ****
--- 1686,1698 ----
  	      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)
*** 1709,1714 ****
--- 1731,1751 ----
  	  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 ****
--- 4333,4339 ----
  	    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)
--- 4693,4702 ----
      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;
  
--- 4705,4711 ----
  	 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 ****
--- 4723,4734 ----
  	     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 ****
--- 4746,4757 ----
  	}
      }
  
+ #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
--- 4774,4780 ----
     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 ()
*** 4820,4827 ****
    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 ()
*** 4844,4849 ****
--- 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 ()
*** 4871,4876 ****
--- 4926,4933 ----
  				  + 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 ()
*** 4881,4886 ****
--- 4938,4944 ----
  
      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->cr_save_offset   = reg_size; /* first word when 64-bit.  */
*************** rs6000_stack_info ()
*** 4925,4931 ****
  
    else
      info_ptr->push_p = (frame_pointer_needed
! 			|| write_symbols != NO_DEBUG
  			|| ((total_raw_size - info_ptr->fixed_size)
  			    > (TARGET_32BIT ? 220 : 288)));
  
--- 4983,4989 ----
  
    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)
*** 4968,4973 ****
--- 5026,5032 ----
      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()
*** 5723,5730 ****
  	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);
--- 5782,5791 ----
  	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()
*** 5816,5821 ****
--- 5877,5894 ----
        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)
*** 5988,5995 ****
        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 
--- 6061,6070 ----
        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
*** 6555,6560 ****
--- 6630,6646 ----
  	  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
  	}
      }
  }
*************** output_function_profiler (file, labelno)
*** 7227,7235 ****
--- 7313,7369 ----
      case ABI_AIX:
        /* Don't do anything, done in output_profile_hook (). */
        break;
+     }
+ }
+ 
+ #if TARGET_MACHO
+ /* Write function profiler code. */
+ 
+ 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");
+       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]);
  }
+ #endif
  
  /* Adjust the cost of a scheduling dependency.  Return the new cost of
     a dependency LINK or INSN on DEP_INSN.  COST is the current cost.  */
*************** rs6000_add_gc_roots ()
*** 7763,7766 ****
--- 7897,8290 ----
    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
+ 
+ void
+ apple_output_ascii (file, p, size)
+      FILE *file;
+      unsigned char *p;
+      int size;
+ {
+   char *opcode = ".ascii";
+   int max = 48;
+   int i;
+ 
+   register int num = 0;
+ 
+   fprintf (file, "\t%s\t \"", opcode);
+   for (i = 0; i < size; i++)
+     {
+       register int c = p[i];
+ 
+       if (num > max)
+ 	{
+ 	  fprintf (file, "\"\n\t%s\t \"", opcode);
+ 	  num = 0;
+ 	}
+ 
+       if (c == '\"' || c == '\\')
+ 	{
+ 	  putc ('\\', file);
+ 	  num++;
+ 	}
+ 
+       if (c >= ' ' && c < 0177)
+ 	{
+ 	  putc (c, file);
+ 	  num++;
+ 	}
+       else
+ 	{
+ 	  fprintf (file, "\\%03o", c);
+ 	  num += 4;
+ 	  /* After an octal-escape, if a digit follows,
+ 	     terminate one string constant and start another.
+ 	     The Vax assembler fails to stop reading the escape
+ 	     after three digits, so this is the only way we
+ 	     can get it to parse the data properly.  */
+ 	  if (i < size - 1 && p[i + 1] >= '0' && p[i + 1] <= '9')
+ 	    num = max + 1;	/* next pass will start a new string */
+ 	}
+     }
+   fprintf (file, "\"\n");
+ }
+ 
+ #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);
  }
+ 
+ /* Emit special PIC prologues and epilogues. */
+ 
+ void
+ finalize_pic ()
+ {
+   rtx picbase_label;
+   rtx seq;
+   int orig_flag_pic = flag_pic;
+   char *piclabel_name;
+ 
+   if (current_function_uses_pic_offset_table == 0)
+     {
+       /* Assume the PIC base register is needed whenever any
+ 	 floating-point constants are present.  Though perhaps a bit
+ 	 pessimistic, this avoids any surprises in cases in which the
+ 	 PIC base register is not needed for any other reason.  */
+       if (flag_pic && const_double_used ())
+ 	current_function_uses_pic_offset_table = 1;
+       else
+ 	return;
+     }
+ 
+   if (! flag_pic)
+     abort ();
+ 
+   flag_pic = 0;
+   picbase_label = gen_label_rtx();
+ 	
+   start_sequence ();
+ 
+   emit_insn (gen_rtx (USE, VOIDmode, pic_offset_table_rtx));
+ 
+   flag_pic = orig_flag_pic;
+ 
+   seq = gen_sequence ();
+   end_sequence ();
+   emit_insn_after (seq, get_insns ());
+ 
+ #if 1 /* Without this statement libgcc2.c can almost be built with insn scheduling enabled; the comment may be inaccurate.  */
+   /* Do this so setjmp/longjmp can't confuse us */
+   emit_insn (gen_rtx (USE, VOIDmode, pic_offset_table_rtx));
+ #endif
+ }
+ 
+ /* 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: gcc/config/rs6000/rs6000.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.h,v
retrieving revision 1.105
diff -c -3 -p -r1.105 rs6000.h
*** rs6000.h	2001/02/08 20:30:16	1.105
--- rs6000.h	2001/03/01 21:54:35
*************** 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 {
*** 1209,1221 ****
  
  /* 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 */
--- 1216,1229 ----
  
  /* 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 {
*** 1350,1356 ****
  #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)
  
--- 1358,1365 ----
  #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
*** 1641,1646 ****
--- 1650,1656 ----
     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: gcc/config/rs6000/rs6000.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.md,v
retrieving revision 1.108
diff -c -3 -p -r1.108 rs6000.md
*** rs6000.md	2000/12/27 11:01:02	1.108
--- rs6000.md	2001/03/01 21:54:38
***************
*** 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: gcc/config/rs6000/t-darwin
===================================================================
RCS file: t-darwin
diff -N t-darwin
*** /dev/null	Tue May  5 13:32:27 1998
--- t-darwin	Thu Mar  1 13:54:38 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: gcc/f/com.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/f/com.c,v
retrieving revision 1.112
diff -c -3 -p -r1.112 com.c
*** com.c	2001/02/25 05:23:33	1.112
--- com.c	2001/03/01 21:54:41
*************** lang_print_error_function (const char *f
*** 14118,14123 ****
--- 14118,14141 ----
  }
  #endif
  
+ /* Look up NAME in the current binding level and its superiors.
+    Return a ..._DECL node of some kind representing its definition,
+    or return 0 if it is undefined.  */
+ 
+ tree
+ lookup_name (name)
+      tree name;
+ {
+   register tree val;
+ 
+   if (current_binding_level != global_binding_level
+       && IDENTIFIER_LOCAL_VALUE (name))
+     val = IDENTIFIER_LOCAL_VALUE (name);
+   else
+     val = IDENTIFIER_GLOBAL_VALUE (name);
+   return val;
+ }
+ 
  /* Similar to `lookup_name' but look only at current binding level.  */
  
  static tree
Index: gcc/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/03/01 21:54:42
*************** 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]