c-common.h (enum rid): Add new enumeration values of RID_SAT, RID_FRACT, and RID_ACCUM.
* c-common.h (enum rid): Add new enumeration values of RID_SAT, RID_FRACT, and RID_ACCUM. RID_SAT needs to be inserted before RID_ONEWAY, so that it can be checked in declspecs_add_type. (c_common_fixed_point_type_for_size): Declare. * c-parser.c (reswords): Add _Fract, _Accum, and _Sat. (c_token_starts_typename): Handle RID_FRACT, RID_ACCUM, and RID_SAT. (c_token_starts_declspecs): Likewise. (c_parser_declspecs): Likewise. (c_parser_attributes): Likewise. * c-tree.h (enum c_typespec_keyword): Add cts_fract and cts_accum. (c_declspecs): Add saturating_p. * c-decl.c (build_null_declspecs): Initialize saturating_p. (declspecs_add_type): Avoid using complex with _Fract, _Accum, or _Sat. Handle RID_SAT. Avoid using void, bool, char, int, float, double, _Decimal32, _Decimal64, _Decimal128, and complex with _Sat. Handle RID_FRACT and RID_ACCUM. Make sure _Sat is used with _Fract or _Accum. (finish_declspecs): Handle cts_fract and cts_accum. * c-common.c (fixed-value.h): New include. (constant_expression_warning): Handle FIXED_CST. (overflow_warning): Likewise. (warnings_for_convert_and_check): Likewise. (c_common_fixed_point_type_for_size): New. (c_common_type_for_mode): Handle fixed-point modes to return various saturating/non-saturating, signed/unsigned types. (c_common_signed_or_unsigned_type): Support fixed-point types. (shorten_compare): Check fixed-point zero. Handle FIXED_POINT_TYPE. (c_common_truthvalue_conversion): Handle FIXED_CST. Handle FIXED_POINT_TYPE. (c_common_nodes_and_builtins): Record builtin types for fixed-point types. (handle_mode_attribute): Handle fixed-point modes. Need to check if the signness of base type and fixed-point modes are consistent. (handle_vector_size_attribute): Handle fixed-point modes. (same_scalar_type_ignoring_signedness): Handle FIXED_POINT_TYPE. (warn_for_div_by_zero): Check fixed-point zero. * c-typeck.c (c_common_type): Check FIXED_POINT_TYPE. Build a common fixed-point type based on fbit, ibit, sign, and saturation. (build_unary_op): Allow FIXED_POINT_TYPE for CONVERT_EXPR, NEGATE_EXPR, TRUTH_NOT_EXPR, PREINCREMENT_EXPR, POSTINCREMENT_EXPR, PREDECREMENT_EXPR, and POSTDECREMENT_EXPR. (convert_for_assignment): Support FIXED_POINT_TYPE. (digest_init): Handle FIXED_POINT_TYPE. (build_binary_op): Support FIXED_POINT_TYPE in *_DIV_EXPR, TRUTH_ANDIF_EXPR, TRUTH_ORIF_EXPR, TRUTH_AND_EXPR, TRUTH_OR_EXPR, TRUTH_XOR_EXPR, RSHIFT_EXPR, LSHIFT_EXPR, EQ_EXPR, NE_EXPR, LE_EXPR, GE_EXPR, LT_EXPR, GT_EXPR. * target-def.h (TARGET_FIXED_POINT_SUPPORTED_P): New. (TARGET_INITIALIZER): Add TARGET_FIXED_POINT_SUPPORTED_P. * target.h (gcc_target): Add fixed_point_supported_p. * targhooks.c (default_scalar_mode_supported_p): Handle MODE_FRACT, MODE_UFRACT, MODE_ACCUM, and MODE_UACCUM. (default_fixed_point_supported_p): Define. * targhooks.h (default_fixed_point_supported_p): Declare. * doc/tm.texi (TARGET_FIXED_POINT_SUPPORTED_P): Add. * doc/install.texi (Configuration): Add --enable-fixed-point. * configure.ac (--enable-fixed-point): New to enable fixed-point arithmetic extension to C. For mips targets, we enable it by default. * configure, config.in: Regenerate. From-SVN: r127652
This commit is contained in:
parent
43f1474491
commit
ab22c1fa94
|
@ -1,3 +1,67 @@
|
|||
2007-08-20 Chao-ying Fu <fu@mips.com>
|
||||
|
||||
* c-common.h (enum rid): Add new enumeration values of RID_SAT,
|
||||
RID_FRACT, and RID_ACCUM. RID_SAT needs to be inserted before
|
||||
RID_ONEWAY, so that it can be checked in declspecs_add_type.
|
||||
(c_common_fixed_point_type_for_size): Declare.
|
||||
* c-parser.c (reswords): Add _Fract, _Accum, and _Sat.
|
||||
(c_token_starts_typename): Handle RID_FRACT, RID_ACCUM, and RID_SAT.
|
||||
(c_token_starts_declspecs): Likewise.
|
||||
(c_parser_declspecs): Likewise.
|
||||
(c_parser_attributes): Likewise.
|
||||
* c-tree.h (enum c_typespec_keyword): Add cts_fract and cts_accum.
|
||||
(c_declspecs): Add saturating_p.
|
||||
* c-decl.c (build_null_declspecs): Initialize saturating_p.
|
||||
(declspecs_add_type): Avoid using complex with _Fract, _Accum, or _Sat.
|
||||
Handle RID_SAT.
|
||||
Avoid using void, bool, char, int, float, double, _Decimal32,
|
||||
_Decimal64, _Decimal128, and complex with _Sat.
|
||||
Handle RID_FRACT and RID_ACCUM.
|
||||
Make sure _Sat is used with _Fract or _Accum.
|
||||
(finish_declspecs): Handle cts_fract and cts_accum.
|
||||
* c-common.c (fixed-value.h): New include.
|
||||
(constant_expression_warning): Handle FIXED_CST.
|
||||
(overflow_warning): Likewise.
|
||||
(warnings_for_convert_and_check): Likewise.
|
||||
(c_common_fixed_point_type_for_size): New.
|
||||
(c_common_type_for_mode): Handle fixed-point modes to
|
||||
return various saturating/non-saturating, signed/unsigned types.
|
||||
(c_common_signed_or_unsigned_type): Support fixed-point types.
|
||||
(shorten_compare): Check fixed-point zero.
|
||||
Handle FIXED_POINT_TYPE.
|
||||
(c_common_truthvalue_conversion): Handle FIXED_CST.
|
||||
Handle FIXED_POINT_TYPE.
|
||||
(c_common_nodes_and_builtins): Record builtin types for fixed-point
|
||||
types.
|
||||
(handle_mode_attribute): Handle fixed-point modes. Need to check
|
||||
if the signness of base type and fixed-point modes are consistent.
|
||||
(handle_vector_size_attribute): Handle fixed-point modes.
|
||||
(same_scalar_type_ignoring_signedness): Handle FIXED_POINT_TYPE.
|
||||
(warn_for_div_by_zero): Check fixed-point zero.
|
||||
* c-typeck.c (c_common_type): Check FIXED_POINT_TYPE. Build
|
||||
a common fixed-point type based on fbit, ibit, sign, and saturation.
|
||||
(build_unary_op): Allow FIXED_POINT_TYPE for CONVERT_EXPR,
|
||||
NEGATE_EXPR, TRUTH_NOT_EXPR, PREINCREMENT_EXPR, POSTINCREMENT_EXPR,
|
||||
PREDECREMENT_EXPR, and POSTDECREMENT_EXPR.
|
||||
(convert_for_assignment): Support FIXED_POINT_TYPE.
|
||||
(digest_init): Handle FIXED_POINT_TYPE.
|
||||
(build_binary_op): Support FIXED_POINT_TYPE in *_DIV_EXPR,
|
||||
TRUTH_ANDIF_EXPR, TRUTH_ORIF_EXPR, TRUTH_AND_EXPR, TRUTH_OR_EXPR,
|
||||
TRUTH_XOR_EXPR, RSHIFT_EXPR, LSHIFT_EXPR, EQ_EXPR, NE_EXPR, LE_EXPR,
|
||||
GE_EXPR, LT_EXPR, GT_EXPR.
|
||||
* target-def.h (TARGET_FIXED_POINT_SUPPORTED_P): New.
|
||||
(TARGET_INITIALIZER): Add TARGET_FIXED_POINT_SUPPORTED_P.
|
||||
* target.h (gcc_target): Add fixed_point_supported_p.
|
||||
* targhooks.c (default_scalar_mode_supported_p): Handle MODE_FRACT,
|
||||
MODE_UFRACT, MODE_ACCUM, and MODE_UACCUM.
|
||||
(default_fixed_point_supported_p): Define.
|
||||
* targhooks.h (default_fixed_point_supported_p): Declare.
|
||||
* doc/tm.texi (TARGET_FIXED_POINT_SUPPORTED_P): Add.
|
||||
* doc/install.texi (Configuration): Add --enable-fixed-point.
|
||||
* configure.ac (--enable-fixed-point): New to enable fixed-point
|
||||
arithmetic extension to C. For mips targets, we enable it by default.
|
||||
* configure, config.in: Regenerate.
|
||||
|
||||
2007-08-20 Pawel Sikora <pluto@pld-linux.org>
|
||||
|
||||
* doc/invoke.texi (-Wnon-virtual-dtor): Update documentation.
|
||||
|
|
296
gcc/c-common.c
296
gcc/c-common.c
|
@ -48,6 +48,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
#include "real.h"
|
||||
#include "cgraph.h"
|
||||
#include "target-def.h"
|
||||
#include "fixed-value.h"
|
||||
|
||||
cpp_reader *parse_in; /* Declared in c-pragma.h. */
|
||||
|
||||
|
@ -929,6 +930,7 @@ void
|
|||
constant_expression_warning (tree value)
|
||||
{
|
||||
if ((TREE_CODE (value) == INTEGER_CST || TREE_CODE (value) == REAL_CST
|
||||
|| TREE_CODE (value) == FIXED_CST
|
||||
|| TREE_CODE (value) == VECTOR_CST
|
||||
|| TREE_CODE (value) == COMPLEX_CST)
|
||||
&& TREE_OVERFLOW (value)
|
||||
|
@ -963,6 +965,10 @@ overflow_warning (tree value)
|
|||
warning (OPT_Woverflow, "floating point overflow in expression");
|
||||
break;
|
||||
|
||||
case FIXED_CST:
|
||||
warning (OPT_Woverflow, "fixed-point overflow in expression");
|
||||
break;
|
||||
|
||||
case VECTOR_CST:
|
||||
warning (OPT_Woverflow, "vector overflow in expression");
|
||||
break;
|
||||
|
@ -1360,7 +1366,8 @@ warnings_for_convert_and_check (tree type, tree expr, tree result)
|
|||
else
|
||||
conversion_warning (type, expr);
|
||||
}
|
||||
else if (TREE_CODE (result) == INTEGER_CST && TREE_OVERFLOW (result))
|
||||
else if ((TREE_CODE (result) == INTEGER_CST
|
||||
|| TREE_CODE (result) == FIXED_CST) && TREE_OVERFLOW (result))
|
||||
warning (OPT_Woverflow,
|
||||
"overflow in implicit constant conversion");
|
||||
else
|
||||
|
@ -1928,13 +1935,44 @@ c_common_type_for_size (unsigned int bits, int unsignedp)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Return a fixed-point type that has at least IBIT ibits and FBIT fbits
|
||||
that is unsigned if UNSIGNEDP is nonzero, otherwise signed;
|
||||
and saturating if SATP is nonzero, otherwise not saturating. */
|
||||
|
||||
tree
|
||||
c_common_fixed_point_type_for_size (unsigned int ibit, unsigned int fbit,
|
||||
int unsignedp, int satp)
|
||||
{
|
||||
enum machine_mode mode;
|
||||
if (ibit == 0)
|
||||
mode = unsignedp ? UQQmode : QQmode;
|
||||
else
|
||||
mode = unsignedp ? UHAmode : HAmode;
|
||||
|
||||
for (; mode != VOIDmode; mode = GET_MODE_WIDER_MODE (mode))
|
||||
if (GET_MODE_IBIT (mode) >= ibit && GET_MODE_FBIT (mode) >= fbit)
|
||||
break;
|
||||
|
||||
if (mode == VOIDmode || !targetm.scalar_mode_supported_p (mode))
|
||||
{
|
||||
sorry ("GCC cannot support operators with integer types and "
|
||||
"fixed-point types that have too many integral and "
|
||||
"fractional bits together");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return c_common_type_for_mode (mode, satp);
|
||||
}
|
||||
|
||||
/* Used for communication between c_common_type_for_mode and
|
||||
c_register_builtin_type. */
|
||||
static GTY(()) tree registered_builtin_types;
|
||||
|
||||
/* Return a data type that has machine mode MODE.
|
||||
If the mode is an integer,
|
||||
then UNSIGNEDP selects between signed and unsigned types. */
|
||||
then UNSIGNEDP selects between signed and unsigned types.
|
||||
If the mode is a fixed-point mode,
|
||||
then UNSIGNEDP selects between saturating and nonsaturating types. */
|
||||
|
||||
tree
|
||||
c_common_type_for_mode (enum machine_mode mode, int unsignedp)
|
||||
|
@ -2034,6 +2072,95 @@ c_common_type_for_mode (enum machine_mode mode, int unsignedp)
|
|||
if (mode == TYPE_MODE (dfloat128_type_node))
|
||||
return dfloat128_type_node;
|
||||
|
||||
if (ALL_SCALAR_FIXED_POINT_MODE_P (mode))
|
||||
{
|
||||
if (mode == TYPE_MODE (short_fract_type_node))
|
||||
return unsignedp ? sat_short_fract_type_node : short_fract_type_node;
|
||||
if (mode == TYPE_MODE (fract_type_node))
|
||||
return unsignedp ? sat_fract_type_node : fract_type_node;
|
||||
if (mode == TYPE_MODE (long_fract_type_node))
|
||||
return unsignedp ? sat_long_fract_type_node : long_fract_type_node;
|
||||
if (mode == TYPE_MODE (long_long_fract_type_node))
|
||||
return unsignedp ? sat_long_long_fract_type_node
|
||||
: long_long_fract_type_node;
|
||||
|
||||
if (mode == TYPE_MODE (unsigned_short_fract_type_node))
|
||||
return unsignedp ? sat_unsigned_short_fract_type_node
|
||||
: unsigned_short_fract_type_node;
|
||||
if (mode == TYPE_MODE (unsigned_fract_type_node))
|
||||
return unsignedp ? sat_unsigned_fract_type_node
|
||||
: unsigned_fract_type_node;
|
||||
if (mode == TYPE_MODE (unsigned_long_fract_type_node))
|
||||
return unsignedp ? sat_unsigned_long_fract_type_node
|
||||
: unsigned_long_fract_type_node;
|
||||
if (mode == TYPE_MODE (unsigned_long_long_fract_type_node))
|
||||
return unsignedp ? sat_unsigned_long_long_fract_type_node
|
||||
: unsigned_long_long_fract_type_node;
|
||||
|
||||
if (mode == TYPE_MODE (short_accum_type_node))
|
||||
return unsignedp ? sat_short_accum_type_node : short_accum_type_node;
|
||||
if (mode == TYPE_MODE (accum_type_node))
|
||||
return unsignedp ? sat_accum_type_node : accum_type_node;
|
||||
if (mode == TYPE_MODE (long_accum_type_node))
|
||||
return unsignedp ? sat_long_accum_type_node : long_accum_type_node;
|
||||
if (mode == TYPE_MODE (long_long_accum_type_node))
|
||||
return unsignedp ? sat_long_long_accum_type_node
|
||||
: long_long_accum_type_node;
|
||||
|
||||
if (mode == TYPE_MODE (unsigned_short_accum_type_node))
|
||||
return unsignedp ? sat_unsigned_short_accum_type_node
|
||||
: unsigned_short_accum_type_node;
|
||||
if (mode == TYPE_MODE (unsigned_accum_type_node))
|
||||
return unsignedp ? sat_unsigned_accum_type_node
|
||||
: unsigned_accum_type_node;
|
||||
if (mode == TYPE_MODE (unsigned_long_accum_type_node))
|
||||
return unsignedp ? sat_unsigned_long_accum_type_node
|
||||
: unsigned_long_accum_type_node;
|
||||
if (mode == TYPE_MODE (unsigned_long_long_accum_type_node))
|
||||
return unsignedp ? sat_unsigned_long_long_accum_type_node
|
||||
: unsigned_long_long_accum_type_node;
|
||||
|
||||
if (mode == QQmode)
|
||||
return unsignedp ? sat_qq_type_node : qq_type_node;
|
||||
if (mode == HQmode)
|
||||
return unsignedp ? sat_hq_type_node : hq_type_node;
|
||||
if (mode == SQmode)
|
||||
return unsignedp ? sat_sq_type_node : sq_type_node;
|
||||
if (mode == DQmode)
|
||||
return unsignedp ? sat_dq_type_node : dq_type_node;
|
||||
if (mode == TQmode)
|
||||
return unsignedp ? sat_tq_type_node : tq_type_node;
|
||||
|
||||
if (mode == UQQmode)
|
||||
return unsignedp ? sat_uqq_type_node : uqq_type_node;
|
||||
if (mode == UHQmode)
|
||||
return unsignedp ? sat_uhq_type_node : uhq_type_node;
|
||||
if (mode == USQmode)
|
||||
return unsignedp ? sat_usq_type_node : usq_type_node;
|
||||
if (mode == UDQmode)
|
||||
return unsignedp ? sat_udq_type_node : udq_type_node;
|
||||
if (mode == UTQmode)
|
||||
return unsignedp ? sat_utq_type_node : utq_type_node;
|
||||
|
||||
if (mode == HAmode)
|
||||
return unsignedp ? sat_ha_type_node : ha_type_node;
|
||||
if (mode == SAmode)
|
||||
return unsignedp ? sat_sa_type_node : sa_type_node;
|
||||
if (mode == DAmode)
|
||||
return unsignedp ? sat_da_type_node : da_type_node;
|
||||
if (mode == TAmode)
|
||||
return unsignedp ? sat_ta_type_node : ta_type_node;
|
||||
|
||||
if (mode == UHAmode)
|
||||
return unsignedp ? sat_uha_type_node : uha_type_node;
|
||||
if (mode == USAmode)
|
||||
return unsignedp ? sat_usa_type_node : usa_type_node;
|
||||
if (mode == UDAmode)
|
||||
return unsignedp ? sat_uda_type_node : uda_type_node;
|
||||
if (mode == UTAmode)
|
||||
return unsignedp ? sat_uta_type_node : uta_type_node;
|
||||
}
|
||||
|
||||
for (t = registered_builtin_types; t; t = TREE_CHAIN (t))
|
||||
if (TYPE_MODE (TREE_VALUE (t)) == mode)
|
||||
return TREE_VALUE (t);
|
||||
|
@ -2095,6 +2222,54 @@ c_common_signed_or_unsigned_type (int unsignedp, tree type)
|
|||
if (type1 == intQI_type_node || type1 == unsigned_intQI_type_node)
|
||||
return unsignedp ? unsigned_intQI_type_node : intQI_type_node;
|
||||
|
||||
#define C_COMMON_FIXED_TYPES(SAT,NAME) \
|
||||
if (type1 == SAT ## short_ ## NAME ## _type_node \
|
||||
|| type1 == SAT ## unsigned_short_ ## NAME ## _type_node) \
|
||||
return unsignedp ? SAT ## unsigned_short_ ## NAME ## _type_node \
|
||||
: SAT ## short_ ## NAME ## _type_node; \
|
||||
if (type1 == SAT ## NAME ## _type_node \
|
||||
|| type1 == SAT ## unsigned_ ## NAME ## _type_node) \
|
||||
return unsignedp ? SAT ## unsigned_ ## NAME ## _type_node \
|
||||
: SAT ## NAME ## _type_node; \
|
||||
if (type1 == SAT ## long_ ## NAME ## _type_node \
|
||||
|| type1 == SAT ## unsigned_long_ ## NAME ## _type_node) \
|
||||
return unsignedp ? SAT ## unsigned_long_ ## NAME ## _type_node \
|
||||
: SAT ## long_ ## NAME ## _type_node; \
|
||||
if (type1 == SAT ## long_long_ ## NAME ## _type_node \
|
||||
|| type1 == SAT ## unsigned_long_long_ ## NAME ## _type_node) \
|
||||
return unsignedp ? SAT ## unsigned_long_long_ ## NAME ## _type_node \
|
||||
: SAT ## long_long_ ## NAME ## _type_node;
|
||||
|
||||
#define C_COMMON_FIXED_MODE_TYPES(SAT,NAME) \
|
||||
if (type1 == SAT ## NAME ## _type_node \
|
||||
|| type1 == SAT ## u ## NAME ## _type_node) \
|
||||
return unsignedp ? SAT ## u ## NAME ## _type_node \
|
||||
: SAT ## NAME ## _type_node;
|
||||
|
||||
C_COMMON_FIXED_TYPES (, fract);
|
||||
C_COMMON_FIXED_TYPES (sat_, fract);
|
||||
C_COMMON_FIXED_TYPES (, accum);
|
||||
C_COMMON_FIXED_TYPES (sat_, accum);
|
||||
|
||||
C_COMMON_FIXED_MODE_TYPES (, qq);
|
||||
C_COMMON_FIXED_MODE_TYPES (, hq);
|
||||
C_COMMON_FIXED_MODE_TYPES (, sq);
|
||||
C_COMMON_FIXED_MODE_TYPES (, dq);
|
||||
C_COMMON_FIXED_MODE_TYPES (, tq);
|
||||
C_COMMON_FIXED_MODE_TYPES (sat_, qq);
|
||||
C_COMMON_FIXED_MODE_TYPES (sat_, hq);
|
||||
C_COMMON_FIXED_MODE_TYPES (sat_, sq);
|
||||
C_COMMON_FIXED_MODE_TYPES (sat_, dq);
|
||||
C_COMMON_FIXED_MODE_TYPES (sat_, tq);
|
||||
C_COMMON_FIXED_MODE_TYPES (, ha);
|
||||
C_COMMON_FIXED_MODE_TYPES (, sa);
|
||||
C_COMMON_FIXED_MODE_TYPES (, da);
|
||||
C_COMMON_FIXED_MODE_TYPES (, ta);
|
||||
C_COMMON_FIXED_MODE_TYPES (sat_, ha);
|
||||
C_COMMON_FIXED_MODE_TYPES (sat_, sa);
|
||||
C_COMMON_FIXED_MODE_TYPES (sat_, da);
|
||||
C_COMMON_FIXED_MODE_TYPES (sat_, ta);
|
||||
|
||||
/* For ENUMERAL_TYPEs in C++, must check the mode of the types, not
|
||||
the precision; they have precision set to match their range, but
|
||||
may use a wider mode to match an ABI. If we change modes, we may
|
||||
|
@ -2323,7 +2498,8 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr,
|
|||
the second arg is 0. */
|
||||
|
||||
if (TREE_CONSTANT (primop0)
|
||||
&& !integer_zerop (primop1) && !real_zerop (primop1))
|
||||
&& !integer_zerop (primop1) && !real_zerop (primop1)
|
||||
&& !fixed_zerop (primop1))
|
||||
{
|
||||
tree tem = primop0;
|
||||
int temi = unsignedp0;
|
||||
|
@ -2378,6 +2554,7 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr,
|
|||
and see if that preserves the constant's value. */
|
||||
|
||||
if (!real1 && !real2
|
||||
&& TREE_CODE (TREE_TYPE (primop0)) != FIXED_POINT_TYPE
|
||||
&& TREE_CODE (primop1) == INTEGER_CST
|
||||
&& TYPE_PRECISION (TREE_TYPE (primop0)) < TYPE_PRECISION (*restype_ptr))
|
||||
{
|
||||
|
@ -2783,6 +2960,12 @@ c_common_truthvalue_conversion (tree expr)
|
|||
? truthvalue_true_node
|
||||
: truthvalue_false_node;
|
||||
|
||||
case FIXED_CST:
|
||||
return fixed_compare (NE_EXPR, &TREE_FIXED_CST (expr),
|
||||
&FCONST0 (TYPE_MODE (TREE_TYPE (expr))))
|
||||
? truthvalue_true_node
|
||||
: truthvalue_false_node;
|
||||
|
||||
case FUNCTION_DECL:
|
||||
expr = build_unary_op (ADDR_EXPR, expr, 0);
|
||||
/* Fall through. */
|
||||
|
@ -2883,6 +3066,14 @@ c_common_truthvalue_conversion (tree expr)
|
|||
0));
|
||||
}
|
||||
|
||||
if (TREE_CODE (TREE_TYPE (expr)) == FIXED_POINT_TYPE)
|
||||
{
|
||||
tree fixed_zero_node = build_fixed (TREE_TYPE (expr),
|
||||
FCONST0 (TYPE_MODE
|
||||
(TREE_TYPE (expr))));
|
||||
return build_binary_op (NE_EXPR, expr, fixed_zero_node, 1);
|
||||
}
|
||||
|
||||
return build_binary_op (NE_EXPR, expr, integer_zero_node, 1);
|
||||
}
|
||||
|
||||
|
@ -3594,6 +3785,67 @@ c_common_nodes_and_builtins (void)
|
|||
record_builtin_type (RID_DFLOAT128, NULL, dfloat128_type_node);
|
||||
}
|
||||
|
||||
if (targetm.fixed_point_supported_p ())
|
||||
{
|
||||
record_builtin_type (RID_MAX, "short _Fract", short_fract_type_node);
|
||||
record_builtin_type (RID_FRACT, NULL, fract_type_node);
|
||||
record_builtin_type (RID_MAX, "long _Fract", long_fract_type_node);
|
||||
record_builtin_type (RID_MAX, "long long _Fract",
|
||||
long_long_fract_type_node);
|
||||
record_builtin_type (RID_MAX, "unsigned short _Fract",
|
||||
unsigned_short_fract_type_node);
|
||||
record_builtin_type (RID_MAX, "unsigned _Fract",
|
||||
unsigned_fract_type_node);
|
||||
record_builtin_type (RID_MAX, "unsigned long _Fract",
|
||||
unsigned_long_fract_type_node);
|
||||
record_builtin_type (RID_MAX, "unsigned long long _Fract",
|
||||
unsigned_long_long_fract_type_node);
|
||||
record_builtin_type (RID_MAX, "_Sat short _Fract",
|
||||
sat_short_fract_type_node);
|
||||
record_builtin_type (RID_MAX, "_Sat _Fract", sat_fract_type_node);
|
||||
record_builtin_type (RID_MAX, "_Sat long _Fract",
|
||||
sat_long_fract_type_node);
|
||||
record_builtin_type (RID_MAX, "_Sat long long _Fract",
|
||||
sat_long_long_fract_type_node);
|
||||
record_builtin_type (RID_MAX, "_Sat unsigned short _Fract",
|
||||
sat_unsigned_short_fract_type_node);
|
||||
record_builtin_type (RID_MAX, "_Sat unsigned _Fract",
|
||||
sat_unsigned_fract_type_node);
|
||||
record_builtin_type (RID_MAX, "_Sat unsigned long _Fract",
|
||||
sat_unsigned_long_fract_type_node);
|
||||
record_builtin_type (RID_MAX, "_Sat unsigned long long _Fract",
|
||||
sat_unsigned_long_long_fract_type_node);
|
||||
record_builtin_type (RID_MAX, "short _Accum", short_accum_type_node);
|
||||
record_builtin_type (RID_ACCUM, NULL, accum_type_node);
|
||||
record_builtin_type (RID_MAX, "long _Accum", long_accum_type_node);
|
||||
record_builtin_type (RID_MAX, "long long _Accum",
|
||||
long_long_accum_type_node);
|
||||
record_builtin_type (RID_MAX, "unsigned short _Accum",
|
||||
unsigned_short_accum_type_node);
|
||||
record_builtin_type (RID_MAX, "unsigned _Accum",
|
||||
unsigned_accum_type_node);
|
||||
record_builtin_type (RID_MAX, "unsigned long _Accum",
|
||||
unsigned_long_accum_type_node);
|
||||
record_builtin_type (RID_MAX, "unsigned long long _Accum",
|
||||
unsigned_long_long_accum_type_node);
|
||||
record_builtin_type (RID_MAX, "_Sat short _Accum",
|
||||
sat_short_accum_type_node);
|
||||
record_builtin_type (RID_MAX, "_Sat _Accum", sat_accum_type_node);
|
||||
record_builtin_type (RID_MAX, "_Sat long _Accum",
|
||||
sat_long_accum_type_node);
|
||||
record_builtin_type (RID_MAX, "_Sat long long _Accum",
|
||||
sat_long_long_accum_type_node);
|
||||
record_builtin_type (RID_MAX, "_Sat unsigned short _Accum",
|
||||
sat_unsigned_short_accum_type_node);
|
||||
record_builtin_type (RID_MAX, "_Sat unsigned _Accum",
|
||||
sat_unsigned_accum_type_node);
|
||||
record_builtin_type (RID_MAX, "_Sat unsigned long _Accum",
|
||||
sat_unsigned_long_accum_type_node);
|
||||
record_builtin_type (RID_MAX, "_Sat unsigned long long _Accum",
|
||||
sat_unsigned_long_long_accum_type_node);
|
||||
|
||||
}
|
||||
|
||||
lang_hooks.decls.pushdecl (build_decl (TYPE_DECL,
|
||||
get_identifier ("complex int"),
|
||||
complex_integer_type_node));
|
||||
|
@ -5013,6 +5265,10 @@ handle_mode_attribute (tree *node, tree name, tree args,
|
|||
case MODE_PARTIAL_INT:
|
||||
case MODE_FLOAT:
|
||||
case MODE_DECIMAL_FLOAT:
|
||||
case MODE_FRACT:
|
||||
case MODE_UFRACT:
|
||||
case MODE_ACCUM:
|
||||
case MODE_UACCUM:
|
||||
valid_mode = targetm.scalar_mode_supported_p (mode);
|
||||
break;
|
||||
|
||||
|
@ -5023,6 +5279,10 @@ handle_mode_attribute (tree *node, tree name, tree args,
|
|||
|
||||
case MODE_VECTOR_INT:
|
||||
case MODE_VECTOR_FLOAT:
|
||||
case MODE_VECTOR_FRACT:
|
||||
case MODE_VECTOR_UFRACT:
|
||||
case MODE_VECTOR_ACCUM:
|
||||
case MODE_VECTOR_UACCUM:
|
||||
warning (OPT_Wattributes, "specifying vector types with "
|
||||
"__attribute__ ((mode)) is deprecated");
|
||||
warning (OPT_Wattributes,
|
||||
|
@ -5056,7 +5316,20 @@ handle_mode_attribute (tree *node, tree name, tree args,
|
|||
typefm = fn (TREE_TYPE (type), mode, false);
|
||||
}
|
||||
else
|
||||
typefm = lang_hooks.types.type_for_mode (mode, TYPE_UNSIGNED (type));
|
||||
{
|
||||
/* For fixed-point modes, we need to test if the signness of type
|
||||
and the machine mode are consistent. */
|
||||
if (ALL_FIXED_POINT_MODE_P (mode)
|
||||
&& TYPE_UNSIGNED (type) != UNSIGNED_FIXED_POINT_MODE_P (mode))
|
||||
{
|
||||
error ("signness of type and machine mode %qs don't match", p);
|
||||
return NULL_TREE;
|
||||
}
|
||||
/* For fixed-point modes, we need to pass saturating info. */
|
||||
typefm = lang_hooks.types.type_for_mode (mode,
|
||||
ALL_FIXED_POINT_MODE_P (mode) ? TYPE_SATURATING (type)
|
||||
: TYPE_UNSIGNED (type));
|
||||
}
|
||||
|
||||
if (typefm == NULL_TREE)
|
||||
{
|
||||
|
@ -5805,7 +6078,8 @@ handle_vector_size_attribute (tree *node, tree name, tree args,
|
|||
|| TREE_CODE (type) == UNION_TYPE
|
||||
|| TREE_CODE (type) == VECTOR_TYPE
|
||||
|| (!SCALAR_FLOAT_MODE_P (orig_mode)
|
||||
&& GET_MODE_CLASS (orig_mode) != MODE_INT)
|
||||
&& GET_MODE_CLASS (orig_mode) != MODE_INT
|
||||
&& !ALL_SCALAR_FIXED_POINT_MODE_P (orig_mode))
|
||||
|| !host_integerp (TYPE_SIZE_UNIT (type), 1))
|
||||
{
|
||||
error ("invalid vector type for attribute %qE", name);
|
||||
|
@ -6938,8 +7212,9 @@ same_scalar_type_ignoring_signedness (tree t1, tree t2)
|
|||
{
|
||||
enum tree_code c1 = TREE_CODE (t1), c2 = TREE_CODE (t2);
|
||||
|
||||
gcc_assert ((c1 == INTEGER_TYPE || c1 == REAL_TYPE)
|
||||
&& (c2 == INTEGER_TYPE || c2 == REAL_TYPE));
|
||||
gcc_assert ((c1 == INTEGER_TYPE || c1 == REAL_TYPE || c1 == FIXED_POINT_TYPE)
|
||||
&& (c2 == INTEGER_TYPE || c2 == REAL_TYPE
|
||||
|| c2 == FIXED_POINT_TYPE));
|
||||
|
||||
/* Equality works here because c_common_signed_type uses
|
||||
TYPE_MAIN_VARIANT. */
|
||||
|
@ -7104,11 +7379,12 @@ struct gcc_targetcm targetcm = TARGETCM_INITIALIZER;
|
|||
void
|
||||
warn_for_div_by_zero (tree divisor)
|
||||
{
|
||||
/* If DIVISOR is zero, and has integral type, issue a warning about
|
||||
division by zero. Do not issue a warning if DIVISOR has a
|
||||
/* If DIVISOR is zero, and has integral or fixed-point type, issue a warning
|
||||
about division by zero. Do not issue a warning if DIVISOR has a
|
||||
floating-point type, since we consider 0.0/0.0 a valid way of
|
||||
generating a NaN. */
|
||||
if (skip_evaluation == 0 && integer_zerop (divisor))
|
||||
if (skip_evaluation == 0
|
||||
&& (integer_zerop (divisor) || fixed_zerop (divisor)))
|
||||
warning (OPT_Wdiv_by_zero, "division by zero");
|
||||
}
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ enum rid
|
|||
RID_VOLATILE, RID_SIGNED, RID_AUTO, RID_RESTRICT,
|
||||
|
||||
/* C extensions */
|
||||
RID_COMPLEX, RID_THREAD,
|
||||
RID_COMPLEX, RID_THREAD, RID_SAT,
|
||||
|
||||
/* C++ */
|
||||
RID_FRIEND, RID_VIRTUAL, RID_EXPLICIT, RID_EXPORT, RID_MUTABLE,
|
||||
|
@ -72,6 +72,7 @@ enum rid
|
|||
RID_EXTENSION, RID_IMAGPART, RID_REALPART, RID_LABEL, RID_CHOOSE_EXPR,
|
||||
RID_TYPES_COMPATIBLE_P,
|
||||
RID_DFLOAT32, RID_DFLOAT64, RID_DFLOAT128,
|
||||
RID_FRACT, RID_ACCUM,
|
||||
|
||||
/* Too many ways of getting the name of a function as a string */
|
||||
RID_FUNCTION_NAME, RID_PRETTY_FUNCTION_NAME, RID_C99_FUNCTION_NAME,
|
||||
|
@ -670,6 +671,8 @@ extern int c_common_handle_option (size_t code, const char *arg, int value);
|
|||
extern bool c_common_missing_argument (const char *opt, size_t code);
|
||||
extern tree c_common_type_for_mode (enum machine_mode, int);
|
||||
extern tree c_common_type_for_size (unsigned int, int);
|
||||
extern tree c_common_fixed_point_type_for_size (unsigned int, unsigned int,
|
||||
int, int);
|
||||
extern tree c_common_unsigned_type (tree);
|
||||
extern tree c_common_signed_type (tree);
|
||||
extern tree c_common_signed_or_unsigned_type (int, tree);
|
||||
|
|
181
gcc/c-decl.c
181
gcc/c-decl.c
|
@ -7134,6 +7134,7 @@ build_null_declspecs (void)
|
|||
ret->const_p = false;
|
||||
ret->volatile_p = false;
|
||||
ret->restrict_p = false;
|
||||
ret->saturating_p = false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -7196,7 +7197,7 @@ declspecs_add_type (struct c_declspecs *specs, struct c_typespec spec)
|
|||
}
|
||||
if ((int) i <= (int) RID_LAST_MODIFIER)
|
||||
{
|
||||
/* "long", "short", "signed", "unsigned" or "_Complex". */
|
||||
/* "long", "short", "signed", "unsigned", "_Complex" or "_Sat". */
|
||||
bool dupe = false;
|
||||
switch (i)
|
||||
{
|
||||
|
@ -7356,9 +7357,55 @@ declspecs_add_type (struct c_declspecs *specs, struct c_typespec spec)
|
|||
else if (specs->typespec_word == cts_dfloat128)
|
||||
error ("both %<complex%> and %<_Decimal128%> in "
|
||||
"declaration specifiers");
|
||||
else if (specs->typespec_word == cts_fract)
|
||||
error ("both %<complex%> and %<_Fract%> in "
|
||||
"declaration specifiers");
|
||||
else if (specs->typespec_word == cts_accum)
|
||||
error ("both %<complex%> and %<_Accum%> in "
|
||||
"declaration specifiers");
|
||||
else if (specs->saturating_p)
|
||||
error ("both %<complex%> and %<_Sat%> in "
|
||||
"declaration specifiers");
|
||||
else
|
||||
specs->complex_p = true;
|
||||
break;
|
||||
case RID_SAT:
|
||||
dupe = specs->saturating_p;
|
||||
if (pedantic)
|
||||
pedwarn ("ISO C does not support saturating types");
|
||||
if (specs->typespec_word == cts_void)
|
||||
error ("both %<_Sat%> and %<void%> in "
|
||||
"declaration specifiers");
|
||||
else if (specs->typespec_word == cts_bool)
|
||||
error ("both %<_Sat%> and %<_Bool%> in "
|
||||
"declaration specifiers");
|
||||
else if (specs->typespec_word == cts_char)
|
||||
error ("both %<_Sat%> and %<char%> in "
|
||||
"declaration specifiers");
|
||||
else if (specs->typespec_word == cts_int)
|
||||
error ("both %<_Sat%> and %<int%> in "
|
||||
"declaration specifiers");
|
||||
else if (specs->typespec_word == cts_float)
|
||||
error ("both %<_Sat%> and %<float%> in "
|
||||
"declaration specifiers");
|
||||
else if (specs->typespec_word == cts_double)
|
||||
error ("both %<_Sat%> and %<double%> in "
|
||||
"declaration specifiers");
|
||||
else if (specs->typespec_word == cts_dfloat32)
|
||||
error ("both %<_Sat%> and %<_Decimal32%> in "
|
||||
"declaration specifiers");
|
||||
else if (specs->typespec_word == cts_dfloat64)
|
||||
error ("both %<_Sat%> and %<_Decimal64%> in "
|
||||
"declaration specifiers");
|
||||
else if (specs->typespec_word == cts_dfloat128)
|
||||
error ("both %<_Sat%> and %<_Decimal128%> in "
|
||||
"declaration specifiers");
|
||||
else if (specs->complex_p)
|
||||
error ("both %<_Sat%> and %<complex%> in "
|
||||
"declaration specifiers");
|
||||
else
|
||||
specs->saturating_p = true;
|
||||
break;
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
@ -7370,7 +7417,8 @@ declspecs_add_type (struct c_declspecs *specs, struct c_typespec spec)
|
|||
}
|
||||
else
|
||||
{
|
||||
/* "void", "_Bool", "char", "int", "float" or "double". */
|
||||
/* "void", "_Bool", "char", "int", "float", "double", "_Decimal32",
|
||||
"_Decimal64", "_Decimal128", "_Fract" or "_Accum". */
|
||||
if (specs->typespec_word != cts_none)
|
||||
{
|
||||
error ("two or more data types in declaration specifiers");
|
||||
|
@ -7394,6 +7442,9 @@ declspecs_add_type (struct c_declspecs *specs, struct c_typespec spec)
|
|||
else if (specs->complex_p)
|
||||
error ("both %<complex%> and %<void%> in "
|
||||
"declaration specifiers");
|
||||
else if (specs->saturating_p)
|
||||
error ("both %<_Sat%> and %<void%> in "
|
||||
"declaration specifiers");
|
||||
else
|
||||
specs->typespec_word = cts_void;
|
||||
return specs;
|
||||
|
@ -7413,6 +7464,9 @@ declspecs_add_type (struct c_declspecs *specs, struct c_typespec spec)
|
|||
else if (specs->complex_p)
|
||||
error ("both %<complex%> and %<_Bool%> in "
|
||||
"declaration specifiers");
|
||||
else if (specs->saturating_p)
|
||||
error ("both %<_Sat%> and %<_Bool%> in "
|
||||
"declaration specifiers");
|
||||
else
|
||||
specs->typespec_word = cts_bool;
|
||||
return specs;
|
||||
|
@ -7423,11 +7477,18 @@ declspecs_add_type (struct c_declspecs *specs, struct c_typespec spec)
|
|||
else if (specs->short_p)
|
||||
error ("both %<short%> and %<char%> in "
|
||||
"declaration specifiers");
|
||||
else if (specs->saturating_p)
|
||||
error ("both %<_Sat%> and %<char%> in "
|
||||
"declaration specifiers");
|
||||
else
|
||||
specs->typespec_word = cts_char;
|
||||
return specs;
|
||||
case RID_INT:
|
||||
specs->typespec_word = cts_int;
|
||||
if (specs->saturating_p)
|
||||
error ("both %<_Sat%> and %<int%> in "
|
||||
"declaration specifiers");
|
||||
else
|
||||
specs->typespec_word = cts_int;
|
||||
return specs;
|
||||
case RID_FLOAT:
|
||||
if (specs->long_p)
|
||||
|
@ -7442,6 +7503,9 @@ declspecs_add_type (struct c_declspecs *specs, struct c_typespec spec)
|
|||
else if (specs->unsigned_p)
|
||||
error ("both %<unsigned%> and %<float%> in "
|
||||
"declaration specifiers");
|
||||
else if (specs->saturating_p)
|
||||
error ("both %<_Sat%> and %<float%> in "
|
||||
"declaration specifiers");
|
||||
else
|
||||
specs->typespec_word = cts_float;
|
||||
return specs;
|
||||
|
@ -7458,6 +7522,9 @@ declspecs_add_type (struct c_declspecs *specs, struct c_typespec spec)
|
|||
else if (specs->unsigned_p)
|
||||
error ("both %<unsigned%> and %<double%> in "
|
||||
"declaration specifiers");
|
||||
else if (specs->saturating_p)
|
||||
error ("both %<_Sat%> and %<double%> in "
|
||||
"declaration specifiers");
|
||||
else
|
||||
specs->typespec_word = cts_double;
|
||||
return specs;
|
||||
|
@ -7490,6 +7557,9 @@ declspecs_add_type (struct c_declspecs *specs, struct c_typespec spec)
|
|||
else if (specs->complex_p)
|
||||
error ("both %<complex%> and %<%s%> in "
|
||||
"declaration specifiers", str);
|
||||
else if (specs->saturating_p)
|
||||
error ("both %<_Sat%> and %<%s%> in "
|
||||
"declaration specifiers", str);
|
||||
else if (i == RID_DFLOAT32)
|
||||
specs->typespec_word = cts_dfloat32;
|
||||
else if (i == RID_DFLOAT64)
|
||||
|
@ -7502,6 +7572,27 @@ declspecs_add_type (struct c_declspecs *specs, struct c_typespec spec)
|
|||
if (pedantic)
|
||||
pedwarn ("ISO C does not support decimal floating point");
|
||||
return specs;
|
||||
case RID_FRACT:
|
||||
case RID_ACCUM:
|
||||
{
|
||||
const char *str;
|
||||
if (i == RID_FRACT)
|
||||
str = "_Fract";
|
||||
else
|
||||
str = "_Accum";
|
||||
if (specs->complex_p)
|
||||
error ("both %<complex%> and %<%s%> in "
|
||||
"declaration specifiers", str);
|
||||
else if (i == RID_FRACT)
|
||||
specs->typespec_word = cts_fract;
|
||||
else
|
||||
specs->typespec_word = cts_accum;
|
||||
}
|
||||
if (!targetm.fixed_point_supported_p ())
|
||||
error ("fixed-point types not supported for this target");
|
||||
if (pedantic)
|
||||
pedwarn ("ISO C does not support fixed-point types");
|
||||
return specs;
|
||||
default:
|
||||
/* ObjC reserved word "id", handled below. */
|
||||
break;
|
||||
|
@ -7673,6 +7764,8 @@ finish_declspecs (struct c_declspecs *specs)
|
|||
"_Complex short" is equivalent to "_Complex short int". */
|
||||
if (specs->typespec_word == cts_none)
|
||||
{
|
||||
if (specs->saturating_p)
|
||||
error ("%<_Sat%> is used without %<_Fract%> or %<_Accum%>");
|
||||
if (specs->long_p || specs->short_p
|
||||
|| specs->signed_p || specs->unsigned_p)
|
||||
{
|
||||
|
@ -7792,6 +7885,88 @@ finish_declspecs (struct c_declspecs *specs)
|
|||
else
|
||||
specs->type = dfloat128_type_node;
|
||||
break;
|
||||
case cts_fract:
|
||||
gcc_assert (!specs->complex_p);
|
||||
if (specs->saturating_p)
|
||||
{
|
||||
if (specs->long_long_p)
|
||||
specs->type = specs->unsigned_p
|
||||
? sat_unsigned_long_long_fract_type_node
|
||||
: sat_long_long_fract_type_node;
|
||||
else if (specs->long_p)
|
||||
specs->type = specs->unsigned_p
|
||||
? sat_unsigned_long_fract_type_node
|
||||
: sat_long_fract_type_node;
|
||||
else if (specs->short_p)
|
||||
specs->type = specs->unsigned_p
|
||||
? sat_unsigned_short_fract_type_node
|
||||
: sat_short_fract_type_node;
|
||||
else
|
||||
specs->type = specs->unsigned_p
|
||||
? sat_unsigned_fract_type_node
|
||||
: sat_fract_type_node;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (specs->long_long_p)
|
||||
specs->type = specs->unsigned_p
|
||||
? unsigned_long_long_fract_type_node
|
||||
: long_long_fract_type_node;
|
||||
else if (specs->long_p)
|
||||
specs->type = specs->unsigned_p
|
||||
? unsigned_long_fract_type_node
|
||||
: long_fract_type_node;
|
||||
else if (specs->short_p)
|
||||
specs->type = specs->unsigned_p
|
||||
? unsigned_short_fract_type_node
|
||||
: short_fract_type_node;
|
||||
else
|
||||
specs->type = specs->unsigned_p
|
||||
? unsigned_fract_type_node
|
||||
: fract_type_node;
|
||||
}
|
||||
break;
|
||||
case cts_accum:
|
||||
gcc_assert (!specs->complex_p);
|
||||
if (specs->saturating_p)
|
||||
{
|
||||
if (specs->long_long_p)
|
||||
specs->type = specs->unsigned_p
|
||||
? sat_unsigned_long_long_accum_type_node
|
||||
: sat_long_long_accum_type_node;
|
||||
else if (specs->long_p)
|
||||
specs->type = specs->unsigned_p
|
||||
? sat_unsigned_long_accum_type_node
|
||||
: sat_long_accum_type_node;
|
||||
else if (specs->short_p)
|
||||
specs->type = specs->unsigned_p
|
||||
? sat_unsigned_short_accum_type_node
|
||||
: sat_short_accum_type_node;
|
||||
else
|
||||
specs->type = specs->unsigned_p
|
||||
? sat_unsigned_accum_type_node
|
||||
: sat_accum_type_node;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (specs->long_long_p)
|
||||
specs->type = specs->unsigned_p
|
||||
? unsigned_long_long_accum_type_node
|
||||
: long_long_accum_type_node;
|
||||
else if (specs->long_p)
|
||||
specs->type = specs->unsigned_p
|
||||
? unsigned_long_accum_type_node
|
||||
: long_accum_type_node;
|
||||
else if (specs->short_p)
|
||||
specs->type = specs->unsigned_p
|
||||
? unsigned_short_accum_type_node
|
||||
: short_accum_type_node;
|
||||
else
|
||||
specs->type = specs->unsigned_p
|
||||
? unsigned_accum_type_node
|
||||
: accum_type_node;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
|
|
@ -80,6 +80,9 @@ static const struct resword reswords[] =
|
|||
{ "_Decimal32", RID_DFLOAT32, D_EXT },
|
||||
{ "_Decimal64", RID_DFLOAT64, D_EXT },
|
||||
{ "_Decimal128", RID_DFLOAT128, D_EXT },
|
||||
{ "_Fract", RID_FRACT, D_EXT },
|
||||
{ "_Accum", RID_ACCUM, D_EXT },
|
||||
{ "_Sat", RID_SAT, D_EXT },
|
||||
{ "__FUNCTION__", RID_FUNCTION_NAME, 0 },
|
||||
{ "__PRETTY_FUNCTION__", RID_PRETTY_FUNCTION_NAME, 0 },
|
||||
{ "__alignof", RID_ALIGNOF, 0 },
|
||||
|
@ -486,6 +489,9 @@ c_token_starts_typename (c_token *token)
|
|||
case RID_VOLATILE:
|
||||
case RID_RESTRICT:
|
||||
case RID_ATTRIBUTE:
|
||||
case RID_FRACT:
|
||||
case RID_ACCUM:
|
||||
case RID_SAT:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
@ -560,6 +566,9 @@ c_token_starts_declspecs (c_token *token)
|
|||
case RID_VOLATILE:
|
||||
case RID_RESTRICT:
|
||||
case RID_ATTRIBUTE:
|
||||
case RID_FRACT:
|
||||
case RID_ACCUM:
|
||||
case RID_SAT:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
@ -1493,6 +1502,12 @@ c_parser_asm_definition (c_parser *parser)
|
|||
_Decimal32
|
||||
_Decimal64
|
||||
_Decimal128
|
||||
_Fract
|
||||
_Accum
|
||||
_Sat
|
||||
|
||||
(_Fract, _Accum, and _Sat are new from ISO/IEC DTR 18037:
|
||||
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1169.pdf)
|
||||
|
||||
Objective-C:
|
||||
|
||||
|
@ -1595,6 +1610,9 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
|
|||
case RID_DFLOAT64:
|
||||
case RID_DFLOAT128:
|
||||
case RID_BOOL:
|
||||
case RID_FRACT:
|
||||
case RID_ACCUM:
|
||||
case RID_SAT:
|
||||
if (!typespec_ok)
|
||||
goto out;
|
||||
attrs_ok = true;
|
||||
|
@ -2857,6 +2875,9 @@ c_parser_attributes (c_parser *parser)
|
|||
case RID_DFLOAT64:
|
||||
case RID_DFLOAT128:
|
||||
case RID_BOOL:
|
||||
case RID_FRACT:
|
||||
case RID_ACCUM:
|
||||
case RID_SAT:
|
||||
ok = true;
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -202,7 +202,8 @@ enum c_storage_class {
|
|||
};
|
||||
|
||||
/* A type specifier keyword "void", "_Bool", "char", "int", "float",
|
||||
"double", or none of these. */
|
||||
"double", "_Decimal32", "_Decimal64", "_Decimal128", "_Fract", "_Accum",
|
||||
or none of these. */
|
||||
enum c_typespec_keyword {
|
||||
cts_none,
|
||||
cts_void,
|
||||
|
@ -213,7 +214,9 @@ enum c_typespec_keyword {
|
|||
cts_double,
|
||||
cts_dfloat32,
|
||||
cts_dfloat64,
|
||||
cts_dfloat128
|
||||
cts_dfloat128,
|
||||
cts_fract,
|
||||
cts_accum
|
||||
};
|
||||
|
||||
/* A sequence of declaration specifiers in C. */
|
||||
|
@ -281,6 +284,8 @@ struct c_declspecs {
|
|||
BOOL_BITFIELD volatile_p : 1;
|
||||
/* Whether "restrict" was specified. */
|
||||
BOOL_BITFIELD restrict_p : 1;
|
||||
/* Whether "_Sat" was specified. */
|
||||
BOOL_BITFIELD saturating_p : 1;
|
||||
};
|
||||
|
||||
/* The various kinds of declarators in C. */
|
||||
|
|
157
gcc/c-typeck.c
157
gcc/c-typeck.c
|
@ -604,9 +604,11 @@ c_common_type (tree t1, tree t2)
|
|||
code2 = TREE_CODE (t2);
|
||||
|
||||
gcc_assert (code1 == VECTOR_TYPE || code1 == COMPLEX_TYPE
|
||||
|| code1 == REAL_TYPE || code1 == INTEGER_TYPE);
|
||||
|| code1 == FIXED_POINT_TYPE || code1 == REAL_TYPE
|
||||
|| code1 == INTEGER_TYPE);
|
||||
gcc_assert (code2 == VECTOR_TYPE || code2 == COMPLEX_TYPE
|
||||
|| code2 == REAL_TYPE || code2 == INTEGER_TYPE);
|
||||
|| code2 == FIXED_POINT_TYPE || code2 == REAL_TYPE
|
||||
|| code2 == INTEGER_TYPE);
|
||||
|
||||
/* When one operand is a decimal float type, the other operand cannot be
|
||||
a generic float type or a complex type. We also disallow vector types
|
||||
|
@ -681,6 +683,91 @@ c_common_type (tree t1, tree t2)
|
|||
return dfloat32_type_node;
|
||||
}
|
||||
|
||||
/* Deal with fixed-point types. */
|
||||
if (code1 == FIXED_POINT_TYPE || code2 == FIXED_POINT_TYPE)
|
||||
{
|
||||
unsigned int unsignedp = 0, satp = 0;
|
||||
enum machine_mode m1, m2;
|
||||
unsigned int fbit1, ibit1, fbit2, ibit2, max_fbit, max_ibit;
|
||||
|
||||
m1 = TYPE_MODE (t1);
|
||||
m2 = TYPE_MODE (t2);
|
||||
|
||||
/* If one input type is saturating, the result type is saturating. */
|
||||
if (TYPE_SATURATING (t1) || TYPE_SATURATING (t2))
|
||||
satp = 1;
|
||||
|
||||
/* If both fixed-point types are unsigned, the result type is unsigned.
|
||||
When mixing fixed-point and integer types, follow the sign of the
|
||||
fixed-point type.
|
||||
Otherwise, the result type is signed. */
|
||||
if ((TYPE_UNSIGNED (t1) && TYPE_UNSIGNED (t2)
|
||||
&& code1 == FIXED_POINT_TYPE && code2 == FIXED_POINT_TYPE)
|
||||
|| (code1 == FIXED_POINT_TYPE && code2 != FIXED_POINT_TYPE
|
||||
&& TYPE_UNSIGNED (t1))
|
||||
|| (code1 != FIXED_POINT_TYPE && code2 == FIXED_POINT_TYPE
|
||||
&& TYPE_UNSIGNED (t2)))
|
||||
unsignedp = 1;
|
||||
|
||||
/* The result type is signed. */
|
||||
if (unsignedp == 0)
|
||||
{
|
||||
/* If the input type is unsigned, we need to convert to the
|
||||
signed type. */
|
||||
if (code1 == FIXED_POINT_TYPE && TYPE_UNSIGNED (t1))
|
||||
{
|
||||
unsigned char mclass = 0;
|
||||
if (GET_MODE_CLASS (m1) == MODE_UFRACT)
|
||||
mclass = MODE_FRACT;
|
||||
else if (GET_MODE_CLASS (m1) == MODE_UACCUM)
|
||||
mclass = MODE_ACCUM;
|
||||
else
|
||||
gcc_unreachable ();
|
||||
m1 = mode_for_size (GET_MODE_PRECISION (m1), mclass, 0);
|
||||
}
|
||||
if (code2 == FIXED_POINT_TYPE && TYPE_UNSIGNED (t2))
|
||||
{
|
||||
unsigned char mclass = 0;
|
||||
if (GET_MODE_CLASS (m2) == MODE_UFRACT)
|
||||
mclass = MODE_FRACT;
|
||||
else if (GET_MODE_CLASS (m2) == MODE_UACCUM)
|
||||
mclass = MODE_ACCUM;
|
||||
else
|
||||
gcc_unreachable ();
|
||||
m2 = mode_for_size (GET_MODE_PRECISION (m2), mclass, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (code1 == FIXED_POINT_TYPE)
|
||||
{
|
||||
fbit1 = GET_MODE_FBIT (m1);
|
||||
ibit1 = GET_MODE_IBIT (m1);
|
||||
}
|
||||
else
|
||||
{
|
||||
fbit1 = 0;
|
||||
/* Signed integers need to subtract one sign bit. */
|
||||
ibit1 = TYPE_PRECISION (t1) - (!TYPE_UNSIGNED (t1));
|
||||
}
|
||||
|
||||
if (code2 == FIXED_POINT_TYPE)
|
||||
{
|
||||
fbit2 = GET_MODE_FBIT (m2);
|
||||
ibit2 = GET_MODE_IBIT (m2);
|
||||
}
|
||||
else
|
||||
{
|
||||
fbit2 = 0;
|
||||
/* Signed integers need to subtract one sign bit. */
|
||||
ibit2 = TYPE_PRECISION (t2) - (!TYPE_UNSIGNED (t2));
|
||||
}
|
||||
|
||||
max_ibit = ibit1 >= ibit2 ? ibit1 : ibit2;
|
||||
max_fbit = fbit1 >= fbit2 ? fbit1 : fbit2;
|
||||
return c_common_fixed_point_type_for_size (max_ibit, max_fbit, unsignedp,
|
||||
satp);
|
||||
}
|
||||
|
||||
/* Both real or both integers; use the one with greater precision. */
|
||||
|
||||
if (TYPE_PRECISION (t1) > TYPE_PRECISION (t2))
|
||||
|
@ -2808,7 +2895,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
|
|||
is enough to prevent anybody from looking inside for
|
||||
associativity, but won't generate any code. */
|
||||
if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE
|
||||
|| typecode == COMPLEX_TYPE
|
||||
|| typecode == FIXED_POINT_TYPE || typecode == COMPLEX_TYPE
|
||||
|| typecode == VECTOR_TYPE))
|
||||
{
|
||||
error ("wrong type argument to unary plus");
|
||||
|
@ -2821,7 +2908,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
|
|||
|
||||
case NEGATE_EXPR:
|
||||
if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE
|
||||
|| typecode == COMPLEX_TYPE
|
||||
|| typecode == FIXED_POINT_TYPE || typecode == COMPLEX_TYPE
|
||||
|| typecode == VECTOR_TYPE))
|
||||
{
|
||||
error ("wrong type argument to unary minus");
|
||||
|
@ -2878,7 +2965,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
|
|||
break;
|
||||
|
||||
case TRUTH_NOT_EXPR:
|
||||
if (typecode != INTEGER_TYPE
|
||||
if (typecode != INTEGER_TYPE && typecode != FIXED_POINT_TYPE
|
||||
&& typecode != REAL_TYPE && typecode != POINTER_TYPE
|
||||
&& typecode != COMPLEX_TYPE)
|
||||
{
|
||||
|
@ -2931,7 +3018,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
|
|||
|
||||
/* Report invalid types. */
|
||||
|
||||
if (typecode != POINTER_TYPE
|
||||
if (typecode != POINTER_TYPE && typecode != FIXED_POINT_TYPE
|
||||
&& typecode != INTEGER_TYPE && typecode != REAL_TYPE)
|
||||
{
|
||||
if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
|
||||
|
@ -2975,6 +3062,25 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
|
|||
inc = c_size_in_bytes (TREE_TYPE (result_type));
|
||||
inc = fold_convert (sizetype, inc);
|
||||
}
|
||||
else if (FRACT_MODE_P (TYPE_MODE (result_type)))
|
||||
{
|
||||
/* For signed fract types, we invert ++ to -- or
|
||||
-- to ++, and change inc from 1 to -1, because
|
||||
it is not possible to represent 1 in signed fract constants.
|
||||
For unsigned fract types, the result always overflows and
|
||||
we get an undefined (original) or the maximum value. */
|
||||
if (code == PREINCREMENT_EXPR)
|
||||
code = PREDECREMENT_EXPR;
|
||||
else if (code == PREDECREMENT_EXPR)
|
||||
code = PREINCREMENT_EXPR;
|
||||
else if (code == POSTINCREMENT_EXPR)
|
||||
code = POSTDECREMENT_EXPR;
|
||||
else /* code == POSTDECREMENT_EXPR */
|
||||
code = POSTINCREMENT_EXPR;
|
||||
|
||||
inc = integer_minus_one_node;
|
||||
inc = convert (argtype, inc);
|
||||
}
|
||||
else
|
||||
{
|
||||
inc = integer_one_node;
|
||||
|
@ -3924,9 +4030,11 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
|
|||
return convert (type, rhs);
|
||||
/* Arithmetic types all interconvert, and enum is treated like int. */
|
||||
else if ((codel == INTEGER_TYPE || codel == REAL_TYPE
|
||||
|| codel == FIXED_POINT_TYPE
|
||||
|| codel == ENUMERAL_TYPE || codel == COMPLEX_TYPE
|
||||
|| codel == BOOLEAN_TYPE)
|
||||
&& (coder == INTEGER_TYPE || coder == REAL_TYPE
|
||||
|| coder == FIXED_POINT_TYPE
|
||||
|| coder == ENUMERAL_TYPE || coder == COMPLEX_TYPE
|
||||
|| coder == BOOLEAN_TYPE))
|
||||
return convert_and_check (type, rhs);
|
||||
|
@ -4746,9 +4854,9 @@ digest_init (tree type, tree init, bool strict_string, int require_constant)
|
|||
|
||||
/* Handle scalar types, including conversions. */
|
||||
|
||||
if (code == INTEGER_TYPE || code == REAL_TYPE || code == POINTER_TYPE
|
||||
|| code == ENUMERAL_TYPE || code == BOOLEAN_TYPE || code == COMPLEX_TYPE
|
||||
|| code == VECTOR_TYPE)
|
||||
if (code == INTEGER_TYPE || code == REAL_TYPE || code == FIXED_POINT_TYPE
|
||||
|| code == POINTER_TYPE || code == ENUMERAL_TYPE || code == BOOLEAN_TYPE
|
||||
|| code == COMPLEX_TYPE || code == VECTOR_TYPE)
|
||||
{
|
||||
if (TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE
|
||||
&& (TREE_CODE (init) == STRING_CST
|
||||
|
@ -7862,8 +7970,10 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
|
|||
warn_for_div_by_zero (op1);
|
||||
|
||||
if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
|
||||
|| code0 == FIXED_POINT_TYPE
|
||||
|| code0 == COMPLEX_TYPE || code0 == VECTOR_TYPE)
|
||||
&& (code1 == INTEGER_TYPE || code1 == REAL_TYPE
|
||||
|| code1 == FIXED_POINT_TYPE
|
||||
|| code1 == COMPLEX_TYPE || code1 == VECTOR_TYPE))
|
||||
{
|
||||
enum tree_code tcode0 = code0, tcode1 = code1;
|
||||
|
@ -7873,7 +7983,8 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
|
|||
if (code1 == COMPLEX_TYPE || code1 == VECTOR_TYPE)
|
||||
tcode1 = TREE_CODE (TREE_TYPE (TREE_TYPE (op1)));
|
||||
|
||||
if (!(tcode0 == INTEGER_TYPE && tcode1 == INTEGER_TYPE))
|
||||
if (!((tcode0 == INTEGER_TYPE && tcode1 == INTEGER_TYPE)
|
||||
|| (tcode0 == FIXED_POINT_TYPE && tcode1 == FIXED_POINT_TYPE)))
|
||||
resultcode = RDIV_EXPR;
|
||||
else
|
||||
/* Although it would be tempting to shorten always here, that
|
||||
|
@ -7924,9 +8035,11 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
|
|||
case TRUTH_OR_EXPR:
|
||||
case TRUTH_XOR_EXPR:
|
||||
if ((code0 == INTEGER_TYPE || code0 == POINTER_TYPE
|
||||
|| code0 == REAL_TYPE || code0 == COMPLEX_TYPE)
|
||||
|| code0 == REAL_TYPE || code0 == COMPLEX_TYPE
|
||||
|| code0 == FIXED_POINT_TYPE)
|
||||
&& (code1 == INTEGER_TYPE || code1 == POINTER_TYPE
|
||||
|| code1 == REAL_TYPE || code1 == COMPLEX_TYPE))
|
||||
|| code1 == REAL_TYPE || code1 == COMPLEX_TYPE
|
||||
|| code1 == FIXED_POINT_TYPE))
|
||||
{
|
||||
/* Result of these operations is always an int,
|
||||
but that does not mean the operands should be
|
||||
|
@ -7943,7 +8056,8 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
|
|||
Also set SHORT_SHIFT if shifting rightward. */
|
||||
|
||||
case RSHIFT_EXPR:
|
||||
if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
|
||||
if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
|
||||
&& code1 == INTEGER_TYPE)
|
||||
{
|
||||
if (TREE_CODE (op1) == INTEGER_CST && skip_evaluation == 0)
|
||||
{
|
||||
|
@ -7971,7 +8085,8 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
|
|||
break;
|
||||
|
||||
case LSHIFT_EXPR:
|
||||
if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
|
||||
if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
|
||||
&& code1 == INTEGER_TYPE)
|
||||
{
|
||||
if (TREE_CODE (op1) == INTEGER_CST && skip_evaluation == 0)
|
||||
{
|
||||
|
@ -8002,9 +8117,9 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
|
|||
but don't convert the args to int! */
|
||||
build_type = integer_type_node;
|
||||
if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
|
||||
|| code0 == COMPLEX_TYPE)
|
||||
|| code0 == FIXED_POINT_TYPE || code0 == COMPLEX_TYPE)
|
||||
&& (code1 == INTEGER_TYPE || code1 == REAL_TYPE
|
||||
|| code1 == COMPLEX_TYPE))
|
||||
|| code1 == FIXED_POINT_TYPE || code1 == COMPLEX_TYPE))
|
||||
short_compare = 1;
|
||||
else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
|
||||
{
|
||||
|
@ -8072,8 +8187,10 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
|
|||
case LT_EXPR:
|
||||
case GT_EXPR:
|
||||
build_type = integer_type_node;
|
||||
if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE)
|
||||
&& (code1 == INTEGER_TYPE || code1 == REAL_TYPE))
|
||||
if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
|
||||
|| code0 == FIXED_POINT_TYPE)
|
||||
&& (code1 == INTEGER_TYPE || code1 == REAL_TYPE
|
||||
|| code1 == FIXED_POINT_TYPE))
|
||||
short_compare = 1;
|
||||
else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
|
||||
{
|
||||
|
@ -8134,10 +8251,10 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
|
|||
}
|
||||
|
||||
if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE || code0 == COMPLEX_TYPE
|
||||
|| code0 == VECTOR_TYPE)
|
||||
|| code0 == FIXED_POINT_TYPE || code0 == VECTOR_TYPE)
|
||||
&&
|
||||
(code1 == INTEGER_TYPE || code1 == REAL_TYPE || code1 == COMPLEX_TYPE
|
||||
|| code1 == VECTOR_TYPE))
|
||||
|| code1 == FIXED_POINT_TYPE || code1 == VECTOR_TYPE))
|
||||
{
|
||||
int none_complex = (code0 != COMPLEX_TYPE && code1 != COMPLEX_TYPE);
|
||||
|
||||
|
|
|
@ -65,6 +65,12 @@
|
|||
#endif
|
||||
|
||||
|
||||
/* Define to 1 to enable fixed-point arithmetic extension to C. */
|
||||
#ifndef USED_FOR_TARGET
|
||||
#undef ENABLE_FIXED_POINT
|
||||
#endif
|
||||
|
||||
|
||||
/* Define if you want fold checked that it never destructs its argument. This
|
||||
is quite expensive. */
|
||||
#ifndef USED_FOR_TARGET
|
||||
|
@ -1363,37 +1369,37 @@
|
|||
#endif
|
||||
|
||||
|
||||
/* The size of a `int', as computed by sizeof. */
|
||||
/* The size of `int', as computed by sizeof. */
|
||||
#ifndef USED_FOR_TARGET
|
||||
#undef SIZEOF_INT
|
||||
#endif
|
||||
|
||||
|
||||
/* The size of a `long', as computed by sizeof. */
|
||||
/* The size of `long', as computed by sizeof. */
|
||||
#ifndef USED_FOR_TARGET
|
||||
#undef SIZEOF_LONG
|
||||
#endif
|
||||
|
||||
|
||||
/* The size of a `long long', as computed by sizeof. */
|
||||
/* The size of `long long', as computed by sizeof. */
|
||||
#ifndef USED_FOR_TARGET
|
||||
#undef SIZEOF_LONG_LONG
|
||||
#endif
|
||||
|
||||
|
||||
/* The size of a `short', as computed by sizeof. */
|
||||
/* The size of `short', as computed by sizeof. */
|
||||
#ifndef USED_FOR_TARGET
|
||||
#undef SIZEOF_SHORT
|
||||
#endif
|
||||
|
||||
|
||||
/* The size of a `void *', as computed by sizeof. */
|
||||
/* The size of `void *', as computed by sizeof. */
|
||||
#ifndef USED_FOR_TARGET
|
||||
#undef SIZEOF_VOID_P
|
||||
#endif
|
||||
|
||||
|
||||
/* The size of a `__int64', as computed by sizeof. */
|
||||
/* The size of `__int64', as computed by sizeof. */
|
||||
#ifndef USED_FOR_TARGET
|
||||
#undef SIZEOF___INT64
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -641,6 +641,28 @@ AC_DEFINE_UNQUOTED(ENABLE_DECIMAL_BID_FORMAT, $bid,
|
|||
[Define to 1 to specify that we are using the BID decimal floating
|
||||
point format instead of DPD])
|
||||
|
||||
# Enable C extension for fixed-point arithmetic.
|
||||
AC_ARG_ENABLE(fixed-point,
|
||||
[ --enable-fixed-point enable fixed-point arithmetic extension to C],
|
||||
[
|
||||
],
|
||||
[
|
||||
case $target in
|
||||
mips*-*-*)
|
||||
enable_fixed_point=yes
|
||||
;;
|
||||
*)
|
||||
AC_MSG_WARN(fixed-point is not supported for this target, ignored)
|
||||
enable_fixed_point=no
|
||||
;;
|
||||
esac
|
||||
])
|
||||
AC_SUBST(enable_fixed_point)
|
||||
|
||||
fixedpoint=`if test $enable_fixed_point = yes; then echo 1; else echo 0; fi`
|
||||
AC_DEFINE_UNQUOTED(ENABLE_FIXED_POINT, $fixedpoint,
|
||||
[Define to 1 to enable fixed-point arithmetic extension to C.])
|
||||
|
||||
# Enable threads
|
||||
# Pass with no value to take the default
|
||||
# Pass with a value to specify a thread package
|
||||
|
|
|
@ -1317,6 +1317,13 @@ or @samp{dpd}). The @samp{bid} (binary integer decimal) format is
|
|||
default on i386 and x86_64 systems, and the @samp{dpd} (densely packed
|
||||
decimal) format is default on PowerPC systems.
|
||||
|
||||
@item --enable-fixed-point
|
||||
@itemx --disable-fixed-point
|
||||
Enable (or disable) support for C fixed-point arithmetic.
|
||||
This option is enabled by default for some targets (such as MIPS) which
|
||||
have hardware-support for fixed-point operations. On other targets, you
|
||||
may enable this option manually.
|
||||
|
||||
@item --with-long-double-128
|
||||
Specify if @code{long double} type should be 128-bit by default on selected
|
||||
GNU/Linux architectures. If using @code{--without-long-double-128},
|
||||
|
|
|
@ -1502,6 +1502,10 @@ may affect its placement.
|
|||
Returns true if the target supports decimal floating point.
|
||||
@end deftypefn
|
||||
|
||||
@deftypefn {Target Hook} {bool} TARGET_FIXED_POINT_SUPPORTED_P (void)
|
||||
Returns true if the target supports fixed-point arithmetic.
|
||||
@end deftypefn
|
||||
|
||||
@deftypefn {Target Hook} {const char *} TARGET_MANGLE_TYPE (tree @var{type})
|
||||
If your target defines any fundamental types, or any types your target
|
||||
uses should be mangled differently from the default, define this hook
|
||||
|
|
|
@ -437,6 +437,10 @@
|
|||
#define TARGET_DECIMAL_FLOAT_SUPPORTED_P default_decimal_float_supported_p
|
||||
#endif
|
||||
|
||||
#ifndef TARGET_FIXED_POINT_SUPPORTED_P
|
||||
#define TARGET_FIXED_POINT_SUPPORTED_P default_fixed_point_supported_p
|
||||
#endif
|
||||
|
||||
#ifndef TARGET_VECTOR_MODE_SUPPORTED_P
|
||||
#define TARGET_VECTOR_MODE_SUPPORTED_P hook_bool_mode_false
|
||||
#endif
|
||||
|
@ -689,6 +693,7 @@
|
|||
TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P, \
|
||||
TARGET_MS_BITFIELD_LAYOUT_P, \
|
||||
TARGET_DECIMAL_FLOAT_SUPPORTED_P, \
|
||||
TARGET_FIXED_POINT_SUPPORTED_P, \
|
||||
TARGET_ALIGN_ANON_BITFIELD, \
|
||||
TARGET_NARROW_VOLATILE_BITFIELD, \
|
||||
TARGET_INIT_BUILTINS, \
|
||||
|
|
|
@ -479,6 +479,9 @@ struct gcc_target
|
|||
/* True if the target supports decimal floating point. */
|
||||
bool (* decimal_float_supported_p) (void);
|
||||
|
||||
/* True if the target supports fixed-point. */
|
||||
bool (* fixed_point_supported_p) (void);
|
||||
|
||||
/* Return true if anonymous bitfields affect structure alignment. */
|
||||
bool (* align_anon_bitfield) (void);
|
||||
|
||||
|
|
|
@ -298,6 +298,10 @@ default_scalar_mode_supported_p (enum machine_mode mode)
|
|||
return false;
|
||||
|
||||
case MODE_DECIMAL_FLOAT:
|
||||
case MODE_FRACT:
|
||||
case MODE_UFRACT:
|
||||
case MODE_ACCUM:
|
||||
case MODE_UACCUM:
|
||||
return false;
|
||||
|
||||
default:
|
||||
|
@ -313,6 +317,14 @@ default_decimal_float_supported_p (void)
|
|||
return ENABLE_DECIMAL_FLOAT;
|
||||
}
|
||||
|
||||
/* True if the target supports fixed-point arithmetic. */
|
||||
|
||||
bool
|
||||
default_fixed_point_supported_p (void)
|
||||
{
|
||||
return ENABLE_FIXED_POINT;
|
||||
}
|
||||
|
||||
/* NULL if INSN insn is valid within a low-overhead loop, otherwise returns
|
||||
an error message.
|
||||
|
||||
|
|
|
@ -55,6 +55,7 @@ extern void default_unwind_emit (FILE *, rtx);
|
|||
|
||||
extern bool default_scalar_mode_supported_p (enum machine_mode);
|
||||
extern bool default_decimal_float_supported_p (void);
|
||||
extern bool default_fixed_point_supported_p (void);
|
||||
|
||||
extern const char * default_invalid_within_doloop (rtx);
|
||||
|
||||
|
|
Loading…
Reference in New Issue