linux.h (TARGET_ASM_FILE_END): Don't define.

* config/rs6000/linux.h (TARGET_ASM_FILE_END): Don't define.
	* config/rs6000/linux64.h (TARGET_ASM_FILE_END): Don't define.
	* config/rs6000/sysv4.h (TARGET_ASM_FILE_END): Define.
	* config/rs6000/rs6000-protos.h (init_cumulative_args): Add fndecl and
	return_mode args.
	* config/rs6000/rs6000.h (CUMULATIVE_ARGS): Add "escapes".
	(INIT_CUMULATIVE_ARGS): Pass FNDECL, VOIDmode.
	(INIT_CUMULATIVE_INCOMING_ARGS): Pass current_function_decl, VOIDmode.
	(INIT_CUMULATIVE_LIBCALL_ARGS): Pass NULL_TREE, MODE.
	* config/rs6000/rs6000.c
	(rs6000_elf_end_indicate_exec_stack): Rename to..
	(rs6000_elf_file_end): ..this.  Only call file_end_indicate_exec_stack
	for POWERPC_LINUX.  Move code emitting .gnu_attribute to here, from..
	(rs6000_file_start): ..here.
	(rs6000_passes_float, rs6000_passes_vector, rs6000_returns_struct): New
	file scope variables.
	(call_ABI_of_interest): New function.
	(init_cumulative_args): Set above vars when function return value
	is a float, vector, or small struct.
	(rs6000_function_arg_advance_1): Likewise for function args.
	(rs6000_va_start): Set rs6000_passes_float if variable arg function
	references float args.

From-SVN: r170734
This commit is contained in:
Alan Modra 2011-03-07 18:20:23 +10:30 committed by Alan Modra
parent fb72848b0c
commit 617718f72d
7 changed files with 158 additions and 32 deletions

View File

@ -1,3 +1,28 @@
2011-03-07 Alan Modra <amodra@gmail.com>
* config/rs6000/linux.h (TARGET_ASM_FILE_END): Don't define.
* config/rs6000/linux64.h (TARGET_ASM_FILE_END): Don't define.
* config/rs6000/sysv4.h (TARGET_ASM_FILE_END): Define.
* config/rs6000/rs6000-protos.h (init_cumulative_args): Add fndecl and
return_mode args.
* config/rs6000/rs6000.h (CUMULATIVE_ARGS): Add "escapes".
(INIT_CUMULATIVE_ARGS): Pass FNDECL, VOIDmode.
(INIT_CUMULATIVE_INCOMING_ARGS): Pass current_function_decl, VOIDmode.
(INIT_CUMULATIVE_LIBCALL_ARGS): Pass NULL_TREE, MODE.
* config/rs6000/rs6000.c
(rs6000_elf_end_indicate_exec_stack): Rename to..
(rs6000_elf_file_end): ..this. Only call file_end_indicate_exec_stack
for POWERPC_LINUX. Move code emitting .gnu_attribute to here, from..
(rs6000_file_start): ..here.
(rs6000_passes_float, rs6000_passes_vector, rs6000_returns_struct): New
file scope variables.
(call_ABI_of_interest): New function.
(init_cumulative_args): Set above vars when function return value
is a float, vector, or small struct.
(rs6000_function_arg_advance_1): Likewise for function args.
(rs6000_va_start): Set rs6000_passes_float if variable arg function
references float args.
2011-03-07 Mingjie Xing <mingjie.xing@gmail.com>
* doc/cfg.texi: Remove "See" before @ref.

View File

@ -1,7 +1,7 @@
/* Definitions of target machine for GNU compiler,
for PowerPC machines running Linux.
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
2004, 2005, 2006, 2007, 2010 Free Software Foundation, Inc.
2004, 2005, 2006, 2007, 2010, 2011 Free Software Foundation, Inc.
Contributed by Michael Meissner (meissner@cygnus.com).
This file is part of GCC.
@ -114,8 +114,6 @@
#define RELOCATABLE_NEEDS_FIXUP \
(target_flags & target_flags_explicit & MASK_RELOCATABLE)
#define TARGET_ASM_FILE_END file_end_indicate_exec_stack
#define TARGET_POSIX_IO
#define MD_UNWIND_SUPPORT "config/rs6000/linux-unwind.h"

View File

@ -537,8 +537,6 @@ extern int dot_symbols;
#undef DRAFT_V4_STRUCT_RET
#define DRAFT_V4_STRUCT_RET (!TARGET_64BIT)
#define TARGET_ASM_FILE_END rs6000_elf_end_indicate_exec_stack
#define TARGET_POSIX_IO
#define LINK_GCC_C_SEQUENCE_SPEC \

View File

@ -28,7 +28,8 @@
#ifdef RTX_CODE
#ifdef TREE_CODE
extern void init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, int, int, int);
extern void init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, int, int, int,
tree, enum machine_mode);
#endif /* TREE_CODE */
extern bool easy_altivec_constant (rtx, enum machine_mode);

View File

