mirror of git://gcc.gnu.org/git/gcc.git
target.h (invalid_conversion, [...]): New hooks.
* target.h (invalid_conversion, invalid_unary_op, invalid_binary_op): New hooks. * target-def.h (TARGET_INVALID_CONVERSION, TARGET_INVALID_UNARY_OP, TARGET_INVALID_BINARY_OP, TARGET_INITIALIZER): Likewise. * hooks.h (hook_constcharptr_tree_tree_null, hook_constcharptr_int_tree_null, hook_constcharptr_int_tree_tree_null): New. * hooks.c (hook_constcharptr_tree_tree_null, hook_constcharptr_int_tree_null, hook_constcharptr_int_tree_tree_null): Likewise. * gcc/doc/tm.texi (TARGET_INVALID_CONVERSION, TARGET_INVALID_UNARY_OP, TARGET_INVALID_BINARY_OP): Document. * c-convert.c (convert): Use invalid_conversion hook. * c-typeck.c (build_unary_op): Use invalid_unary_op hook. (build_binary_op): Use invalid_binary_op hook. * config/ia64/ia64-modes.def: Define RFmode. * config/ia64/ia64-protos.h (spill_xfmode_operand): Remove. (ia64_expand_movxf_movrf): New. * config/ia64/ia64.md (movxf): Move code to ia64_expand_movxf_movrf. (movrf, movrf_internal): New. * ia64.c (ia64_invalid_conversion, ia64_invalid_unary_op, ia64_invalid_binary_op, TARGET_INVALID_CONVERSION, TARGET_INVALID_UNARY_OP, TARGET_INVALID_BINARY_OP): New. (spill_xfmode_operand): Rename to spill_xfmode_rfmode_operand. Add mode parameter. Make static. (ia64_expand_movxf_movrf): New, moved from ia64.md. Handle RFmode as well as XFmode. (ia64_function_arg, ia64_function_value, ia64_register_move_cost, ia64_scalar_mode_supported_p): Handle RFmode as well as XFmode. (ia64_init_builtins): Set up __fpreg as RFmode. (ia64_mangle_fundamental_type): Mangle __fpreg as u7__fpreg. cp: * cvt.c (ocp_convert): Use invalid_conversion hook. * typeck.c (build_binary_op): Use invalid_binary_op hook. (build_unary_op): Use invalid_unary_op hook. testsuite: * g++.dg/ext/fpreg1.C, gcc.target/ia64/fpreg-1.c, gcc.target/ia64/fpreg-2.c: New tests. From-SVN: r101391
This commit is contained in:
parent
2a75c0b6d2
commit
4de67c26fe
|
@ -1,3 +1,39 @@
|
||||||
|
2005-06-28 Joseph S. Myers <joseph@codesourcery.com>
|
||||||
|
|
||||||
|
* target.h (invalid_conversion, invalid_unary_op,
|
||||||
|
invalid_binary_op): New hooks.
|
||||||
|
* target-def.h (TARGET_INVALID_CONVERSION,
|
||||||
|
TARGET_INVALID_UNARY_OP, TARGET_INVALID_BINARY_OP,
|
||||||
|
TARGET_INITIALIZER): Likewise.
|
||||||
|
* hooks.h (hook_constcharptr_tree_tree_null,
|
||||||
|
hook_constcharptr_int_tree_null,
|
||||||
|
hook_constcharptr_int_tree_tree_null): New.
|
||||||
|
* hooks.c (hook_constcharptr_tree_tree_null,
|
||||||
|
hook_constcharptr_int_tree_null,
|
||||||
|
hook_constcharptr_int_tree_tree_null): Likewise.
|
||||||
|
* gcc/doc/tm.texi (TARGET_INVALID_CONVERSION,
|
||||||
|
TARGET_INVALID_UNARY_OP, TARGET_INVALID_BINARY_OP): Document.
|
||||||
|
* c-convert.c (convert): Use invalid_conversion hook.
|
||||||
|
* c-typeck.c (build_unary_op): Use invalid_unary_op hook.
|
||||||
|
(build_binary_op): Use invalid_binary_op hook.
|
||||||
|
* config/ia64/ia64-modes.def: Define RFmode.
|
||||||
|
* config/ia64/ia64-protos.h (spill_xfmode_operand): Remove.
|
||||||
|
(ia64_expand_movxf_movrf): New.
|
||||||
|
* config/ia64/ia64.md (movxf): Move code to
|
||||||
|
ia64_expand_movxf_movrf.
|
||||||
|
(movrf, movrf_internal): New.
|
||||||
|
* ia64.c (ia64_invalid_conversion, ia64_invalid_unary_op,
|
||||||
|
ia64_invalid_binary_op, TARGET_INVALID_CONVERSION,
|
||||||
|
TARGET_INVALID_UNARY_OP, TARGET_INVALID_BINARY_OP): New.
|
||||||
|
(spill_xfmode_operand): Rename to spill_xfmode_rfmode_operand.
|
||||||
|
Add mode parameter. Make static.
|
||||||
|
(ia64_expand_movxf_movrf): New, moved from ia64.md. Handle RFmode
|
||||||
|
as well as XFmode.
|
||||||
|
(ia64_function_arg, ia64_function_value, ia64_register_move_cost,
|
||||||
|
ia64_scalar_mode_supported_p): Handle RFmode as well as XFmode.
|
||||||
|
(ia64_init_builtins): Set up __fpreg as RFmode.
|
||||||
|
(ia64_mangle_fundamental_type): Mangle __fpreg as u7__fpreg.
|
||||||
|
|
||||||
2006-06-28 Adrian Straetling <straetling@de.ibm.com>
|
2006-06-28 Adrian Straetling <straetling@de.ibm.com>
|
||||||
|
|
||||||
* builtins.c: (expand_builtin_memset): Rewrite to support
|
* builtins.c: (expand_builtin_memset): Rewrite to support
|
||||||
|
|
|
@ -36,6 +36,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
||||||
#include "c-tree.h"
|
#include "c-tree.h"
|
||||||
#include "langhooks.h"
|
#include "langhooks.h"
|
||||||
#include "toplev.h"
|
#include "toplev.h"
|
||||||
|
#include "target.h"
|
||||||
|
|
||||||
/* Change of width--truncation and extension of integers or reals--
|
/* Change of width--truncation and extension of integers or reals--
|
||||||
is represented with NOP_EXPR. Proper functioning of many things
|
is represented with NOP_EXPR. Proper functioning of many things
|
||||||
|
@ -69,10 +70,21 @@ convert (tree type, tree expr)
|
||||||
{
|
{
|
||||||
tree e = expr;
|
tree e = expr;
|
||||||
enum tree_code code = TREE_CODE (type);
|
enum tree_code code = TREE_CODE (type);
|
||||||
|
const char *invalid_conv_diag;
|
||||||
|
|
||||||
if (type == TREE_TYPE (expr)
|
if (type == error_mark_node
|
||||||
|| TREE_CODE (expr) == ERROR_MARK
|
|| expr == error_mark_node
|
||||||
|| code == ERROR_MARK || TREE_CODE (TREE_TYPE (expr)) == ERROR_MARK)
|
|| TREE_TYPE (expr) == error_mark_node)
|
||||||
|
return error_mark_node;
|
||||||
|
|
||||||
|
if ((invalid_conv_diag
|
||||||
|
= targetm.invalid_conversion (TREE_TYPE (expr), type)))
|
||||||
|
{
|
||||||
|
error (invalid_conv_diag);
|
||||||
|
return error_mark_node;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == TREE_TYPE (expr))
|
||||||
return expr;
|
return expr;
|
||||||
|
|
||||||
if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (expr)))
|
if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (expr)))
|
||||||
|
|
|
@ -2501,12 +2501,20 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
|
||||||
enum tree_code typecode = TREE_CODE (TREE_TYPE (arg));
|
enum tree_code typecode = TREE_CODE (TREE_TYPE (arg));
|
||||||
tree val;
|
tree val;
|
||||||
int noconvert = flag;
|
int noconvert = flag;
|
||||||
|
const char *invalid_op_diag;
|
||||||
|
|
||||||
if (typecode == ERROR_MARK)
|
if (typecode == ERROR_MARK)
|
||||||
return error_mark_node;
|
return error_mark_node;
|
||||||
if (typecode == ENUMERAL_TYPE || typecode == BOOLEAN_TYPE)
|
if (typecode == ENUMERAL_TYPE || typecode == BOOLEAN_TYPE)
|
||||||
typecode = INTEGER_TYPE;
|
typecode = INTEGER_TYPE;
|
||||||
|
|
||||||
|
if ((invalid_op_diag
|
||||||
|
= targetm.invalid_unary_op (code, TREE_TYPE (xarg))))
|
||||||
|
{
|
||||||
|
error (invalid_op_diag);
|
||||||
|
return error_mark_node;
|
||||||
|
}
|
||||||
|
|
||||||
switch (code)
|
switch (code)
|
||||||
{
|
{
|
||||||
case CONVERT_EXPR:
|
case CONVERT_EXPR:
|
||||||
|
@ -7397,6 +7405,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
|
||||||
tree type0, type1;
|
tree type0, type1;
|
||||||
enum tree_code code0, code1;
|
enum tree_code code0, code1;
|
||||||
tree op0, op1;
|
tree op0, op1;
|
||||||
|
const char *invalid_op_diag;
|
||||||
|
|
||||||
/* Expression code to give to the expression when it is built.
|
/* Expression code to give to the expression when it is built.
|
||||||
Normally this is CODE, which is what the caller asked for,
|
Normally this is CODE, which is what the caller asked for,
|
||||||
|
@ -7472,6 +7481,13 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
|
||||||
if (code0 == ERROR_MARK || code1 == ERROR_MARK)
|
if (code0 == ERROR_MARK || code1 == ERROR_MARK)
|
||||||
return error_mark_node;
|
return error_mark_node;
|
||||||
|
|
||||||
|
if ((invalid_op_diag
|
||||||
|
= targetm.invalid_binary_op (code, type0, type1)))
|
||||||
|
{
|
||||||
|
error (invalid_op_diag);
|
||||||
|
return error_mark_node;
|
||||||
|
}
|
||||||
|
|
||||||
objc_ok = objc_compare_types (type0, type1, -3, NULL_TREE);
|
objc_ok = objc_compare_types (type0, type1, -3, NULL_TREE);
|
||||||
|
|
||||||
switch (code)
|
switch (code)
|
||||||
|
|
|
@ -23,9 +23,12 @@ Boston, MA 02110-1301, USA. */
|
||||||
/* IA64 requires both XF and TF modes.
|
/* IA64 requires both XF and TF modes.
|
||||||
XFmode is __float80 is IEEE extended; TFmode is __float128
|
XFmode is __float80 is IEEE extended; TFmode is __float128
|
||||||
is IEEE quad. Both these modes occupy 16 bytes, but XFmode
|
is IEEE quad. Both these modes occupy 16 bytes, but XFmode
|
||||||
only has 80 significant bits. */
|
only has 80 significant bits. RFmode is __fpreg is IA64 internal
|
||||||
|
register format with 82 significant bits but otherwise handled like
|
||||||
|
XFmode. */
|
||||||
|
|
||||||
FRACTIONAL_FLOAT_MODE (XF, 80, 16, ieee_extended_intel_128_format);
|
FRACTIONAL_FLOAT_MODE (XF, 80, 16, ieee_extended_intel_128_format);
|
||||||
|
FRACTIONAL_FLOAT_MODE (RF, 82, 16, ieee_extended_intel_128_format);
|
||||||
FLOAT_MODE (TF, 16, ieee_quad_format);
|
FLOAT_MODE (TF, 16, ieee_quad_format);
|
||||||
|
|
||||||
/* The above produces:
|
/* The above produces:
|
||||||
|
@ -54,6 +57,12 @@ ADJUST_FLOAT_FORMAT (XF, (TARGET_ILP32 && !TARGET_HPUX)
|
||||||
ADJUST_BYTESIZE (XF, (TARGET_ILP32 && !TARGET_HPUX) ? 12 : 16);
|
ADJUST_BYTESIZE (XF, (TARGET_ILP32 && !TARGET_HPUX) ? 12 : 16);
|
||||||
ADJUST_ALIGNMENT (XF, (TARGET_ILP32 && !TARGET_HPUX) ? 4 : 16);
|
ADJUST_ALIGNMENT (XF, (TARGET_ILP32 && !TARGET_HPUX) ? 4 : 16);
|
||||||
|
|
||||||
|
ADJUST_FLOAT_FORMAT (RF, (TARGET_ILP32 && !TARGET_HPUX)
|
||||||
|
? &ieee_extended_intel_96_format
|
||||||
|
: &ieee_extended_intel_128_format);
|
||||||
|
ADJUST_BYTESIZE (RF, (TARGET_ILP32 && !TARGET_HPUX) ? 12 : 16);
|
||||||
|
ADJUST_ALIGNMENT (RF, (TARGET_ILP32 && !TARGET_HPUX) ? 4 : 16);
|
||||||
|
|
||||||
ADJUST_ALIGNMENT (TF, (TARGET_ILP32 && TARGET_HPUX) ? 8 : 16);
|
ADJUST_ALIGNMENT (TF, (TARGET_ILP32 && TARGET_HPUX) ? 8 : 16);
|
||||||
|
|
||||||
/* 256-bit integer mode is needed for STACK_SAVEAREA_MODE. */
|
/* 256-bit integer mode is needed for STACK_SAVEAREA_MODE. */
|
||||||
|
|
|
@ -45,7 +45,7 @@ extern int addp4_optimize_ok (rtx, rtx);
|
||||||
extern void ia64_emit_cond_move (rtx, rtx, rtx);
|
extern void ia64_emit_cond_move (rtx, rtx, rtx);
|
||||||
extern int ia64_depz_field_mask (rtx, rtx);
|
extern int ia64_depz_field_mask (rtx, rtx);
|
||||||
extern void ia64_split_tmode_move (rtx[]);
|
extern void ia64_split_tmode_move (rtx[]);
|
||||||
extern rtx spill_xfmode_operand (rtx, int);
|
extern bool ia64_expand_movxf_movrf (enum machine_mode, rtx[]);
|
||||||
extern rtx ia64_expand_compare (enum rtx_code, enum machine_mode);
|
extern rtx ia64_expand_compare (enum rtx_code, enum machine_mode);
|
||||||
extern void ia64_expand_vecint_cmov (rtx[]);
|
extern void ia64_expand_vecint_cmov (rtx[]);
|
||||||
extern bool ia64_expand_vecint_minmax (enum rtx_code, enum machine_mode, rtx[]);
|
extern bool ia64_expand_vecint_minmax (enum rtx_code, enum machine_mode, rtx[]);
|
||||||
|
|
|
@ -52,6 +52,7 @@ Boston, MA 02110-1301, USA. */
|
||||||
#include "langhooks.h"
|
#include "langhooks.h"
|
||||||
#include "cfglayout.h"
|
#include "cfglayout.h"
|
||||||
#include "tree-gimple.h"
|
#include "tree-gimple.h"
|
||||||
|
#include "intl.h"
|
||||||
|
|
||||||
/* This is used for communication between ASM_OUTPUT_LABEL and
|
/* This is used for communication between ASM_OUTPUT_LABEL and
|
||||||
ASM_OUTPUT_LABELREF. */
|
ASM_OUTPUT_LABELREF. */
|
||||||
|
@ -263,6 +264,9 @@ static bool ia64_scalar_mode_supported_p (enum machine_mode mode);
|
||||||
static bool ia64_vector_mode_supported_p (enum machine_mode mode);
|
static bool ia64_vector_mode_supported_p (enum machine_mode mode);
|
||||||
static bool ia64_cannot_force_const_mem (rtx);
|
static bool ia64_cannot_force_const_mem (rtx);
|
||||||
static const char *ia64_mangle_fundamental_type (tree);
|
static const char *ia64_mangle_fundamental_type (tree);
|
||||||
|
static const char *ia64_invalid_conversion (tree, tree);
|
||||||
|
static const char *ia64_invalid_unary_op (int, tree);
|
||||||
|
static const char *ia64_invalid_binary_op (int, tree, tree);
|
||||||
|
|
||||||
/* Table of valid machine attributes. */
|
/* Table of valid machine attributes. */
|
||||||
static const struct attribute_spec ia64_attribute_table[] =
|
static const struct attribute_spec ia64_attribute_table[] =
|
||||||
|
@ -433,6 +437,13 @@ static const struct attribute_spec ia64_attribute_table[] =
|
||||||
#undef TARGET_MANGLE_FUNDAMENTAL_TYPE
|
#undef TARGET_MANGLE_FUNDAMENTAL_TYPE
|
||||||
#define TARGET_MANGLE_FUNDAMENTAL_TYPE ia64_mangle_fundamental_type
|
#define TARGET_MANGLE_FUNDAMENTAL_TYPE ia64_mangle_fundamental_type
|
||||||
|
|
||||||
|
#undef TARGET_INVALID_CONVERSION
|
||||||
|
#define TARGET_INVALID_CONVERSION ia64_invalid_conversion
|
||||||
|
#undef TARGET_INVALID_UNARY_OP
|
||||||
|
#define TARGET_INVALID_UNARY_OP ia64_invalid_unary_op
|
||||||
|
#undef TARGET_INVALID_BINARY_OP
|
||||||
|
#define TARGET_INVALID_BINARY_OP ia64_invalid_binary_op
|
||||||
|
|
||||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
|
@ -1285,8 +1296,8 @@ ia64_split_tmode_move (rtx operands[])
|
||||||
This solution attempts to prevent this situation from occurring. When
|
This solution attempts to prevent this situation from occurring. When
|
||||||
we see something like the above, we spill the inner register to memory. */
|
we see something like the above, we spill the inner register to memory. */
|
||||||
|
|
||||||
rtx
|
static rtx
|
||||||
spill_xfmode_operand (rtx in, int force)
|
spill_xfmode_rfmode_operand (rtx in, int force, enum machine_mode mode)
|
||||||
{
|
{
|
||||||
if (GET_CODE (in) == SUBREG
|
if (GET_CODE (in) == SUBREG
|
||||||
&& GET_MODE (SUBREG_REG (in)) == TImode
|
&& GET_MODE (SUBREG_REG (in)) == TImode
|
||||||
|
@ -1294,11 +1305,11 @@ spill_xfmode_operand (rtx in, int force)
|
||||||
{
|
{
|
||||||
rtx memt = assign_stack_temp (TImode, 16, 0);
|
rtx memt = assign_stack_temp (TImode, 16, 0);
|
||||||
emit_move_insn (memt, SUBREG_REG (in));
|
emit_move_insn (memt, SUBREG_REG (in));
|
||||||
return adjust_address (memt, XFmode, 0);
|
return adjust_address (memt, mode, 0);
|
||||||
}
|
}
|
||||||
else if (force && GET_CODE (in) == REG)
|
else if (force && GET_CODE (in) == REG)
|
||||||
{
|
{
|
||||||
rtx memx = assign_stack_temp (XFmode, 16, 0);
|
rtx memx = assign_stack_temp (mode, 16, 0);
|
||||||
emit_move_insn (memx, in);
|
emit_move_insn (memx, in);
|
||||||
return memx;
|
return memx;
|
||||||
}
|
}
|
||||||
|
@ -1306,6 +1317,132 @@ spill_xfmode_operand (rtx in, int force)
|
||||||
return in;
|
return in;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Expand the movxf or movrf pattern (MODE says which) with the given
|
||||||
|
OPERANDS, returning true if the pattern should then invoke
|
||||||
|
DONE. */
|
||||||
|
|
||||||
|
bool
|
||||||
|
ia64_expand_movxf_movrf (enum machine_mode mode, rtx operands[])
|
||||||
|
{
|
||||||
|
rtx op0 = operands[0];
|
||||||
|
|
||||||
|
if (GET_CODE (op0) == SUBREG)
|
||||||
|
op0 = SUBREG_REG (op0);
|
||||||
|
|
||||||
|
/* We must support XFmode loads into general registers for stdarg/vararg,
|
||||||
|
unprototyped calls, and a rare case where a long double is passed as
|
||||||
|
an argument after a float HFA fills the FP registers. We split them into
|
||||||
|
DImode loads for convenience. We also need to support XFmode stores
|
||||||
|
for the last case. This case does not happen for stdarg/vararg routines,
|
||||||
|
because we do a block store to memory of unnamed arguments. */
|
||||||
|
|
||||||
|
if (GET_CODE (op0) == REG && GR_REGNO_P (REGNO (op0)))
|
||||||
|
{
|
||||||
|
rtx out[2];
|
||||||
|
|
||||||
|
/* We're hoping to transform everything that deals with XFmode
|
||||||
|
quantities and GR registers early in the compiler. */
|
||||||
|
gcc_assert (!no_new_pseudos);
|
||||||
|
|
||||||
|
/* Struct to register can just use TImode instead. */
|
||||||
|
if ((GET_CODE (operands[1]) == SUBREG
|
||||||
|
&& GET_MODE (SUBREG_REG (operands[1])) == TImode)
|
||||||
|
|| (GET_CODE (operands[1]) == REG
|
||||||
|
&& GR_REGNO_P (REGNO (operands[1]))))
|
||||||
|
{
|
||||||
|
rtx op1 = operands[1];
|
||||||
|
|
||||||
|
if (GET_CODE (op1) == SUBREG)
|
||||||
|
op1 = SUBREG_REG (op1);
|
||||||
|
else
|
||||||
|
op1 = gen_rtx_REG (TImode, REGNO (op1));
|
||||||
|
|
||||||
|
emit_move_insn (gen_rtx_REG (TImode, REGNO (op0)), op1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GET_CODE (operands[1]) == CONST_DOUBLE)
|
||||||
|
{
|
||||||
|
emit_move_insn (gen_rtx_REG (DImode, REGNO (op0)),
|
||||||
|
operand_subword (operands[1], 0, 0, mode));
|
||||||
|
emit_move_insn (gen_rtx_REG (DImode, REGNO (op0) + 1),
|
||||||
|
operand_subword (operands[1], 1, 0, mode));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the quantity is in a register not known to be GR, spill it. */
|
||||||
|
if (register_operand (operands[1], mode))
|
||||||
|
operands[1] = spill_xfmode_rfmode_operand (operands[1], 1, mode);
|
||||||
|
|
||||||
|
gcc_assert (GET_CODE (operands[1]) == MEM);
|
||||||
|
|
||||||
|
out[WORDS_BIG_ENDIAN] = gen_rtx_REG (DImode, REGNO (op0));
|
||||||
|
out[!WORDS_BIG_ENDIAN] = gen_rtx_REG (DImode, REGNO (op0) + 1);
|
||||||
|
|
||||||
|
emit_move_insn (out[0], adjust_address (operands[1], DImode, 0));
|
||||||
|
emit_move_insn (out[1], adjust_address (operands[1], DImode, 8));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GET_CODE (operands[1]) == REG && GR_REGNO_P (REGNO (operands[1])))
|
||||||
|
{
|
||||||
|
/* We're hoping to transform everything that deals with XFmode
|
||||||
|
quantities and GR registers early in the compiler. */
|
||||||
|
gcc_assert (!no_new_pseudos);
|
||||||
|
|
||||||
|
/* Op0 can't be a GR_REG here, as that case is handled above.
|
||||||
|
If op0 is a register, then we spill op1, so that we now have a
|
||||||
|
MEM operand. This requires creating an XFmode subreg of a TImode reg
|
||||||
|
to force the spill. */
|
||||||
|
if (register_operand (operands[0], mode))
|
||||||
|
{
|
||||||
|
rtx op1 = gen_rtx_REG (TImode, REGNO (operands[1]));
|
||||||
|
op1 = gen_rtx_SUBREG (mode, op1, 0);
|
||||||
|
operands[1] = spill_xfmode_rfmode_operand (op1, 0, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rtx in[2];
|
||||||
|
|
||||||
|
gcc_assert (GET_CODE (operands[0]) == MEM);
|
||||||
|
in[WORDS_BIG_ENDIAN] = gen_rtx_REG (DImode, REGNO (operands[1]));
|
||||||
|
in[!WORDS_BIG_ENDIAN] = gen_rtx_REG (DImode, REGNO (operands[1]) + 1);
|
||||||
|
|
||||||
|
emit_move_insn (adjust_address (operands[0], DImode, 0), in[0]);
|
||||||
|
emit_move_insn (adjust_address (operands[0], DImode, 8), in[1]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!reload_in_progress && !reload_completed)
|
||||||
|
{
|
||||||
|
operands[1] = spill_xfmode_rfmode_operand (operands[1], 0, mode);
|
||||||
|
|
||||||
|
if (GET_MODE (op0) == TImode && GET_CODE (op0) == REG)
|
||||||
|
{
|
||||||
|
rtx memt, memx, in = operands[1];
|
||||||
|
if (CONSTANT_P (in))
|
||||||
|
in = validize_mem (force_const_mem (mode, in));
|
||||||
|
if (GET_CODE (in) == MEM)
|
||||||
|
memt = adjust_address (in, TImode, 0);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memt = assign_stack_temp (TImode, 16, 0);
|
||||||
|
memx = adjust_address (memt, mode, 0);
|
||||||
|
emit_move_insn (memx, in);
|
||||||
|
}
|
||||||
|
emit_move_insn (op0, memt);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ia64_move_ok (operands[0], operands[1]))
|
||||||
|
operands[1] = force_reg (mode, operands[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/* Emit comparison instruction if necessary, returning the expression
|
/* Emit comparison instruction if necessary, returning the expression
|
||||||
that holds the compare result in the proper mode. */
|
that holds the compare result in the proper mode. */
|
||||||
|
|
||||||
|
@ -3839,9 +3976,9 @@ ia64_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
|
||||||
gen_rtx_EXPR_LIST (VOIDmode,
|
gen_rtx_EXPR_LIST (VOIDmode,
|
||||||
gen_rtx_REG (DImode, basereg + cum->words + offset),
|
gen_rtx_REG (DImode, basereg + cum->words + offset),
|
||||||
const0_rtx)));
|
const0_rtx)));
|
||||||
/* Similarly, an anonymous XFmode value must be split into two
|
/* Similarly, an anonymous XFmode or RFmode value must be split
|
||||||
registers and padded appropriately. */
|
into two registers and padded appropriately. */
|
||||||
else if (BYTES_BIG_ENDIAN && mode == XFmode)
|
else if (BYTES_BIG_ENDIAN && (mode == XFmode || mode == RFmode))
|
||||||
{
|
{
|
||||||
rtx loc[2];
|
rtx loc[2];
|
||||||
loc[0] = gen_rtx_EXPR_LIST (VOIDmode,
|
loc[0] = gen_rtx_EXPR_LIST (VOIDmode,
|
||||||
|
@ -4159,7 +4296,7 @@ ia64_function_value (tree valtype, tree func ATTRIBUTE_UNUSED)
|
||||||
the middle-end will give it XFmode anyway, and XFmode values
|
the middle-end will give it XFmode anyway, and XFmode values
|
||||||
don't normally fit in integer registers. So we need to smuggle
|
don't normally fit in integer registers. So we need to smuggle
|
||||||
the value inside a parallel. */
|
the value inside a parallel. */
|
||||||
else if (mode == XFmode || mode == XCmode)
|
else if (mode == XFmode || mode == XCmode || mode == RFmode)
|
||||||
need_parallel = true;
|
need_parallel = true;
|
||||||
|
|
||||||
if (need_parallel)
|
if (need_parallel)
|
||||||
|
@ -4574,7 +4711,7 @@ ia64_register_move_cost (enum machine_mode mode, enum reg_class from,
|
||||||
so that we get secondary memory reloads. Between FR_REGS,
|
so that we get secondary memory reloads. Between FR_REGS,
|
||||||
we have to make this at least as expensive as MEMORY_MOVE_COST
|
we have to make this at least as expensive as MEMORY_MOVE_COST
|
||||||
to avoid spectacularly poor register class preferencing. */
|
to avoid spectacularly poor register class preferencing. */
|
||||||
if (mode == XFmode)
|
if (mode == XFmode || mode == RFmode)
|
||||||
{
|
{
|
||||||
if (to != GR_REGS || from != GR_REGS)
|
if (to != GR_REGS || from != GR_REGS)
|
||||||
return MEMORY_MOVE_COST (mode, to, 0);
|
return MEMORY_MOVE_COST (mode, to, 0);
|
||||||
|
@ -8058,9 +8195,7 @@ ia64_init_builtins (void)
|
||||||
|
|
||||||
/* The __fpreg type. */
|
/* The __fpreg type. */
|
||||||
fpreg_type = make_node (REAL_TYPE);
|
fpreg_type = make_node (REAL_TYPE);
|
||||||
/* ??? The back end should know to load/save __fpreg variables using
|
TYPE_PRECISION (fpreg_type) = 82;
|
||||||
the ldf.fill and stf.spill instructions. */
|
|
||||||
TYPE_PRECISION (fpreg_type) = 80;
|
|
||||||
layout_type (fpreg_type);
|
layout_type (fpreg_type);
|
||||||
(*lang_hooks.types.register_builtin_type) (fpreg_type, "__fpreg");
|
(*lang_hooks.types.register_builtin_type) (fpreg_type, "__fpreg");
|
||||||
|
|
||||||
|
@ -8549,6 +8684,7 @@ ia64_scalar_mode_supported_p (enum machine_mode mode)
|
||||||
case SFmode:
|
case SFmode:
|
||||||
case DFmode:
|
case DFmode:
|
||||||
case XFmode:
|
case XFmode:
|
||||||
|
case RFmode:
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case TFmode:
|
case TFmode:
|
||||||
|
@ -8659,6 +8795,48 @@ ia64_mangle_fundamental_type (tree type)
|
||||||
double is 80 bits. */
|
double is 80 bits. */
|
||||||
if (TYPE_MODE (type) == XFmode)
|
if (TYPE_MODE (type) == XFmode)
|
||||||
return TARGET_HPUX ? "u9__float80" : "e";
|
return TARGET_HPUX ? "u9__float80" : "e";
|
||||||
|
if (TYPE_MODE (type) == RFmode)
|
||||||
|
return "u7__fpreg";
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the diagnostic message string if conversion from FROMTYPE to
|
||||||
|
TOTYPE is not allowed, NULL otherwise. */
|
||||||
|
static const char *
|
||||||
|
ia64_invalid_conversion (tree fromtype, tree totype)
|
||||||
|
{
|
||||||
|
/* Reject nontrivial conversion to or from __fpreg. */
|
||||||
|
if (TYPE_MODE (fromtype) == RFmode
|
||||||
|
&& TYPE_MODE (totype) != RFmode
|
||||||
|
&& TYPE_MODE (totype) != VOIDmode)
|
||||||
|
return N_("invalid conversion from %<__fpreg%>");
|
||||||
|
if (TYPE_MODE (totype) == RFmode
|
||||||
|
&& TYPE_MODE (fromtype) != RFmode)
|
||||||
|
return N_("invalid conversion to %<__fpreg%>");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the diagnostic message string if the unary operation OP is
|
||||||
|
not permitted on TYPE, NULL otherwise. */
|
||||||
|
static const char *
|
||||||
|
ia64_invalid_unary_op (int op, tree type)
|
||||||
|
{
|
||||||
|
/* Reject operations on __fpreg other than unary + or &. */
|
||||||
|
if (TYPE_MODE (type) == RFmode
|
||||||
|
&& op != CONVERT_EXPR
|
||||||
|
&& op != ADDR_EXPR)
|
||||||
|
return N_("invalid operation on %<__fpreg%>");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the diagnostic message string if the binary operation OP is
|
||||||
|
not permitted on TYPE1 and TYPE2, NULL otherwise. */
|
||||||
|
static const char *
|
||||||
|
ia64_invalid_binary_op (int op ATTRIBUTE_UNUSED, tree type1, tree type2)
|
||||||
|
{
|
||||||
|
/* Reject operations on __fpreg. */
|
||||||
|
if (TYPE_MODE (type1) == RFmode || TYPE_MODE (type2) == RFmode)
|
||||||
|
return N_("invalid operation on %<__fpreg%>");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -736,121 +736,8 @@
|
||||||
(match_operand:XF 1 "general_operand" ""))]
|
(match_operand:XF 1 "general_operand" ""))]
|
||||||
""
|
""
|
||||||
{
|
{
|
||||||
rtx op0 = operands[0];
|
if (ia64_expand_movxf_movrf (XFmode, operands))
|
||||||
|
|
||||||
if (GET_CODE (op0) == SUBREG)
|
|
||||||
op0 = SUBREG_REG (op0);
|
|
||||||
|
|
||||||
/* We must support XFmode loads into general registers for stdarg/vararg,
|
|
||||||
unprototyped calls, and a rare case where a long double is passed as
|
|
||||||
an argument after a float HFA fills the FP registers. We split them into
|
|
||||||
DImode loads for convenience. We also need to support XFmode stores
|
|
||||||
for the last case. This case does not happen for stdarg/vararg routines,
|
|
||||||
because we do a block store to memory of unnamed arguments. */
|
|
||||||
|
|
||||||
if (GET_CODE (op0) == REG && GR_REGNO_P (REGNO (op0)))
|
|
||||||
{
|
|
||||||
rtx out[2];
|
|
||||||
|
|
||||||
/* We're hoping to transform everything that deals with XFmode
|
|
||||||
quantities and GR registers early in the compiler. */
|
|
||||||
gcc_assert (!no_new_pseudos);
|
|
||||||
|
|
||||||
/* Struct to register can just use TImode instead. */
|
|
||||||
if ((GET_CODE (operands[1]) == SUBREG
|
|
||||||
&& GET_MODE (SUBREG_REG (operands[1])) == TImode)
|
|
||||||
|| (GET_CODE (operands[1]) == REG
|
|
||||||
&& GR_REGNO_P (REGNO (operands[1]))))
|
|
||||||
{
|
|
||||||
rtx op1 = operands[1];
|
|
||||||
|
|
||||||
if (GET_CODE (op1) == SUBREG)
|
|
||||||
op1 = SUBREG_REG (op1);
|
|
||||||
else
|
|
||||||
op1 = gen_rtx_REG (TImode, REGNO (op1));
|
|
||||||
|
|
||||||
emit_move_insn (gen_rtx_REG (TImode, REGNO (op0)), op1);
|
|
||||||
DONE;
|
DONE;
|
||||||
}
|
|
||||||
|
|
||||||
if (GET_CODE (operands[1]) == CONST_DOUBLE)
|
|
||||||
{
|
|
||||||
emit_move_insn (gen_rtx_REG (DImode, REGNO (op0)),
|
|
||||||
operand_subword (operands[1], 0, 0, XFmode));
|
|
||||||
emit_move_insn (gen_rtx_REG (DImode, REGNO (op0) + 1),
|
|
||||||
operand_subword (operands[1], 1, 0, XFmode));
|
|
||||||
DONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If the quantity is in a register not known to be GR, spill it. */
|
|
||||||
if (register_operand (operands[1], XFmode))
|
|
||||||
operands[1] = spill_xfmode_operand (operands[1], 1);
|
|
||||||
|
|
||||||
gcc_assert (GET_CODE (operands[1]) == MEM);
|
|
||||||
|
|
||||||
out[WORDS_BIG_ENDIAN] = gen_rtx_REG (DImode, REGNO (op0));
|
|
||||||
out[!WORDS_BIG_ENDIAN] = gen_rtx_REG (DImode, REGNO (op0) + 1);
|
|
||||||
|
|
||||||
emit_move_insn (out[0], adjust_address (operands[1], DImode, 0));
|
|
||||||
emit_move_insn (out[1], adjust_address (operands[1], DImode, 8));
|
|
||||||
DONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (GET_CODE (operands[1]) == REG && GR_REGNO_P (REGNO (operands[1])))
|
|
||||||
{
|
|
||||||
/* We're hoping to transform everything that deals with XFmode
|
|
||||||
quantities and GR registers early in the compiler. */
|
|
||||||
gcc_assert (!no_new_pseudos);
|
|
||||||
|
|
||||||
/* Op0 can't be a GR_REG here, as that case is handled above.
|
|
||||||
If op0 is a register, then we spill op1, so that we now have a
|
|
||||||
MEM operand. This requires creating an XFmode subreg of a TImode reg
|
|
||||||
to force the spill. */
|
|
||||||
if (register_operand (operands[0], XFmode))
|
|
||||||
{
|
|
||||||
rtx op1 = gen_rtx_REG (TImode, REGNO (operands[1]));
|
|
||||||
op1 = gen_rtx_SUBREG (XFmode, op1, 0);
|
|
||||||
operands[1] = spill_xfmode_operand (op1, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rtx in[2];
|
|
||||||
|
|
||||||
gcc_assert (GET_CODE (operands[0]) == MEM);
|
|
||||||
in[WORDS_BIG_ENDIAN] = gen_rtx_REG (DImode, REGNO (operands[1]));
|
|
||||||
in[!WORDS_BIG_ENDIAN] = gen_rtx_REG (DImode, REGNO (operands[1]) + 1);
|
|
||||||
|
|
||||||
emit_move_insn (adjust_address (operands[0], DImode, 0), in[0]);
|
|
||||||
emit_move_insn (adjust_address (operands[0], DImode, 8), in[1]);
|
|
||||||
DONE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! reload_in_progress && ! reload_completed)
|
|
||||||
{
|
|
||||||
operands[1] = spill_xfmode_operand (operands[1], 0);
|
|
||||||
|
|
||||||
if (GET_MODE (op0) == TImode && GET_CODE (op0) == REG)
|
|
||||||
{
|
|
||||||
rtx memt, memx, in = operands[1];
|
|
||||||
if (CONSTANT_P (in))
|
|
||||||
in = validize_mem (force_const_mem (XFmode, in));
|
|
||||||
if (GET_CODE (in) == MEM)
|
|
||||||
memt = adjust_address (in, TImode, 0);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
memt = assign_stack_temp (TImode, 16, 0);
|
|
||||||
memx = adjust_address (memt, XFmode, 0);
|
|
||||||
emit_move_insn (memx, in);
|
|
||||||
}
|
|
||||||
emit_move_insn (op0, memt);
|
|
||||||
DONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! ia64_move_ok (operands[0], operands[1]))
|
|
||||||
operands[1] = force_reg (XFmode, operands[1]);
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
;; ??? There's no easy way to mind volatile acquire/release semantics.
|
;; ??? There's no easy way to mind volatile acquire/release semantics.
|
||||||
|
@ -865,6 +752,26 @@
|
||||||
stfe %0 = %F1%P0"
|
stfe %0 = %F1%P0"
|
||||||
[(set_attr "itanium_class" "fmisc,fld,stf")])
|
[(set_attr "itanium_class" "fmisc,fld,stf")])
|
||||||
|
|
||||||
|
;; Same as for movxf, but for RFmode.
|
||||||
|
(define_expand "movrf"
|
||||||
|
[(set (match_operand:RF 0 "general_operand" "")
|
||||||
|
(match_operand:RF 1 "general_operand" ""))]
|
||||||
|
""
|
||||||
|
{
|
||||||
|
if (ia64_expand_movxf_movrf (RFmode, operands))
|
||||||
|
DONE;
|
||||||
|
})
|
||||||
|
|
||||||
|
(define_insn "*movrf_internal"
|
||||||
|
[(set (match_operand:RF 0 "destination_operand" "=f,f, m")
|
||||||
|
(match_operand:RF 1 "general_operand" "fG,m,fG"))]
|
||||||
|
"ia64_move_ok (operands[0], operands[1])"
|
||||||
|
"@
|
||||||
|
mov %0 = %F1
|
||||||
|
ldf.fill %0 = %1%P1
|
||||||
|
stf.spill %0 = %F1%P0"
|
||||||
|
[(set_attr "itanium_class" "fmisc,fld,stf")])
|
||||||
|
|
||||||
;; Better code generation via insns that deal with TFmode register pairs
|
;; Better code generation via insns that deal with TFmode register pairs
|
||||||
;; directly. Same concerns apply as for TImode.
|
;; directly. Same concerns apply as for TImode.
|
||||||
(define_expand "movtf"
|
(define_expand "movtf"
|
||||||
|
|
|
@ -1,3 +1,9 @@
|
||||||
|
2005-06-28 Joseph S. Myers <joseph@codesourcery.com>
|
||||||
|
|
||||||
|
* cvt.c (ocp_convert): Use invalid_conversion hook.
|
||||||
|
* typeck.c (build_binary_op): Use invalid_binary_op hook.
|
||||||
|
(build_unary_op): Use invalid_unary_op hook.
|
||||||
|
|
||||||
2005-06-28 Paul Brook <paul@codesourcery.com>
|
2005-06-28 Paul Brook <paul@codesourcery.com>
|
||||||
|
|
||||||
* Make-lang.in (cp/except.o): Depend on $(TARGET_H)
|
* Make-lang.in (cp/except.o): Depend on $(TARGET_H)
|
||||||
|
|
|
@ -36,6 +36,7 @@ Boston, MA 02110-1301, USA. */
|
||||||
#include "convert.h"
|
#include "convert.h"
|
||||||
#include "toplev.h"
|
#include "toplev.h"
|
||||||
#include "decl.h"
|
#include "decl.h"
|
||||||
|
#include "target.h"
|
||||||
|
|
||||||
static tree cp_convert_to_pointer (tree, tree, bool);
|
static tree cp_convert_to_pointer (tree, tree, bool);
|
||||||
static tree convert_to_pointer_force (tree, tree);
|
static tree convert_to_pointer_force (tree, tree);
|
||||||
|
@ -601,6 +602,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
|
||||||
{
|
{
|
||||||
tree e = expr;
|
tree e = expr;
|
||||||
enum tree_code code = TREE_CODE (type);
|
enum tree_code code = TREE_CODE (type);
|
||||||
|
const char *invalid_conv_diag;
|
||||||
|
|
||||||
if (error_operand_p (e) || type == error_mark_node)
|
if (error_operand_p (e) || type == error_mark_node)
|
||||||
return error_mark_node;
|
return error_mark_node;
|
||||||
|
@ -608,6 +610,13 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
|
||||||
complete_type (type);
|
complete_type (type);
|
||||||
complete_type (TREE_TYPE (expr));
|
complete_type (TREE_TYPE (expr));
|
||||||
|
|
||||||
|
if ((invalid_conv_diag
|
||||||
|
= targetm.invalid_conversion (TREE_TYPE (expr), type)))
|
||||||
|
{
|
||||||
|
error (invalid_conv_diag);
|
||||||
|
return error_mark_node;
|
||||||
|
}
|
||||||
|
|
||||||
e = integral_constant_value (e);
|
e = integral_constant_value (e);
|
||||||
|
|
||||||
if (IS_AGGR_TYPE (type) && (convtype & CONV_FORCE_TEMP)
|
if (IS_AGGR_TYPE (type) && (convtype & CONV_FORCE_TEMP)
|
||||||
|
|
|
@ -2736,6 +2736,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
|
||||||
tree op0, op1;
|
tree op0, op1;
|
||||||
enum tree_code code0, code1;
|
enum tree_code code0, code1;
|
||||||
tree type0, type1;
|
tree type0, type1;
|
||||||
|
const char *invalid_op_diag;
|
||||||
|
|
||||||
/* Expression code to give to the expression when it is built.
|
/* Expression code to give to the expression when it is built.
|
||||||
Normally this is CODE, which is what the caller asked for,
|
Normally this is CODE, which is what the caller asked for,
|
||||||
|
@ -2845,6 +2846,13 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
|
||||||
if (code0 == ERROR_MARK || code1 == ERROR_MARK)
|
if (code0 == ERROR_MARK || code1 == ERROR_MARK)
|
||||||
return error_mark_node;
|
return error_mark_node;
|
||||||
|
|
||||||
|
if ((invalid_op_diag
|
||||||
|
= targetm.invalid_binary_op (code, type0, type1)))
|
||||||
|
{
|
||||||
|
error (invalid_op_diag);
|
||||||
|
return error_mark_node;
|
||||||
|
}
|
||||||
|
|
||||||
switch (code)
|
switch (code)
|
||||||
{
|
{
|
||||||
case PLUS_EXPR:
|
case PLUS_EXPR:
|
||||||
|
@ -3725,10 +3733,21 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
|
||||||
tree argtype = 0;
|
tree argtype = 0;
|
||||||
const char *errstring = NULL;
|
const char *errstring = NULL;
|
||||||
tree val;
|
tree val;
|
||||||
|
const char *invalid_op_diag;
|
||||||
|
|
||||||
if (arg == error_mark_node)
|
if (arg == error_mark_node)
|
||||||
return error_mark_node;
|
return error_mark_node;
|
||||||
|
|
||||||
|
if ((invalid_op_diag
|
||||||
|
= targetm.invalid_unary_op ((code == UNARY_PLUS_EXPR
|
||||||
|
? CONVERT_EXPR
|
||||||
|
: code),
|
||||||
|
TREE_TYPE (xarg))))
|
||||||
|
{
|
||||||
|
error (invalid_op_diag);
|
||||||
|
return error_mark_node;
|
||||||
|
}
|
||||||
|
|
||||||
switch (code)
|
switch (code)
|
||||||
{
|
{
|
||||||
case UNARY_PLUS_EXPR:
|
case UNARY_PLUS_EXPR:
|
||||||
|
|
|
@ -9606,6 +9606,26 @@ illegal to pass argument @var{val} to function @var{funcdecl}
|
||||||
with prototype @var{typelist}.
|
with prototype @var{typelist}.
|
||||||
@end deftypefn
|
@end deftypefn
|
||||||
|
|
||||||
|
@deftypefn {Target Hook} {const char *} TARGET_INVALID_CONVERSION (tree @var{fromtype}, tree @var{totype})
|
||||||
|
If defined, this macro returns the diagnostic message when it is
|
||||||
|
invalid to convert from @var{fromtype} to @var{totype}, or @code{NULL}
|
||||||
|
if validity should be determined by the front end.
|
||||||
|
@end deftypefn
|
||||||
|
|
||||||
|
@deftypefn {Target Hook} {const char *} TARGET_INVALID_UNARY_OP (int @var{op}, tree @var{type})
|
||||||
|
If defined, this macro returns the diagnostic message when it is
|
||||||
|
invalid to apply operation @var{op} (where unary plus is denoted by
|
||||||
|
@code{CONVERT_EXPR}) to an operand of type @var{type}, or @code{NULL}
|
||||||
|
if validity should be determined by the front end.
|
||||||
|
@end deftypefn
|
||||||
|
|
||||||
|
@deftypefn {Target Hook} {const char *} TARGET_INVALID_BINARY_OP (int @var{op}, tree @var{type1}, tree @var{type2})
|
||||||
|
If defined, this macro returns the diagnostic message when it is
|
||||||
|
invalid to apply operation @var{op} to operands of types @var{type1}
|
||||||
|
and @var{type2}, or @code{NULL} if validity should be determined by
|
||||||
|
the front end.
|
||||||
|
@end deftypefn
|
||||||
|
|
||||||
@defmac TARGET_USE_JCR_SECTION
|
@defmac TARGET_USE_JCR_SECTION
|
||||||
This macro determines whether to use the JCR section to register Java
|
This macro determines whether to use the JCR section to register Java
|
||||||
classes. By default, TARGET_USE_JCR_SECTION is defined to 1 if both
|
classes. By default, TARGET_USE_JCR_SECTION is defined to 1 if both
|
||||||
|
|
22
gcc/hooks.c
22
gcc/hooks.c
|
@ -256,3 +256,25 @@ hook_constcharptr_rtx_null (rtx r ATTRIBUTE_UNUSED)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
hook_constcharptr_tree_tree_null (tree t0 ATTRIBUTE_UNUSED,
|
||||||
|
tree t1 ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
hook_constcharptr_int_tree_null (int i ATTRIBUTE_UNUSED,
|
||||||
|
tree t0 ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
hook_constcharptr_int_tree_tree_null (int i ATTRIBUTE_UNUSED,
|
||||||
|
tree t0 ATTRIBUTE_UNUSED,
|
||||||
|
tree t1 ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
|
@ -66,4 +66,7 @@ extern tree hook_tree_tree_tree_tree_3rd_identity (tree, tree, tree);
|
||||||
extern const char *hook_constcharptr_tree_null (tree);
|
extern const char *hook_constcharptr_tree_null (tree);
|
||||||
extern tree hook_tree_tree_tree_bool_null (tree, tree, bool);
|
extern tree hook_tree_tree_tree_bool_null (tree, tree, bool);
|
||||||
extern const char *hook_constcharptr_rtx_null (rtx);
|
extern const char *hook_constcharptr_rtx_null (rtx);
|
||||||
|
extern const char *hook_constcharptr_tree_tree_null (tree, tree);
|
||||||
|
extern const char *hook_constcharptr_int_tree_null (int, tree);
|
||||||
|
extern const char *hook_constcharptr_int_tree_tree_null (int, tree, tree);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -379,6 +379,10 @@ Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
#define TARGET_INVALID_ARG_FOR_UNPROTOTYPED_FN hook_invalid_arg_for_unprototyped_fn
|
#define TARGET_INVALID_ARG_FOR_UNPROTOTYPED_FN hook_invalid_arg_for_unprototyped_fn
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define TARGET_INVALID_CONVERSION hook_constcharptr_tree_tree_null
|
||||||
|
#define TARGET_INVALID_UNARY_OP hook_constcharptr_int_tree_null
|
||||||
|
#define TARGET_INVALID_BINARY_OP hook_constcharptr_int_tree_tree_null
|
||||||
|
|
||||||
#define TARGET_FIXED_CONDITION_CODE_REGS hook_bool_uintp_uintp_false
|
#define TARGET_FIXED_CONDITION_CODE_REGS hook_bool_uintp_uintp_false
|
||||||
|
|
||||||
#define TARGET_CC_MODES_COMPATIBLE default_cc_modes_compatible
|
#define TARGET_CC_MODES_COMPATIBLE default_cc_modes_compatible
|
||||||
|
@ -581,6 +585,9 @@ Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
TARGET_STACK_PROTECT_FAIL, \
|
TARGET_STACK_PROTECT_FAIL, \
|
||||||
TARGET_INVALID_WITHIN_DOLOOP, \
|
TARGET_INVALID_WITHIN_DOLOOP, \
|
||||||
TARGET_CALLS, \
|
TARGET_CALLS, \
|
||||||
|
TARGET_INVALID_CONVERSION, \
|
||||||
|
TARGET_INVALID_UNARY_OP, \
|
||||||
|
TARGET_INVALID_BINARY_OP, \
|
||||||
TARGET_CXX, \
|
TARGET_CXX, \
|
||||||
TARGET_UNWIND_TABLES_DEFAULT, \
|
TARGET_UNWIND_TABLES_DEFAULT, \
|
||||||
TARGET_HAVE_NAMED_SECTIONS, \
|
TARGET_HAVE_NAMED_SECTIONS, \
|
||||||
|
|
12
gcc/target.h
12
gcc/target.h
|
@ -598,6 +598,18 @@ struct gcc_target
|
||||||
tree funcdecl, tree val);
|
tree funcdecl, tree val);
|
||||||
} calls;
|
} calls;
|
||||||
|
|
||||||
|
/* Return the diagnostic message string if conversion from FROMTYPE
|
||||||
|
to TOTYPE is not allowed, NULL otherwise. */
|
||||||
|
const char *(*invalid_conversion) (tree fromtype, tree totype);
|
||||||
|
|
||||||
|
/* Return the diagnostic message string if the unary operation OP is
|
||||||
|
not permitted on TYPE, NULL otherwise. */
|
||||||
|
const char *(*invalid_unary_op) (int op, tree type);
|
||||||
|
|
||||||
|
/* Return the diagnostic message string if the binary operation OP
|
||||||
|
is not permitted on TYPE1 and TYPE2, NULL otherwise. */
|
||||||
|
const char *(*invalid_binary_op) (int op, tree type1, tree type2);
|
||||||
|
|
||||||
/* Functions specific to the C++ frontend. */
|
/* Functions specific to the C++ frontend. */
|
||||||
struct cxx {
|
struct cxx {
|
||||||
/* Return the integer type used for guard variables. */
|
/* Return the integer type used for guard variables. */
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
2005-06-28 Joseph S. Myers <joseph@codesourcery.com>
|
||||||
|
|
||||||
|
* g++.dg/ext/fpreg1.C, gcc.target/ia64/fpreg-1.c,
|
||||||
|
gcc.target/ia64/fpreg-2.c: New tests.
|
||||||
|
|
||||||
2005-06-28 Francois-Xavier Coudert <coudert@clipper.ens.fr>
|
2005-06-28 Francois-Xavier Coudert <coudert@clipper.ens.fr>
|
||||||
|
|
||||||
* gfortran.dg/dev_null.f90: Run test only on linux and solaris.
|
* gfortran.dg/dev_null.f90: Run test only on linux and solaris.
|
||||||
|
|
|
@ -0,0 +1,82 @@
|
||||||
|
// Test permitted and invalid uses of __fpreg, for C++.
|
||||||
|
// Origin: Joseph Myers <joseph@codesourcery.com>
|
||||||
|
// { dg-do compile { target ia64-*-* } }
|
||||||
|
// { dg-options "" }
|
||||||
|
|
||||||
|
__float80 f80;
|
||||||
|
double d;
|
||||||
|
// Default initialized __fpreg is OK.
|
||||||
|
__fpreg fpreg, fpreg2;
|
||||||
|
// But explicitly zero-initialized is an invalid conversion.
|
||||||
|
__fpreg fi = 0; // { dg-error "error: invalid conversion to '__fpreg'" }
|
||||||
|
|
||||||
|
__fpreg f0 (__fpreg);
|
||||||
|
int f1 (__float80);
|
||||||
|
|
||||||
|
// __fpreg in a structure is OK.
|
||||||
|
struct s {
|
||||||
|
__float80 b;
|
||||||
|
__fpreg a;
|
||||||
|
} x;
|
||||||
|
|
||||||
|
void
|
||||||
|
f (void)
|
||||||
|
{
|
||||||
|
__fpreg *p;
|
||||||
|
// Valid operations.
|
||||||
|
fpreg = fpreg2;
|
||||||
|
fpreg2 = (__fpreg) fpreg;
|
||||||
|
fpreg = f0 (fpreg2);
|
||||||
|
fpreg = +fpreg2;
|
||||||
|
p = &fpreg;
|
||||||
|
(void) fpreg;
|
||||||
|
fpreg = x.a;
|
||||||
|
fpreg2 = (struct s) { 0 }.a;
|
||||||
|
fpreg = (d ? fpreg : fpreg2);
|
||||||
|
d = sizeof (fpreg);
|
||||||
|
(void)(fpreg, fpreg);
|
||||||
|
// Invalid operations.
|
||||||
|
++fpreg; // { dg-error "error: invalid operation on '__fpreg'" }
|
||||||
|
--fpreg; // { dg-error "error: invalid operation on '__fpreg'" }
|
||||||
|
fpreg++; // { dg-error "error: invalid operation on '__fpreg'" }
|
||||||
|
fpreg--; // { dg-error "error: invalid operation on '__fpreg'" }
|
||||||
|
fpreg = -fpreg; // { dg-error "error: invalid operation on '__fpreg'" }
|
||||||
|
fpreg = ~fpreg; // { dg-error "error: invalid operation on '__fpreg'" }
|
||||||
|
d = !fpreg; // { dg-error "error: invalid operation on '__fpreg'" }
|
||||||
|
d = *fpreg; // { dg-error "error: invalid type argument" }
|
||||||
|
if (fpreg) // { dg-error "error: invalid conversion from '__fpreg'" }
|
||||||
|
return;
|
||||||
|
d = fpreg; // { dg-error "error: invalid conversion from '__fpreg'" }
|
||||||
|
d = (double) fpreg; // { dg-error "error: invalid conversion from '__fpreg'" }
|
||||||
|
fpreg = (__fpreg) d; // { dg-error "error: invalid conversion to '__fpreg'" }
|
||||||
|
fpreg = fpreg * fpreg; // { dg-error "error: invalid operation on '__fpreg'" }
|
||||||
|
fpreg = fpreg / fpreg; // { dg-error "error: invalid operation on '__fpreg'" }
|
||||||
|
fpreg = fpreg % fpreg; // { dg-error "error: invalid operation on '__fpreg'" }
|
||||||
|
fpreg = fpreg + fpreg; // { dg-error "error: invalid operation on '__fpreg'" }
|
||||||
|
fpreg = fpreg - fpreg; // { dg-error "error: invalid operation on '__fpreg'" }
|
||||||
|
fpreg = fpreg << fpreg; // { dg-error "error: invalid operation on '__fpreg'" }
|
||||||
|
fpreg = fpreg >> fpreg; // { dg-error "error: invalid operation on '__fpreg'" }
|
||||||
|
d = fpreg < fpreg; // { dg-error "error: invalid operation on '__fpreg'" }
|
||||||
|
d = fpreg > fpreg; // { dg-error "error: invalid operation on '__fpreg'" }
|
||||||
|
d = fpreg <= fpreg; // { dg-error "error: invalid operation on '__fpreg'" }
|
||||||
|
d = fpreg >= fpreg; // { dg-error "error: invalid operation on '__fpreg'" }
|
||||||
|
d = fpreg == fpreg; // { dg-error "error: invalid operation on '__fpreg'" }
|
||||||
|
d = fpreg != fpreg; // { dg-error "error: invalid operation on '__fpreg'" }
|
||||||
|
d = fpreg & fpreg; // { dg-error "error: invalid operation on '__fpreg'" }
|
||||||
|
d = fpreg ^ fpreg; // { dg-error "error: invalid operation on '__fpreg'" }
|
||||||
|
d = fpreg | fpreg; // { dg-error "error: invalid operation on '__fpreg'" }
|
||||||
|
d = fpreg && fpreg; // { dg-error "error: invalid operation on '__fpreg'" }
|
||||||
|
d = fpreg || fpreg; // { dg-error "error: invalid operation on '__fpreg'" }
|
||||||
|
d = (fpreg ? 1 : 2); // { dg-error "error: invalid conversion from '__fpreg'" }
|
||||||
|
fpreg = (d ? fpreg : d); // { dg-error "error: invalid conversion to '__fpreg'" }
|
||||||
|
fpreg *= fpreg; // { dg-error "error: invalid operation on '__fpreg'|in evaluation" }
|
||||||
|
fpreg /= fpreg; // { dg-error "error: invalid operation on '__fpreg'|in evaluation" }
|
||||||
|
fpreg %= fpreg; // { dg-error "error: invalid operation on '__fpreg'|in evaluation" }
|
||||||
|
fpreg += fpreg; // { dg-error "error: invalid operation on '__fpreg'|in evaluation" }
|
||||||
|
fpreg -= fpreg; // { dg-error "error: invalid operation on '__fpreg'|in evaluation" }
|
||||||
|
fpreg <<= fpreg; // { dg-error "error: invalid operation on '__fpreg'|in evaluation" }
|
||||||
|
fpreg >>= fpreg; // { dg-error "error: invalid operation on '__fpreg'|in evaluation" }
|
||||||
|
fpreg &= fpreg; // { dg-error "error: invalid operation on '__fpreg'|in evaluation" }
|
||||||
|
fpreg ^= fpreg; // { dg-error "error: invalid operation on '__fpreg'|in evaluation" }
|
||||||
|
fpreg |= fpreg; // { dg-error "error: invalid operation on '__fpreg'|in evaluation" }
|
||||||
|
}
|
|
@ -0,0 +1,82 @@
|
||||||
|
/* Test permitted and invalid uses of __fpreg. */
|
||||||
|
/* Origin: Joseph Myers <joseph@codesourcery.com> */
|
||||||
|
/* { dg-do compile } */
|
||||||
|
/* { dg-options "" } */
|
||||||
|
|
||||||
|
__float80 f80;
|
||||||
|
double d;
|
||||||
|
/* Default initialized __fpreg is OK. */
|
||||||
|
__fpreg fpreg, fpreg2;
|
||||||
|
/* But explicitly zero-initialized is an invalid conversion. */
|
||||||
|
__fpreg fi = 0; /* { dg-error "error: invalid conversion to '__fpreg'" } */
|
||||||
|
|
||||||
|
__fpreg f0 (__fpreg);
|
||||||
|
int f1 (__float80);
|
||||||
|
|
||||||
|
/* __fpreg in a structure is OK. */
|
||||||
|
struct s {
|
||||||
|
__float80 b;
|
||||||
|
__fpreg a;
|
||||||
|
} x;
|
||||||
|
|
||||||
|
void
|
||||||
|
f (void)
|
||||||
|
{
|
||||||
|
__fpreg *p;
|
||||||
|
/* Valid operations. */
|
||||||
|
fpreg = fpreg2;
|
||||||
|
fpreg2 = (__fpreg) fpreg;
|
||||||
|
fpreg = f0 (fpreg2);
|
||||||
|
fpreg = +fpreg2;
|
||||||
|
p = &fpreg;
|
||||||
|
(void) fpreg;
|
||||||
|
fpreg = x.a;
|
||||||
|
fpreg2 = (struct s) { 0 }.a;
|
||||||
|
fpreg = (d ? fpreg : fpreg2);
|
||||||
|
d = sizeof (fpreg);
|
||||||
|
(void)(fpreg, fpreg);
|
||||||
|
/* Invalid operations. */
|
||||||
|
++fpreg; /* { dg-error "error: invalid operation on '__fpreg'" } */
|
||||||
|
--fpreg; /* { dg-error "error: invalid operation on '__fpreg'" } */
|
||||||
|
fpreg++; /* { dg-error "error: invalid operation on '__fpreg'" } */
|
||||||
|
fpreg--; /* { dg-error "error: invalid operation on '__fpreg'" } */
|
||||||
|
fpreg = -fpreg; /* { dg-error "error: invalid operation on '__fpreg'" } */
|
||||||
|
fpreg = ~fpreg; /* { dg-error "error: invalid operation on '__fpreg'" } */
|
||||||
|
d = !fpreg; /* { dg-error "error: invalid operation on '__fpreg'" } */
|
||||||
|
d = *fpreg; /* { dg-error "error: invalid type argument" } */
|
||||||
|
if (fpreg) /* { dg-error "error: invalid operation on '__fpreg'" } */
|
||||||
|
return;
|
||||||
|
d = fpreg; /* { dg-error "error: invalid conversion from '__fpreg'" } */
|
||||||
|
d = (double) fpreg; /* { dg-error "error: invalid conversion from '__fpreg'" } */
|
||||||
|
fpreg = (__fpreg) d; /* { dg-error "error: invalid conversion to '__fpreg'" } */
|
||||||
|
fpreg = fpreg * fpreg; /* { dg-error "error: invalid operation on '__fpreg'" } */
|
||||||
|
fpreg = fpreg / fpreg; /* { dg-error "error: invalid operation on '__fpreg'" } */
|
||||||
|
fpreg = fpreg % fpreg; /* { dg-error "error: invalid operation on '__fpreg'" } */
|
||||||
|
fpreg = fpreg + fpreg; /* { dg-error "error: invalid operation on '__fpreg'" } */
|
||||||
|
fpreg = fpreg - fpreg; /* { dg-error "error: invalid operation on '__fpreg'" } */
|
||||||
|
fpreg = fpreg << fpreg; /* { dg-error "error: invalid operation on '__fpreg'" } */
|
||||||
|
fpreg = fpreg >> fpreg; /* { dg-error "error: invalid operation on '__fpreg'" } */
|
||||||
|
d = fpreg < fpreg; /* { dg-error "error: invalid operation on '__fpreg'" } */
|
||||||
|
d = fpreg > fpreg; /* { dg-error "error: invalid operation on '__fpreg'" } */
|
||||||
|
d = fpreg <= fpreg; /* { dg-error "error: invalid operation on '__fpreg'" } */
|
||||||
|
d = fpreg >= fpreg; /* { dg-error "error: invalid operation on '__fpreg'" } */
|
||||||
|
d = fpreg == fpreg; /* { dg-error "error: invalid operation on '__fpreg'" } */
|
||||||
|
d = fpreg != fpreg; /* { dg-error "error: invalid operation on '__fpreg'" } */
|
||||||
|
d = fpreg & fpreg; /* { dg-error "error: invalid operation on '__fpreg'" } */
|
||||||
|
d = fpreg ^ fpreg; /* { dg-error "error: invalid operation on '__fpreg'" } */
|
||||||
|
d = fpreg | fpreg; /* { dg-error "error: invalid operation on '__fpreg'" } */
|
||||||
|
d = fpreg && fpreg; /* { dg-error "error: invalid operation on '__fpreg'" } */
|
||||||
|
d = fpreg || fpreg; /* { dg-error "error: invalid operation on '__fpreg'" } */
|
||||||
|
d = (fpreg ? 1 : 2); /* { dg-error "error: invalid operation on '__fpreg'" } */
|
||||||
|
fpreg = (d ? fpreg : d); /* { dg-error "error: invalid conversion to '__fpreg'" } */
|
||||||
|
fpreg *= fpreg; /* { dg-error "error: invalid operation on '__fpreg'" } */
|
||||||
|
fpreg /= fpreg; /* { dg-error "error: invalid operation on '__fpreg'" } */
|
||||||
|
fpreg %= fpreg; /* { dg-error "error: invalid operation on '__fpreg'" } */
|
||||||
|
fpreg += fpreg; /* { dg-error "error: invalid operation on '__fpreg'" } */
|
||||||
|
fpreg -= fpreg; /* { dg-error "error: invalid operation on '__fpreg'" } */
|
||||||
|
fpreg <<= fpreg; /* { dg-error "error: invalid operation on '__fpreg'" } */
|
||||||
|
fpreg >>= fpreg; /* { dg-error "error: invalid operation on '__fpreg'" } */
|
||||||
|
fpreg &= fpreg; /* { dg-error "error: invalid operation on '__fpreg'" } */
|
||||||
|
fpreg ^= fpreg; /* { dg-error "error: invalid operation on '__fpreg'" } */
|
||||||
|
fpreg |= fpreg; /* { dg-error "error: invalid operation on '__fpreg'" } */
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
/* Test __fpreg ABI. */
|
||||||
|
/* Origin: Joseph Myers <joseph@codesourcery.com> */
|
||||||
|
/* { dg-do compile } */
|
||||||
|
/* { dg-options "" } */
|
||||||
|
/* { dg-final { scan-assembler "ldf.fill" } } */
|
||||||
|
/* { dg-final { scan-assembler "stf.spill" } } */
|
||||||
|
|
||||||
|
__fpreg x;
|
||||||
|
|
||||||
|
void f (void);
|
||||||
|
|
||||||
|
void
|
||||||
|
g (void)
|
||||||
|
{
|
||||||
|
__fpreg b = x;
|
||||||
|
f ();
|
||||||
|
x = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
char t1[(sizeof (__fpreg) == sizeof (__float80) ? 1 : -1)];
|
||||||
|
char t2[(__alignof (__fpreg) == __alignof (__float80) ? 1 : -1)];
|
Loading…
Reference in New Issue