Commit ee890fe2 by Stan Shebs Committed by Stan Shebs

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_.

From-SVN: r41277
parent 5101b304
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> 2001-04-11 Mark Mitchell <mark@codesourcery.com>
* dwarf2out.c (modified_type_die): Don't create new types here. * dwarf2out.c (modified_type_die): Don't create new types here.
......
...@@ -2647,8 +2647,15 @@ powerpc-*-beos*) ...@@ -2647,8 +2647,15 @@ powerpc-*-beos*)
tmake_file=rs6000/t-beos tmake_file=rs6000/t-beos
;; ;;
powerpc-*-darwin*) 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 xm_file=rs6000/xm-darwin.h
xmake_file=rs6000/x-darwin xmake_file=rs6000/x-darwin
extra_objs="darwin.o"
# Darwin linker does collect2 functionality
use_collect2=no
;; ;;
powerpc-*-sysv*) powerpc-*-sysv*)
tm_file="${tm_file} svr4.h rs6000/sysv4.h" tm_file="${tm_file} svr4.h rs6000/sysv4.h"
......
/* 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 *));
/* 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;
}
/* 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)
/* 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
...@@ -108,8 +108,12 @@ extern void rs6000_emit_eh_toc_restore PARAMS ((rtx)); ...@@ -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 void rs6000_emit_move PARAMS ((rtx, rtx, enum machine_mode));
extern rtx rs6000_legitimize_address 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 void rs6000_select_rtx_section PARAMS ((enum machine_mode, rtx));
extern rtx rs6000_return_addr PARAMS ((int, rtx)); extern rtx rs6000_return_addr PARAMS ((int, rtx));
extern void rs6000_output_symbol_ref PARAMS ((FILE*, 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 */ #endif /* RTX_CODE */
#ifdef TREE_CODE #ifdef TREE_CODE
...@@ -139,6 +143,7 @@ extern void rs6000_unique_section PARAMS ((tree, int)); ...@@ -139,6 +143,7 @@ extern void rs6000_unique_section PARAMS ((tree, int));
/* expr.h defines ARGS_SIZE_RTX and `enum direction' */ /* expr.h defines ARGS_SIZE_RTX and `enum direction' */
extern enum direction function_arg_padding PARAMS ((enum machine_mode, tree)); extern enum direction function_arg_padding PARAMS ((enum machine_mode, tree));
#endif /* ARGS_SIZE_RTX */ #endif /* ARGS_SIZE_RTX */
#endif /* TREE_CODE */ #endif /* TREE_CODE */
extern void optimization_options PARAMS ((int, int)); extern void optimization_options PARAMS ((int, int));
...@@ -172,3 +177,5 @@ extern void rs6000_emit_load_toc_table PARAMS ((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_aix_emit_builtin_unwind_init PARAMS ((void));
extern void rs6000_emit_epilogue PARAMS ((int)); extern void rs6000_emit_epilogue PARAMS ((int));
extern void debug_stack_info PARAMS ((rs6000_stack_t *)); extern void debug_stack_info PARAMS ((rs6000_stack_t *));
extern void machopic_output_stub PARAMS ((FILE *, const char *, const char *));
...@@ -1526,6 +1526,19 @@ rs6000_legitimize_address (x, oldx, mode) ...@@ -1526,6 +1526,19 @@ rs6000_legitimize_address (x, oldx, mode)
emit_insn (gen_elf_high (reg, (x))); emit_insn (gen_elf_high (reg, (x)));
return gen_rtx_LO_SUM (Pmode, 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 else if (TARGET_TOC
&& CONSTANT_POOL_EXPR_P (x) && CONSTANT_POOL_EXPR_P (x)
&& ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (x), Pmode)) && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (x), Pmode))
...@@ -1644,7 +1657,8 @@ rs6000_emit_move (dest, source, mode) ...@@ -1644,7 +1657,8 @@ rs6000_emit_move (dest, source, mode)
return; return;
} }
if (TARGET_ELF && TARGET_NO_TOC && ! flag_pic if ((TARGET_ELF || DEFAULT_ABI == ABI_DARWIN)
&& TARGET_NO_TOC && ! flag_pic
&& mode == Pmode && mode == Pmode
&& CONSTANT_P (operands[1]) && CONSTANT_P (operands[1])
&& GET_CODE (operands[1]) != HIGH && GET_CODE (operands[1]) != HIGH
...@@ -1670,6 +1684,13 @@ rs6000_emit_move (dest, source, mode) ...@@ -1670,6 +1684,13 @@ rs6000_emit_move (dest, source, mode)
operands[1] = new_ref; 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_high (target, operands[1]));
emit_insn (gen_elf_low (operands[0], target, operands[1])); emit_insn (gen_elf_low (operands[0], target, operands[1]));
return; return;
...@@ -1708,6 +1729,21 @@ rs6000_emit_move (dest, source, mode) ...@@ -1708,6 +1729,21 @@ rs6000_emit_move (dest, source, mode)
if (GET_CODE (operands[1]) != LABEL_REF) if (GET_CODE (operands[1]) != LABEL_REF)
emit_insn (gen_rtx_USE (VOIDmode, operands[1])); 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 /* 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, 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 just put the symbol in the TOC and add the constant. Don't do
...@@ -4296,6 +4332,7 @@ print_operand (file, x, code) ...@@ -4296,6 +4332,7 @@ print_operand (file, x, code)
case ABI_V4: case ABI_V4:
case ABI_AIX_NODESC: case ABI_AIX_NODESC:
case ABI_SOLARIS: case ABI_SOLARIS:
case ABI_DARWIN:
break; break;
} }
} }
...@@ -4655,8 +4692,10 @@ first_reg_to_save () ...@@ -4655,8 +4692,10 @@ first_reg_to_save ()
if (regs_ever_live[first_reg] if (regs_ever_live[first_reg]
&& (! call_used_regs[first_reg] && (! call_used_regs[first_reg]
|| (first_reg == PIC_OFFSET_TABLE_REGNUM || (first_reg == PIC_OFFSET_TABLE_REGNUM
&& (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS) && (((DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS)
&& flag_pic == 1))) && flag_pic == 1)
|| (DEFAULT_ABI == ABI_DARWIN
&& flag_pic)))))
break; break;
if (profile_flag) if (profile_flag)
...@@ -4665,7 +4704,7 @@ first_reg_to_save () ...@@ -4665,7 +4704,7 @@ first_reg_to_save ()
before/after the .__mcount call plus an additional register before/after the .__mcount call plus an additional register
for the static chain, if needed; use registers from 30 down to 22 for the static chain, if needed; use registers from 30 down to 22
to do this. */ to do this. */
if (DEFAULT_ABI == ABI_AIX) if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN)
{ {
int last_parm_reg, profile_first_reg; int last_parm_reg, profile_first_reg;
...@@ -4683,6 +4722,12 @@ first_reg_to_save () ...@@ -4683,6 +4722,12 @@ first_reg_to_save ()
Skip reg 31 which may contain the frame pointer. */ Skip reg 31 which may contain the frame pointer. */
profile_first_reg = (33 - last_parm_reg profile_first_reg = (33 - last_parm_reg
- (current_function_needs_context ? 1 : 0)); - (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. */ /* Do not save frame pointer if no parameters needs to be saved. */
if (profile_first_reg == 31) if (profile_first_reg == 31)
profile_first_reg = 32; profile_first_reg = 32;
...@@ -4700,6 +4745,12 @@ first_reg_to_save () ...@@ -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; return first_reg;
} }
...@@ -4722,7 +4773,7 @@ first_fp_reg_to_save () ...@@ -4722,7 +4773,7 @@ first_fp_reg_to_save ()
complicated by having two separate calling sequences, the AIX calling complicated by having two separate calling sequences, the AIX calling
sequence and the V.4 calling sequence. 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 32-bit 64-bit
SP----> +---------------------------------------+ SP----> +---------------------------------------+
| back chain to caller | 0 0 | back chain to caller | 0 0
...@@ -4821,8 +4872,10 @@ rs6000_stack_info () ...@@ -4821,8 +4872,10 @@ rs6000_stack_info ()
info_ptr->first_gp_reg_save = first_reg_to_save (); info_ptr->first_gp_reg_save = first_reg_to_save ();
/* Assume that we will have to save PIC_OFFSET_TABLE_REGNUM, /* Assume that we will have to save PIC_OFFSET_TABLE_REGNUM,
even if it currently looks like we won't. */ even if it currently looks like we won't. */
if (flag_pic == 1 if (((flag_pic == 1
&& (abi == ABI_V4 || abi == ABI_SOLARIS) && (abi == ABI_V4 || abi == ABI_SOLARIS))
|| (flag_pic &&
abi == ABI_DARWIN))
&& info_ptr->first_gp_reg_save > PIC_OFFSET_TABLE_REGNUM) && info_ptr->first_gp_reg_save > PIC_OFFSET_TABLE_REGNUM)
info_ptr->gp_size = reg_size * (32 - PIC_OFFSET_TABLE_REGNUM); info_ptr->gp_size = reg_size * (32 - PIC_OFFSET_TABLE_REGNUM);
else else
...@@ -4845,6 +4898,7 @@ rs6000_stack_info () ...@@ -4845,6 +4898,7 @@ rs6000_stack_info ()
&& !FP_SAVE_INLINE (info_ptr->first_fp_reg_save)) && !FP_SAVE_INLINE (info_ptr->first_fp_reg_save))
|| (abi == ABI_V4 && current_function_calls_alloca) || (abi == ABI_V4 && current_function_calls_alloca)
|| (abi == ABI_SOLARIS && 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->calls_p)
{ {
info_ptr->lr_save_p = 1; info_ptr->lr_save_p = 1;
...@@ -4886,6 +4940,8 @@ rs6000_stack_info () ...@@ -4886,6 +4940,8 @@ rs6000_stack_info ()
+ info_ptr->cr_size + info_ptr->cr_size
+ info_ptr->lr_size + info_ptr->lr_size
+ info_ptr->toc_size, 8); + info_ptr->toc_size, 8);
if (DEFAULT_ABI == ABI_DARWIN)
info_ptr->save_size = RS6000_ALIGN (info_ptr->save_size, 16);
/* Calculate the offsets */ /* Calculate the offsets */
switch (abi) switch (abi)
...@@ -4896,6 +4952,7 @@ rs6000_stack_info () ...@@ -4896,6 +4952,7 @@ rs6000_stack_info ()
case ABI_AIX: case ABI_AIX:
case ABI_AIX_NODESC: case ABI_AIX_NODESC:
case ABI_DARWIN:
info_ptr->fp_save_offset = - info_ptr->fp_size; 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->gp_save_offset = info_ptr->fp_save_offset - info_ptr->gp_size;
info_ptr->ehrd_offset = info_ptr->gp_save_offset - ehrd_size; info_ptr->ehrd_offset = info_ptr->gp_save_offset - ehrd_size;
...@@ -4942,7 +4999,7 @@ rs6000_stack_info () ...@@ -4942,7 +4999,7 @@ rs6000_stack_info ()
else else
info_ptr->push_p = (frame_pointer_needed 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) || ((total_raw_size - info_ptr->fixed_size)
> (TARGET_32BIT ? 220 : 288))); > (TARGET_32BIT ? 220 : 288)));
...@@ -4985,6 +5042,7 @@ debug_stack_info (info) ...@@ -4985,6 +5042,7 @@ debug_stack_info (info)
case ABI_NONE: abi_string = "NONE"; break; case ABI_NONE: abi_string = "NONE"; break;
case ABI_AIX: abi_string = "AIX"; break; case ABI_AIX: abi_string = "AIX"; break;
case ABI_AIX_NODESC: 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_V4: abi_string = "V.4"; break;
case ABI_SOLARIS: abi_string = "Solaris"; break; case ABI_SOLARIS: abi_string = "Solaris"; break;
} }
...@@ -5740,8 +5798,10 @@ rs6000_emit_prologue () ...@@ -5740,8 +5798,10 @@ rs6000_emit_prologue ()
if ((regs_ever_live[info->first_gp_reg_save+i] if ((regs_ever_live[info->first_gp_reg_save+i]
&& ! call_used_regs[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 || (i+info->first_gp_reg_save == PIC_OFFSET_TABLE_REGNUM
&& (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS) && (((DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS)
&& flag_pic == 1)) && flag_pic == 1)
|| (DEFAULT_ABI == ABI_DARWIN
&& flag_pic))))
{ {
rtx addr, reg, mem; rtx addr, reg, mem;
reg = gen_rtx_REG (reg_mode, info->first_gp_reg_save + i); reg = gen_rtx_REG (reg_mode, info->first_gp_reg_save + i);
...@@ -5858,6 +5918,18 @@ rs6000_emit_prologue () ...@@ -5858,6 +5918,18 @@ rs6000_emit_prologue ()
emit_move_insn (gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM), emit_move_insn (gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM),
gen_rtx_REG (Pmode, 11)); 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) ...@@ -6051,8 +6123,10 @@ rs6000_emit_epilogue (sibcall)
if ((regs_ever_live[info->first_gp_reg_save+i] if ((regs_ever_live[info->first_gp_reg_save+i]
&& ! call_used_regs[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 || (i+info->first_gp_reg_save == PIC_OFFSET_TABLE_REGNUM
&& (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS) && (((DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS)
&& flag_pic == 1)) && flag_pic == 1)
|| (DEFAULT_ABI == ABI_DARWIN
&& flag_pic))))
{ {
rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx, rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
GEN_INT (info->gp_save_offset GEN_INT (info->gp_save_offset
...@@ -6626,6 +6700,17 @@ output_mi_thunk (file, thunk_fndecl, delta, function) ...@@ -6626,6 +6700,17 @@ output_mi_thunk (file, thunk_fndecl, delta, function)
if (flag_pic) fputs ("@plt", file); if (flag_pic) fputs ("@plt", file);
putc ('\n', file); putc ('\n', file);
break; 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) ...@@ -7226,6 +7311,28 @@ output_profile_hook (labelno)
emit_library_call (init_one_libfunc (RS6000_MCOUNT), 0, VOIDmode, 1, emit_library_call (init_one_libfunc (RS6000_MCOUNT), 0, VOIDmode, 1,
fun, Pmode); 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. */ /* Write function profiler code. */
...@@ -7296,6 +7403,7 @@ output_function_profiler (file, labelno) ...@@ -7296,6 +7403,7 @@ output_function_profiler (file, labelno)
break; break;
case ABI_AIX: case ABI_AIX:
case ABI_DARWIN:
/* Don't do anything, done in output_profile_hook (). */ /* Don't do anything, done in output_profile_hook (). */
break; break;
...@@ -7834,4 +7942,325 @@ rs6000_add_gc_roots () ...@@ -7834,4 +7942,325 @@ rs6000_add_gc_roots ()
toc_hash_table = htab_create (1021, toc_hash_function, toc_hash_eq, NULL); toc_hash_table = htab_create (1021, toc_hash_function, toc_hash_eq, NULL);
ggc_add_root (&toc_hash_table, 1, sizeof (toc_hash_table), ggc_add_root (&toc_hash_table, 1, sizeof (toc_hash_table),
toc_hash_mark_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 */
...@@ -30,10 +30,12 @@ Boston, MA 02111-1307, USA. */ ...@@ -30,10 +30,12 @@ Boston, MA 02111-1307, USA. */
#define OBJECT_XCOFF 1 #define OBJECT_XCOFF 1
#define OBJECT_ELF 2 #define OBJECT_ELF 2
#define OBJECT_PEF 3 #define OBJECT_PEF 3
#define OBJECT_MACHO 4
#define TARGET_ELF (TARGET_OBJECT_FORMAT == OBJECT_ELF) #define TARGET_ELF (TARGET_OBJECT_FORMAT == OBJECT_ELF)
#define TARGET_AIX (TARGET_OBJECT_FORMAT == OBJECT_XCOFF) #define TARGET_AIX (TARGET_OBJECT_FORMAT == OBJECT_XCOFF)
#define TARGET_MACOS (TARGET_OBJECT_FORMAT == OBJECT_PEF) #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. */ /* Print subsidiary information on the compiler version in use. */
#define TARGET_VERSION ; #define TARGET_VERSION ;
...@@ -861,6 +863,10 @@ extern int rs6000_debug_arg; /* debug argument handling */ ...@@ -861,6 +863,10 @@ extern int rs6000_debug_arg; /* debug argument handling */
&& flag_pic == 1) \ && flag_pic == 1) \
fixed_regs[PIC_OFFSET_TABLE_REGNUM] \ fixed_regs[PIC_OFFSET_TABLE_REGNUM] \
= call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1; \ = 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. /* Specify the registers used for certain standard purposes.
...@@ -1159,7 +1165,8 @@ enum rs6000_abi { ...@@ -1159,7 +1165,8 @@ enum rs6000_abi {
ABI_AIX, /* IBM's AIX */ ABI_AIX, /* IBM's AIX */
ABI_AIX_NODESC, /* AIX calling sequence minus function descriptors */ ABI_AIX_NODESC, /* AIX calling sequence minus function descriptors */
ABI_V4, /* System V.4/eabi */ 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 */ extern enum rs6000_abi rs6000_current_abi; /* available for use by subtarget */
...@@ -1210,13 +1217,14 @@ typedef struct rs6000_stack { ...@@ -1210,13 +1217,14 @@ typedef struct rs6000_stack {
/* Size of the outgoing register save area */ /* Size of the outgoing register save area */
#define RS6000_REG_SAVE ((DEFAULT_ABI == ABI_AIX \ #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) \ ? (TARGET_64BIT ? 64 : 32) \
: 0) : 0)
/* Size of the fixed area on the stack */ /* Size of the fixed area on the stack */
#define RS6000_SAVE_AREA \ #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)) << (TARGET_64BIT ? 1 : 0))
/* MEM representing address to save the TOC register */ /* MEM representing address to save the TOC register */
...@@ -1351,7 +1359,8 @@ typedef struct rs6000_stack { ...@@ -1351,7 +1359,8 @@ typedef struct rs6000_stack {
#define FP_ARG_AIX_MAX_REG 45 #define FP_ARG_AIX_MAX_REG 45
#define FP_ARG_V4_MAX_REG 40 #define FP_ARG_V4_MAX_REG 40
#define FP_ARG_MAX_REG ((DEFAULT_ABI == ABI_AIX \ #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) ? FP_ARG_AIX_MAX_REG : FP_ARG_V4_MAX_REG)
#define FP_ARG_NUM_REG (FP_ARG_MAX_REG - FP_ARG_MIN_REG + 1) #define FP_ARG_NUM_REG (FP_ARG_MAX_REG - FP_ARG_MIN_REG + 1)
...@@ -1645,6 +1654,7 @@ typedef struct rs6000_args ...@@ -1645,6 +1654,7 @@ typedef struct rs6000_args
abi's store the return address. */ abi's store the return address. */
#define RETURN_ADDRESS_OFFSET \ #define RETURN_ADDRESS_OFFSET \
((DEFAULT_ABI == ABI_AIX \ ((DEFAULT_ABI == ABI_AIX \
|| DEFAULT_ABI == ABI_DARWIN \
|| DEFAULT_ABI == ABI_AIX_NODESC) ? (TARGET_32BIT ? 8 : 16) : \ || DEFAULT_ABI == ABI_AIX_NODESC) ? (TARGET_32BIT ? 8 : 16) : \
(DEFAULT_ABI == ABI_V4 \ (DEFAULT_ABI == ABI_V4 \
|| DEFAULT_ABI == ABI_SOLARIS) ? (TARGET_32BIT ? 4 : 8) : \ || DEFAULT_ABI == ABI_SOLARIS) ? (TARGET_32BIT ? 4 : 8) : \
......
...@@ -1449,6 +1449,14 @@ ...@@ -1449,6 +1449,14 @@
{cau|addis} %0,%1,%v2" {cau|addis} %0,%1,%v2"
[(set_attr "length" "4,4,4,4")]) [(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" (define_insn "*addsi3_internal2"
[(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y") [(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") (compare:CC (plus:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r")
...@@ -7347,6 +7355,22 @@ ...@@ -7347,6 +7355,22 @@
{cal|la} %0,%2@l(%1) {cal|la} %0,%2@l(%1)
{ai|addic} %0,%1,%K2") {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 ;; Set up a register with a value from the GOT table
(define_expand "movsi_got" (define_expand "movsi_got"
...@@ -7406,6 +7430,15 @@ ...@@ -7406,6 +7430,15 @@
"" ""
"{ rs6000_emit_move (operands[0], operands[1], SImode); DONE; }") "{ 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" (define_insn "*movsi_internal1"
[(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,m,r,r,r,r,r,*q,*c*l,*h") [(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"))] (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); ...@@ -9257,6 +9290,21 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
"{l|lwz} %0,%2-%3(%1)" "{l|lwz} %0,%2-%3(%1)"
[(set_attr "type" "load")]) [(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 ;; 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 ;; the kinds of PIC that we support, we need to restore the TOC
;; pointer only when jumping over units of translation. ;; pointer only when jumping over units of translation.
...@@ -9376,6 +9424,11 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32); ...@@ -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) if (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != CONST_INT)
abort (); abort ();
...@@ -9389,6 +9442,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32); ...@@ -9389,6 +9442,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
if (DEFAULT_ABI == ABI_V4 if (DEFAULT_ABI == ABI_V4
|| DEFAULT_ABI == ABI_AIX_NODESC || DEFAULT_ABI == ABI_AIX_NODESC
|| DEFAULT_ABI == ABI_DARWIN
|| DEFAULT_ABI == ABI_SOLARIS) || DEFAULT_ABI == ABI_SOLARIS)
operands[0] = force_reg (Pmode, operands[0]); operands[0] = force_reg (Pmode, operands[0]);
...@@ -9419,6 +9473,11 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32); ...@@ -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) if (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != CONST_INT)
abort (); abort ();
...@@ -9432,6 +9491,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32); ...@@ -9432,6 +9491,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
if (DEFAULT_ABI == ABI_V4 if (DEFAULT_ABI == ABI_V4
|| DEFAULT_ABI == ABI_AIX_NODESC || DEFAULT_ABI == ABI_AIX_NODESC
|| DEFAULT_ABI == ABI_DARWIN
|| DEFAULT_ABI == ABI_SOLARIS) || DEFAULT_ABI == ABI_SOLARIS)
operands[0] = force_reg (Pmode, operands[0]); operands[0] = force_reg (Pmode, operands[0]);
...@@ -9664,6 +9724,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32); ...@@ -9664,6 +9724,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
(clobber (match_scratch:SI 3 "=l,l,l,l"))] (clobber (match_scratch:SI 3 "=l,l,l,l"))]
"DEFAULT_ABI == ABI_AIX_NODESC "DEFAULT_ABI == ABI_AIX_NODESC
|| DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_V4
|| DEFAULT_ABI == ABI_DARWIN
|| DEFAULT_ABI == ABI_SOLARIS" || DEFAULT_ABI == ABI_SOLARIS"
"* "*
{ {
...@@ -9696,6 +9757,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32); ...@@ -9696,6 +9757,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
(clobber (match_scratch:SI 4 "=l,l,l,l"))] (clobber (match_scratch:SI 4 "=l,l,l,l"))]
"DEFAULT_ABI == ABI_AIX_NODESC "DEFAULT_ABI == ABI_AIX_NODESC
|| DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_V4
|| DEFAULT_ABI == ABI_DARWIN
|| DEFAULT_ABI == ABI_SOLARIS" || DEFAULT_ABI == ABI_SOLARIS"
"* "*
{ {
......
# 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
...@@ -234,6 +234,7 @@ typedef long ssize_t; ...@@ -234,6 +234,7 @@ typedef long ssize_t;
#ifndef __WCHAR_T #ifndef __WCHAR_T
#ifndef _WCHAR_T_ #ifndef _WCHAR_T_
#ifndef _BSD_WCHAR_T_ #ifndef _BSD_WCHAR_T_
#ifndef _BSD_WCHAR_T_DEFINED_ /* Darwin */
#ifndef _WCHAR_T_DEFINED_ #ifndef _WCHAR_T_DEFINED_
#ifndef _WCHAR_T_DEFINED #ifndef _WCHAR_T_DEFINED
#ifndef _WCHAR_T_H #ifndef _WCHAR_T_H
...@@ -298,6 +299,7 @@ typedef __WCHAR_TYPE__ wchar_t; ...@@ -298,6 +299,7 @@ typedef __WCHAR_TYPE__ wchar_t;
#endif #endif
#endif #endif
#endif #endif
#endif
#endif /* __wchar_t__ */ #endif /* __wchar_t__ */
#undef __need_wchar_t #undef __need_wchar_t
#endif /* _STDDEF_H or __need_wchar_t. */ #endif /* _STDDEF_H or __need_wchar_t. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment