public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* fixed-point support in c++
@ 2010-03-16  1:28 Sean D'Epagnier
  2010-03-16  1:32 ` Dave Korn
  0 siblings, 1 reply; 6+ messages in thread
From: Sean D'Epagnier @ 2010-03-16  1:28 UTC (permalink / raw)
  To: gcc

It looks like my patches for avr target to get native fixed-point
support may be included soon.  I realized that many users use avr-g++
for their projects, and I cannot get the fixed point types working in
c++.   The question is generic and should apply to all targets.

Compiling a simple test program:

int main()
{
    _Accum x;
}

Works fine in c, but under c++ I get:

test.cpp:5: error: ‘_Accum’ was not declared in this scope

So I modified c-common.c:

Index: c-common.c
===================================================================
--- c-common.c	(revision 157409)
+++ c-common.c	(working copy)
@@ -561,9 +561,9 @@
   { "_Decimal32",       RID_DFLOAT32,  D_CONLY | D_EXT },
   { "_Decimal64",       RID_DFLOAT64,  D_CONLY | D_EXT },
   { "_Decimal128",      RID_DFLOAT128, D_CONLY | D_EXT },
-  { "_Fract",           RID_FRACT,     D_CONLY | D_EXT },
-  { "_Accum",           RID_ACCUM,     D_CONLY | D_EXT },
-  { "_Sat",             RID_SAT,       D_CONLY | 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 },


Now the error is:

test.cpp:5:4: error: expected primary-expression before ‘_Accum’

Does anyone have clues as to the problem?  I have tried a few other
things with no success.


Thanks
Sean

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: fixed-point support in c++
  2010-03-16  1:28 fixed-point support in c++ Sean D'Epagnier
@ 2010-03-16  1:32 ` Dave Korn
  2010-03-16 10:12   ` Sean D'Epagnier
  0 siblings, 1 reply; 6+ messages in thread
From: Dave Korn @ 2010-03-16  1:32 UTC (permalink / raw)
  To: Sean D'Epagnier; +Cc: gcc

On 15/03/2010 22:03, Sean D'Epagnier wrote:

> -  { "_Fract",           RID_FRACT,     D_CONLY | D_EXT },
> -  { "_Accum",           RID_ACCUM,     D_CONLY | D_EXT },
> -  { "_Sat",             RID_SAT,       D_CONLY | D_EXT },
> +  { "_Fract",           RID_FRACT,     D_EXT },
> +  { "_Accum",           RID_ACCUM,     D_EXT },
> +  { "_Sat",             RID_SAT,       D_EXT },

> Now the error is:
> 
> test.cpp:5:4: error: expected primary-expression before ‘_Accum’
> 
> Does anyone have clues as to the problem?  

  The problem is that it won't be as simple as that.  You'll have to extend
the C++ parser to accept those new RID_ values that it was previously never
expecting to see in those contexts, I would think (but haven't verified
against the source yet).  The C++ parser is a hand-coded recursive-descent
parser, so I wouldn't expect it to be generically able to deal with
previously-unknown token types suddenly appearing in its input stream at
arbitrary points.

    cheers,
      DaveK

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: fixed-point support in c++
  2010-03-16  1:32 ` Dave Korn
@ 2010-03-16 10:12   ` Sean D'Epagnier
  2010-03-19 13:04     ` Dave Korn
  0 siblings, 1 reply; 6+ messages in thread
From: Sean D'Epagnier @ 2010-03-16 10:12 UTC (permalink / raw)
  To: Dave Korn; +Cc: gcc

