This is the mail archive of the gcc@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]

Re: fixed-point support in c++


>   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
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 },

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