Commit 4de67c26 by Joseph Myers Committed by Joseph Myers

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
parent 2a75c0b6
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>
* 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 "langhooks.h"
#include "toplev.h"
#include "target.h"
/* Change of width--truncation and extension of integers or reals--
is represented with NOP_EXPR. Proper functioning of many things
......@@ -69,10 +70,21 @@ convert (tree type, tree expr)
{
tree e = expr;
enum tree_code code = TREE_CODE (type);
const char *invalid_conv_diag;
if (type == TREE_TYPE (expr)
|| TREE_CODE (expr) == ERROR_MARK
|| code == ERROR_MARK || TREE_CODE (TREE_TYPE (expr)) == ERROR_MARK)
if (type == error_mark_node
|| expr == error_mark_node
|| 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;
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));
tree val;
int noconvert = flag;
const char *invalid_op_diag;
if (typecode == ERROR_MARK)
return error_mark_node;
if (typecode == ENUMERAL_TYPE || typecode == BOOLEAN_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)
{
case CONVERT_EXPR:
......@@ -7397,6 +7405,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
tree type0, type1;
enum tree_code code0, code1;
tree op0, op1;
const char *invalid_op_diag;
/* Expression code to give to the expression when it is built.
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)
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);
switch (code)
......
......@@ -23,9 +23,12 @@ Boston, MA 02110-1301, USA. */
/* IA64 requires both XF and TF modes.
XFmode is __float80 is IEEE extended; TFmode is __float128
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 (RF, 82, 16, ieee_extended_intel_128_format);
FLOAT_MODE (TF, 16, ieee_quad_format);
/* 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_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);
/* 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 int ia64_depz_field_mask (rtx, 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 void ia64_expand_vecint_cmov (rtx[]);
extern bool ia64_expand_vecint_minmax (enum rtx_code, enum machine_mode, rtx[]);
......
......@@ -736,121 +736,8 @@
(match_operand:XF 1 "general_operand" ""))]
""
{
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);
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]);
}
if (ia64_expand_movxf_movrf (XFmode, operands))
DONE;
})
;; ??? There's no easy way to mind volatile acquire/release semantics.
......@@ -865,6 +752,26 @@
stfe %0 = %F1%P0"
[(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
;; directly. Same concerns apply as for TImode.
(define_expand "movtf"
......
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>
* Make-lang.in (cp/except.o): Depend on $(TARGET_H)
......
......@@ -36,6 +36,7 @@ Boston, MA 02110-1301, USA. */
#include "convert.h"
#include "toplev.h"
#include "decl.h"
#include "target.h"
static tree cp_convert_to_pointer (tree, tree, bool);
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;
enum tree_code code = TREE_CODE (type);
const char *invalid_conv_diag;
if (error_operand_p (e) || type == 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 (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);
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;
enum tree_code code0, code1;
tree type0, type1;
const char *invalid_op_diag;
/* Expression code to give to the expression when it is built.
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)
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)
{
case PLUS_EXPR:
......@@ -3725,10 +3733,21 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
tree argtype = 0;
const char *errstring = NULL;
tree val;
const char *invalid_op_diag;
if (arg == 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)
{
case UNARY_PLUS_EXPR:
......
......@@ -9606,6 +9606,26 @@ illegal to pass argument @var{val} to function @var{funcdecl}
with prototype @var{typelist}.
@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
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
......
......@@ -256,3 +256,25 @@ hook_constcharptr_rtx_null (rtx r ATTRIBUTE_UNUSED)
{
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 tree hook_tree_tree_tree_bool_null (tree, tree, bool);
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
......@@ -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
#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_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_INVALID_WITHIN_DOLOOP, \
TARGET_CALLS, \
TARGET_INVALID_CONVERSION, \
TARGET_INVALID_UNARY_OP, \
TARGET_INVALID_BINARY_OP, \
TARGET_CXX, \
TARGET_UNWIND_TABLES_DEFAULT, \
TARGET_HAVE_NAMED_SECTIONS, \
......
......@@ -598,6 +598,18 @@ struct gcc_target
tree funcdecl, tree val);
} 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. */
struct cxx {
/* Return the integer type used for guard variables. */
......
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>
* gfortran.dg/dev_null.f90: Run test only on linux and solaris.
......
// 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" }
}
/* 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'" } */
}
/* 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)];
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment