OSDN Git Service

2007-08-29 Douglas Gregor <doug.gregor@gmail.com>
[pf3gnuchains/gcc-fork.git] / gcc / tree.c
index b8bbfc0..fc5c824 100644 (file)
@@ -50,6 +50,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-flow.h"
 #include "params.h"
 #include "pointer-set.h"
+#include "fixed-value.h"
 
 /* Each tree code class has an associated string representation.
    These must correspond to the tree_code_class entries.  */
@@ -399,6 +400,7 @@ tree_code_size (enum tree_code code)
        {
        case INTEGER_CST:       return sizeof (struct tree_int_cst);
        case REAL_CST:          return sizeof (struct tree_real_cst);
+       case FIXED_CST:         return sizeof (struct tree_fixed_cst);
        case COMPLEX_CST:       return sizeof (struct tree_complex);
        case VECTOR_CST:        return sizeof (struct tree_vector);
        case STRING_CST:        gcc_unreachable ();
@@ -1095,6 +1097,22 @@ build_constructor_from_list (tree type, tree vals)
   return t;
 }
 
+/* Return a new FIXED_CST node whose type is TYPE and value is F.  */
+
+tree
+build_fixed (tree type, FIXED_VALUE_TYPE f)
+{
+  tree v;
+  FIXED_VALUE_TYPE *fp;
+
+  v = make_node (FIXED_CST);
+  fp = ggc_alloc (sizeof (FIXED_VALUE_TYPE));
+  memcpy (fp, &f, sizeof (FIXED_VALUE_TYPE));
+
+  TREE_TYPE (v) = type;
+  TREE_FIXED_CST_PTR (v) = fp;
+  return v;
+}
 
 /* Return a new REAL_CST node whose type is TYPE and value is D.  */
 
@@ -1176,8 +1194,8 @@ build_string (int len, const char *str)
   TREE_CONSTANT (s) = 1;
   TREE_INVARIANT (s) = 1;
   TREE_STRING_LENGTH (s) = len;
-  memcpy ((char *) TREE_STRING_POINTER (s), str, len);
-  ((char *) TREE_STRING_POINTER (s))[len] = '\0';
+  memcpy (CONST_CAST (TREE_STRING_POINTER (s)), str, len);
+  ((char *) CONST_CAST (TREE_STRING_POINTER (s)))[len] = '\0';
 
   return s;
 }
@@ -1215,6 +1233,11 @@ build_one_cst (tree type)
     case REAL_TYPE:
       return build_real (type, dconst1);
 
+    case FIXED_POINT_TYPE:
+      /* We can only generate 1 for accum types.  */
+      gcc_assert (ALL_SCALAR_ACCUM_MODE_P (TYPE_MODE (type)));
+      return build_fixed (type, FCONST1(TYPE_MODE (type)));
+
     case VECTOR_TYPE:
       {
        tree scalar, cst;
@@ -1434,6 +1457,15 @@ integer_nonzerop (const_tree expr)
                  || integer_nonzerop (TREE_IMAGPART (expr)))));
 }
 
+/* Return 1 if EXPR is the fixed-point constant zero.  */
+
+int
+fixed_zerop (const_tree expr)
+{
+  return (TREE_CODE (expr) == FIXED_CST
+         && double_int_zero_p (TREE_FIXED_CST (expr).data));
+}
+
 /* Return the power of two represented by a tree node known to be a
    power of two.  */
 
@@ -1769,7 +1801,7 @@ tree_cons_stat (tree purpose, tree value, tree chain MEM_STAT_DECL)
    make_unsigned_type).  */
 
 tree