@ -184,6 +184,14 @@ unsigned rs6000_pmode;
/* Width in bits of a pointer. */
unsigned rs6000_pointer_size;
#ifdef HAVE_AS_GNU_ATTRIBUTE
/* Flag whether floating point values have been passed/returned. */
static bool rs6000_passes_float;
/* Flag whether vector values have been passed/returned. */
static bool rs6000_passes_vector;
/* Flag whether small (<= 8 byte) structures have been returned. */
static bool rs6000_returns_struct;
#endif
/* Value is TRUE if register/mode pair is acceptable. */
bool rs6000_hard_regno_mode_ok_p[NUM_MACHINE_MODES][FIRST_PSEUDO_REGISTER];
@ -940,7 +948,7 @@ static void rs6000_file_start (void);
static int rs6000_elf_reloc_rw_mask (void);
static void rs6000_elf_asm_out_constructor (rtx, int) ATTRIBUTE_UNUSED;
static void rs6000_elf_asm_out_destructor (rtx, int) ATTRIBUTE_UNUSED;
static void rs6000_elf_end_indicate_exec_stack (void) ATTRIBUTE_UNUSED;
static void rs6000_elf_file_end (void) ATTRIBUTE_UNUSED;
static void rs6000_elf_asm_init_sections (void);
static section *rs6000_elf_select_rtx_section (enum machine_mode, rtx,
unsigned HOST_WIDE_INT);
@ -4695,23 +4703,6 @@ rs6000_file_start (void)
putc ('\n', file);
}
#ifdef HAVE_AS_GNU_ATTRIBUTE
if (TARGET_32BIT && DEFAULT_ABI == ABI_V4)
{
fprintf (file, "\t.gnu_attribute 4, %d\n",
((TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT) ? 1
: (TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT) ? 3
: 2));
fprintf (file, "\t.gnu_attribute 8, %d\n",
(TARGET_ALTIVEC_ABI ? 2
: TARGET_SPE_ABI ? 3
: 1));
fprintf (file, "\t.gnu_attribute 12, %d\n",
aix_struct_return ? 2 : 1);
}
#endif
if (DEFAULT_ABI == ABI_AIX || (TARGET_ELF && flag_pic == 2))
{
switch_to_section (toc_section);
@ -7865,9 +7856,36 @@ rs6000_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
return false;
}
#ifdef HAVE_AS_GNU_ATTRIBUTE
/* Return TRUE if a call to function FNDECL may be one that
potentially affects the function calling ABI of the object file. */
static bool
call_ABI_of_interest (tree fndecl)
{
if (cgraph_state == CGRAPH_STATE_EXPANSION)
{
struct cgraph_node *c_node;
/* Libcalls are always interesting. */
if (fndecl == NULL_TREE)
return true;
/* Any call to an external function is interesting. */
if (DECL_EXTERNAL (fndecl))
return true;
/* Interesting functions that we are emitting in this object file. */
c_node = cgraph_node (fndecl);
return !cgraph_only_called_directly_p (c_node);
}
return false;
}
#endif
/* Initialize a variable CUM of type CUMULATIVE_ARGS
for a call to a function whose data type is FNTYPE.
For a library call, FNTYPE is 0.
For a library call, FNTYPE is 0 and RETURN_MODE the return value mode.
For incoming args we set the number of arguments in the prototype large
so we never return a PARALLEL. */
@ -7875,7 +7893,9 @@ rs6000_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
void
init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype,
rtx libname ATTRIBUTE_UNUSED, int incoming,
int libcall, int n_named_args)
int libcall, int n_named_args,
tree fndecl ATTRIBUTE_UNUSED,
enum machine_mode return_mode ATTRIBUTE_UNUSED)
{
static CUMULATIVE_ARGS zero_cumulative;
@ -7917,6 +7937,45 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype,
cum->prototype, cum->nargs_prototype);
}
#ifdef HAVE_AS_GNU_ATTRIBUTE
if (DEFAULT_ABI == ABI_V4)
{
cum->escapes = call_ABI_of_interest (fndecl);
if (cum->escapes)
{
tree return_type;
if (fntype)
{
return_type = TREE_TYPE (fntype);
return_mode = TYPE_MODE (return_type);
}
else
return_type = lang_hooks.types.type_for_mode (return_mode, 0);
if (return_type != NULL)
{
if (TREE_CODE (return_type) == RECORD_TYPE
&& TYPE_TRANSPARENT_AGGR (return_type))
{
return_type = TREE_TYPE (first_field (return_type));
return_mode = TYPE_MODE (return_type);
}
if (AGGREGATE_TYPE_P (return_type)
&& ((unsigned HOST_WIDE_INT) int_size_in_bytes (return_type)
<= 8))
rs6000_returns_struct = true;
}
if (SCALAR_FLOAT_MODE_P (return_mode))
rs6000_passes_float = true;
else if (ALTIVEC_VECTOR_MODE (return_mode)
|| VSX_VECTOR_MODE (return_mode)
|| SPE_VECTOR_MODE (return_mode))
rs6000_passes_vector = true;
}
}
#endif
if (fntype
&& !TARGET_ALTIVEC
&& TARGET_ALTIVEC_ABI
@ -8235,11 +8294,25 @@ static void
rs6000_function_arg_advance_1 (CUMULATIVE_ARGS *cum, enum machine_mode mode,
const_tree type, bool named, int depth)
{
/* Only tick off an argument if we're not recursing. */
if (depth == 0)
cum->nargs_prototype--;
#ifdef HAVE_AS_GNU_ATTRIBUTE
if (DEFAULT_ABI == ABI_V4
&& cum->escapes)
{
if (SCALAR_FLOAT_MODE_P (mode))
rs6000_passes_float = true;
else if (named && (ALTIVEC_VECTOR_MODE (mode) || VSX_VECTOR_MODE (mode)))
rs6000_passes_vector = true;
else if (SPE_VECTOR_MODE (mode)
&& !cum->stdarg
&& cum->sysv_gregno <= GP_ARG_MAX_REG)
rs6000_passes_vector = true;
}
#endif
if (TARGET_ALTIVEC_ABI
&& (ALTIVEC_VECTOR_MODE (mode)
|| VSX_VECTOR_MODE (mode)
@ -9504,6 +9577,11 @@ rs6000_va_start (tree valist, rtx nextarg)
build_int_cst (NULL_TREE, n_fpr));
TREE_SIDE_EFFECTS (t) = 1;
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
#ifdef HAVE_AS_GNU_ATTRIBUTE
if (call_ABI_of_interest (cfun->decl))
rs6000_passes_float = true;
#endif
}
/* Find the overflow area. */
@ -25786,10 +25864,30 @@ rs6000_elf_declare_function_name (FILE *file, const char *name, tree decl)
}
static void
rs6000_elf_end_indicate_exec_stack (void)
rs6000_elf_file_end (void)
{
#ifdef HAVE_AS_GNU_ATTRIBUTE
if (TARGET_32BIT && DEFAULT_ABI == ABI_V4)
{
if (rs6000_passes_float)
fprintf (asm_out_file, "\t.gnu_attribute 4, %d\n",
((TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT) ? 1
: (TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT) ? 3
: 2));
if (rs6000_passes_vector)
fprintf (asm_out_file, "\t.gnu_attribute 8, %d\n",
(TARGET_ALTIVEC_ABI ? 2
: TARGET_SPE_ABI ? 3
: 1));
if (rs6000_returns_struct)
fprintf (asm_out_file, "\t.gnu_attribute 12, %d\n",
aix_struct_return ? 2 : 1);
}
#endif
#ifdef POWERPC_LINUX
if (TARGET_32BIT)
file_end_indicate_exec_stack ();
#endif
}
#endif

View File

@ -1570,25 +1570,29 @@ typedef struct rs6000_args
int floats_in_gpr; /* count of SFmode floats taking up
GPR space (darwin64) */
int named; /* false for varargs params */
int escapes; /* if function visible outside tu */
} CUMULATIVE_ARGS;
/* Initialize a variable CUM of type CUMULATIVE_ARGS
for a call to a function whose data type is FNTYPE.
For a library call, FNTYPE is 0. */
#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT, N_NAMED_ARGS) \
init_cumulative_args (&CUM, FNTYPE, LIBNAME, FALSE, FALSE, N_NAMED_ARGS)
#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, FNDECL, N_NAMED_ARGS) \
init_cumulative_args (&CUM, FNTYPE, LIBNAME, FALSE, FALSE, \
N_NAMED_ARGS, FNDECL, VOIDmode)
/* Similar, but when scanning the definition of a procedure. We always
set NARGS_PROTOTYPE large so we never return an EXPR_LIST. */
#define INIT_CUMULATIVE_INCOMING_ARGS(CUM, FNTYPE, LIBNAME) \
init_cumulative_args (&CUM, FNTYPE, LIBNAME, TRUE, FALSE, 1000)
init_cumulative_args (&CUM, FNTYPE, LIBNAME, TRUE, FALSE, \
1000, current_function_decl, VOIDmode)
/* Like INIT_CUMULATIVE_ARGS' but only used for outgoing libcalls. */
#define INIT_CUMULATIVE_LIBCALL_ARGS(CUM, MODE, LIBNAME) \
init_cumulative_args (&CUM, NULL_TREE, LIBNAME, FALSE, TRUE, 0)
init_cumulative_args (&CUM, NULL_TREE, LIBNAME, FALSE, TRUE, \
0, NULL_TREE, MODE)
/* If defined, a C expression which determines whether, and in which
direction, to pad out an argument with extra space. The value

View File

@ -1031,6 +1031,8 @@ ncrtn.o%s"
/* Generate entries in .fixup for relocatable addresses. */
#define RELOCATABLE_NEEDS_FIXUP 1
#define TARGET_ASM_FILE_END rs6000_elf_file_end
/* This target uses the sysv4.opt file. */
#define TARGET_USES_SYSV4_OPT 1