[-- Attachment #1: Type: text/plain, Size: 826 bytes --]

>   The problem is that it won't be as simple as that.  You'll have to extend
> the C++ parser to accept those new RID_ values that it was previously never
> expecting to see in those contexts, I would think (but haven't verified
> against the source yet).  The C++ parser is a hand-coded recursive-descent
> parser, so I wouldn't expect it to be generically able to deal with
> previously-unknown token types suddenly appearing in its input stream at
> arbitrary points.
>
>     cheers,
>       DaveK
>

I went through the c++ parser and added support for fixed point there.
 Everything seems to be working, and I am able to use fixed-point
numbers in c++.

The c++ parser is kind of complex and it is possible I missed
something.  I would love to get feedback on this patch, and hopefully
it can get committed to gcc.

Sean

[-- Attachment #2: gcc-fixedpoint-cp.patch --]
[-- Type: text/x-diff, Size: 25723 bytes --]

Index: gcc/builtins.c
===================================================================
--- gcc/builtins.c	(revision 157409)
+++ gcc/builtins.c	(working copy)
@@ -1708,6 +1708,7 @@
     case INTEGER_TYPE:	   return integer_type_class;
     case ENUMERAL_TYPE:	   return enumeral_type_class;
     case BOOLEAN_TYPE:	   return boolean_type_class;
+    case FIXED_POINT_TYPE: return fixed_point_type_class;
     case POINTER_TYPE:	   return pointer_type_class;
     case REFERENCE_TYPE:   return reference_type_class;
     case OFFSET_TYPE:	   return offset_type_class;
Index: gcc/fold-const.c
===================================================================
--- gcc/fold-const.c	(revision 157409)
+++ gcc/fold-const.c	(working copy)
@@ -12303,6 +12303,11 @@
       if (TREE_CODE (arg1) == INTEGER_CST && tree_int_cst_sgn (arg1) < 0)
 	return NULL_TREE;
 
+      /* Since fixed point types cannot perform bitwise and, or, etc..
+	 don't try to convert to an expression with them.  */
+      if (TREE_CODE(type) == FIXED_POINT_TYPE)
+	return NULL_TREE;
+
       /* Turn (a OP c1) OP c2 into a OP (c1+c2).  */
       if (TREE_CODE (op0) == code && host_integerp (arg1, false)
 	  && TREE_INT_CST_LOW (arg1) < TYPE_PRECISION (type)
Index: gcc/cp/typeck.c
===================================================================
--- gcc/cp/typeck.c	(revision 157409)
+++ gcc/cp/typeck.c	(working copy)
@@ -316,6 +316,91 @@
   if (code2 == REAL_TYPE && code1 != REAL_TYPE)
     return build_type_attribute_variant (t2, attributes);
 
+  /* 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))
+	    {
+	      enum mode_class mclass = (enum mode_class) 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))
+	    {
+	      enum mode_class mclass = (enum mode_class) 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))
     return build_type_attribute_variant (t1, attributes);
@@ -3734,9 +3819,11 @@
     case ROUND_DIV_EXPR:
     case EXACT_DIV_EXPR:
       if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
-	   || code0 == COMPLEX_TYPE || code0 == VECTOR_TYPE)
+          || code0 == FIXED_POINT_TYPE || code0 == COMPLEX_TYPE
+          || code0 == VECTOR_TYPE)
 	  && (code1 == INTEGER_TYPE || code1 == REAL_TYPE
-	      || code1 == COMPLEX_TYPE || code1 == VECTOR_TYPE))
+             || code1 == FIXED_POINT_TYPE || code1 == COMPLEX_TYPE
+             || code1 == VECTOR_TYPE))
 	{
 	  enum tree_code tcode0 = code0, tcode1 = code1;
 
@@ -3906,9 +3993,11 @@
 
       build_type = boolean_type_node;
       if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
-	   || code0 == COMPLEX_TYPE || code0 == ENUMERAL_TYPE)
+          || code0 == FIXED_POINT_TYPE || code0 == COMPLEX_TYPE
+          || code0 == ENUMERAL_TYPE)
 	  && (code1 == INTEGER_TYPE || code1 == REAL_TYPE
-	      || code1 == COMPLEX_TYPE || code1 == ENUMERAL_TYPE))
+             || code1 == FIXED_POINT_TYPE || code1 == COMPLEX_TYPE
+             || code1 == ENUMERAL_TYPE))
 	short_compare = 1;
       else if ((code0 == POINTER_TYPE && code1 == POINTER_TYPE)
 	       || (TYPE_PTRMEM_P (type0) && TYPE_PTRMEM_P (type1)))
@@ -4109,8 +4198,10 @@
 
     case MAX_EXPR:
     case MIN_EXPR:
-      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))
 	shorten = 1;
       else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
 	result_type = composite_pointer_type (type0, type1, op0, op1,
@@ -4129,8 +4220,10 @@
 	}
 
       build_type = boolean_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)
 	result_type = composite_pointer_type (type0, type1, op0, op1,
@@ -4181,9 +4274,10 @@
     }
 
   if (((code0 == INTEGER_TYPE || code0 == REAL_TYPE || code0 == COMPLEX_TYPE
-	|| code0 == ENUMERAL_TYPE)
+	|| code0 == ENUMERAL_TYPE || code0 == FIXED_POINT_TYPE)
        && (code1 == INTEGER_TYPE || code1 == REAL_TYPE
-	   || code1 == COMPLEX_TYPE || code1 == ENUMERAL_TYPE)))
+          || code1 == COMPLEX_TYPE || code1 == ENUMERAL_TYPE
+          || code1 == FIXED_POINT_TYPE)))
     arithmetic_types_p = 1;
   else
     {
Index: gcc/cp/decl.c
===================================================================
--- gcc/cp/decl.c	(revision 157409)
+++ gcc/cp/decl.c	(working copy)
@@ -7692,7 +7692,7 @@
      namespace scope.  */
   tree in_namespace = NULL_TREE;
   cp_storage_class storage_class;
-  bool unsigned_p, signed_p, short_p, long_p, thread_p;
+  bool unsigned_p, signed_p, short_p, long_p, thread_p, saturating_p;
   bool type_was_error_mark_node = false;
   bool parameter_pack_p = declarator? declarator->parameter_pack_p : false;
   bool template_type_arg = false;
@@ -7706,6 +7706,7 @@
   long_p = declspecs->specs[(int)ds_long];
   longlong = declspecs->specs[(int)ds_long] >= 2;
   thread_p = declspecs->specs[(int)ds_thread];
+  saturating_p = declspecs->specs[(int)ds_sat];
 
   if (decl_context == FUNCDEF)
     funcdef_flag = true, decl_context = NORMAL;
@@ -8023,21 +8024,24 @@
 
   /* Check all other uses of type modifiers.  */
 
-  if (unsigned_p || signed_p || long_p || short_p)
+  if (unsigned_p || signed_p || long_p || short_p || saturating_p)
     {
       int ok = 0;
 
-      if ((signed_p || unsigned_p) && TREE_CODE (type) != INTEGER_TYPE)
+      if ((signed_p || unsigned_p) && TREE_CODE (type) != INTEGER_TYPE
+          && TREE_CODE (type) != FIXED_POINT_TYPE)
 	error ("%<signed%> or %<unsigned%> invalid for %qs", name);
       else if (signed_p && unsigned_p)
 	error ("%<signed%> and %<unsigned%> specified together for %qs", name);
-      else if (longlong && TREE_CODE (type) != INTEGER_TYPE)
+      else if (longlong && TREE_CODE (type) != INTEGER_TYPE
+               && TREE_CODE (type) != FIXED_POINT_TYPE)
 	error ("%<long long%> invalid for %qs", name);
       else if (long_p && TREE_CODE (type) == REAL_TYPE)
 	error ("%<long%> invalid for %qs", name);
       else if (short_p && TREE_CODE (type) == REAL_TYPE)
 	error ("%<short%> invalid for %qs", name);
-      else if ((long_p || short_p) && TREE_CODE (type) != INTEGER_TYPE)
+      else if ((long_p || short_p) && TREE_CODE (type) != INTEGER_TYPE
+               && TREE_CODE (type) != FIXED_POINT_TYPE)
 	error ("%<long%> or %<short%> invalid for %qs", name);
       else if ((long_p || short_p) && explicit_char)
 	error ("%<long%> or %<short%> specified with char for %qs", name);
@@ -8050,6 +8054,12 @@
 	  else if (short_p || long_p)
 	    error ("%<short%> or %<long%> invalid for %qs", name);
 	}
+      else if (saturating_p && TREE_CODE (type) != FIXED_POINT_TYPE)
+      {
+        error ("%<_Sat%> specified for non fixed-point type %qs", name);
+        if (!targetm.fixed_point_supported_p ())
+          error ("fixed-point types not supported for this target");
+      }
       else
 	{
 	  ok = 1;
@@ -8071,12 +8081,126 @@
 	  long_p = false;
 	  short_p = false;
 	  longlong = 0;
+          saturating_p = false;
 	}
     }
 
+  /* Determine correct fixed-point mode.  */
+  if (TREE_CODE (type) == FIXED_POINT_TYPE)
+    {
+      if (!targetm.fixed_point_supported_p ())
+        error ("fixed-point types not supported for this target");
+
+      if (unsigned_p)
+        {
+          if (TYPE_MAIN_VARIANT (type) == fract_type_node)
+            {
+              if (saturating_p)
+                {
+                  if (longlong)
+                    type = sat_unsigned_long_long_fract_type_node;
+                  else if (long_p)
+                    type = sat_unsigned_long_fract_type_node;
+                  else if (short_p)
+                    type = sat_unsigned_short_fract_type_node;
+                  else
+                    type = sat_unsigned_fract_type_node;
+                }
+              else
+                {
+                  if (longlong)
+                    type = unsigned_long_long_fract_type_node;
+                  else if (long_p)
+                    type = unsigned_long_fract_type_node;
+                  else if (short_p)
+                    type = unsigned_short_fract_type_node;
+                  else
+                    type = unsigned_fract_type_node;
+                }
+            }
+          else
+            {
+              if (saturating_p)
+                {
+                  if (longlong)
+                    type = sat_unsigned_long_long_accum_type_node;
+                  else if (long_p)
+                    type = sat_unsigned_long_accum_type_node;
+                  else if (short_p)
+                    type = sat_unsigned_short_accum_type_node;
+                  else
+                    type = sat_unsigned_accum_type_node;
+                }
+              else
+                {
+                  if (longlong)
+                    type = unsigned_long_long_accum_type_node;
+                  else if (long_p)
+                    type = unsigned_long_accum_type_node;
+                  else if (short_p)
+                    type = unsigned_short_accum_type_node;
+                  else
+                    type = unsigned_accum_type_node;
+                }
+            }
+        }
+      else /* It is a signed fixed point type.  */
+        {
+          if (TYPE_MAIN_VARIANT (type) == fract_type_node)
+            {
+              if (saturating_p)
+                {
+                  if (longlong)
+                    type = sat_long_long_fract_type_node;
+                  else if (long_p)
+                    type = sat_long_fract_type_node;
+                  else if (short_p)
+                    type = sat_short_fract_type_node;
+                  else
+                    type = sat_fract_type_node;
+                }
+              else
+                {
+                  if (longlong)
+                    type = long_long_fract_type_node;
+                  else if (long_p)
+                    type = long_fract_type_node;
+                  else if (short_p)
+                    type = short_fract_type_node;
+                  else
+                    type = fract_type_node;
+                }
+            }
+          else
+            {
+              if (saturating_p)
+                {
+                  if (longlong)
+                    type = sat_long_long_accum_type_node;
+                  else if (long_p)
+                    type = sat_long_accum_type_node;
+                  else if (short_p)
+                    type = sat_short_accum_type_node;
+                  else
+                    type = sat_accum_type_node;
+                }
+              else
+                {
+                  if (longlong)
+                    type = long_long_accum_type_node;
+                  else if (long_p)
+                    type = long_accum_type_node;
+                  else if (short_p)
+                    type = short_accum_type_node;
+                  else
+                    type = accum_type_node;
+                }
+            }
+        }
+    }
   /* Decide whether an integer type is signed or not.
      Optionally treat bitfields as signed by default.  */
-  if (unsigned_p
+  else if (unsigned_p
       /* [class.bit]
 
 	 It is implementation-defined whether a plain (neither
Index: gcc/cp/rtti.c
===================================================================
--- gcc/cp/rtti.c	(revision 157409)
+++ gcc/cp/rtti.c	(working copy)
@@ -1034,6 +1034,7 @@
     case INTEGER_TYPE:
     case BOOLEAN_TYPE:
     case REAL_TYPE:
+    case FIXED_POINT_TYPE:
     case VOID_TYPE:
       return true;
 
@@ -1452,6 +1453,22 @@
     &long_long_integer_type_node, &long_long_unsigned_type_node,
     &float_type_node, &double_type_node, &long_double_type_node,
     &dfloat32_type_node, &dfloat64_type_node, &dfloat128_type_node,
+    &short_fract_type_node, &unsigned_short_fract_type_node,
+    &fract_type_node, &unsigned_fract_type_node,
+    &long_fract_type_node, &unsigned_long_fract_type_node,
+    &long_long_fract_type_node, &unsigned_long_long_fract_type_node,
+    &sat_short_fract_type_node, &sat_unsigned_short_fract_type_node,
+    &sat_fract_type_node, &sat_unsigned_fract_type_node,
+    &sat_long_fract_type_node, &sat_unsigned_long_fract_type_node,
+    &sat_long_long_fract_type_node, &sat_unsigned_long_long_fract_type_node,
+    &short_accum_type_node, &unsigned_short_accum_type_node,
+    &accum_type_node, &unsigned_accum_type_node,
+    &long_accum_type_node, &unsigned_long_accum_type_node,
+    &long_long_accum_type_node, &unsigned_long_long_accum_type_node,
+    &sat_short_accum_type_node, &sat_unsigned_short_accum_type_node,
+    &sat_accum_type_node, &sat_unsigned_accum_type_node,
+    &sat_long_accum_type_node, &sat_unsigned_long_accum_type_node,
+    &sat_long_long_accum_type_node, &sat_unsigned_long_long_accum_type_node,
     0
   };
   int ix;
Index: gcc/cp/error.c
===================================================================
--- gcc/cp/error.c	(revision 157409)
+++ gcc/cp/error.c	(working copy)
@@ -2169,6 +2169,7 @@
     case INTEGER_TYPE:
     case COMPLEX_TYPE:
     case VECTOR_TYPE:
+    case FIXED_POINT_TYPE:
       pp_type_specifier_seq (cxx_pp, t);
       break;
 
Index: gcc/cp/typeck2.c
===================================================================
--- gcc/cp/typeck2.c	(revision 157409)
+++ gcc/cp/typeck2.c	(working copy)
@@ -755,7 +755,7 @@
   if (DECL_P (init))
     init = decl_constant_value (init);
 
-  if (TREE_CODE (type) == INTEGER_TYPE
+  if ((TREE_CODE (type) == INTEGER_TYPE || TREE_CODE (type) == FIXED_POINT_TYPE)
       && TREE_CODE (ftype) == REAL_TYPE)
     ok = false;
   else if (INTEGRAL_OR_ENUMERATION_TYPE_P (ftype)
Index: gcc/cp/pt.c
===================================================================
--- gcc/cp/pt.c	(revision 157409)
+++ gcc/cp/pt.c	(working copy)
@@ -9942,6 +9942,7 @@
     case REAL_TYPE:
     case COMPLEX_TYPE:
     case VECTOR_TYPE:
+    case FIXED_POINT_TYPE:
     case BOOLEAN_TYPE:
     case INTEGER_CST:
     case REAL_CST:
@@ -14845,6 +14846,7 @@
     case VECTOR_TYPE:
     case INTEGER_TYPE:
     case BOOLEAN_TYPE:
+    case FIXED_POINT_TYPE:
     case ENUMERAL_TYPE:
     case VOID_TYPE:
       if (TREE_CODE (arg) != TREE_CODE (parm))
Index: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c	(revision 157409)
+++ gcc/cp/parser.c	(working copy)
@@ -570,6 +570,9 @@
       /* GNU extensions.  */ 
     case RID_ATTRIBUTE:
     case RID_TYPEOF:
+    case RID_FRACT:
+    case RID_ACCUM:
+    case RID_SAT:
       /* C++0x extensions.  */
     case RID_DECLTYPE:
       return true;
@@ -3203,10 +3206,11 @@
     case CPP_WCHAR:
     case CPP_NUMBER:
       token = cp_lexer_consume_token (parser->lexer);
-      if (TREE_CODE (token->u.value) == FIXED_CST)
-	{
-	  error_at (token->location,
-		    "fixed-point types not supported in C++");
+      if (TREE_CODE (token->u.value) == FIXED_CST
+          && !targetm.fixed_point_supported_p ())
+        {
+          error_at (token->location,
+                    "fixed-point types not supported for this target");
 	  return error_mark_node;
 	}
       /* Floating-point literals are only allowed in an integral
@@ -11950,6 +11954,17 @@
 	++decl_specs->specs[(int) ds_unsigned];
       type = unsigned_type_node;
       break;
+    case RID_FRACT:
+      type = fract_type_node;
+      break;
+    case RID_ACCUM:
+      type = accum_type_node;
+      break;
+    case RID_SAT:
+      if (decl_specs)
+	++decl_specs->specs[(int) ds_sat];
+      type = long_integer_type_node; /* must set accum or fract */
+      break;
     case RID_FLOAT:
       type = float_type_node;
       break;
@@ -12004,7 +12019,8 @@
 	  && (token->keyword != RID_SIGNED
 	      && token->keyword != RID_UNSIGNED
 	      && token->keyword != RID_SHORT
-	      && token->keyword != RID_LONG))
+	      && token->keyword != RID_LONG
+	      && token->keyword != RID_SAT))
 	cp_parser_set_decl_spec_type (decl_specs,
 				      type,
 				      token->location,
Index: gcc/cp/call.c
===================================================================
--- gcc/cp/call.c	(revision 157409)
+++ gcc/cp/call.c	(working copy)
@@ -929,7 +929,8 @@
   /* As an extension, allow conversion to complex type.  */
   else if (ARITHMETIC_TYPE_P (to))
     {
-      if (! (INTEGRAL_CODE_P (fcode) || fcode == REAL_TYPE)
+      if (! (INTEGRAL_CODE_P (fcode) || fcode == REAL_TYPE
+             || fcode == FIXED_POINT_TYPE)
           || SCOPED_ENUM_P (from))
 	return NULL;
       conv = build_conv (ck_std, to, conv);
@@ -1848,7 +1849,8 @@
      integral types plus floating types.  */
   return ((CP_INTEGRAL_TYPE_P (type)
 	   && same_type_p (type_promotes_to (type), type))
-	  || TREE_CODE (type) == REAL_TYPE);
+	  || TREE_CODE (type) == REAL_TYPE
+	  || TREE_CODE (type) == FIXED_POINT_TYPE);
 }
 
 /* Create any builtin operator overload candidates for the operator in
Index: gcc/cp/cvt.c
===================================================================
--- gcc/cp/cvt.c	(revision 157409)
+++ gcc/cp/cvt.c	(working copy)
@@ -662,7 +662,8 @@
 	  /* enum = enum, enum = int, enum = float, (enum)pointer are all
 	     errors.  */
 	  if (((INTEGRAL_OR_ENUMERATION_TYPE_P (intype)
-		|| TREE_CODE (intype) == REAL_TYPE)
+                || TREE_CODE (intype) == REAL_TYPE
+                || TREE_CODE (intype) == FIXED_POINT_TYPE)
 	       && ! (convtype & CONV_STATIC))
 	      || TREE_CODE (intype) == POINTER_TYPE)
 	    {
@@ -736,6 +737,21 @@
       else if (code == COMPLEX_TYPE)
 	return fold_if_not_in_template (convert_to_complex (type, e));
     }
+  if (code == FIXED_POINT_TYPE)
+    {
+      if (MAYBE_CLASS_TYPE_P (TREE_TYPE (e)))
+	{
+	  tree rval;
+	  rval = build_type_conversion (type, e);
+	  if (rval)
+	    return rval;
+	  else
+	    if (flags & LOOKUP_COMPLAIN)
+	      error ("%q#T used where a fixed point value was expected",
+			TREE_TYPE (e));
+	}
+      return fold_if_not_in_template (convert_to_fixed (type, e));
+    }
 
   /* New C++ semantics:  since assignment is now based on
      memberwise copying,  if the rhs type is derived from the
@@ -1163,6 +1179,8 @@
 	return (desires & WANT_ENUM) ? expr : NULL_TREE;
       case REAL_TYPE:
 	return (desires & WANT_FLOAT) ? expr : NULL_TREE;
+      case FIXED_POINT_TYPE:
+	return (desires & WANT_FIXED_POINT) ? expr : NULL_TREE;
       case POINTER_TYPE:
 	return (desires & WANT_POINTER) ? expr : NULL_TREE;
 
@@ -1225,6 +1243,8 @@
 	  win = (desires & WANT_ENUM); break;
 	case REAL_TYPE:
 	  win = (desires & WANT_FLOAT); break;
+	case FIXED_POINT_TYPE:
+	  win = (desires & WANT_FIXED_POINT); break;
 	case POINTER_TYPE:
 	  win = (desires & WANT_POINTER); break;
 
Index: gcc/cp/mangle.c
===================================================================
--- gcc/cp/mangle.c	(revision 157409)
+++ gcc/cp/mangle.c	(working copy)
@@ -1818,6 +1818,7 @@
 	      if (TREE_CODE (type) != VOID_TYPE
 		  && TREE_CODE (type) != INTEGER_TYPE
 		  && TREE_CODE (type) != REAL_TYPE
+		  && TREE_CODE (type) != FIXED_POINT_TYPE
 		  && TREE_CODE (type) != BOOLEAN_TYPE)
 		add_substitution (type);
 	      return;
Index: gcc/cp/cp-tree.h
===================================================================
--- gcc/cp/cp-tree.h	(revision 157409)
+++ gcc/cp/cp-tree.h	(working copy)
@@ -2985,13 +2985,14 @@
    Integral and floating types are collectively called arithmetic
    types.  
 
-   As a GNU extension, we also accept complex types.
+   As a GNU extension, we also accept complex and fixed-point types.
 
    Keep these checks in ascending code order.  */
 #define ARITHMETIC_TYPE_P(TYPE) \
   (CP_INTEGRAL_TYPE_P (TYPE) \
    || TREE_CODE (TYPE) == REAL_TYPE \
-   || TREE_CODE (TYPE) == COMPLEX_TYPE)
+   || TREE_CODE (TYPE) == COMPLEX_TYPE \
+   || TREE_CODE (TYPE) == FIXED_POINT_TYPE)
 
 /* [basic.types]
 
@@ -4168,7 +4169,9 @@
 #define WANT_POINTER	8 /* pointer types */
 #define WANT_NULL      16 /* null pointer constant */
 #define WANT_VECTOR_OR_COMPLEX 32 /* vector or complex types */
-#define WANT_ARITH	(WANT_INT | WANT_FLOAT | WANT_VECTOR_OR_COMPLEX)
+#define WANT_FIXED_POINT 64 /* fixed point types */
+#define WANT_ARITH	(WANT_INT | WANT_FLOAT | \
+                         WANT_VECTOR_OR_COMPLEX | WANT_FIXED_POINT)
 
 /* Used with comptypes, and related functions, to guide type
    comparison.  */
