Makefile.in (expr.o): Depend on $(TARGET_H).
* Makefile.in (expr.o): Depend on $(TARGET_H). * target.h (return_in_msb): New target hook. * target-def.h (TARGET_RETURN_IN_MSB): New macro. (TARGET_CALLS): Include it. * calls.c (shift_returned_value): New function. (expand_call): Use it. * expr.c: Include target.h. (copy_blkmode_from_reg): Check targetm.calls.return_in_msb when deciding what padding is needed. Change the name of the local padding variable from big_endian_correction to padding_correction. * stmt.c (shift_return_value): New function. (expand_return): Use it. Adjust memory->register copy in the same way as copy_blkmode_from_reg. Only change the return register's mode if it was originally BLKmode. * doc/tm.texi (TARGET_RETURN_IN_MSB): Document. * config/mips/mips.c (TARGET_RETURN_IN_MSB): Define. (mips_fpr_return_fields): New, split out from mips_function_value. (mips_return_in_msb, mips_return_fpr_pair): New functions. (mips_function_value): Rework to use the functions above. * config/mips/irix6-libc-compat.c: Delete. * config/mips/t-iris6 (LIB2FUNCS_STATIC_EXTRA): Undefine. From-SVN: r73652
This commit is contained in:
parent
e0c99e151e
commit
c988af2b8c
|
@ -1,3 +1,27 @@
|
||||||
|
2003-11-16 Richard Sandiford <rsandifo@redhat.com>
|
||||||
|
|
||||||
|
* Makefile.in (expr.o): Depend on $(TARGET_H).
|
||||||
|
* target.h (return_in_msb): New target hook.
|
||||||
|
* target-def.h (TARGET_RETURN_IN_MSB): New macro.
|
||||||
|
(TARGET_CALLS): Include it.
|
||||||
|
* calls.c (shift_returned_value): New function.
|
||||||
|
(expand_call): Use it.
|
||||||
|
* expr.c: Include target.h.
|
||||||
|
(copy_blkmode_from_reg): Check targetm.calls.return_in_msb when
|
||||||
|
deciding what padding is needed. Change the name of the local
|
||||||
|
padding variable from big_endian_correction to padding_correction.
|
||||||
|
* stmt.c (shift_return_value): New function.
|
||||||
|
(expand_return): Use it. Adjust memory->register copy in the same
|
||||||
|
way as copy_blkmode_from_reg. Only change the return register's
|
||||||
|
mode if it was originally BLKmode.
|
||||||
|
* doc/tm.texi (TARGET_RETURN_IN_MSB): Document.
|
||||||
|
* config/mips/mips.c (TARGET_RETURN_IN_MSB): Define.
|
||||||
|
(mips_fpr_return_fields): New, split out from mips_function_value.
|
||||||
|
(mips_return_in_msb, mips_return_fpr_pair): New functions.
|
||||||
|
(mips_function_value): Rework to use the functions above.
|
||||||
|
* config/mips/irix6-libc-compat.c: Delete.
|
||||||
|
* config/mips/t-iris6 (LIB2FUNCS_STATIC_EXTRA): Undefine.
|
||||||
|
|
||||||
2003-11-16 Kazu Hirata <kazu@cs.umass.edu>
|
2003-11-16 Kazu Hirata <kazu@cs.umass.edu>
|
||||||
|
|
||||||
* doc/install.texi (--enable-checking): Update valgrind's URL.
|
* doc/install.texi (--enable-checking): Update valgrind's URL.
|
||||||
|
|
|
@ -1578,7 +1578,7 @@ except.o : except.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
|
||||||
expr.o : expr.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) flags.h \
|
expr.o : expr.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) flags.h \
|
||||||
function.h $(REGS_H) $(EXPR_H) $(OPTABS_H) libfuncs.h $(INSN_ATTR_H) insn-config.h \
|
function.h $(REGS_H) $(EXPR_H) $(OPTABS_H) libfuncs.h $(INSN_ATTR_H) insn-config.h \
|
||||||
$(RECOG_H) output.h typeclass.h hard-reg-set.h toplev.h hard-reg-set.h \
|
$(RECOG_H) output.h typeclass.h hard-reg-set.h toplev.h hard-reg-set.h \
|
||||||
except.h reload.h $(GGC_H) langhooks.h intl.h $(TM_P_H) real.h
|
except.h reload.h $(GGC_H) langhooks.h intl.h $(TM_P_H) real.h $(TARGET_H)
|
||||||
dojump.o : dojump.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) \
|
dojump.o : dojump.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) \
|
||||||
flags.h function.h $(EXPR_H) $(OPTABS_H) $(INSN_ATTR_H) insn-config.h \
|
flags.h function.h $(EXPR_H) $(OPTABS_H) $(INSN_ATTR_H) insn-config.h \
|
||||||
langhooks.h
|
langhooks.h
|
||||||
|
|
36
gcc/calls.c
36
gcc/calls.c
|
@ -148,6 +148,7 @@ static int check_sibcall_argument_overlap (rtx, struct arg_data *, int);
|
||||||
static int combine_pending_stack_adjustment_and_call (int, struct args_size *,
|
static int combine_pending_stack_adjustment_and_call (int, struct args_size *,
|
||||||
int);
|
int);
|
||||||
static tree fix_unsafe_tree (tree);
|
static tree fix_unsafe_tree (tree);
|
||||||
|
static bool shift_returned_value (tree, rtx *);
|
||||||
|
|
||||||
#ifdef REG_PARM_STACK_SPACE
|
#ifdef REG_PARM_STACK_SPACE
|
||||||
static rtx save_fixed_argument_area (int, rtx, int *, int *);
|
static rtx save_fixed_argument_area (int, rtx, int *, int *);
|
||||||
|
@ -2022,6 +2023,34 @@ fix_unsafe_tree (tree t)
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* If function value *VALUE was returned at the most significant end of a
|
||||||
|
register, shift it towards the least significant end and convert it to
|
||||||
|
TYPE's mode. Return true and update *VALUE if some action was needed.
|
||||||
|
|
||||||
|
TYPE is the type of the function's return value, which is known not
|
||||||
|
to have mode BLKmode. */
|
||||||
|
|
||||||
|
static bool
|
||||||
|
shift_returned_value (tree type, rtx *value)
|
||||||
|
{
|
||||||
|
if (targetm.calls.return_in_msb (type))
|
||||||
|
{
|
||||||
|
HOST_WIDE_INT shift;
|
||||||
|
|
||||||
|
shift = (GET_MODE_BITSIZE (GET_MODE (*value))
|
||||||
|
- BITS_PER_UNIT * int_size_in_bytes (type));
|
||||||
|
if (shift > 0)
|
||||||
|
{
|
||||||
|
*value = expand_binop (GET_MODE (*value), lshr_optab, *value,
|
||||||
|
GEN_INT (shift), 0, 1, OPTAB_WIDEN);
|
||||||
|
*value = convert_to_mode (TYPE_MODE (type), *value, 0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/* Generate all the code for a function call
|
/* Generate all the code for a function call
|
||||||
and return an rtx for its value.
|
and return an rtx for its value.
|
||||||
Store the value in TARGET (specified as an rtx) if convenient.
|
Store the value in TARGET (specified as an rtx) if convenient.
|
||||||
|
@ -3281,7 +3310,12 @@ expand_call (tree exp, rtx target, int ignore)
|
||||||
sibcall_failure = 1;
|
sibcall_failure = 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
target = copy_to_reg (valreg);
|
{
|
||||||
|
if (shift_returned_value (TREE_TYPE (exp), &valreg))
|
||||||
|
sibcall_failure = 1;
|
||||||
|
|
||||||
|
target = copy_to_reg (valreg);
|
||||||
|
}
|
||||||
|
|
||||||
if (targetm.calls.promote_function_return(funtype))
|
if (targetm.calls.promote_function_return(funtype))
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,84 +0,0 @@
|
||||||
/* Compensate for inconsistent structure return conventions on IRIX 6. */
|
|
||||||
/* Compile this one with gcc. */
|
|
||||||
/* Copyright (C) 2001 Free Software Foundation, Inc.
|
|
||||||
|
|
||||||
This file is part of GCC.
|
|
||||||
|
|
||||||
GCC 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.
|
|
||||||
|
|
||||||
In addition to the permissions in the GNU General Public License, the
|
|
||||||
Free Software Foundation gives you unlimited permission to link the
|
|
||||||
compiled version of this file into combinations with other programs,
|
|
||||||
and to distribute those combinations without any restriction coming
|
|
||||||
from the use of this file. (The General Public License restrictions
|
|
||||||
do apply in other respects; for example, they cover modification of
|
|
||||||
the file, and distribution when not linked into a combine
|
|
||||||
executable.)
|
|
||||||
|
|
||||||
GCC 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 GCC; see the file COPYING. If not, write to
|
|
||||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
|
||||||
Boston, MA 02111-1307, USA. */
|
|
||||||
|
|
||||||
/* GCC doesn't correctly implement the structure and union return
|
|
||||||
conventions of the N32 and N64 ABIs on IRIX 6, as described in the
|
|
||||||
MIPSpro N32 ABI Handbook, ch. 2, Calling Convention Implementations, p.7.
|
|
||||||
The ABI requires that structures (or trailing parts of structures) smaller
|
|
||||||
than 8 bytes (a 64-bit register) are left-justified, whereas GCC
|
|
||||||
right-justifies them.
|
|
||||||
|
|
||||||
While GCC is internally consistent, calling routines compiled with a
|
|
||||||
compiler that does implement the documented ABI (like SGIs MIPSpro C
|
|
||||||
compiler) doesn't work. This is primarily an issue for system libraries
|
|
||||||
like libc. Fortunately, there exist only very few routines that return
|
|
||||||
structures by value, so until the underlying bug is fixed, it is possible
|
|
||||||
to work around it by providing wrappers for the few affected routines.
|
|
||||||
|
|
||||||
These wrappers rely on the fact that e.g. libc contains weak versions of
|
|
||||||
those routines, and the real implementation is provided by _-prefixed
|
|
||||||
variants. So we can provide our own versions, which will only be linked
|
|
||||||
if the application uses any of the affected functions, calling the private
|
|
||||||
variants and then shifting the result as required.
|
|
||||||
|
|
||||||
This is a rewrite of code created by Andy Polyakov. */
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
#include "system.h"
|
|
||||||
#include "coretypes.h"
|
|
||||||
#include "tm.h"
|
|
||||||
|
|
||||||
/* This must only be used for the N32 and N64 ABIs. O32 is correct. */
|
|
||||||
|
|
||||||
#if _MIPS_SIM == _ABIN32 || _MIPS_SIM == _ABI64
|
|
||||||
|
|
||||||
/* The affected return values need to be shifted by
|
|
||||||
|
|
||||||
BITS_PER_WORD - (sizeof (value) * BITS_PER_UNIT).
|
|
||||||
|
|
||||||
Since only 32-bit results are involved, the shift count is always 32. */
|
|
||||||
#define SHIFT_BITS 32
|
|
||||||
|
|
||||||
extern machreg_t _inet_makeaddr (machreg_t, machreg_t);
|
|
||||||
|
|
||||||
/* <arpa/inet.h> has
|
|
||||||
|
|
||||||
struct in_addr inet_makeaddr (int, int); (IRIX 6.2)
|
|
||||||
struct in_addr inet_makeaddr (in_addr_t, in_addr_t); (IRIX 6.5) */
|
|
||||||
|
|
||||||
extern machreg_t inet_makeaddr (machreg_t, machreg_t);
|
|
||||||
|
|
||||||
machreg_t
|
|
||||||
inet_makeaddr (machreg_t net, machreg_t lna)
|
|
||||||
{
|
|
||||||
return _inet_makeaddr (net, lna) >> SHIFT_BITS;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* _ABIN32 || _ABI64 */
|
|
|
@ -255,6 +255,11 @@ static void mips_select_section (tree, int, unsigned HOST_WIDE_INT)
|
||||||
ATTRIBUTE_UNUSED;
|
ATTRIBUTE_UNUSED;
|
||||||
static bool mips_in_small_data_p (tree);
|
static bool mips_in_small_data_p (tree);
|
||||||
static void mips_encode_section_info (tree, rtx, int);
|
static void mips_encode_section_info (tree, rtx, int);
|
||||||
|
static int mips_fpr_return_fields (tree, tree *);
|
||||||
|
static bool mips_return_in_msb (tree);
|
||||||
|
static rtx mips_return_fpr_pair (enum machine_mode mode,
|
||||||
|
enum machine_mode mode1, HOST_WIDE_INT,
|
||||||
|
enum machine_mode mode2, HOST_WIDE_INT);
|
||||||
static rtx mips16_gp_pseudo_reg (void);
|
static rtx mips16_gp_pseudo_reg (void);
|
||||||
static void mips16_fp_args (FILE *, int, int);
|
static void mips16_fp_args (FILE *, int, int);
|
||||||
static void build_mips16_function_stub (FILE *);
|
static void build_mips16_function_stub (FILE *);
|
||||||
|
@ -787,6 +792,8 @@ const struct mips_cpu_info mips_cpu_info_table[] = {
|
||||||
|
|
||||||
#undef TARGET_BUILD_BUILTIN_VA_LIST
|
#undef TARGET_BUILD_BUILTIN_VA_LIST
|
||||||
#define TARGET_BUILD_BUILTIN_VA_LIST mips_build_builtin_va_list
|
#define TARGET_BUILD_BUILTIN_VA_LIST mips_build_builtin_va_list
|
||||||
|
#undef TARGET_RETURN_IN_MSB
|
||||||
|
#define TARGET_RETURN_IN_MSB mips_return_in_msb
|
||||||
|
|
||||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||||
|
|
||||||
|
@ -7120,6 +7127,96 @@ mips_encode_section_info (tree decl, rtx rtl, int first)
|
||||||
default_encode_section_info (decl, rtl, first);
|
default_encode_section_info (decl, rtl, first);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* See whether VALTYPE is a record whose fields should be returned in
|
||||||
|
floating-point registers. If so, return the number of fields and
|
||||||
|
list them in FIELDS (which should have two elements). Return 0
|
||||||
|
otherwise.
|
||||||
|
|
||||||
|
For n32 & n64, a structure with one or two fields is returned in
|
||||||
|
floating-point registers as long as every field has a floating-point
|
||||||
|
type. */
|
||||||
|
|
||||||
|
static int
|
||||||
|
mips_fpr_return_fields (tree valtype, tree *fields)
|
||||||
|
{
|
||||||
|
tree field;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!TARGET_NEWABI)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (TREE_CODE (valtype) != RECORD_TYPE)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
for (field = TYPE_FIELDS (valtype); field != 0; field = TREE_CHAIN (field))
|
||||||
|
{
|
||||||
|
if (TREE_CODE (field) != FIELD_DECL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (TREE_CODE (TREE_TYPE (field)) != REAL_TYPE)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (i == 2)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
fields[i++] = field;
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Implement TARGET_RETURN_IN_MSB. For n32 & n64, we should return
|
||||||
|
a value in the most significant part of $2/$3 if:
|
||||||
|
|
||||||
|
- the target is big-endian;
|
||||||
|
|
||||||
|
- the value has a structure or union type (we generalize this to
|
||||||
|
cover aggregates from other languages too); and
|
||||||
|
|
||||||
|
- the structure is not returned in floating-point registers. */
|
||||||
|
|
||||||
|
static bool
|
||||||
|
mips_return_in_msb (tree valtype)
|
||||||
|
{
|
||||||
|
tree fields[2];
|
||||||
|
|
||||||
|
return (TARGET_NEWABI
|
||||||
|
&& TARGET_BIG_ENDIAN
|
||||||
|
&& AGGREGATE_TYPE_P (valtype)
|
||||||
|
&& mips_fpr_return_fields (valtype, fields) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Return a composite value in a pair of floating-point registers.
|
||||||
|
MODE1 and OFFSET1 are the mode and byte offset for the first value,
|
||||||
|
likewise MODE2 and OFFSET2 for the second. MODE is the mode of the
|
||||||
|
complete value.
|
||||||
|
|
||||||
|
For n32 & n64, $f0 always holds the first value and $f2 the second.
|
||||||
|
Otherwise the values are packed together as closely as possible. */
|
||||||
|
|
||||||
|
static rtx
|
||||||
|
mips_return_fpr_pair (enum machine_mode mode,
|
||||||
|
enum machine_mode mode1, HOST_WIDE_INT offset1,
|
||||||
|
enum machine_mode mode2, HOST_WIDE_INT offset2)
|
||||||
|
{
|
||||||
|
int inc;
|
||||||
|
|
||||||
|
inc = (TARGET_NEWABI ? 2 : FP_INC);
|
||||||
|
return gen_rtx_PARALLEL
|
||||||
|
(mode,
|
||||||
|
gen_rtvec (2,
|
||||||
|
gen_rtx_EXPR_LIST (VOIDmode,
|
||||||
|
gen_rtx_REG (mode1, FP_RETURN),
|
||||||
|
GEN_INT (offset1)),
|
||||||
|
gen_rtx_EXPR_LIST (VOIDmode,
|
||||||
|
gen_rtx_REG (mode2, FP_RETURN + inc),
|
||||||
|
GEN_INT (offset2))));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Implement FUNCTION_VALUE and LIBCALL_VALUE. For normal calls,
|
/* Implement FUNCTION_VALUE and LIBCALL_VALUE. For normal calls,
|
||||||
VALTYPE is the return type and MODE is VOIDmode. For libcalls,
|
VALTYPE is the return type and MODE is VOIDmode. For libcalls,
|
||||||
VALTYPE is null and MODE is the mode of the return value. */
|
VALTYPE is null and MODE is the mode of the return value. */
|
||||||
|
@ -7128,121 +7225,63 @@ rtx
|
||||||
mips_function_value (tree valtype, tree func ATTRIBUTE_UNUSED,
|
mips_function_value (tree valtype, tree func ATTRIBUTE_UNUSED,
|
||||||
enum machine_mode mode)
|
enum machine_mode mode)
|
||||||
{
|
{
|
||||||
int reg = GP_RETURN;
|
|
||||||
enum mode_class mclass;
|
|
||||||
int unsignedp = 1;
|
|
||||||
|
|
||||||
if (valtype)
|
if (valtype)
|
||||||
{
|
{
|
||||||
|
tree fields[2];
|
||||||
|
int unsignedp;
|
||||||
|
|
||||||
mode = TYPE_MODE (valtype);
|
mode = TYPE_MODE (valtype);
|
||||||
unsignedp = TREE_UNSIGNED (valtype);
|
unsignedp = TREE_UNSIGNED (valtype);
|
||||||
|
|
||||||
/* Since we define PROMOTE_FUNCTION_RETURN, we must promote
|
/* Since we define PROMOTE_FUNCTION_RETURN, we must promote
|
||||||
the mode just as PROMOTE_MODE does. */
|
the mode just as PROMOTE_MODE does. */
|
||||||
mode = promote_mode (valtype, mode, &unsignedp, 1);
|
mode = promote_mode (valtype, mode, &unsignedp, 1);
|
||||||
}
|
|
||||||
mclass = GET_MODE_CLASS (mode);
|
|
||||||
|
|
||||||
if (mclass == MODE_FLOAT && GET_MODE_SIZE (mode) <= UNITS_PER_HWFPVALUE)
|
/* Handle structures whose fields are returned in $f0/$f2. */
|
||||||
reg = FP_RETURN;
|
switch (mips_fpr_return_fields (valtype, fields))
|
||||||
|
|
||||||
else if (mclass == MODE_FLOAT && mode == TFmode)
|
|
||||||
/* long doubles are really split between f0 and f2, not f1. Eek.
|
|
||||||
Use DImode for each component, since GCC wants integer modes
|
|
||||||
for subregs. */
|
|
||||||
return gen_rtx_PARALLEL
|
|
||||||
(VOIDmode,
|
|
||||||
gen_rtvec (2,
|
|
||||||
gen_rtx_EXPR_LIST (VOIDmode,
|
|
||||||
gen_rtx_REG (DImode, FP_RETURN),
|
|
||||||
GEN_INT (0)),
|
|
||||||
gen_rtx_EXPR_LIST (VOIDmode,
|
|
||||||
gen_rtx_REG (DImode, FP_RETURN + 2),
|
|
||||||
GEN_INT (GET_MODE_SIZE (mode) / 2))));
|
|
||||||
|
|
||||||
|
|
||||||
else if (mclass == MODE_COMPLEX_FLOAT
|
|
||||||
&& GET_MODE_SIZE (mode) <= UNITS_PER_HWFPVALUE * 2)
|
|
||||||
{
|
|
||||||
enum machine_mode cmode = GET_MODE_INNER (mode);
|
|
||||||
|
|
||||||
return gen_rtx_PARALLEL
|
|
||||||
(VOIDmode,
|
|
||||||
gen_rtvec (2,
|
|
||||||
gen_rtx_EXPR_LIST (VOIDmode,
|
|
||||||
gen_rtx_REG (cmode, FP_RETURN),
|
|
||||||
GEN_INT (0)),
|
|
||||||
gen_rtx_EXPR_LIST (VOIDmode,
|
|
||||||
gen_rtx_REG (cmode, FP_RETURN + FP_INC),
|
|
||||||
GEN_INT (GET_MODE_SIZE (cmode)))));
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (valtype && TREE_CODE (valtype) == RECORD_TYPE
|
|
||||||
&& mips_abi != ABI_32
|
|
||||||
&& mips_abi != ABI_O64
|
|
||||||
&& mips_abi != ABI_EABI)
|
|
||||||
{
|
|
||||||
/* A struct with only one or two floating point fields is returned in
|
|
||||||
the floating point registers. */
|
|
||||||
tree field, fields[2];
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0, field = TYPE_FIELDS (valtype); field;
|
|
||||||
field = TREE_CHAIN (field))
|
|
||||||
{
|
{
|
||||||
if (TREE_CODE (field) != FIELD_DECL)
|
case 1:
|
||||||
continue;
|
return gen_rtx_REG (mode, FP_RETURN);
|
||||||
|
|
||||||
if (TREE_CODE (TREE_TYPE (field)) != REAL_TYPE || i >= 2)
|
case 2:
|
||||||
break;
|
return mips_return_fpr_pair (mode,
|
||||||
|
TYPE_MODE (TREE_TYPE (fields[0])),
|
||||||
fields[i++] = field;
|
int_byte_position (fields[0]),
|
||||||
|
TYPE_MODE (TREE_TYPE (fields[1])),
|
||||||
|
int_byte_position (fields[1]));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Must check i, so that we reject structures with no elements. */
|
/* If a value is passed in the most significant part of a register, see
|
||||||
if (! field)
|
whether we have to round the mode up to a whole number of words. */
|
||||||
|
if (mips_return_in_msb (valtype))
|
||||||
{
|
{
|
||||||
if (i == 1)
|
HOST_WIDE_INT size = int_size_in_bytes (valtype);
|
||||||
|
if (size % UNITS_PER_WORD != 0)
|
||||||
{
|
{
|
||||||
/* The structure has DImode, but we don't allow DImode values
|
size += UNITS_PER_WORD - size % UNITS_PER_WORD;
|
||||||
in FP registers, so we use a PARALLEL even though it isn't
|
mode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0);
|
||||||
strictly necessary. */
|
|
||||||
enum machine_mode field_mode = TYPE_MODE (TREE_TYPE (fields[0]));
|
|
||||||
|
|
||||||
return gen_rtx_PARALLEL
|
|
||||||
(mode,
|
|
||||||
gen_rtvec (1,
|
|
||||||
gen_rtx_EXPR_LIST (VOIDmode,
|
|
||||||
gen_rtx_REG (field_mode,
|
|
||||||
FP_RETURN),
|
|
||||||
const0_rtx)));
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (i == 2)
|
|
||||||
{
|
|
||||||
enum machine_mode first_mode
|
|
||||||
= TYPE_MODE (TREE_TYPE (fields[0]));
|
|
||||||
enum machine_mode second_mode
|
|
||||||
= TYPE_MODE (TREE_TYPE (fields[1]));
|
|
||||||
HOST_WIDE_INT first_offset = int_byte_position (fields[0]);
|
|
||||||
HOST_WIDE_INT second_offset = int_byte_position (fields[1]);
|
|
||||||
|
|
||||||
return gen_rtx_PARALLEL
|
|
||||||
(mode,
|
|
||||||
gen_rtvec (2,
|
|
||||||
gen_rtx_EXPR_LIST (VOIDmode,
|
|
||||||
gen_rtx_REG (first_mode,
|
|
||||||
FP_RETURN),
|
|
||||||
GEN_INT (first_offset)),
|
|
||||||
gen_rtx_EXPR_LIST (VOIDmode,
|
|
||||||
gen_rtx_REG (second_mode,
|
|
||||||
FP_RETURN + 2),
|
|
||||||
GEN_INT (second_offset))));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return gen_rtx_REG (mode, reg);
|
if (GET_MODE_CLASS (mode) == MODE_FLOAT
|
||||||
|
&& GET_MODE_SIZE (mode) <= UNITS_PER_HWFPVALUE)
|
||||||
|
return gen_rtx_REG (mode, FP_RETURN);
|
||||||
|
|
||||||
|
/* Handle long doubles for n32 & n64. */
|
||||||
|
if (mode == TFmode)
|
||||||
|
return mips_return_fpr_pair (mode,
|
||||||
|
DImode, 0,
|
||||||
|
DImode, GET_MODE_SIZE (mode) / 2);
|
||||||
|
|
||||||
|
if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT
|
||||||
|
&& GET_MODE_SIZE (mode) <= UNITS_PER_HWFPVALUE * 2)
|
||||||
|
return mips_return_fpr_pair (mode,
|
||||||
|
GET_MODE_INNER (mode), 0,
|
||||||
|
GET_MODE_INNER (mode),
|
||||||
|
GET_MODE_SIZE (mode) / 2);
|
||||||
|
|
||||||
|
return gen_rtx_REG (mode, GP_RETURN);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The implementation of FUNCTION_ARG_PASS_BY_REFERENCE. Return
|
/* The implementation of FUNCTION_ARG_PASS_BY_REFERENCE. Return
|
||||||
|
|
|
@ -14,10 +14,6 @@ INSTALL_LIBGCC = install-multilib
|
||||||
EXTRA_MULTILIB_PARTS=crtbegin.o crtend.o
|
EXTRA_MULTILIB_PARTS=crtbegin.o crtend.o
|
||||||
CRTSTUFF_T_CFLAGS=-g1
|
CRTSTUFF_T_CFLAGS=-g1
|
||||||
|
|
||||||
# This is only needed in the static libgcc as a band-aid until gcc correctly
|
|
||||||
# implements the N32/N64 ABI structure passing conventions
|
|
||||||
LIB2FUNCS_STATIC_EXTRA = $(srcdir)/config/mips/irix6-libc-compat.c
|
|
||||||
|
|
||||||
LIB2FUNCS_EXTRA = $(srcdir)/config/mips/_tilib.c
|
LIB2FUNCS_EXTRA = $(srcdir)/config/mips/_tilib.c
|
||||||
|
|
||||||
TPBIT = tp-bit.c
|
TPBIT = tp-bit.c
|
||||||
|
|
|
@ -3903,6 +3903,18 @@ need more space than is implied by @code{FUNCTION_VALUE_REGNO_P} for
|
||||||
saving and restoring an arbitrary return value.
|
saving and restoring an arbitrary return value.
|
||||||
@end defmac
|
@end defmac
|
||||||
|
|
||||||
|
@deftypefn {Target Hook} bool TARGET_RETURN_IN_MSB (tree @var{type})
|
||||||
|
This hook should return true if values of type @var{type} are returned
|
||||||
|
at the most significant end of a register (in other words, if they are
|
||||||
|
padded at the least significant end). You can assume that @var{type}
|
||||||
|
is returned in a register; the caller is required to check this.
|
||||||
|
|
||||||
|
Note that the register provided by @code{FUNCTION_VALUE} must be able
|
||||||
|
to hold the complete return value. For example, if a 1-, 2- or 3-byte
|
||||||
|
structure is returned at the most significant end of a 4-byte register,
|
||||||
|
@code{FUNCTION_VALUE} should provide an @code{SImode} rtx.
|
||||||
|
@end deftypefn
|
||||||
|
|
||||||
@node Aggregate Return
|
@node Aggregate Return
|
||||||
@subsection How Large Values Are Returned
|
@subsection How Large Values Are Returned
|
||||||
@cindex aggregates as return values
|
@cindex aggregates as return values
|
||||||
|
|
38
gcc/expr.c
38
gcc/expr.c
|
@ -47,6 +47,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||||
#include "langhooks.h"
|
#include "langhooks.h"
|
||||||
#include "intl.h"
|
#include "intl.h"
|
||||||
#include "tm_p.h"
|
#include "tm_p.h"
|
||||||
|
#include "target.h"
|
||||||
|
|
||||||
/* Decide whether a function's arguments should be processed
|
/* Decide whether a function's arguments should be processed
|
||||||
from first to last or from last to first.
|
from first to last or from last to first.
|
||||||
|
@ -2121,10 +2122,10 @@ emit_group_store (rtx orig_dst, rtx src, tree type ATTRIBUTE_UNUSED, int ssize)
|
||||||
set of registers starting with SRCREG into TGTBLK. If TGTBLK
|
set of registers starting with SRCREG into TGTBLK. If TGTBLK
|
||||||
is null, a stack temporary is created. TGTBLK is returned.
|
is null, a stack temporary is created. TGTBLK is returned.
|
||||||
|
|
||||||
The primary purpose of this routine is to handle functions
|
The purpose of this routine is to handle functions that return
|
||||||
that return BLKmode structures in registers. Some machines
|
BLKmode structures in registers. Some machines (the PA for example)
|
||||||
(the PA for example) want to return all small structures
|
want to return all small structures in registers regardless of the
|
||||||
in registers regardless of the structure's alignment. */
|
structure's alignment. */
|
||||||
|
|
||||||
rtx
|
rtx
|
||||||
copy_blkmode_from_reg (rtx tgtblk, rtx srcreg, tree type)
|
copy_blkmode_from_reg (rtx tgtblk, rtx srcreg, tree type)
|
||||||
|
@ -2132,7 +2133,7 @@ copy_blkmode_from_reg (rtx tgtblk, rtx srcreg, tree type)
|
||||||
unsigned HOST_WIDE_INT bytes = int_size_in_bytes (type);
|
unsigned HOST_WIDE_INT bytes = int_size_in_bytes (type);
|
||||||
rtx src = NULL, dst = NULL;
|
rtx src = NULL, dst = NULL;
|
||||||
unsigned HOST_WIDE_INT bitsize = MIN (TYPE_ALIGN (type), BITS_PER_WORD);
|
unsigned HOST_WIDE_INT bitsize = MIN (TYPE_ALIGN (type), BITS_PER_WORD);
|
||||||
unsigned HOST_WIDE_INT bitpos, xbitpos, big_endian_correction = 0;
|
unsigned HOST_WIDE_INT bitpos, xbitpos, padding_correction = 0;
|
||||||
|
|
||||||
if (tgtblk == 0)
|
if (tgtblk == 0)
|
||||||
{
|
{
|
||||||
|
@ -2150,13 +2151,20 @@ copy_blkmode_from_reg (rtx tgtblk, rtx srcreg, tree type)
|
||||||
&& GET_MODE_SIZE (GET_MODE (srcreg)) < UNITS_PER_WORD)
|
&& GET_MODE_SIZE (GET_MODE (srcreg)) < UNITS_PER_WORD)
|
||||||
srcreg = convert_to_mode (word_mode, srcreg, TREE_UNSIGNED (type));
|
srcreg = convert_to_mode (word_mode, srcreg, TREE_UNSIGNED (type));
|
||||||
|
|
||||||
/* Structures whose size is not a multiple of a word are aligned
|
/* If the structure doesn't take up a whole number of words, see whether
|
||||||
to the least significant byte (to the right). On a BYTES_BIG_ENDIAN
|
SRCREG is padded on the left or on the right. If it's on the left,
|
||||||
machine, this means we must skip the empty high order bytes when
|
set PADDING_CORRECTION to the number of bits to skip.
|
||||||
calculating the bit offset. */
|
|
||||||
if (BYTES_BIG_ENDIAN
|
In most ABIs, the structure will be returned at the least end of
|
||||||
&& bytes % UNITS_PER_WORD)
|
the register, which translates to right padding on little-endian
|
||||||
big_endian_correction
|
targets and left padding on big-endian targets. The opposite
|
||||||
|
holds if the structure is returned at the most significant
|
||||||
|
end of the register. */
|
||||||
|
if (bytes % UNITS_PER_WORD != 0
|
||||||
|
&& (targetm.calls.return_in_msb (type)
|
||||||
|
? !BYTES_BIG_ENDIAN
|
||||||
|
: BYTES_BIG_ENDIAN))
|
||||||
|
padding_correction
|
||||||
= (BITS_PER_WORD - ((bytes % UNITS_PER_WORD) * BITS_PER_UNIT));
|
= (BITS_PER_WORD - ((bytes % UNITS_PER_WORD) * BITS_PER_UNIT));
|
||||||
|
|
||||||
/* Copy the structure BITSIZE bites at a time.
|
/* Copy the structure BITSIZE bites at a time.
|
||||||
|
@ -2164,15 +2172,15 @@ copy_blkmode_from_reg (rtx tgtblk, rtx srcreg, tree type)
|
||||||
We could probably emit more efficient code for machines which do not use
|
We could probably emit more efficient code for machines which do not use
|
||||||
strict alignment, but it doesn't seem worth the effort at the current
|
strict alignment, but it doesn't seem worth the effort at the current
|
||||||
time. */
|
time. */
|
||||||
for (bitpos = 0, xbitpos = big_endian_correction;
|
for (bitpos = 0, xbitpos = padding_correction;
|
||||||
bitpos < bytes * BITS_PER_UNIT;
|
bitpos < bytes * BITS_PER_UNIT;
|
||||||
bitpos += bitsize, xbitpos += bitsize)
|
bitpos += bitsize, xbitpos += bitsize)
|
||||||
{
|
{
|
||||||
/* We need a new source operand each time xbitpos is on a
|
/* We need a new source operand each time xbitpos is on a
|
||||||
word boundary and when xbitpos == big_endian_correction
|
word boundary and when xbitpos == padding_correction
|
||||||
(the first time through). */
|
(the first time through). */
|
||||||
if (xbitpos % BITS_PER_WORD == 0
|
if (xbitpos % BITS_PER_WORD == 0
|
||||||
|| xbitpos == big_endian_correction)
|
|| xbitpos == padding_correction)
|
||||||
src = operand_subword_force (srcreg, xbitpos / BITS_PER_WORD,
|
src = operand_subword_force (srcreg, xbitpos / BITS_PER_WORD,
|
||||||
GET_MODE (srcreg));
|
GET_MODE (srcreg));
|
||||||
|
|
||||||
|
|
93
gcc/stmt.c
93
gcc/stmt.c
|
@ -403,6 +403,7 @@ static bool check_unique_operand_names (tree, tree);
|
||||||
static char *resolve_operand_name_1 (char *, tree, tree);
|
static char *resolve_operand_name_1 (char *, tree, tree);
|
||||||
static void expand_null_return_1 (rtx);
|
static void expand_null_return_1 (rtx);
|
||||||
static enum br_predictor return_prediction (rtx);
|
static enum br_predictor return_prediction (rtx);
|
||||||
|
static rtx shift_return_value (rtx);
|
||||||
static void expand_value_return (rtx);
|
static void expand_value_return (rtx);
|
||||||
static int tail_recursion_args (tree, tree);
|
static int tail_recursion_args (tree, tree);
|
||||||
static void expand_cleanups (tree, int, int);
|
static void expand_cleanups (tree, int, int);
|
||||||
|
@ -2902,6 +2903,34 @@ return_prediction (rtx val)
|
||||||
return PRED_NO_PREDICTION;
|
return PRED_NO_PREDICTION;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* If the current function returns values in the most significant part
|
||||||
|
of a register, shift return value VAL appropriately. The mode of
|
||||||
|
the function's return type is known not to be BLKmode. */
|
||||||
|
|
||||||
|
static rtx
|
||||||
|
shift_return_value (rtx val)
|
||||||
|
{
|
||||||
|
tree type;
|
||||||
|
|
||||||
|
type = TREE_TYPE (DECL_RESULT (current_function_decl));
|
||||||
|
if (targetm.calls.return_in_msb (type))
|
||||||
|
{
|
||||||
|
rtx target;
|
||||||
|
HOST_WIDE_INT shift;
|
||||||
|
|
||||||
|
target = DECL_RTL (DECL_RESULT (current_function_decl));
|
||||||
|
shift = (GET_MODE_BITSIZE (GET_MODE (target))
|
||||||
|
- BITS_PER_UNIT * int_size_in_bytes (type));
|
||||||
|
if (shift > 0)
|
||||||
|
val = expand_binop (GET_MODE (target), ashl_optab,
|
||||||
|
gen_lowpart (GET_MODE (target), val),
|
||||||
|
GEN_INT (shift), target, 1, OPTAB_WIDEN);
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Generate RTL to return from the current function, with value VAL. */
|
/* Generate RTL to return from the current function, with value VAL. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -3066,7 +3095,7 @@ expand_return (tree retval)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
unsigned HOST_WIDE_INT bitpos, xbitpos;
|
unsigned HOST_WIDE_INT bitpos, xbitpos;
|
||||||
unsigned HOST_WIDE_INT big_endian_correction = 0;
|
unsigned HOST_WIDE_INT padding_correction = 0;
|
||||||
unsigned HOST_WIDE_INT bytes
|
unsigned HOST_WIDE_INT bytes
|
||||||
= int_size_in_bytes (TREE_TYPE (retval_rhs));
|
= int_size_in_bytes (TREE_TYPE (retval_rhs));
|
||||||
int n_regs = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
|
int n_regs = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
|
||||||
|
@ -3083,25 +3112,33 @@ expand_return (tree retval)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Structures whose size is not a multiple of a word are aligned
|
/* If the structure doesn't take up a whole number of words, see
|
||||||
to the least significant byte (to the right). On a BYTES_BIG_ENDIAN
|
whether the register value should be padded on the left or on
|
||||||
machine, this means we must skip the empty high order bytes when
|
the right. Set PADDING_CORRECTION to the number of padding
|
||||||
calculating the bit offset. */
|
bits needed on the left side.
|
||||||
if (BYTES_BIG_ENDIAN
|
|
||||||
&& bytes % UNITS_PER_WORD)
|
In most ABIs, the structure will be returned at the least end of
|
||||||
big_endian_correction = (BITS_PER_WORD - ((bytes % UNITS_PER_WORD)
|
the register, which translates to right padding on little-endian
|
||||||
* BITS_PER_UNIT));
|
targets and left padding on big-endian targets. The opposite
|
||||||
|
holds if the structure is returned at the most significant
|
||||||
|
end of the register. */
|
||||||
|
if (bytes % UNITS_PER_WORD != 0
|
||||||
|
&& (targetm.calls.return_in_msb (TREE_TYPE (retval_rhs))
|
||||||
|
? !BYTES_BIG_ENDIAN
|
||||||
|
: BYTES_BIG_ENDIAN))
|
||||||
|
padding_correction = (BITS_PER_WORD - ((bytes % UNITS_PER_WORD)
|
||||||
|
* BITS_PER_UNIT));
|
||||||
|
|
||||||
/* Copy the structure BITSIZE bits at a time. */
|
/* Copy the structure BITSIZE bits at a time. */
|
||||||
for (bitpos = 0, xbitpos = big_endian_correction;
|
for (bitpos = 0, xbitpos = padding_correction;
|
||||||
bitpos < bytes * BITS_PER_UNIT;
|
bitpos < bytes * BITS_PER_UNIT;
|
||||||
bitpos += bitsize, xbitpos += bitsize)
|
bitpos += bitsize, xbitpos += bitsize)
|
||||||
{
|
{
|
||||||
/* We need a new destination pseudo each time xbitpos is
|
/* We need a new destination pseudo each time xbitpos is
|
||||||
on a word boundary and when xbitpos == big_endian_correction
|
on a word boundary and when xbitpos == padding_correction
|
||||||
(the first time through). */
|
(the first time through). */
|
||||||
if (xbitpos % BITS_PER_WORD == 0
|
if (xbitpos % BITS_PER_WORD == 0
|
||||||
|| xbitpos == big_endian_correction)
|
|| xbitpos == padding_correction)
|
||||||
{
|
{
|
||||||
/* Generate an appropriate register. */
|
/* Generate an appropriate register. */
|
||||||
dst = gen_reg_rtx (word_mode);
|
dst = gen_reg_rtx (word_mode);
|
||||||
|
@ -3128,21 +3165,25 @@ expand_return (tree retval)
|
||||||
BITS_PER_WORD);
|
BITS_PER_WORD);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find the smallest integer mode large enough to hold the
|
tmpmode = GET_MODE (result_rtl);
|
||||||
entire structure and use that mode instead of BLKmode
|
if (tmpmode == BLKmode)
|
||||||
on the USE insn for the return register. */
|
{
|
||||||
for (tmpmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
|
/* Find the smallest integer mode large enough to hold the
|
||||||
tmpmode != VOIDmode;
|
entire structure and use that mode instead of BLKmode
|
||||||
tmpmode = GET_MODE_WIDER_MODE (tmpmode))
|
on the USE insn for the return register. */
|
||||||
/* Have we found a large enough mode? */
|
for (tmpmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
|
||||||
if (GET_MODE_SIZE (tmpmode) >= bytes)
|
tmpmode != VOIDmode;
|
||||||
break;
|
tmpmode = GET_MODE_WIDER_MODE (tmpmode))
|
||||||
|
/* Have we found a large enough mode? */
|
||||||
|
if (GET_MODE_SIZE (tmpmode) >= bytes)
|
||||||
|
break;
|
||||||
|
|
||||||
/* No suitable mode found. */
|
/* No suitable mode found. */
|
||||||
if (tmpmode == VOIDmode)
|
if (tmpmode == VOIDmode)
|
||||||
abort ();
|
abort ();
|
||||||
|
|
||||||
PUT_MODE (result_rtl, tmpmode);
|
PUT_MODE (result_rtl, tmpmode);
|
||||||
|
}
|
||||||
|
|
||||||
if (GET_MODE_SIZE (tmpmode) < GET_MODE_SIZE (word_mode))
|
if (GET_MODE_SIZE (tmpmode) < GET_MODE_SIZE (word_mode))
|
||||||
result_reg_mode = word_mode;
|
result_reg_mode = word_mode;
|
||||||
|
@ -3175,7 +3216,7 @@ expand_return (tree retval)
|
||||||
val = force_not_mem (val);
|
val = force_not_mem (val);
|
||||||
emit_queue ();
|
emit_queue ();
|
||||||
/* Return the calculated value, doing cleanups first. */
|
/* Return the calculated value, doing cleanups first. */
|
||||||
expand_value_return (val);
|
expand_value_return (shift_return_value (val));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -329,6 +329,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
#define TARGET_STRUCT_VALUE_RTX default_struct_value_rtx
|
#define TARGET_STRUCT_VALUE_RTX default_struct_value_rtx
|
||||||
#define TARGET_RETURN_IN_MEMORY default_return_in_memory
|
#define TARGET_RETURN_IN_MEMORY default_return_in_memory
|
||||||
|
#define TARGET_RETURN_IN_MSB hook_bool_tree_false
|
||||||
|
|
||||||
#define TARGET_EXPAND_BUILTIN_SAVEREGS default_expand_builtin_saveregs
|
#define TARGET_EXPAND_BUILTIN_SAVEREGS default_expand_builtin_saveregs
|
||||||
#define TARGET_SETUP_INCOMING_VARARGS default_setup_incoming_varargs
|
#define TARGET_SETUP_INCOMING_VARARGS default_setup_incoming_varargs
|
||||||
|
@ -341,6 +342,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
TARGET_PROMOTE_PROTOTYPES, \
|
TARGET_PROMOTE_PROTOTYPES, \
|
||||||
TARGET_STRUCT_VALUE_RTX, \
|
TARGET_STRUCT_VALUE_RTX, \
|
||||||
TARGET_RETURN_IN_MEMORY, \
|
TARGET_RETURN_IN_MEMORY, \
|
||||||
|
TARGET_RETURN_IN_MSB, \
|
||||||
TARGET_EXPAND_BUILTIN_SAVEREGS, \
|
TARGET_EXPAND_BUILTIN_SAVEREGS, \
|
||||||
TARGET_SETUP_INCOMING_VARARGS, \
|
TARGET_SETUP_INCOMING_VARARGS, \
|
||||||
TARGET_STRICT_ARGUMENT_NAMING, \
|
TARGET_STRICT_ARGUMENT_NAMING, \
|
||||||
|
|
|
@ -429,6 +429,7 @@ struct gcc_target
|
||||||
bool (*promote_prototypes) (tree fntype);
|
bool (*promote_prototypes) (tree fntype);
|
||||||
rtx (*struct_value_rtx) (tree fndecl, int incoming);
|
rtx (*struct_value_rtx) (tree fndecl, int incoming);
|
||||||
bool (*return_in_memory) (tree type, tree fndecl);
|
bool (*return_in_memory) (tree type, tree fndecl);
|
||||||
|
bool (*return_in_msb) (tree type);
|
||||||
rtx (*expand_builtin_saveregs) (void);
|
rtx (*expand_builtin_saveregs) (void);
|
||||||
/* Returns pretend_argument_size. */
|
/* Returns pretend_argument_size. */
|
||||||
void (*setup_incoming_varargs) (CUMULATIVE_ARGS *ca, enum machine_mode mode,
|
void (*setup_incoming_varargs) (CUMULATIVE_ARGS *ca, enum machine_mode mode,
|
||||||
|
|
Loading…
Reference in New Issue