-size_in_bytes (tree type)
+size_in_bytes (const_tree type)
 {
   tree t;
 
@@ -1815,7 +1847,7 @@ int_size_in_bytes (const_tree type)
    or return -1 if the size can vary or is larger than an integer.  */
 
 HOST_WIDE_INT
-max_int_size_in_bytes (tree type)
+max_int_size_in_bytes (const_tree type)
 {
   HOST_WIDE_INT size = -1;
   tree size_tree;
@@ -2184,6 +2216,7 @@ tree_node_structure (const_tree t)
       /* tcc_constant cases.  */
     case INTEGER_CST:          return TS_INT_CST;
     case REAL_CST:             return TS_REAL_CST;
+    case FIXED_CST:            return TS_FIXED_CST;
     case COMPLEX_CST:          return TS_COMPLEX;
     case VECTOR_CST:           return TS_VECTOR;
     case STRING_CST:           return TS_STRING;
@@ -2213,7 +2246,7 @@ tree_node_structure (const_tree t)
    or offset that depends on a field within a record.  */
 
 bool
-contains_placeholder_p (tree exp)
+contains_placeholder_p (const_tree exp)
 {
   enum tree_code code;
 
@@ -2274,9 +2307,9 @@ contains_placeholder_p (tree exp)
        {
        case CALL_EXPR:
          {
-           tree arg;
-           call_expr_arg_iterator iter;
-           FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
+           const_tree arg;
+           const_call_expr_arg_iterator iter;
+           FOR_EACH_CONST_CALL_EXPR_ARG (arg, iter, exp)
              if (CONTAINS_PLACEHOLDER_P (arg))
                return 1;
            return 0;
@@ -2324,6 +2357,7 @@ type_contains_placeholder_1 (const_tree type)
 
     case INTEGER_TYPE:
     case REAL_TYPE:
+    case FIXED_POINT_TYPE:
       /* Here we just check the bounds.  */
       return (CONTAINS_PLACEHOLDER_P (TYPE_MIN_VALUE (type))
              || CONTAINS_PLACEHOLDER_P (TYPE_MAX_VALUE (type)));
@@ -3077,7 +3111,7 @@ build2_stat (enum tree_code code, tree tt, tree arg0, tree arg1 MEM_STAT_DECL)
 
   if (code == POINTER_PLUS_EXPR && arg0 && arg1 && tt)
     gcc_assert (POINTER_TYPE_P (tt) && POINTER_TYPE_P (TREE_TYPE (arg0))
-               && TREE_CODE (TREE_TYPE (arg1)) == INTEGER_TYPE
+               && INTEGRAL_TYPE_P (TREE_TYPE (arg1))
                && useless_type_conversion_p (sizetype, TREE_TYPE (arg1)));
 
   t = make_node_stat (code PASS_MEM_STAT);
@@ -3429,7 +3463,7 @@ annotate_with_locus (tree node, location_t locus)
    decls and constants can be shared among multiple locations, so
    return nothing.  */
 location_t
-expr_location (tree node)
+expr_location (const_tree node)
 {
 #ifdef USE_MAPPED_LOCATION
   if (GIMPLE_STMT_P (node))
@@ -3457,7 +3491,7 @@ set_expr_location (tree node, location_t locus)
 }
 
 bool
-expr_has_location (tree node)
+expr_has_location (const_tree node)
 {
 #ifdef USE_MAPPED_LOCATION
   return expr_location (node) != UNKNOWN_LOCATION;
@@ -3471,7 +3505,7 @@ source_location *
 #else
 source_locus
 #endif
-expr_locus (tree node)
+expr_locus (const_tree node)
 {
 #ifdef USE_MAPPED_LOCATION
   if (GIMPLE_STMT_P (node))
@@ -3519,7 +3553,7 @@ set_expr_locus (tree node,
 }
 
 const char **
-expr_filename (tree node)
+expr_filename (const_tree node)
 {
 #ifdef USE_MAPPED_LOCATION
   if (GIMPLE_STMT_P (node))
@@ -3533,7 +3567,7 @@ expr_filename (tree node)
 }
 
 int *
-expr_lineno (tree node)
+expr_lineno (const_tree node)
 {
 #ifdef USE_MAPPED_LOCATION
   if (GIMPLE_STMT_P (node))
@@ -3644,12 +3678,6 @@ build_type_attribute_qual_variant (tree ttype, tree attribute, int quals)
       TYPE_REFERENCE_TO (ntype) = 0;
       TYPE_ATTRIBUTES (ntype) = attribute;
 
-      if (TYPE_STRUCTURAL_EQUALITY_P (ttype))
-       SET_TYPE_STRUCTURAL_EQUALITY (ntype);
-      else
-       TYPE_CANONICAL (ntype)
-         = build_qualified_type (TYPE_CANONICAL (ttype), quals);
-
       /* Create a new main variant of TYPE.  */
       TYPE_MAIN_VARIANT (ntype) = ntype;
       TYPE_NEXT_VARIANT (ntype) = 0;
@@ -3677,6 +3705,7 @@ build_type_attribute_qual_variant (tree ttype, tree attribute, int quals)
            (TREE_INT_CST_HIGH (TYPE_MAX_VALUE (ntype)), hashcode);
          break;
        case REAL_TYPE:
+       case FIXED_POINT_TYPE:
          {
            unsigned int precision = TYPE_PRECISION (ntype);
            hashcode = iterative_hash_object (precision, hashcode);
@@ -3691,8 +3720,12 @@ build_type_attribute_qual_variant (tree ttype, tree attribute, int quals)
       /* If the target-dependent attributes make NTYPE different from
         its canonical type, we will need to use structural equality
         checks for this qualified type. */
-      if (!targetm.comp_type_attributes (ntype, ttype))
+      ttype = build_qualified_type (ttype, TYPE_UNQUALIFIED);
+      if (TYPE_STRUCTURAL_EQUALITY_P (ttype)
+          || !targetm.comp_type_attributes (ntype, ttype))
        SET_TYPE_STRUCTURAL_EQUALITY (ntype);
+      else
+       TYPE_CANONICAL (ntype) = TYPE_CANONICAL (ttype);
 
       ttype = build_qualified_type (ntype, quals);
     }
@@ -3776,20 +3809,28 @@ is_attribute_p (const char *attr, const_tree ident)
    returns the first occurrence; the TREE_CHAIN of the return value should
    be passed back in if further occurrences are wanted.  */
 
+#define LOOKUP_ATTRIBUTE_BODY(TYPE) do { \
+  TYPE l; \
+  size_t attr_len = strlen (attr_name); \
+  for (l = list; l; l = TREE_CHAIN (l)) \
+    { \
+      gcc_assert (TREE_CODE (TREE_PURPOSE (l)) == IDENTIFIER_NODE); \
+      if (is_attribute_with_length_p (attr_name, attr_len, TREE_PURPOSE (l))) \
+       return l; \
+    } \
+  return NULL_TREE; \
+} while (0)
+
 tree
 lookup_attribute (const char *attr_name, tree list)
 {
-  tree l;
-  size_t attr_len = strlen (attr_name);
-
-  for (l = list; l; l = TREE_CHAIN (l))
-    {
-      gcc_assert (TREE_CODE (TREE_PURPOSE (l)) == IDENTIFIER_NODE);
-      if (is_attribute_with_length_p (attr_name, attr_len, TREE_PURPOSE (l)))
-       return l;
-    }
+  LOOKUP_ATTRIBUTE_BODY(tree);
+}
 
-  return NULL_TREE;
+const_tree
+const_lookup_attribute (const char *attr_name, const_tree list)
+{
+  LOOKUP_ATTRIBUTE_BODY(const_tree);
 }
 
 /* Remove any instances of attribute ATTR_NAME in LIST and return the
@@ -4551,6 +4592,9 @@ type_hash_eq (const void *va, const void *vb)
                  || tree_int_cst_equal (TYPE_MIN_VALUE (a->type),
                                         TYPE_MIN_VALUE (b->type))));
 
+    case FIXED_POINT_TYPE:
+      return TYPE_SATURATING (a->type) == TYPE_SATURATING (b->type);
+
     case OFFSET_TYPE:
       return TYPE_OFFSET_BASETYPE (a->type) == TYPE_OFFSET_BASETYPE (b->type);
 
@@ -4719,7 +4763,7 @@ attribute_hash_list (const_tree list, hashval_t hashcode)
    equivalent to l1.  */
 
 int
-attribute_list_equal (tree l1, tree l2)
+attribute_list_equal (const_tree l1, const_tree l2)
 {
   return attribute_list_contained (l1, l2)
         && attribute_list_contained (l2, l1);
@@ -4734,9 +4778,9 @@ attribute_list_equal (tree l1, tree l2)
    correctly.  */
 
 int
-attribute_list_contained (tree l1, tree l2)
+attribute_list_contained (const_tree l1, const_tree l2)
 {
-  tree t1, t2;
+  const_tree t1, t2;
 
   /* First check the obvious, maybe the lists are identical.  */
   if (l1 == l2)
@@ -4755,11 +4799,11 @@ attribute_list_contained (tree l1, tree l2)
 
   for (; t2 != 0; t2 = TREE_CHAIN (t2))
     {
-      tree attr;
-      for (attr = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (t2)), l1);
+      const_tree attr;
+      for (attr = const_lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (t2)), l1);
           attr != NULL_TREE;
-          attr = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (t2)),
-                                   TREE_CHAIN (attr)))
+          attr = const_lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (t2)),
+                                         TREE_CHAIN (attr)))
        {
          if (TREE_VALUE (t2) != NULL
              && TREE_CODE (TREE_VALUE (t2)) == TREE_LIST
@@ -4787,9 +4831,9 @@ attribute_list_contained (tree l1, tree l2)
    Also, the TREE_PURPOSEs must match.  */
 
 int
-type_list_equal (tree l1, tree l2)
+type_list_equal (const_tree l1, const_tree l2)
 {
-  tree t1, t2;
+  const_tree t1, t2;
 
   for (t1 = l1, t2 = l2; t1 && t2; t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2))
     if (TREE_VALUE (t1) != TREE_VALUE (t2)
@@ -4898,7 +4942,8 @@ host_integerp (const_tree t, int pos)
               && (HOST_WIDE_INT) TREE_INT_CST_LOW (t) >= 0)
              || (! pos && TREE_INT_CST_HIGH (t) == -1
                  && (HOST_WIDE_INT) TREE_INT_CST_LOW (t) < 0
-                 && !TYPE_UNSIGNED (TREE_TYPE (t)))
+                 && (!TYPE_UNSIGNED (TREE_TYPE (t))
+                     || TYPE_IS_SIZETYPE (TREE_TYPE (t))))
              || (pos && TREE_INT_CST_HIGH (t) == 0)));
 }
 
