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