@@ -4343,6 +4346,7 @@
   ds_constexpr,
   ds_complex,
   ds_thread,
+  ds_sat,
   ds_last
 } cp_decl_spec;
 
Index: gcc/cse.c
===================================================================
--- gcc/cse.c	(revision 157409)
+++ gcc/cse.c	(working copy)
@@ -3703,9 +3703,10 @@
 			  && exact_log2 (- INTVAL (const_arg1)) >= 0)))
 		break;
 
-	      /* ??? Vector mode shifts by scalar
+	      /* ??? Vector and Fixed Point shifts by scalar
 		 shift operand are not supported yet.  */
-	      if (is_shift && VECTOR_MODE_P (mode))
+	      if (is_shift && (VECTOR_MODE_P (mode)
+			       || ALL_FIXED_POINT_MODE_P (mode)))
                 break;
 
 	      if (is_shift
Index: gcc/typeclass.h
===================================================================
--- gcc/typeclass.h	(revision 157409)
+++ gcc/typeclass.h	(working copy)
@@ -31,7 +31,7 @@
 {
   no_type_class = -1,
   void_type_class, integer_type_class, char_type_class,
-  enumeral_type_class, boolean_type_class,
+  enumeral_type_class, boolean_type_class, fixed_point_type_class,
   pointer_type_class, reference_type_class, offset_type_class,
   real_type_class, complex_type_class,
   function_type_class, method_type_class,
Index: gcc/varasm.c
===================================================================
--- gcc/varasm.c	(revision 157409)
+++ gcc/varasm.c	(working copy)
@@ -2670,7 +2670,7 @@
       else
 	mclass = MODE_INT;
 
-      omode = mode_for_size (subsize * BITS_PER_UNIT, mclass, 0);
+      omode = mode_for_size (subsize * BITS_PER_UNIT, MODE_INT, 0);
       imode = mode_for_size (size * BITS_PER_UNIT, mclass, 0);
 
       for (i = 0; i < size; i += subsize)
Index: gcc/c-common.c
===================================================================
--- gcc/c-common.c	(revision 157409)
+++ gcc/c-common.c	(working copy)
@@ -561,9 +561,9 @@
   { "_Decimal32",       RID_DFLOAT32,  D_CONLY | D_EXT },
   { "_Decimal64",       RID_DFLOAT64,  D_CONLY | D_EXT },
   { "_Decimal128",      RID_DFLOAT128, D_CONLY | D_EXT },
-  { "_Fract",           RID_FRACT,     D_CONLY | D_EXT },
-  { "_Accum",           RID_ACCUM,     D_CONLY | D_EXT },
-  { "_Sat",             RID_SAT,       D_CONLY | 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 },

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: fixed-point support in c++
  2010-03-16 10:12   ` Sean D'Epagnier
@ 2010-03-19 13:04     ` Dave Korn
  2010-04-13 15:34       ` Sean D'Epagnier
  0 siblings, 1 reply; 6+ messages in thread
From: Dave Korn @ 2010-03-19 13:04 UTC (permalink / raw)
  To: Sean D'Epagnier; +Cc: Dave Korn, gcc

On 16/03/2010 09:15, Sean D'Epagnier wrote:

> I went through the c++ parser and added support for fixed point there.
>  Everything seems to be working, and I am able to use fixed-point
> numbers in c++.
> 
> The c++ parser is kind of complex and it is possible I missed
> something.  I would love to get feedback on this patch, and hopefully
> it can get committed to gcc.

  Do you have a copyright assignment on file for GCC?  For a non-trivial
contribution of this size, it's a requirement before the patch can be accepted.

  Once that is established, your patch would need a changelog entry in the
standard format, and you need to have built the compiler both patched and
clean and run a full C and C++ testsuite on both to check for regressions.
Oh, and sending it to the -patches list is the best way to make clear that
it's ready for review, once we've got the rest sorted out.

    cheers,
      DaveK

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: fixed-point support in c++
  2010-03-19 13:04     ` Dave Korn
@ 2010-04-13 15:34       ` Sean D'Epagnier
  2010-04-13 16:33         ` Dave Korn
  0 siblings, 1 reply; 6+ messages in thread
From: Sean D'Epagnier @ 2010-04-13 15:34 UTC (permalink / raw)
  To: Dave Korn; +Cc: gcc

On 3/19/10, Dave Korn <dave.korn.cygwin@googlemail.com> wrote:
> On 16/03/2010 09:15, Sean D'Epagnier wrote:
>
>   Do you have a copyright assignment on file for GCC?  For a non-trivial
> contribution of this size, it's a requirement before the patch can be
> accepted.
>

Yes this should be fine.

>   Once that is established, your patch would need a changelog entry in the
> standard format, and you need to have built the compiler both patched and
> clean and run a full C and C++ testsuite on both to check for regressions.

I have not run the testsuite before, I have run "make check" on the
latest svn gcc for  C and C++ without any patches, and it fails:
# of expected passes            7052
# of unexpected failures        1
# of expected failures          95
# of unsupported tests          341

Would the patch I have be ok if I get the same results?  Or do I need
to wait until there are no unexpected failures?

Thanks
Sean

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: fixed-point support in c++
  2010-04-13 15:34       ` Sean D'Epagnier
@ 2010-04-13 16:33         ` Dave Korn
  0 siblings, 0 replies; 6+ messages in thread
From: Dave Korn @ 2010-04-13 16:33 UTC (permalink / raw)
  To: Sean D'Epagnier; +Cc: Dave Korn, gcc

On 13/04/2010 16:06, Sean D'Epagnier wrote:

> Would the patch I have be ok if I get the same results?  

  Yes, absolutely; we insist only on no regressions, i.e. the patch mustn't
increase the number of fails.  Most targets have the odd outstanding failure
or two.  So there's no reason not to go ahead.  Add a changelog entry, send
your patch to the -patches list, and we'll see who we can get to review it.

    cheers,
      DaveK

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2010-04-13 15:34 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-03-16  1:28 fixed-point support in c++ Sean D'Epagnier
2010-03-16  1:32 ` Dave Korn
2010-03-16 10:12   ` Sean D'Epagnier
2010-03-19 13:04     ` Dave Korn
2010-04-13 15:34       ` Sean D'Epagnier
2010-04-13 16:33         ` Dave Korn

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).