@@ -4972,7 +5017,7 @@ simple_cst_list_equal (const_tree l1, const_tree l2)
    this function.  */
 
 int
-simple_cst_equal (tree t1, tree t2)
+simple_cst_equal (const_tree t1, const_tree t2)
 {
   enum tree_code code1, code2;
   int cmp;
@@ -5011,6 +5056,9 @@ simple_cst_equal (tree t1, tree t2)
     case REAL_CST:
       return REAL_VALUES_IDENTICAL (TREE_REAL_CST (t1), TREE_REAL_CST (t2));
 
+    case FIXED_CST:
+      return FIXED_VALUES_IDENTICAL (TREE_FIXED_CST (t1), TREE_FIXED_CST (t2));
+
     case STRING_CST:
       return (TREE_STRING_LENGTH (t1) == TREE_STRING_LENGTH (t2)
              && ! memcmp (TREE_STRING_POINTER (t1), TREE_STRING_POINTER (t2),
@@ -5043,13 +5091,13 @@ simple_cst_equal (tree t1, tree t2)
       if (call_expr_nargs (t1) != call_expr_nargs (t2))
        return 0;
       {
-       tree arg1, arg2;
-       call_expr_arg_iterator iter1, iter2;
-       for (arg1 = first_call_expr_arg (t1, &iter1),
-              arg2 = first_call_expr_arg (t2, &iter2);
+       const_tree arg1, arg2;
+       const_call_expr_arg_iterator iter1, iter2;
+       for (arg1 = first_const_call_expr_arg (t1, &iter1),
+              arg2 = first_const_call_expr_arg (t2, &iter2);
             arg1 && arg2;
-            arg1 = next_call_expr_arg (&iter1),
-              arg2 = next_call_expr_arg (&iter2))
+            arg1 = next_const_call_expr_arg (&iter1),
+              arg2 = next_const_call_expr_arg (&iter2))
          {
            cmp = simple_cst_equal (arg1, arg2);
            if (cmp <= 0)
@@ -5234,6 +5282,12 @@ iterative_hash_expr (const_tree t, hashval_t val)
 
        return iterative_hash_hashval_t (val2, val);
       }
+    case FIXED_CST:
+      {
+       unsigned int val2 = fixed_hash (TREE_FIXED_CST_PTR (t));
+
+       return iterative_hash_hashval_t (val2, val);
+      }
     case STRING_CST:
       return iterative_hash (TREE_STRING_POINTER (t),
                             TREE_STRING_LENGTH (t), val);
@@ -5637,7 +5691,7 @@ build_array_type (tree elt_type, tree index_type)
    the innermost dimension of ARRAY.  */
 
 tree
-get_inner_array_type (tree array)
+get_inner_array_type (const_tree array)
 {
   tree type = TREE_TYPE (array);
 
@@ -6064,6 +6118,7 @@ get_unwidened (tree op, tree for_type)
   if (TREE_CODE (op) == COMPONENT_REF
       /* Since type_for_size always gives an integer type.  */
       && TREE_CODE (type) != REAL_TYPE
+      && TREE_CODE (type) != FIXED_POINT_TYPE
       /* Don't crash if field not laid out yet.  */
       && DECL_SIZE (TREE_OPERAND (op, 1)) != 0
       && host_integerp (DECL_SIZE (TREE_OPERAND (op, 1)), 1))
@@ -6155,6 +6210,7 @@ get_narrower (tree op, int *unsignedp_ptr)
   if (TREE_CODE (op) == COMPONENT_REF
       /* Since type_for_size always gives an integer type.  */
       && TREE_CODE (TREE_TYPE (op)) != REAL_TYPE
+      && TREE_CODE (TREE_TYPE (op)) != FIXED_POINT_TYPE
       /* Ensure field is laid out already.  */
       && DECL_SIZE (TREE_OPERAND (op, 1)) != 0
       && host_integerp (DECL_SIZE (TREE_OPERAND (op, 1)), 1))
@@ -6270,7 +6326,7 @@ int_fits_type_p (const_tree c, const_tree type)
    precision of the type are returned instead.  */
 
 void
-get_type_static_bounds (tree type, mpz_t min, mpz_t max)
+get_type_static_bounds (const_tree type, mpz_t min, mpz_t max)
 {
   if (!POINTER_TYPE_P (type) && TYPE_MIN_VALUE (type)
       && TREE_CODE (TYPE_MIN_VALUE (type)) == INTEGER_CST)
@@ -6305,6 +6361,19 @@ get_type_static_bounds (tree type, mpz_t min, mpz_t max)
     }
 }
 
+/* auto_var_in_fn_p is called to determine whether VAR is an automatic
+   variable defined in function FN.  */
+
+bool
+auto_var_in_fn_p (const_tree var, const_tree fn)
+{
+  return (DECL_P (var) && DECL_CONTEXT (var) == fn
+         && (((TREE_CODE (var) == VAR_DECL || TREE_CODE (var) == PARM_DECL)
+              && ! TREE_STATIC (var))
+             || TREE_CODE (var) == LABEL_DECL
+             || TREE_CODE (var) == RESULT_DECL));
+}
+
 /* Subprogram of following function.  Called by walk_tree.
 
    Return *TP if it is an automatic variable or parameter of the
@@ -6319,7 +6388,7 @@ find_var_from_fn (tree *tp, int *walk_subtrees, void *data)
     *walk_subtrees = 0;
 
   else if (DECL_P (*tp)
-          && lang_hooks.tree_inlining.auto_var_in_fn_p (*tp, fn))
+          && auto_var_in_fn_p (*tp, fn))
     return *tp;
 
   return NULL_TREE;
@@ -6378,6 +6447,7 @@ variably_modified_type_p (tree type, tree fn)
 
     case INTEGER_TYPE:
     case REAL_TYPE:
+    case FIXED_POINT_TYPE:
     case ENUMERAL_TYPE:
     case BOOLEAN_TYPE:
       /* Scalar types are variably modified if their end points
@@ -6509,12 +6579,12 @@ decl_type_context (const_tree decl)
    determined.  */
 
 tree
-get_callee_fndecl (tree call)
+get_callee_fndecl (const_tree call)
 {
   tree addr;
 
   if (call == error_mark_node)
-    return call;
+    return error_mark_node;
 
   /* It's invalid to call this function with anything but a
      CALL_EXPR.  */
@@ -7048,6 +7118,80 @@ make_or_reuse_type (unsigned size, int unsignedp)
     return make_signed_type (size);
 }
 
+/* Create or reuse a fract type by SIZE, UNSIGNEDP, and SATP.  */
+
+static tree
+make_or_reuse_fract_type (unsigned size, int unsignedp, int satp)
+{
+  if (satp)
+    {
+      if (size == SHORT_FRACT_TYPE_SIZE)
+       return unsignedp ? sat_unsigned_short_fract_type_node
+                        : sat_short_fract_type_node;
+      if (size == FRACT_TYPE_SIZE)
+       return unsignedp ? sat_unsigned_fract_type_node : sat_fract_type_node;
+      if (size == LONG_FRACT_TYPE_SIZE)
+       return unsignedp ? sat_unsigned_long_fract_type_node
+                        : sat_long_fract_type_node;
+      if (size == LONG_LONG_FRACT_TYPE_SIZE)
+       return unsignedp ? sat_unsigned_long_long_fract_type_node
+                        : sat_long_long_fract_type_node;
+    }
+  else
+    {
+      if (size == SHORT_FRACT_TYPE_SIZE)
+       return unsignedp ? unsigned_short_fract_type_node
+                        : short_fract_type_node;
+      if (size == FRACT_TYPE_SIZE)
+       return unsignedp ? unsigned_fract_type_node : fract_type_node;
+      if (size == LONG_FRACT_TYPE_SIZE)
+       return unsignedp ? unsigned_long_fract_type_node
+                        : long_fract_type_node;
+      if (size == LONG_LONG_FRACT_TYPE_SIZE)
+       return unsignedp ? unsigned_long_long_fract_type_node
+                        : long_long_fract_type_node;
+    }
+
+  return make_fract_type (size, unsignedp, satp);
+}
+
+/* Create or reuse an accum type by SIZE, UNSIGNEDP, and SATP.  */
+
+static tree
+make_or_reuse_accum_type (unsigned size, int unsignedp, int satp)
+{
+  if (satp)
+    {
+      if (size == SHORT_ACCUM_TYPE_SIZE)
+       return unsignedp ? sat_unsigned_short_accum_type_node
+                        : sat_short_accum_type_node;
+      if (size == ACCUM_TYPE_SIZE)
+       return unsignedp ? sat_unsigned_accum_type_node : sat_accum_type_node;
+      if (size == LONG_ACCUM_TYPE_SIZE)
+       return unsignedp ? sat_unsigned_long_accum_type_node
+                        : sat_long_accum_type_node;
+      if (size == LONG_LONG_ACCUM_TYPE_SIZE)
+       return unsignedp ? sat_unsigned_long_long_accum_type_node
+                        : sat_long_long_accum_type_node;
+    }
+  else
+    {
+      if (size == SHORT_ACCUM_TYPE_SIZE)
+       return unsignedp ? unsigned_short_accum_type_node
+                        : short_accum_type_node;
+      if (size == ACCUM_TYPE_SIZE)
+       return unsignedp ? unsigned_accum_type_node : accum_type_node;
+      if (size == LONG_ACCUM_TYPE_SIZE)
+       return unsignedp ? unsigned_long_accum_type_node
+                        : long_accum_type_node;
+      if (size == LONG_LONG_ACCUM_TYPE_SIZE)
+       return unsignedp ? unsigned_long_long_accum_type_node
+                        : long_long_accum_type_node;
+    }
+
+  return make_accum_type (size, unsignedp, satp);
+}
+
 /* Create nodes for all integer types (and error_mark_node) using the sizes
    of C datatypes.  The caller should call set_sizetype soon after calling
    this function to select one of the types as sizetype.  */
@@ -7195,6 +7339,50 @@ build_common_tree_nodes_2 (int short_double)
   complex_double_type_node = build_complex_type (double_type_node);
   complex_long_double_type_node = build_complex_type (long_double_type_node);
 
+/* Make fixed-point nodes based on sat/non-sat and signed/unsigned.  */
+#define MAKE_FIXED_TYPE_NODE(KIND,WIDTH,SIZE) \
+  sat_ ## WIDTH ## KIND ## _type_node = \
+    make_sat_signed_ ## KIND ## _type (SIZE); \
+  sat_unsigned_ ## WIDTH ## KIND ## _type_node = \
+    make_sat_unsigned_ ## KIND ## _type (SIZE); \
+  WIDTH ## KIND ## _type_node = make_signed_ ## KIND ## _type (SIZE); \
+  unsigned_ ## WIDTH ## KIND ## _type_node = \
+    make_unsigned_ ## KIND ## _type (SIZE);
+
+/* Make fixed-point type nodes based on four different widths.  */
+#define MAKE_FIXED_TYPE_NODE_FAMILY(N1,N2) \
+  MAKE_FIXED_TYPE_NODE (N1, short_, SHORT_ ## N2 ## _TYPE_SIZE) \
+  MAKE_FIXED_TYPE_NODE (N1, , N2 ## _TYPE_SIZE) \
+  MAKE_FIXED_TYPE_NODE (N1, long_, LONG_ ## N2 ## _TYPE_SIZE) \
+  MAKE_FIXED_TYPE_NODE (N1, long_long_, LONG_LONG_ ## N2 ## _TYPE_SIZE)
+
+/* Make fixed-point mode nodes based on sat/non-sat and signed/unsigned.  */
+#define MAKE_FIXED_MODE_NODE(KIND,NAME,MODE) \
+  NAME ## _type_node = \
+    make_or_reuse_signed_ ## KIND ## _type (GET_MODE_BITSIZE (MODE ## mode)); \
+  u ## NAME ## _type_node = \
+    make_or_reuse_unsigned_ ## KIND ## _type \
+      (GET_MODE_BITSIZE (U ## MODE ## mode)); \
+  sat_ ## NAME ## _type_node = \
+    make_or_reuse_sat_signed_ ## KIND ## _type \
+      (GET_MODE_BITSIZE (MODE ## mode)); \
+  sat_u ## NAME ## _type_node = \
+    make_or_reuse_sat_unsigned_ ## KIND ## _type \
+      (GET_MODE_BITSIZE (U ## MODE ## mode));
+
+  /* Fixed-point type and mode nodes.  */
+  MAKE_FIXED_TYPE_NODE_FAMILY (fract, FRACT)
+  MAKE_FIXED_TYPE_NODE_FAMILY (accum, ACCUM)
+  MAKE_FIXED_MODE_NODE (fract, qq, QQ)
+  MAKE_FIXED_MODE_NODE (fract, hq, HQ)
+  MAKE_FIXED_MODE_NODE (fract, sq, SQ)
+  MAKE_FIXED_MODE_NODE (fract, dq, DQ)
+  MAKE_FIXED_MODE_NODE (fract, tq, TQ)
+  MAKE_FIXED_MODE_NODE (accum, ha, HA)
+  MAKE_FIXED_MODE_NODE (accum, sa, SA)
+  MAKE_FIXED_MODE_NODE (accum, da, DA)
+  MAKE_FIXED_MODE_NODE (accum, ta, TA)
+
   {
     tree t = targetm.build_builtin_va_list ();
 
@@ -7441,10 +7629,7 @@ reconstruct_complex_type (tree type, tree bottom)
   else
     return bottom;
 
-  TYPE_READONLY (outer) = TYPE_READONLY (type);
-  TYPE_VOLATILE (outer) = TYPE_VOLATILE (type);
-
-  return outer;
+  return build_qualified_type (outer, TYPE_QUALS (type));
 }
 
 /* Returns a vector tree node given a mode (integer, vector, or BLKmode) and
@@ -7458,6 +7643,10 @@ build_vector_type_for_mode (tree innertype, enum machine_mode mode)
     {
     case MODE_VECTOR_INT:
     case MODE_VECTOR_FLOAT:
+    case MODE_VECTOR_FRACT:
+    case MODE_VECTOR_UFRACT:
+    case MODE_VECTOR_ACCUM:
+    case MODE_VECTOR_UACCUM:
       nunits = GET_MODE_NUNITS (mode);
       break;
 
@@ -7518,6 +7707,9 @@ initializer_zerop (const_tree init)
       return real_zerop (init)
        && ! REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (init));
 
+    case FIXED_CST:
+      return fixed_zerop (init);
+
     case COMPLEX_CST:
       return integer_zerop (init)
        || (real_zerop (init)
@@ -7787,7 +7979,7 @@ range_in_array_bounds_p (tree ref)
    location.  */
 
 bool
-needs_to_live_in_memory (tree t)
+needs_to_live_in_memory (const_tree t)
 {
   if (TREE_CODE (t) == SSA_NAME)
     t = SSA_NAME_VAR (t);
@@ -7803,7 +7995,7 @@ needs_to_live_in_memory (tree t)
    are compatible.  It is assumed that the parent records are compatible.  */
 
 bool
-fields_compatible_p (tree f1, tree f2)
+fields_compatible_p (const_tree f1, const_tree f2)
 {
   if (!operand_equal_p (DECL_FIELD_BIT_OFFSET (f1),
                        DECL_FIELD_BIT_OFFSET (f2), OEP_ONLY_CONST))
@@ -8010,7 +8202,7 @@ lower_bound_in_type (tree outer, tree inner)
    and get the same result, only slower.  */
 
 int
-operand_equal_for_phi_arg_p (tree arg0, tree arg1)
+operand_equal_for_phi_arg_p (const_tree arg0, const_tree arg1)
 {
   if (arg0 == arg1)
     return 1;
@@ -8061,7 +8253,7 @@ num_ending_zeros (const_tree x)
 #define WALK_SUBTREE(NODE)                             \
   do                                                   \
     {                                                  \
-      result = walk_tree (&(NODE), func, data, pset);  \
+      result = walk_tree_1 (&(NODE), func, data, pset, lh);    \
       if (result)                                      \
        return result;                                  \
     }                                                  \
@@ -8073,7 +8265,7 @@ num_ending_zeros (const_tree x)
 
 static tree
 walk_type_fields (tree type, walk_tree_fn func, void *data,
-                 struct pointer_set_t *pset)
+                 struct pointer_set_t *pset, walk_tree_lh lh)
 {
   tree result = NULL_TREE;
 
@@ -8153,7 +8345,8 @@ walk_type_fields (tree type, walk_tree_fn func, void *data,
    and to avoid visiting a node more than once.  */
 
 tree
-walk_tree (tree *tp, walk_tree_fn func, void *data, struct pointer_set_t *pset)
+walk_tree_1 (tree *tp, walk_tree_fn func, void *data,
+            struct pointer_set_t *pset, walk_tree_lh lh)
 {
   enum tree_code code;
   int walk_subtrees;
@@ -8200,10 +8393,12 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, struct pointer_set_t *pset)
        return NULL_TREE;
     }
 
-  result = lang_hooks.tree_inlining.walk_subtrees (tp, &walk_subtrees, func,
-                                                  data, pset);
-  if (result || !walk_subtrees)
-    return result;
+  if (lh)
+    {
+      result = (*lh) (tp, &walk_subtrees, func, data, pset);
+      if (result || !walk_subtrees)
+        return result;
+    }
 
   switch (code)
     {
@@ -8211,6 +8406,7 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, struct pointer_set_t *pset)
     case IDENTIFIER_NODE:
     case INTEGER_CST:
     case REAL_CST:
+    case FIXED_CST:
     case VECTOR_CST:
     case STRING_CST:
     case BLOCK:
@@ -8356,7 +8552,7 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, struct pointer_set_t *pset)
          if (result || !walk_subtrees)
            return result;
 
-         result = walk_type_fields (*type_p, func, data, pset);
+         result = walk_type_fields (*type_p, func, data, pset, lh);
          if (result)
            return result;
 
@@ -8389,6 +8585,7 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, struct pointer_set_t *pset)
          else if (TREE_CODE (*type_p) == BOOLEAN_TYPE
                   || TREE_CODE (*type_p) == ENUMERAL_TYPE
                   || TREE_CODE (*type_p) == INTEGER_TYPE
+                  || TREE_CODE (*type_p) == FIXED_POINT_TYPE
                   || TREE_CODE (*type_p) == REAL_TYPE)
            {
              WALK_SUBTREE (TYPE_MIN_VALUE (*type_p));
@@ -8420,7 +8617,7 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, struct pointer_set_t *pset)
        }
       /* If this is a type, walk the needed fields in the type.  */
       else if (TYPE_P (*tp))
-       return walk_type_fields (*tp, func, data, pset);
+       return walk_type_fields (*tp, func, data, pset, lh);
       break;
     }
 
@@ -8434,13 +8631,14 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, struct pointer_set_t *pset)
 /* Like walk_tree, but does not walk duplicate nodes more than once.  */
 
 tree
-walk_tree_without_duplicates (tree *tp, walk_tree_fn func, void *data)
+walk_tree_without_duplicates_1 (tree *tp, walk_tree_fn func, void *data,
+                               walk_tree_lh lh)
 {
   tree result;
   struct pointer_set_t *pset;
 
   pset = pointer_set_create ();
-  result = walk_tree (tp, func, data, pset);
+  result = walk_tree_1 (tp, func, data, pset, lh);
   pointer_set_destroy (pset);
   return result;
 }
@@ -8450,10 +8648,10 @@ walk_tree_without_duplicates (tree *tp, walk_tree_fn func, void *data)
    empty statements.  */
 
 bool
-empty_body_p (tree stmt)
+empty_body_p (const_tree stmt)
 {
-  tree_stmt_iterator i;
-  tree body;
+  const_tree_stmt_iterator i;
+  const_tree body;
 
   if (IS_EMPTY_STMT (stmt))
     return true;
@@ -8464,8 +8662,8 @@ empty_body_p (tree stmt)
   else
     return false;
 
-  for (i = tsi_start (body); !tsi_end_p (i); tsi_next (&i))
-    if (!empty_body_p (tsi_stmt (i)))
+  for (i = ctsi_start (body); !ctsi_end_p (i); ctsi_next (&i))
+    if (!empty_body_p (ctsi_stmt (i)))
       return false;
 
   return true;