* [ping][patch] Fixed-point patch 4/10
@ 2007-08-01 23:59 Fu, Chao-Ying
2007-08-06 3:53 ` Mark Mitchell
2007-08-16 15:14 ` Joseph S. Myers
0 siblings, 2 replies; 13+ messages in thread
From: Fu, Chao-Ying @ 2007-08-01 23:59 UTC (permalink / raw)
To: gcc-patches; +Cc: Thekkath, Radhika, Stephens, Nigel, Mark Mitchell
[-- Attachment #1: Type: text/plain, Size: 4139 bytes --]
Hi,
Here is the patch #4. Please review it. Thanks!
> 1. Merge in machine modes to support signed and unsigned
> fract and accum modes. Handle scalar and vector modes.
DONE!
> 2. Merge in fixed-value.h and fixed-value.c to handle fixed-point values.
(fixed-value.diff)
> 3. Merge in TREE structures for fixed-point types and constants.
(tree.diff)
> 4. Merge in C front-end changes to parse _Sat, _Fract and _Accum.
(c-parser.diff)
> 5. Merge in RTL structures for fixed-point constants and operators.
> 6. Merge in libcpp to parse fixed-point constants.
> 7. Merge in changes to support "case" of FIXED_POINT_TYPE, FIXED_CST,
> and CONST_FIXED in .c and .h files.
> 8. Merge in the MIPS backend that supports fixed-point instructions.
> 9. Merge in configure/build system changes for the runtime library.
> 10. Merge in testsuite (from gcc.dg/fixed-point) that only run
> when the compiler is configured to enable fixed-point.
Regards,
Chao-ying
gcc/ChangeLog
2007-08-01 Chao-ying Fu <fu@mips.com>
* c-common.h (enum rid): Add new enumeration values of RID_SAT,
RID_FRACT, and RID_ACCUM.
(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 or _Accum.
Handle RID_SAT.
Avoid using void, bool, char, int, float, double, _Decimal32,
_Decimal64, _Decimal128 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.
* configure, config.in: Regenerate.
[-- Attachment #2: c-parser.diff --]
[-- Type: application/octet-stream, Size: 45286 bytes --]
Index: gcc4x/gcc/gcc/c-common.h
===================================================================
--- gcc4x.orig/gcc/gcc/c-common.h 2007-07-26 10:52:08.000000000 -0700
+++ gcc4x/gcc/gcc/c-common.h 2007-07-26 11:56:42.000000000 -0700
@@ -52,7 +52,7 @@
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 @@
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,
@@ -674,6 +675,8 @@
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);
Index: gcc4x/gcc/gcc/c-parser.c
===================================================================
--- gcc4x.orig/gcc/gcc/c-parser.c 2007-07-26 10:52:09.000000000 -0700
+++ gcc4x/gcc/gcc/c-parser.c 2007-07-26 11:56:42.000000000 -0700
@@ -80,6 +80,9 @@
{ "_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 @@
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 @@
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 @@
_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 @@
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 @@
case RID_DFLOAT64:
case RID_DFLOAT128:
case RID_BOOL:
+ case RID_FRACT:
+ case RID_ACCUM:
+ case RID_SAT:
ok = true;
break;
default:
Index: gcc4x/gcc/gcc/c-tree.h
===================================================================
--- gcc4x.orig/gcc/gcc/c-tree.h 2007-07-26 10:52:03.000000000 -0700
+++ gcc4x/gcc/gcc/c-tree.h 2007-07-26 11:56:42.000000000 -0700
@@ -202,7 +202,7 @@
};
/* A type specifier keyword "void", "_Bool", "char", "int", "float",
- "double", or none of these. */
+ "double", "_Fract", "_Accum", or none of these. */
enum c_typespec_keyword {
cts_none,
cts_void,
@@ -213,7 +213,9 @@
cts_double,
cts_dfloat32,
cts_dfloat64,
- cts_dfloat128
+ cts_dfloat128,
+ cts_fract,
+ cts_accum
};
/* A sequence of declaration specifiers in C. */
@@ -281,6 +283,8 @@
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. */
Index: gcc4x/gcc/gcc/c-decl.c
===================================================================
--- gcc4x.orig/gcc/gcc/c-decl.c 2007-07-26 10:52:04.000000000 -0700
+++ gcc4x/gcc/gcc/c-decl.c 2007-07-26 11:56:42.000000000 -0700
@@ -7134,6 +7134,7 @@
ret->const_p = false;
ret->volatile_p = false;
ret->restrict_p = false;
+ ret->saturating_p = false;
return ret;
}
@@ -7196,7 +7197,7 @@
}
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,49 @@
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
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
+ specs->saturating_p = true;
+ break;
default:
gcc_unreachable ();
}
@@ -7370,7 +7411,8 @@
}
else
{
- /* "void", "_Bool", "char", "int", "float" or "double". */
+ /* "void", "_Bool", "char", "int", "float", "double", "_Fract"
+ or "_Accum". */
if (specs->typespec_word != cts_none)
{
error ("two or more data types in declaration specifiers");
@@ -7394,6 +7436,9 @@
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 +7458,9 @@
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 +7471,18 @@
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 +7497,9 @@
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 +7516,9 @@
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 +7551,9 @@
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 +7566,27 @@
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 +7758,8 @@
"_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 +7879,88 @@
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 ();
}
Index: gcc4x/gcc/gcc/c-common.c
===================================================================
--- gcc4x.orig/gcc/gcc/c-common.c 2007-07-26 10:52:08.000000000 -0700
+++ gcc4x/gcc/gcc/c-common.c 2007-07-26 11:56:42.000000000 -0700
@@ -48,6 +48,7 @@
#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 @@
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 @@
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 @@
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,42 @@
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)
+ {
+ error ("cannot find a common fixed-point mode to operate.");
+ 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 +2070,95 @@
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 +2220,54 @@
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 +2496,8 @@
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 +2552,7 @@
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 +2958,12 @@
? 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 +3064,14 @@
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);
}
\f
@@ -3594,6 +3783,67 @@
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));
@@ -5004,6 +5254,10 @@
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;
@@ -5014,6 +5268,10 @@
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,
@@ -5047,7 +5305,20 @@
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)
{
@@ -5796,7 +6067,8 @@
|| 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);
@@ -6929,8 +7201,9 @@
{
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. */
@@ -7095,11 +7368,12 @@
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");
}
Index: gcc4x/gcc/gcc/c-typeck.c
===================================================================
--- gcc4x.orig/gcc/gcc/c-typeck.c 2007-07-26 10:52:05.000000000 -0700
+++ gcc4x/gcc/gcc/c-typeck.c 2007-07-26 11:56:42.000000000 -0700
@@ -604,9 +604,11 @@
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 @@
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
+ error ("machine mode is wrong");
+ 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
+ error ("machine mode is wrong");
+ 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 @@
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 @@
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");
@@ -2875,7 +2962,7 @@
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)
{
@@ -2928,7 +3015,7 @@
/* 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)
@@ -2972,6 +3059,25 @@
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;
@@ -3920,9 +4026,11 @@
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);
@@ -4741,9 +4849,9 @@
/* 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
@@ -7857,8 +7965,10 @@
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;
@@ -7868,7 +7978,8 @@
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
@@ -7915,9 +8026,11 @@
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
@@ -7934,7 +8047,8 @@
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)
{
@@ -7962,7 +8076,8 @@
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)
{
@@ -7993,9 +8108,9 @@
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)
{
@@ -8063,8 +8178,10 @@
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)
{
@@ -8125,10 +8242,10 @@
}
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);
Index: gcc4x/gcc/gcc/target-def.h
===================================================================
--- gcc4x.orig/gcc/gcc/target-def.h 2007-07-26 10:52:07.000000000 -0700
+++ gcc4x/gcc/gcc/target-def.h 2007-07-26 11:56:42.000000000 -0700
@@ -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, \
Index: gcc4x/gcc/gcc/target.h
===================================================================
--- gcc4x.orig/gcc/gcc/target.h 2007-07-26 10:51:59.000000000 -0700
+++ gcc4x/gcc/gcc/target.h 2007-07-26 11:56:42.000000000 -0700
@@ -479,6 +479,9 @@
/* 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);
Index: gcc4x/gcc/gcc/targhooks.c
===================================================================
--- gcc4x.orig/gcc/gcc/targhooks.c 2007-07-26 10:51:58.000000000 -0700
+++ gcc4x/gcc/gcc/targhooks.c 2007-07-26 11:56:42.000000000 -0700
@@ -298,6 +298,10 @@
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 @@
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.
Index: gcc4x/gcc/gcc/targhooks.h
===================================================================
--- gcc4x.orig/gcc/gcc/targhooks.h 2007-07-26 10:51:58.000000000 -0700
+++ gcc4x/gcc/gcc/targhooks.h 2007-07-26 11:56:42.000000000 -0700
@@ -55,6 +55,7 @@
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);
Index: gcc4x/gcc/gcc/doc/tm.texi
===================================================================
--- gcc4x.orig/gcc/gcc/doc/tm.texi 2007-07-26 11:56:36.000000000 -0700
+++ gcc4x/gcc/gcc/doc/tm.texi 2007-07-26 11:56:42.000000000 -0700
@@ -1502,6 +1502,10 @@
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
Index: gcc4x/gcc/gcc/doc/install.texi
===================================================================
--- gcc4x.orig/gcc/gcc/doc/install.texi 2007-07-26 10:47:21.000000000 -0700
+++ gcc4x/gcc/gcc/doc/install.texi 2007-07-26 11:56:42.000000000 -0700
@@ -1317,6 +1317,11 @@
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 the C fixed-point arithmetic
+extension.
+
@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},
Index: gcc4x/gcc/gcc/configure.ac
===================================================================
--- gcc4x.orig/gcc/gcc/configure.ac 2007-07-26 10:52:04.000000000 -0700
+++ gcc4x/gcc/gcc/configure.ac 2007-07-26 11:56:43.000000000 -0700
@@ -638,6 +638,23 @@
[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],
+[
+ if test x$enableval = xyes ; then
+ enable_fixed_point=yes
+ else
+ enable_fixed_point=no
+ fi
+], [enable_fixed_point=no])
+
+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
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [ping][patch] Fixed-point patch 4/10
2007-08-01 23:59 [ping][patch] Fixed-point patch 4/10 Fu, Chao-Ying
@ 2007-08-06 3:53 ` Mark Mitchell
2007-08-16 0:47 ` Fu, Chao-Ying
2007-08-16 15:14 ` Joseph S. Myers
1 sibling, 1 reply; 13+ messages in thread
From: Mark Mitchell @ 2007-08-06 3:53 UTC (permalink / raw)
To: Fu, Chao-Ying, Joseph S. Myers
Cc: gcc-patches, Thekkath, Radhika, Stephens, Nigel
Fu, Chao-Ying wrote:
> gcc/ChangeLog
> 2007-08-01 Chao-ying Fu <fu@mips.com>
>
> * c-common.h (enum rid): Add new enumeration values of RID_SAT,
> RID_FRACT, and RID_ACCUM.
> (c_common_fixed_point_type_for_size): Declare.
Joseph, would you please review?
Thanks,
--
Mark Mitchell
CodeSourcery
mark@codesourcery.com
(650) 331-3385 x713
^ permalink raw reply [flat|nested] 13+ messages in thread
* RE: [ping][patch] Fixed-point patch 4/10
2007-08-06 3:53 ` Mark Mitchell
@ 2007-08-16 0:47 ` Fu, Chao-Ying
0 siblings, 0 replies; 13+ messages in thread
From: Fu, Chao-Ying @ 2007-08-16 0:47 UTC (permalink / raw)
To: Joseph S. Myers, Mark Mitchell
Cc: gcc-patches, Thekkath, Radhika, Stephens, Nigel
Hi Joseph,
Is there any status update for this patch?
Thanks a lot!
Regards,
Chao-ying
> -----Original Message-----
> From: Mark Mitchell [mailto:mark@codesourcery.com]
> Sent: Sunday, August 05, 2007 8:53 PM
> To: Fu, Chao-Ying; Joseph S. Myers
> Cc: gcc-patches@gcc.gnu.org; Thekkath, Radhika; Stephens, Nigel
> Subject: Re: [ping][patch] Fixed-point patch 4/10
>
>
> Fu, Chao-Ying wrote:
>
> > gcc/ChangeLog
> > 2007-08-01 Chao-ying Fu <fu@mips.com>
> >
> > * c-common.h (enum rid): Add new enumeration values of RID_SAT,
> > RID_FRACT, and RID_ACCUM.
> > (c_common_fixed_point_type_for_size): Declare.
>
> Joseph, would you please review?
>
> Thanks,
>
> --
> Mark Mitchell
> CodeSourcery
> mark@codesourcery.com
> (650) 331-3385 x713
>
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [ping][patch] Fixed-point patch 4/10
2007-08-01 23:59 [ping][patch] Fixed-point patch 4/10 Fu, Chao-Ying
2007-08-06 3:53 ` Mark Mitchell
@ 2007-08-16 15:14 ` Joseph S. Myers
2007-08-16 19:11 ` Fu, Chao-Ying
1 sibling, 1 reply; 13+ messages in thread
From: Joseph S. Myers @ 2007-08-16 15:14 UTC (permalink / raw)
To: Fu, Chao-Ying
Cc: gcc-patches, Thekkath, Radhika, Stephens, Nigel, Mark Mitchell
On Wed, 1 Aug 2007, Fu, Chao-Ying wrote:
> * c-common.h (enum rid): Add new enumeration values of RID_SAT,
> RID_FRACT, and RID_ACCUM.
Why do you have RID_SAT in a different part of the enumeration from
RID_FRACT and RIC_ACCUM, instead of all together?
> * c-tree.h (enum c_typespec_keyword): Add cts_fract and cts_accum.
You correctly add the new keywords to the comment, but it was already out
of date; please add the other missing ones _Decimal32, _Decimal64,
_Decimal128 to the comment at the same time.
> * c-decl.c (build_null_declspecs): Initialize saturating_p.
> (declspecs_add_type): Avoid using complex with _Fract or _Accum.
> Handle RID_SAT.
> Avoid using void, bool, char, int, float, double, _Decimal32,
> _Decimal64, _Decimal128 with _Sat.
> Handle RID_FRACT and RID_ACCUM.
> Make sure _Sat is used with _Fract or _Accum.
_Sat _Complex doesn't appear in any valid types, so I think it would be
worth detecting it whenever the second of those keywords is added rather
than at a later stage.
> (c_common_fixed_point_type_for_size): New.
Errors shouldn't end with a trailing ".",
+ error ("cannot find a common fixed-point mode to operate.");
and in any case this error seems uninformative to the user - it's written
in compiler-internals terms, not in terms of what's wrong with the user's
code. If it's an internal error and should never occur for valid or
invalid user code, make it an internal_error or a gcc_assert; otherwise,
make it explain what's wrong with the user's code (or make the caller give
such a more meaningful error).
> * c-typeck.c (c_common_type): Check FIXED_POINT_TYPE. Build
> a common fixed-point type based on fbit, ibit, sign, and saturation.
Again, you have errors that are not meaningful to the user.
+ error ("machine mode is wrong");
+ error ("machine mode is wrong");
Make them meaningful if they can arise from erroneous user code, make them
internal errors or assertions if they can't.
> * 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.
> * configure, config.in: Regenerate.
I can't review these parts though I don't see anything wrong with them,
except: I think your AC_ARG_ENABLE call is more verbose than necessary for
what it currently does; the variable enable_fixed_point will be
automatically set so you don't need
+ if test x$enableval = xyes ; then
+ enable_fixed_point=yes
+ else
+ enable_fixed_point=no
+ fi
(and appropriate quoting in the subsequent fixedpoint=... will avoid the
need to convert strange arguments to the configure option into "no").
However, the configure test actually needs a whitelist of supported
targets, like --enable-decimal-float has. This should contain only
targets for which there is publically available documentation of the
necessary ABI extensions for layout and argument passing and function
return involving the new types. (If there is no ABI authority for a
target to define the ABI in a compiler-independent way, you can always
write your own GCC ABI and put it in a file in projects/ on the website,
but it should still be documented before allowing the extension to be
enabled for a target.)
gcc/doc/extend.texi needs updating to describe the support for the
fixed-point extension, if this isn't in another of the patches in this
series.
--
Joseph S. Myers
joseph@codesourcery.com
^ permalink raw reply [flat|nested] 13+ messages in thread
* RE: [ping][patch] Fixed-point patch 4/10
2007-08-16 15:14 ` Joseph S. Myers
@ 2007-08-16 19:11 ` Fu, Chao-Ying
2007-08-16 19:53 ` Joseph S. Myers
0 siblings, 1 reply; 13+ messages in thread
From: Fu, Chao-Ying @ 2007-08-16 19:11 UTC (permalink / raw)
To: Joseph S. Myers
Cc: gcc-patches, Thekkath, Radhika, Stephens, Nigel, Mark Mitchell
[-- Attachment #1: Type: text/plain, Size: 13128 bytes --]
Joseph S. Myers wrote:
>
> On Wed, 1 Aug 2007, Fu, Chao-Ying wrote:
>
> > * c-common.h (enum rid): Add new enumeration values of RID_SAT,
> > RID_FRACT, and RID_ACCUM.
>
> Why do you have RID_SAT in a different part of the enumeration from
> RID_FRACT and RIC_ACCUM, instead of all together?
In "declspecs_add_type", the detection of type specifier is as follows.
It checks i <= RID_LAST_MODIFIER.
------ (c-decl.c)
/* Handle type specifier keywords. */
if (TREE_CODE (type) == IDENTIFIER_NODE && C_IS_RESERVED_WORD (type))
{
enum rid i = C_RID_CODE (type);
if (specs->type)
{
error ("two or more data types in declaration specifiers");
return specs;
}
if ((int) i <= (int) RID_LAST_MODIFIER)
{
/* "long", "short", "signed", "unsigned", "_Complex" or "_Sat". */
bool dupe = false;
switch (i)
------
Then, "RID_LAST_MODIFIER" is the same as "RID_ONEWAY", so I need to
insert "RID_SAT" to a location before "RID_ONEWAY" as follows.
------- (c-common.h)
/* C extensions */
RID_COMPLEX, RID_THREAD, RID_SAT,
/* C++ */
RID_FRIEND, RID_VIRTUAL, RID_EXPLICIT, RID_EXPORT, RID_MUTABLE,
/* ObjC */
RID_IN, RID_OUT, RID_INOUT, RID_BYCOPY, RID_BYREF, RID_ONEWAY,
...
RID_MAX,
RID_FIRST_MODIFIER = RID_STATIC,
RID_LAST_MODIFIER = RID_ONEWAY,
-------
>
> > * c-tree.h (enum c_typespec_keyword): Add cts_fract and
> cts_accum.
>
> You correctly add the new keywords to the comment, but it was
> already out
> of date; please add the other missing ones _Decimal32, _Decimal64,
> _Decimal128 to the comment at the same time.
Yes. I will add the missing ones.
>
> > * c-decl.c (build_null_declspecs): Initialize saturating_p.
> > (declspecs_add_type): Avoid using complex with _Fract or _Accum.
> > Handle RID_SAT.
> > Avoid using void, bool, char, int, float, double, _Decimal32,
> > _Decimal64, _Decimal128 with _Sat.
> > Handle RID_FRACT and RID_ACCUM.
> > Make sure _Sat is used with _Fract or _Accum.
>
> _Sat _Complex doesn't appear in any valid types, so I think
> it would be
> worth detecting it whenever the second of those keywords is
> added rather
> than at a later stage.
Yes. I will add code to detect _Sat _Complex and _Complex _Sat.
>
> > (c_common_fixed_point_type_for_size): New.
>
> Errors shouldn't end with a trailing ".",
Yes.
>
> + error ("cannot find a common fixed-point mode to operate.");
>
> and in any case this error seems uninformative to the user -
> it's written
> in compiler-internals terms, not in terms of what's wrong
> with the user's
> code. If it's an internal error and should never occur for valid or
> invalid user code, make it an internal_error or a gcc_assert;
> otherwise,
> make it explain what's wrong with the user's code (or make
> the caller give
> such a more meaningful error).
This error comes from valid user code that tries to operate on
mixed data types of integers and fractional types.
Ex:
long long a; /* 63 integral bits + a sign bit. */
long long _Fract b; /* 63 fractional bits + a sign bit. */
b = a * b; // For this operation (a * b), GCC tries to find an accum mode
that can support at least 63 integral bits and 63 fractional bits.
But, if the target doesn't have this kind of accum mode, GCC fails.
Maybe I will use this error message.
---
error ("should not use integer types and fixed-point types that have too\
\nmany integral and fractional bits together");
---
Is it ok?
>
> > * c-typeck.c (c_common_type): Check FIXED_POINT_TYPE. Build
> > a common fixed-point type based on fbit, ibit, sign,
> and saturation.
>
> Again, you have errors that are not meaningful to the user.
>
> + error ("machine mode is wrong");
>
> + error ("machine mode is wrong");
>
> Make them meaningful if they can arise from erroneous user
> code, make them
> internal errors or assertions if they can't.
I will change to gcc_assert (0), because these cases should not happen.
>
> > * 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.
> > * configure, config.in: Regenerate.
>
> I can't review these parts though I don't see anything wrong
> with them,
> except: I think your AC_ARG_ENABLE call is more verbose than
> necessary for
> what it currently does; the variable enable_fixed_point will be
> automatically set so you don't need
>
> + if test x$enableval = xyes ; then
> + enable_fixed_point=yes
> + else
> + enable_fixed_point=no
> + fi
>
> (and appropriate quoting in the subsequent fixedpoint=...
> will avoid the
> need to convert strange arguments to the configure option into "no").
>
> However, the configure test actually needs a whitelist of supported
> targets, like --enable-decimal-float has.
Ok. I will add mips*-*-* as supported targets for now.
---
# 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)
---
> This should contain only
> targets for which there is publically available documentation of the
> necessary ABI extensions for layout and argument passing and function
> return involving the new types. (If there is no ABI authority for a
> target to define the ABI in a compiler-independent way, you
> can always
> write your own GCC ABI and put it in a file in projects/ on
> the website,
> but it should still be documented before allowing the extension to be
> enabled for a target.)
I think the ABI for the fixed-point types is similar to the ABI for
integer types for MIPS. I will talk to Nigel about the ABI file later.
>
> gcc/doc/extend.texi needs updating to describe the support for the
> fixed-point extension, if this isn't in another of the
> patches in this
> series.
The change of extend.texi is in the patch 7/10 (changes.diff).
---
Index: gcc4x/gcc/gcc/doc/extend.texi
===================================================================
--- gcc4x.orig/gcc/gcc/doc/extend.texi 2007-08-13 10:26:05.000000000 -0700
+++ gcc4x/gcc/gcc/doc/extend.texi 2007-08-13 16:33:30.000000000 -0700
@@ -36,6 +36,7 @@ extensions, accepted by GCC in C89 mode
* Floating Types:: Additional Floating Types.
* Decimal Float:: Decimal Floating Types.
* Hex Floats:: Hexadecimal floating-point constants.
+* Fixed-Point:: Fixed-Point Types.
* Zero Length:: Zero-length arrays.
* Variable Length:: Arrays whose length is computed at run time.
* Empty Structures:: Structures with no members.
@@ -923,6 +924,134 @@ would not be able to resolve the ambigui
could mean @code{1.0f} or @code{1.9375} since @samp{f} is also the
extension for floating-point constants of type @code{float}.
+@node Fixed-Point
+@section Fixed-Point Types
+@cindex fixed-point types
+@cindex @code{_Fract} data type
+@cindex @code{_Accum} data type
+@cindex @code{_Sat} data type
+@cindex @code{hr} fixed-suffix
+@cindex @code{r} fixed-suffix
+@cindex @code{lr} fixed-suffix
+@cindex @code{llr} fixed-suffix
+@cindex @code{uhr} fixed-suffix
+@cindex @code{ur} fixed-suffix
+@cindex @code{ulr} fixed-suffix
+@cindex @code{ullr} fixed-suffix
+@cindex @code{hk} fixed-suffix
+@cindex @code{k} fixed-suffix
+@cindex @code{lk} fixed-suffix
+@cindex @code{llk} fixed-suffix
+@cindex @code{uhk} fixed-suffix
+@cindex @code{uk} fixed-suffix
+@cindex @code{ulk} fixed-suffix
+@cindex @code{ullk} fixed-suffix
+@cindex @code{HR} fixed-suffix
+@cindex @code{R} fixed-suffix
+@cindex @code{LR} fixed-suffix
+@cindex @code{LLR} fixed-suffix
+@cindex @code{UHR} fixed-suffix
+@cindex @code{UR} fixed-suffix
+@cindex @code{ULR} fixed-suffix
+@cindex @code{ULLR} fixed-suffix
+@cindex @code{HK} fixed-suffix
+@cindex @code{K} fixed-suffix
+@cindex @code{LK} fixed-suffix
+@cindex @code{LLK} fixed-suffix
+@cindex @code{UHK} fixed-suffix
+@cindex @code{UK} fixed-suffix
+@cindex @code{ULK} fixed-suffix
+@cindex @code{ULLK} fixed-suffix
+
+As an extension, the GNU C compiler supports fixed-point types as
+defined in the N1169 draft of ISO/IEC DTR 18037. Support for fixed-point
+types in GCC will evolve as the draft technical report changes.
+Calling conventions for any target might also change. Not all targets
+support fixed-point types.
+
+The fixed-point types are
+@code{short _Fract},
+@code{_Fract},
+@code{long _Fract},
+@code{long long _Fract},
+@code{unsigned short _Fract},
+@code{unsigned _Fract},
+@code{unsigned long _Fract},
+@code{unsigned long long _Fract},
+@code{_Sat short _Fract},
+@code{_Sat _Fract},
+@code{_Sat long _Fract},
+@code{_Sat long long _Fract},
+@code{_Sat unsigned short _Fract},
+@code{_Sat unsigned _Fract},
+@code{_Sat unsigned long _Fract},
+@code{_Sat unsigned long long _Fract},
+@code{short _Accum},
+@code{_Accum},
+@code{long _Accum},
+@code{long long _Accum},
+@code{unsigned short _Accum},
+@code{unsigned _Accum},
+@code{unsigned long _Accum},
+@code{unsigned long long _Accum},
+@code{_Sat short _Accum},
+@code{_Sat _Accum},
+@code{_Sat long _Accum},
+@code{_Sat long long _Accum},
+@code{_Sat unsigned short _Accum},
+@code{_Sat unsigned _Accum},
+@code{_Sat unsigned long _Accum},
+@code{_Sat unsigned long long _Accum}.
+Fixed-point data values contain fractional and optional integral parts.
+The format of fixed-point data varies and depends on the target machine.
+
+Support for fixed-point types includes prefix and postfix increment
+and decrement operators (@code{++}, @code{--}); unary arithmetic operators
+(@code{+}, @code{-}, @code{!}); binary arithmetic operators (@code{+},
+@code{-}, @code{*}, @code{/}); binary shift operators (@code{<<}, @code{>>});
+relational operators (@code{<}, @code{<=}, @code{>=}, @code{>});
+equality operators (@code{==}, @code{!=}); assignment operators
+(@code{+=}, @code{-=}, @code{*=}, @code{/=}, @code{<<=}, @code{>>=});
+and conversions to and from integer, floating-point, or fixed-point types.
+
+Use a suffix @samp{hr} or @samp{HR} in a literal constant of type
+@code{short _Fract} and @code{_Sat short _Fract},
+@samp{r} or @samp{R} for @code{_Fract} and @code{_Sat _Fract},
+@samp{lr} or @samp{LR} for @code{long _Fract} and @code{_Sat long _Fract},
+@samp{llr} or @samp{LLR} for @code{long long _Fract} and
+@code{_Sat long long _Fract},
+@samp{uhr} or @samp{UHR} for @code{unsigned short _Fract} and
+@code{_Sat unsigned short _Fract},
+@samp{ur} or @samp{UR} for @code{unsigned _Fract} and
+@code{_Sat unsigned _Fract},
+@samp{ulr} or @samp{ULR} for @code{unsigned long _Fract} and
+@code{_Sat unsigned long _Fract},
+@samp{ullr} or @samp{ULLR} for @code{unsigned long long _Fract}
+@code{_Sat unsigned long _Fract},
+@samp{ullr} or @samp{ULLR} for @code{unsigned long long _Fract}
+and @code{_Sat unsigned long long _Fract},
+@samp{hk} or @samp{HK} for @code{short _Accum} and @code{_Sat short _Accum},
+@samp{k} or @samp{K} for @code{_Accum} and @code{_Sat _Accum},
+@samp{lk} or @samp{LK} for @code{long _Accum} and @code{_Sat long _Accum},
+@samp{llk} or @samp{LLK} for @code{long long _Accum} and
+@code{_Sat long long _Accum},
+@samp{uhk} or @samp{UHK} for @code{unsigned short _Accum} and
+@code{_Sat unsigned short _Accum},
+@samp{uk} or @samp{UK} for @code{unsigned _Accum} and
+@code{_Sat unsigned _Accum},
+@samp{ulk} or @samp{ULK} for @code{unsigned long _Accum} and
+@code{_Sat unsigned long _Accum},
+and @samp{ullk} or @samp{ULLK} for @code{unsigned long long _Accum}
+and @code{_Sat unsigned long long _Accum}.
+
+GCC support of fixed-point types as specified by the draft technical report
+is incomplete:
+
+@itemize @bullet
+@item
+Pragmas to control overflow and rounding behaviors are not implemented.
+@end itemize
+
+Fixed-point types are supported by the DWARF2 debug information format.
+
@node Zero Length
@section Arrays of Length Zero
@cindex arrays of length zero
---
The new patch is attached. Thanks!
Regards,
Chao-ying
[-- Attachment #2: c-parser.diff --]
[-- Type: application/octet-stream, Size: 48186 bytes --]
Index: gcc4x/gcc/gcc/c-common.h
===================================================================
--- gcc4x.orig/gcc/gcc/c-common.h 2007-08-15 09:55:44.000000000 -0700
+++ gcc4x/gcc/gcc/c-common.h 2007-08-15 13:49:21.000000000 -0700
@@ -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,
@@ -674,6 +675,8 @@ extern int c_common_handle_option (size_
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);
Index: gcc4x/gcc/gcc/c-parser.c
===================================================================
--- gcc4x.orig/gcc/gcc/c-parser.c 2007-08-15 09:55:44.000000000 -0700
+++ gcc4x/gcc/gcc/c-parser.c 2007-08-15 13:49:21.000000000 -0700
@@ -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 *parse
_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, st
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:
Index: gcc4x/gcc/gcc/c-tree.h
===================================================================
--- gcc4x.orig/gcc/gcc/c-tree.h 2007-08-15 09:55:44.000000000 -0700
+++ gcc4x/gcc/gcc/c-tree.h 2007-08-16 11:01:54.000000000 -0700
@@ -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. */
Index: gcc4x/gcc/gcc/c-decl.c
===================================================================
--- gcc4x.orig/gcc/gcc/c-decl.c 2007-08-15 09:55:44.000000000 -0700
+++ gcc4x/gcc/gcc/c-decl.c 2007-08-16 11:06:40.000000000 -0700
@@ -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 *
}
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 *
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 *
}
else
{
- /* "void", "_Bool", "char", "int", "float" or "double". */
+ /* "void", "_Bool", "char", "int", "float", "double", "_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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *sp
"_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 *sp
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 ();
}
Index: gcc4x/gcc/gcc/c-common.c
===================================================================
--- gcc4x.orig/gcc/gcc/c-common.c 2007-08-15 09:55:44.000000000 -0700
+++ gcc4x/gcc/gcc/c-common.c 2007-08-16 11:57:54.000000000 -0700
@@ -48,6 +48,7 @@ along with GCC; see the file COPYING3.
#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 typ
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,43 @@ c_common_type_for_size (unsigned int bit
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)
+ {
+ error ("should not use integer types and fixed-point types that have too\
+\nmany 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 +2071,95 @@ c_common_type_for_mode (enum machine_mod
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 +2221,54 @@ c_common_signed_or_unsigned_type (int un
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 +2497,8 @@ shorten_compare (tree *op0_ptr, tree *op
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 +2553,7 @@ shorten_compare (tree *op0_ptr, tree *op
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 +2959,12 @@ c_common_truthvalue_conversion (tree exp
? 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 +3065,14 @@ c_common_truthvalue_conversion (tree exp
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);
}
\f
@@ -3594,6 +3784,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));
@@ -5004,6 +5255,10 @@ handle_mode_attribute (tree *node, tree
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;
@@ -5014,6 +5269,10 @@ handle_mode_attribute (tree *node, tree
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,
@@ -5047,7 +5306,20 @@ handle_mode_attribute (tree *node, tree
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)
{
@@ -5796,7 +6068,8 @@ handle_vector_size_attribute (tree *node
|| 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);
@@ -6929,8 +7202,9 @@ same_scalar_type_ignoring_signedness (tr
{
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. */
@@ -7095,11 +7369,12 @@ struct gcc_targetcm targetcm = TARGETCM_
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");
}
Index: gcc4x/gcc/gcc/c-typeck.c
===================================================================
--- gcc4x.orig/gcc/gcc/c-typeck.c 2007-08-15 09:55:44.000000000 -0700
+++ gcc4x/gcc/gcc/c-typeck.c 2007-08-16 11:26:28.000000000 -0700
@@ -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_assert (0);
+ 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_assert (0);
+ 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, tre
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, tre
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, tre
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, tre
/* 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, tre
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
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);
@@ -4745,9 +4853,9 @@ digest_init (tree type, tree init, bool
/* 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
@@ -7861,8 +7969,10 @@ build_binary_op (enum tree_code code, tr
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;
@@ -7872,7 +7982,8 @@ build_binary_op (enum tree_code code, tr
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
@@ -7923,9 +8034,11 @@ build_binary_op (enum tree_code code, tr
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
@@ -7942,7 +8055,8 @@ build_binary_op (enum tree_code code, tr
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)
{
@@ -7970,7 +8084,8 @@ build_binary_op (enum tree_code code, tr
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)
{
@@ -8001,9 +8116,9 @@ build_binary_op (enum tree_code code, tr
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)
{
@@ -8071,8 +8186,10 @@ build_binary_op (enum tree_code code, tr
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)
{
@@ -8133,10 +8250,10 @@ build_binary_op (enum tree_code code, tr
}
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);
Index: gcc4x/gcc/gcc/target-def.h
===================================================================
--- gcc4x.orig/gcc/gcc/target-def.h 2007-08-15 09:55:44.000000000 -0700
+++ gcc4x/gcc/gcc/target-def.h 2007-08-15 13:49:21.000000000 -0700
@@ -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, \
Index: gcc4x/gcc/gcc/target.h
===================================================================
--- gcc4x.orig/gcc/gcc/target.h 2007-08-15 09:55:44.000000000 -0700
+++ gcc4x/gcc/gcc/target.h 2007-08-15 13:49:21.000000000 -0700
@@ -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);
Index: gcc4x/gcc/gcc/targhooks.c
===================================================================
--- gcc4x.orig/gcc/gcc/targhooks.c 2007-08-15 09:55:44.000000000 -0700
+++ gcc4x/gcc/gcc/targhooks.c 2007-08-15 13:49:21.000000000 -0700
@@ -298,6 +298,10 @@ default_scalar_mode_supported_p (enum ma
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.
Index: gcc4x/gcc/gcc/targhooks.h
===================================================================
--- gcc4x.orig/gcc/gcc/targhooks.h 2007-08-15 09:55:44.000000000 -0700
+++ gcc4x/gcc/gcc/targhooks.h 2007-08-15 13:49:21.000000000 -0700
@@ -55,6 +55,7 @@ extern void default_unwind_emit (FILE *,
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);
Index: gcc4x/gcc/gcc/doc/tm.texi
===================================================================
--- gcc4x.orig/gcc/gcc/doc/tm.texi 2007-08-15 09:55:44.000000000 -0700
+++ gcc4x/gcc/gcc/doc/tm.texi 2007-08-15 13:49:21.000000000 -0700
@@ -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
Index: gcc4x/gcc/gcc/doc/install.texi
===================================================================
--- gcc4x.orig/gcc/gcc/doc/install.texi 2007-08-15 09:55:44.000000000 -0700
+++ gcc4x/gcc/gcc/doc/install.texi 2007-08-15 13:49:21.000000000 -0700
@@ -1317,6 +1317,11 @@ or @samp{dpd}). The @samp{bid} (binary
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 the C fixed-point arithmetic
+extension.
+
@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},
Index: gcc4x/gcc/gcc/configure.ac
===================================================================
--- gcc4x.orig/gcc/gcc/configure.ac 2007-08-15 09:55:44.000000000 -0700
+++ gcc4x/gcc/gcc/configure.ac 2007-08-16 12:02:53.000000000 -0700
@@ -641,6 +641,28 @@ AC_DEFINE_UNQUOTED(ENABLE_DECIMAL_BID_FO
[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
^ permalink raw reply [flat|nested] 13+ messages in thread
* RE: [ping][patch] Fixed-point patch 4/10
2007-08-16 19:11 ` Fu, Chao-Ying
@ 2007-08-16 19:53 ` Joseph S. Myers
2007-08-16 20:32 ` Fu, Chao-Ying
0 siblings, 1 reply; 13+ messages in thread
From: Joseph S. Myers @ 2007-08-16 19:53 UTC (permalink / raw)
To: Fu, Chao-Ying
Cc: gcc-patches, Thekkath, Radhika, Stephens, Nigel, Mark Mitchell
On Thu, 16 Aug 2007, Fu, Chao-Ying wrote:
> This error comes from valid user code that tries to operate on
> mixed data types of integers and fractional types.
> Ex:
> long long a; /* 63 integral bits + a sign bit. */
> long long _Fract b; /* 63 fractional bits + a sign bit. */
> b = a * b; // For this operation (a * b), GCC tries to find an accum mode
> that can support at least 63 integral bits and 63 fractional bits.
> But, if the target doesn't have this kind of accum mode, GCC fails.
It appears to me that the result type in N1169 is to be the fixed-point
type (with the specified overflow rules applied) for arithmetic between
fixed-point and integer types.
If the problem here is an internal implementation matter - if you generate
the correct result type, but need this other mode for internal arithmetic
- then that's a bug in the implementation. Preferably this bug should be
fixed (if the target doesn't have the modes, generate appropriate code
using a libgcc function if necessary), but if that is hard then file a PR
in Bugzilla, add a comment referencing the PR, and use sorry (), which
will output a message starting "sorry, unimplemented: ".
> Maybe I will use this error message.
> ---
> error ("should not use integer types and fixed-point types that have too\
> \nmany integral and fractional bits together");
> ---
> Is it ok?
Don't put newlines in the middle of messages; just output the message,
however long it is, and let the user use options to wrap if it they so
wish.
> I will change to gcc_assert (0), because these cases should not happen.
The idiom is gcc_unreachable ().
--
Joseph S. Myers
joseph@codesourcery.com
^ permalink raw reply [flat|nested] 13+ messages in thread
* RE: [ping][patch] Fixed-point patch 4/10
2007-08-16 19:53 ` Joseph S. Myers
@ 2007-08-16 20:32 ` Fu, Chao-Ying
2007-08-17 1:16 ` Fu, Chao-Ying
0 siblings, 1 reply; 13+ messages in thread
From: Fu, Chao-Ying @ 2007-08-16 20:32 UTC (permalink / raw)
To: Joseph S. Myers
Cc: gcc-patches, Thekkath, Radhika, Stephens, Nigel, Mark Mitchell
Joseph S. Myers wrote:
>
> > This error comes from valid user code that tries to operate on
> > mixed data types of integers and fractional types.
> > Ex:
> > long long a; /* 63 integral bits + a sign bit. */
> > long long _Fract b; /* 63 fractional bits + a sign bit. */
> > b = a * b; // For this operation (a * b), GCC tries to find
> an accum mode
> > that can support at least 63 integral bits and 63 fractional bits.
> > But, if the target doesn't have this kind of accum mode, GCC fails.
>
> It appears to me that the result type in N1169 is to be the
> fixed-point
> type (with the specified overflow rules applied) for
> arithmetic between
> fixed-point and integer types.
>
> If the problem here is an internal implementation matter - if
> you generate
> the correct result type, but need this other mode for
> internal arithmetic
> - then that's a bug in the implementation. Preferably this
> bug should be
> fixed (if the target doesn't have the modes, generate
> appropriate code
> using a libgcc function if necessary), but if that is hard
> then file a PR
> in Bugzilla, add a comment referencing the PR, and use sorry
> (), which
> will output a message starting "sorry, unimplemented: ".
What you describe is right. The current implementation may not support
all kinds of mixed integer and fixed-point types. I will use
sorry ("GCC cannot support operators with integer types and fixed-point \
types that have too many integral and fractional bits together");
About the PR, after all patches are checked in, I will file one bug
for this case.
>
> > Maybe I will use this error message.
> > ---
> > error ("should not use integer types and fixed-point
> types that have too\
> > \nmany integral and fractional bits together");
> > ---
> > Is it ok?
>
> Don't put newlines in the middle of messages; just output the
> message,
> however long it is, and let the user use options to wrap if
> it they so
> wish.
>
> > I will change to gcc_assert (0), because these cases
> should not happen.
>
> The idiom is gcc_unreachable ().
Yes. Thanks!
Regards,
Chao-ying
^ permalink raw reply [flat|nested] 13+ messages in thread
* RE: [ping][patch] Fixed-point patch 4/10
2007-08-16 20:32 ` Fu, Chao-Ying
@ 2007-08-17 1:16 ` Fu, Chao-Ying
2007-08-17 10:43 ` Joseph S. Myers
0 siblings, 1 reply; 13+ messages in thread
From: Fu, Chao-Ying @ 2007-08-17 1:16 UTC (permalink / raw)
To: Joseph S. Myers
Cc: gcc-patches, Thekkath, Radhika, Stephens, Nigel, Mark Mitchell
[-- Attachment #1: Type: text/plain, Size: 6289 bytes --]
> >
> > > This error comes from valid user code that tries to operate on
> > > mixed data types of integers and fractional types.
> > > Ex:
> > > long long a; /* 63 integral bits + a sign bit. */
> > > long long _Fract b; /* 63 fractional bits + a sign bit. */
> > > b = a * b; // For this operation (a * b), GCC tries to find
> > an accum mode
> > > that can support at least 63 integral bits and 63 fractional bits.
> > > But, if the target doesn't have this kind of accum mode,
> GCC fails.
> >
> > It appears to me that the result type in N1169 is to be the
> > fixed-point
> > type (with the specified overflow rules applied) for
> > arithmetic between
> > fixed-point and integer types.
> >
> > If the problem here is an internal implementation matter - if
> > you generate
> > the correct result type, but need this other mode for
> > internal arithmetic
> > - then that's a bug in the implementation. Preferably this
> > bug should be
> > fixed (if the target doesn't have the modes, generate
> > appropriate code
> > using a libgcc function if necessary), but if that is hard
> > then file a PR
> > in Bugzilla, add a comment referencing the PR, and use sorry
> > (), which
> > will output a message starting "sorry, unimplemented: ".
>
> What you describe is right. The current implementation may
> not support
> all kinds of mixed integer and fixed-point types. I will use
>
> sorry ("GCC cannot support operators with integer types
> and fixed-point \
> types that have too many integral and fractional bits together");
>
> About the PR, after all patches are checked in, I will file one bug
> for this case.
>
> >
> > > Maybe I will use this error message.
> > > ---
> > > error ("should not use integer types and fixed-point
> > types that have too\
> > > \nmany integral and fractional bits together");
> > > ---
> > > Is it ok?
> >
> > Don't put newlines in the middle of messages; just output the
> > message,
> > however long it is, and let the user use options to wrap if
> > it they so
> > wish.
> >
> > > I will change to gcc_assert (0), because these cases
> > should not happen.
> >
> > The idiom is gcc_unreachable ().
>
> Yes. Thanks!
>
> Regards,
> Chao-ying
>
Here is the new patch and updated ChangeLog. The new changes from the last time
include:
1. In "c_common_fixed_point_type_for_size()", we test if the target
can support the mode and use "sorry()".
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;
}
2. In "c_common_type()", use gcc_unreachable ().
3. Update install.texi to mention MIPS is enabled by default.
4. Update ChangeLog.
Is it ok to check in? Thanks a lot!
gcc/ChangeLog
2007-08-16 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 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.
[-- Attachment #2: c-parser.diff --]
[-- Type: application/octet-stream, Size: 48382 bytes --]
Index: gcc4x/gcc/gcc/c-common.h
===================================================================
--- gcc4x.orig/gcc/gcc/c-common.h 2007-08-16 14:27:17.000000000 -0700
+++ gcc4x/gcc/gcc/c-common.h 2007-08-16 15:51:38.000000000 -0700
@@ -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_
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);
Index: gcc4x/gcc/gcc/c-parser.c
===================================================================
--- gcc4x.orig/gcc/gcc/c-parser.c 2007-08-16 14:24:31.000000000 -0700
+++ gcc4x/gcc/gcc/c-parser.c 2007-08-16 15:51:38.000000000 -0700
@@ -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 *parse
_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, st
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:
Index: gcc4x/gcc/gcc/c-tree.h
===================================================================
--- gcc4x.orig/gcc/gcc/c-tree.h 2007-08-16 14:27:17.000000000 -0700
+++ gcc4x/gcc/gcc/c-tree.h 2007-08-16 15:51:38.000000000 -0700
@@ -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. */
Index: gcc4x/gcc/gcc/c-decl.c
===================================================================
--- gcc4x.orig/gcc/gcc/c-decl.c 2007-08-16 14:24:31.000000000 -0700
+++ gcc4x/gcc/gcc/c-decl.c 2007-08-16 15:51:38.000000000 -0700
@@ -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 *
}
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 *
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 *
}
else
{
- /* "void", "_Bool", "char", "int", "float" or "double". */
+ /* "void", "_Bool", "char", "int", "float", "double", "_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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *sp
"_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 *sp
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 ();
}
Index: gcc4x/gcc/gcc/c-common.c
===================================================================
--- gcc4x.orig/gcc/gcc/c-common.c 2007-08-16 14:27:17.000000000 -0700
+++ gcc4x/gcc/gcc/c-common.c 2007-08-16 17:42:52.000000000 -0700
@@ -48,6 +48,7 @@ along with GCC; see the file COPYING3.
#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 typ
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,43 @@ c_common_type_for_size (unsigned int bit
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 +2071,95 @@ c_common_type_for_mode (enum machine_mod
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 +2221,54 @@ c_common_signed_or_unsigned_type (int un
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 +2497,8 @@ shorten_compare (tree *op0_ptr, tree *op
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 +2553,7 @@ shorten_compare (tree *op0_ptr, tree *op
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 +2959,12 @@ c_common_truthvalue_conversion (tree exp
? 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 +3065,14 @@ c_common_truthvalue_conversion (tree exp
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);
}
\f
@@ -3594,6 +3784,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 +5264,10 @@ handle_mode_attribute (tree *node, tree
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 +5278,10 @@ handle_mode_attribute (tree *node, tree
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 +5315,20 @@ handle_mode_attribute (tree *node, tree
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 +6077,8 @@ handle_vector_size_attribute (tree *node
|| 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 +7211,9 @@ same_scalar_type_ignoring_signedness (tr
{
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 +7378,12 @@ struct gcc_targetcm targetcm = TARGETCM_
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");
}
Index: gcc4x/gcc/gcc/c-typeck.c
===================================================================
--- gcc4x.orig/gcc/gcc/c-typeck.c 2007-08-16 14:27:17.000000000 -0700
+++ gcc4x/gcc/gcc/c-typeck.c 2007-08-16 15:51:38.000000000 -0700
@@ -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, tre
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, tre
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, tre
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, tre
/* 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, tre
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
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);
@@ -4745,9 +4853,9 @@ digest_init (tree type, tree init, bool
/* 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
@@ -7861,8 +7969,10 @@ build_binary_op (enum tree_code code, tr
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;
@@ -7872,7 +7982,8 @@ build_binary_op (enum tree_code code, tr
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
@@ -7923,9 +8034,11 @@ build_binary_op (enum tree_code code, tr
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
@@ -7942,7 +8055,8 @@ build_binary_op (enum tree_code code, tr
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)
{
@@ -7970,7 +8084,8 @@ build_binary_op (enum tree_code code, tr
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)
{
@@ -8001,9 +8116,9 @@ build_binary_op (enum tree_code code, tr
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)
{
@@ -8071,8 +8186,10 @@ build_binary_op (enum tree_code code, tr
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)
{
@@ -8133,10 +8250,10 @@ build_binary_op (enum tree_code code, tr
}
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);
Index: gcc4x/gcc/gcc/target-def.h
===================================================================
--- gcc4x.orig/gcc/gcc/target-def.h 2007-08-16 14:24:31.000000000 -0700
+++ gcc4x/gcc/gcc/target-def.h 2007-08-16 15:51:38.000000000 -0700
@@ -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, \
Index: gcc4x/gcc/gcc/target.h
===================================================================
--- gcc4x.orig/gcc/gcc/target.h 2007-08-16 14:24:31.000000000 -0700
+++ gcc4x/gcc/gcc/target.h 2007-08-16 15:51:38.000000000 -0700
@@ -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);
Index: gcc4x/gcc/gcc/targhooks.c
===================================================================
--- gcc4x.orig/gcc/gcc/targhooks.c 2007-08-16 14:24:31.000000000 -0700
+++ gcc4x/gcc/gcc/targhooks.c 2007-08-16 15:51:38.000000000 -0700
@@ -298,6 +298,10 @@ default_scalar_mode_supported_p (enum ma
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.
Index: gcc4x/gcc/gcc/targhooks.h
===================================================================
--- gcc4x.orig/gcc/gcc/targhooks.h 2007-08-16 14:24:31.000000000 -0700
+++ gcc4x/gcc/gcc/targhooks.h 2007-08-16 15:51:38.000000000 -0700
@@ -55,6 +55,7 @@ extern void default_unwind_emit (FILE *,
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);
Index: gcc4x/gcc/gcc/doc/tm.texi
===================================================================
--- gcc4x.orig/gcc/gcc/doc/tm.texi 2007-08-16 14:24:31.000000000 -0700
+++ gcc4x/gcc/gcc/doc/tm.texi 2007-08-16 15:51:39.000000000 -0700
@@ -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
Index: gcc4x/gcc/gcc/doc/install.texi
===================================================================
--- gcc4x.orig/gcc/gcc/doc/install.texi 2007-08-16 14:24:31.000000000 -0700
+++ gcc4x/gcc/gcc/doc/install.texi 2007-08-16 17:57:48.000000000 -0700
@@ -1317,6 +1317,13 @@ or @samp{dpd}). The @samp{bid} (binary
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 the C fixed-point arithmetic
+This is enabled by default only on MIPS. Other systems may also support it,
+but require the user to specifically enable it.
+extension.
+
@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},
Index: gcc4x/gcc/gcc/configure.ac
===================================================================
--- gcc4x.orig/gcc/gcc/configure.ac 2007-08-16 14:24:31.000000000 -0700
+++ gcc4x/gcc/gcc/configure.ac 2007-08-16 15:51:39.000000000 -0700
@@ -641,6 +641,28 @@ AC_DEFINE_UNQUOTED(ENABLE_DECIMAL_BID_FO
[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
^ permalink raw reply [flat|nested] 13+ messages in thread
* RE: [ping][patch] Fixed-point patch 4/10
2007-08-17 1:16 ` Fu, Chao-Ying
@ 2007-08-17 10:43 ` Joseph S. Myers
2007-08-17 22:16 ` Fu, Chao-Ying
0 siblings, 1 reply; 13+ messages in thread
From: Joseph S. Myers @ 2007-08-17 10:43 UTC (permalink / raw)
To: Fu, Chao-Ying
Cc: gcc-patches, Thekkath, Radhika, Stephens, Nigel, Mark Mitchell
On Thu, 16 Aug 2007, Fu, Chao-Ying wrote:
> 1. In "c_common_fixed_point_type_for_size()", we test if the target
> can support the mode and use "sorry()".
> 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");
Using ISO C string constant concatenation would be better than using
backslash-newline,
sorry ("GCC cannot support operators with integer types and "
"fixed-point types that have too many integral and "
"fractional bits together");
The C front-end changes are OK with that change; someone else will need to
review the other changes in this patch.
--
Joseph S. Myers
joseph@codesourcery.com
^ permalink raw reply [flat|nested] 13+ messages in thread
* RE: [ping][patch] Fixed-point patch 4/10
2007-08-17 10:43 ` Joseph S. Myers
@ 2007-08-17 22:16 ` Fu, Chao-Ying
2007-08-17 23:47 ` Mark Mitchell
0 siblings, 1 reply; 13+ messages in thread
From: Fu, Chao-Ying @ 2007-08-17 22:16 UTC (permalink / raw)
To: Mark Mitchell, Joseph S. Myers
Cc: gcc-patches, Thekkath, Radhika, Stephens, Nigel
Joseph S. Myers wrote:
>
> On Thu, 16 Aug 2007, Fu, Chao-Ying wrote:
>
> > 1. In "c_common_fixed_point_type_for_size()", we test if the target
> > can support the mode and use "sorry()".
> > 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");
>
> Using ISO C string constant concatenation would be better than using
> backslash-newline,
>
> sorry ("GCC cannot support operators with integer types and "
> "fixed-point types that have too many integral and "
> "fractional bits together");
>
> The C front-end changes are OK with that change; someone else
> will need to
> review the other changes in this patch.
>
> --
> Joseph S. Myers
> joseph@codesourcery.com
>
Hi Mark,
Could you review the non-C-front-end part of this patch?
http://gcc.gnu.org/ml/gcc-patches/2007-08/msg01070.html
This includes a new target hook and a config option to enable the
fixed-point extension. Thanks a lot!
Regards,
Chao-ying
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [ping][patch] Fixed-point patch 4/10
2007-08-17 22:16 ` Fu, Chao-Ying
@ 2007-08-17 23:47 ` Mark Mitchell
2007-08-17 23:55 ` Fu, Chao-Ying
0 siblings, 1 reply; 13+ messages in thread
From: Mark Mitchell @ 2007-08-17 23:47 UTC (permalink / raw)
To: Fu, Chao-Ying
Cc: Joseph S. Myers, gcc-patches, Thekkath, Radhika, Stephens, Nigel
Fu, Chao-Ying wrote:
> Could you review the non-C-front-end part of this patch?
> http://gcc.gnu.org/ml/gcc-patches/2007-08/msg01070.html
>
> This includes a new target hook and a config option to enable the
> fixed-point extension. Thanks a lot!
+Enable (or disable) support for the C fixed-point arithmetic
Remove "the". End with a period.
> +This is enabled by default only on MIPS. Other systems may also support it,
> +but require the user to specifically enable it.
> +extension.
Future-proof this by saying:
"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."
OK with those changes.
--
Mark Mitchell
CodeSourcery
mark@codesourcery.com
(650) 331-3385 x713
^ permalink raw reply [flat|nested] 13+ messages in thread
* RE: [ping][patch] Fixed-point patch 4/10
2007-08-17 23:47 ` Mark Mitchell
@ 2007-08-17 23:55 ` Fu, Chao-Ying
2007-08-20 22:46 ` Fu, Chao-Ying
0 siblings, 1 reply; 13+ messages in thread
From: Fu, Chao-Ying @ 2007-08-17 23:55 UTC (permalink / raw)
To: Mark Mitchell
Cc: Joseph S. Myers, gcc-patches, Thekkath, Radhika, Stephens, Nigel
Mark Mitchell wrote:
>
> > Could you review the non-C-front-end part of this patch?
> > http://gcc.gnu.org/ml/gcc-patches/2007-08/msg01070.html
> >
> > This includes a new target hook and a config option to enable the
> > fixed-point extension. Thanks a lot!
>
> +Enable (or disable) support for the C fixed-point arithmetic
>
> Remove "the". End with a period.
>
> > +This is enabled by default only on MIPS. Other systems
> may also support it,
> > +but require the user to specifically enable it.
> > +extension.
>
> Future-proof this by saying:
>
> "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."
>
> OK with those changes.
>
Thanks a lot! Here is the diff file for install.texi.
I plan to check in this patch (4/10) next Monday.
Regards,
Chao-ying
Index: install.texi
===================================================================
--- install.texi (revision 127589)
+++ install.texi (working copy)
@@ -1317,6 +1317,13 @@
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},
^ permalink raw reply [flat|nested] 13+ messages in thread
* RE: [ping][patch] Fixed-point patch 4/10
2007-08-17 23:55 ` Fu, Chao-Ying
@ 2007-08-20 22:46 ` Fu, Chao-Ying
0 siblings, 0 replies; 13+ messages in thread
From: Fu, Chao-Ying @ 2007-08-20 22:46 UTC (permalink / raw)
To: gcc-patches, Mark Mitchell, Joseph S. Myers
Cc: Thekkath, Radhika, Stephens, Nigel
> >
> > Future-proof this by saying:
> >
> > "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."
> >
> > OK with those changes.
> >
>
> Thanks a lot! Here is the diff file for install.texi.
> I plan to check in this patch (4/10) next Monday.
>
This patch (4/10) is applied. Thanks a lot!
Regards,
Chao-ying
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2007-08-20 22:36 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-08-01 23:59 [ping][patch] Fixed-point patch 4/10 Fu, Chao-Ying
2007-08-06 3:53 ` Mark Mitchell
2007-08-16 0:47 ` Fu, Chao-Ying
2007-08-16 15:14 ` Joseph S. Myers
2007-08-16 19:11 ` Fu, Chao-Ying
2007-08-16 19:53 ` Joseph S. Myers
2007-08-16 20:32 ` Fu, Chao-Ying
2007-08-17 1:16 ` Fu, Chao-Ying
2007-08-17 10:43 ` Joseph S. Myers
2007-08-17 22:16 ` Fu, Chao-Ying
2007-08-17 23:47 ` Mark Mitchell
2007-08-17 23:55 ` Fu, Chao-Ying
2007-08-20 22:46 ` Fu, Chao-Ying
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).