This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

fixed-point support for c++ [patch]


Sorry for first email, it was premature.

I have two patches for gcc.  The first fixes some important bugs
within gcc for fixed point support and applies to all languages and
targets.  The second is c++ related only, and adds support to the
parser for fixed point.

These are the first patches I have submitted to gcc and I would be
glad to make any modifications or improvements as required.

I have a copyright assignment, and I have tested gcc and found no
regressions with these patches.

Thanks
Sean
Index: gcc/fold-const.c
===================================================================
--- gcc/fold-const.c	(revision 158228)
+++ gcc/fold-const.c	(working copy)
@@ -12311,6 +12311,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/ChangeLog
===================================================================
--- gcc/ChangeLog	(revision 158228)
+++ gcc/ChangeLog	(working copy)
@@ -1,3 +1,12 @@
+2010-04-14  Sean D'Epagnier <geckosenator@gmail.com>
+	Fixed-point bugfixes
+	* fold-const.c (fold_binary_loc):  Avoid optimization that relies
+	on bitwise operations which are undefined for fixed point
+	* cse.c (fold_rtx0): Ditto from fold_binary_loc
+	* varasm.c (assemble_integer): Fix breakage caused on machines which
+	have a register size smaller than smallest fixed-point size of
+	a given type
+	
 2010-04-12  Steve Ellcey  <sje@cup.hp.com>
 
 	* function.c (assign_parms_initialize_all): Add unused attribute
Index: gcc/cse.c
===================================================================
--- gcc/cse.c	(revision 158228)
+++ 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/varasm.c
===================================================================
--- gcc/varasm.c	(revision 158228)
+++ gcc/varasm.c	(working copy)
@@ -2709,7 +2709,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/builtins.c
===================================================================
--- gcc/builtins.c	(revision 158228)
+++ 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/ChangeLog
===================================================================
--- gcc/ChangeLog	(revision 158228)
+++ gcc/ChangeLog	(working copy)
@@ -1,3 +1,31 @@
+2010-04-14  Sean D'Epagnier <geckosenator@gmail.com>
+	Fixed-point support for C++
+	* builtins.c (type_to_class): Add Fixed Point class
+	* cp/typeck.c (cp_common_type): Common type for fixed-point types in c++ parser
+	* cp/decl.c (grokdeclarator): Add parsing for fixed-point keywords.
+	* cp/rtti.c (typeinfo_in_lib_p): Add fixed-point class
+	(emit_support_tinfos): Add fixed-point types
+	* cp/error.c (dump_type): Add fixed-point class
+	* cp/typeck2.c (check_narrowing): Add fixed-point class
+	* cp/pt.c (tsubst): Add fixed-point class
+	(unify): Add fixed-point class
+	* cp/parser.c
+	(cp_lexer_next_token_is_decl_specifier_keyword): Add fixed-point keywords
+	(cp_parser_primary_expression): Support fixed-point in C++ if the target supports it
+	(cp_parser_simple_type_specifier): Parse types from keywords for fixed-point
+	* cp/call.c
+	(standard_conversion): Add fixed-point type.
+	(promoted_arithmetic_type_p): Add fixed-point types.
+	* cp/cvt.c
+	(ocp_convert): Errors to convert fixed-point to enum, and fixed-point conversions
+	(build_expr_type_conversion): Add fixed-point type
+	* cp/mangle.c (write_type): Add fixed-point type
+	* cp/cp-tree.h: Add fixed-point type to arithmetic types,
+	add WANT_FIXED_POINT for build_expr_type_conversion,
+	add sat decl-specifier
+	* typeclass.h: Add fixed-point type class
+	* c-common.c: Allow fixed-point keywords in languages besides C only.
+
 2010-04-14  Sean D'Epagnier <geckosenator@gmail.com>
 	Fixed-point bugfixes
 	* fold-const.c (fold_binary_loc):  Avoid optimization that relies
Index: gcc/cp/typeck.c
===================================================================
--- gcc/cp/typeck.c	(revision 158228)
+++ 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);
@@ -3759,9 +3844,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;
 
@@ -3931,9 +4018,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)))
@@ -4134,8 +4223,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,
@@ -4154,8 +4245,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,
@@ -4206,9 +4299,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 158228)
+++ gcc/cp/decl.c	(working copy)
@@ -7698,7 +7698,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;
@@ -7712,6 +7712,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;
@@ -8029,21 +8030,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);
@@ -8056,6 +8060,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;
@@ -8077,12 +8087,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 158228)
+++ 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 158228)
+++ 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 158228)
+++ gcc/cp/typeck2.c	(working copy)
@@ -772,7 +772,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 158228)
+++ gcc/cp/pt.c	(working copy)
@@ -9980,6 +9980,7 @@
     case REAL_TYPE:
     case COMPLEX_TYPE:
     case VECTOR_TYPE:
+    case FIXED_POINT_TYPE:
     case BOOLEAN_TYPE:
     case INTEGER_CST:
     case REAL_CST:
@@ -14883,6 +14884,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 158228)
+++ 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;
@@ -3204,10 +3207,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
@@ -11954,6 +11958,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;
@@ -12008,7 +12023,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 158228)
+++ gcc/cp/call.c	(working copy)
@@ -933,7 +933,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);
@@ -1852,7 +1853,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 158228)
+++ 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 158228)
+++ 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 158228)
+++ gcc/cp/cp-tree.h	(working copy)
@@ -2994,13 +2994,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]
 
@@ -4177,7 +4178,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.  */
@@ -4356,6 +4359,7 @@
   ds_constexpr,
   ds_complex,
   ds_thread,
+  ds_sat,
   ds_last
 } cp_decl_spec;
 
Index: gcc/typeclass.h
===================================================================
--- gcc/typeclass.h	(revision 158228)
+++ 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/c-common.c
===================================================================
--- gcc/c-common.c	(revision 158228)
+++ 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 },

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]