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]

Re: fixed-point support for c++ [patch]


>
> Thus some comments.  Please create diffs with the -p option so
> the function context is displayed in the diffs header (see gcc.gnu.org/wiki
> on how to teach svn to use an external diff tool).
>

Thanks for the quick reply, and I have  set up the external patch tool.

I fixed the formatting issues you found, I looked for more but did not find any.
>
> +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
>
> don't post diffs of ChangeLog but rather paste the changelog entry
> in the submission mail.  vertical space after the initial line, no
> overall comment "Fixed-point bugfixes".  Sentences should terminate
> with a fullstop.  Instead of "Ditto ..." simply use "Likewise."


 I saw Ditto in the ChangeLog for other changes which is why I used
it, but I see Likewise also.

> 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);
>
> I don't think that change is correct.
>

I have done a lot of debugging of gcc when this line is hit when
compiling code with fixed point numbers.   I agree that this change is
probably not ideal, but the original change that added mclass in the
first place was not correct.  It was added for mips fixed point
support, but it breaks on targets with 8 bit registers (since the
smallest accum type is still 16 bits).  If you look and see what omode
is actually used for in the functions it is passed to, it has no real
effect of the actual type, and it is just testing to make sure the
code can be generated (without actually doing it yet)

I do know that this change works and gcc emits correct assembly
everytime, where without this change I get internal compiler errors
trying to compile programs.  If you can suggest a better solution I
would work on that.

My updated Changelogs and patches:

2010-04-14  Sean D'Epagnier <geckosenator@gmail.com>

	* fold-const.c (fold_binary_loc):  Avoid optimization that relies
	on bitwise operations which are undefined for fixed point.
	* cse.c (fold_rtx0): Likewise 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-14  Sean D'Epagnier <geckosenator@gmail.com>

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

Thanks
Sean
Index: gcc/builtins.c
===================================================================
--- gcc/builtins.c	(revision 158228)
+++ gcc/builtins.c	(working copy)
@@ -1708,6 +1708,7 @@ type_to_class (tree type)
     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/cp/typeck.c
===================================================================
--- gcc/cp/typeck.c	(revision 158228)
+++ gcc/cp/typeck.c	(working copy)
@@ -316,6 +316,91 @@ cp_common_type (tree t1, tree t2)
   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 @@ cp_build_binary_op (location_t location,
     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 @@ cp_build_binary_op (location_t location,
 
       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 @@ cp_build_binary_op (location_t location,
 
     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 @@ cp_build_binary_op (location_t location,
 	}
 
       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 @@ cp_build_binary_op (location_t location,
     }
 
   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 @@ grokdeclarator (const cp_declarator *dec
      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 @@ grokdeclarator (const cp_declarator *dec
   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 @@ grokdeclarator (const cp_declarator *dec
 
   /* 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 @@ grokdeclarator (const cp_declarator *dec
 	  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 @@ grokdeclarator (const cp_declarator *dec
 	  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 @@ typeinfo_in_lib_p (tree type)
     case INTEGER_TYPE:
     case BOOLEAN_TYPE:
     case REAL_TYPE:
+    case FIXED_POINT_TYPE:
     case VOID_TYPE:
       return true;
 
@@ -1452,6 +1453,22 @@ emit_support_tinfos (void)
     &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 @@ dump_expr (tree t, int flags)
     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 @@ check_narrowing (tree type, tree init)
   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 @@ tsubst (tree t, tree args, tsubst_flags_
     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 @@ unify (tree tparms, tree targs, tree par
     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 @@ cp_lexer_next_token_is_decl_specifier_ke
       /* 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 @@ cp_parser_primary_expression (cp_parser 
     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 @@ cp_parser_simple_type_specifier (cp_pars
 	++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 @@ cp_parser_simple_type_specifier (cp_pars
 	  && (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 @@ standard_conversion (tree to, tree from,
   /* 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 @@ promoted_arithmetic_type_p (tree type)
      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 @@ ocp_convert (tree type, tree expr, int c
 	  /* 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 @@ ocp_convert (tree type, tree expr, int c
       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 @@ build_expr_type_conversion (int desires,
 	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 @@ build_expr_type_conversion (int desires,
 	  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 @@ write_type (tree type)
 	      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 @@ more_aggr_init_expr_args_p (const aggr_i
    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 @@ enum overload_flags { NO_SPECIAL = 0, DT
 #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 @@ typedef enum cp_decl_spec {
   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 @@ enum type_class
 {
   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 @@ const struct c_common_resword c_common_r
   { "_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: gcc/fold-const.c
===================================================================
--- gcc/fold-const.c	(revision 158228)
+++ gcc/fold-const.c	(working copy)
@@ -12311,6 +12311,11 @@ fold_binary_loc (location_t loc,
       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/cse.c
===================================================================
--- gcc/cse.c	(revision 158228)
+++ gcc/cse.c	(working copy)
@@ -3703,9 +3703,10 @@ fold_rtx (rtx x, rtx insn)
 			  && 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 @@ assemble_integer (rtx x, unsigned int si
       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 Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]