"random kinds",
"lang_decl kinds",
"lang_type kinds",
- "omp clauses"
+ "omp clauses",
+ "gimple statements"
};
#endif /* GATHER_STATISTICS */
tree_contains_struct[STRUCT_FIELD_TAG][TS_DECL_MINIMAL] = 1;
tree_contains_struct[NAME_MEMORY_TAG][TS_DECL_MINIMAL] = 1;
tree_contains_struct[SYMBOL_MEMORY_TAG][TS_DECL_MINIMAL] = 1;
+ tree_contains_struct[MEMORY_PARTITION_TAG][TS_DECL_MINIMAL] = 1;
tree_contains_struct[STRUCT_FIELD_TAG][TS_MEMORY_TAG] = 1;
tree_contains_struct[NAME_MEMORY_TAG][TS_MEMORY_TAG] = 1;
tree_contains_struct[SYMBOL_MEMORY_TAG][TS_MEMORY_TAG] = 1;
+ tree_contains_struct[MEMORY_PARTITION_TAG][TS_MEMORY_TAG] = 1;
tree_contains_struct[STRUCT_FIELD_TAG][TS_STRUCT_FIELD_TAG] = 1;
+ tree_contains_struct[MEMORY_PARTITION_TAG][TS_MEMORY_PARTITION_TAG] = 1;
tree_contains_struct[VAR_DECL][TS_DECL_WITH_VIS] = 1;
tree_contains_struct[FUNCTION_DECL][TS_DECL_WITH_VIS] = 1;
return DECL_WITH_VIS_CHECK (decl)->decl_with_vis.assembler_name;
}
+/* Compare ASMNAME with the DECL_ASSEMBLER_NAME of DECL. */
+
+bool
+decl_assembler_name_equal (tree decl, tree asmname)
+{
+ tree decl_asmname = DECL_ASSEMBLER_NAME (decl);
+
+ if (decl_asmname == asmname)
+ return true;
+
+ /* If the target assembler name was set by the user, things are trickier.
+ We have a leading '*' to begin with. After that, it's arguable what
+ is the correct thing to do with -fleading-underscore. Arguably, we've
+ historically been doing the wrong thing in assemble_alias by always
+ printing the leading underscore. Since we're not changing that, make
+ sure user_label_prefix follows the '*' before matching. */
+ if (IDENTIFIER_POINTER (decl_asmname)[0] == '*')
+ {
+ const char *decl_str = IDENTIFIER_POINTER (decl_asmname) + 1;
+ size_t ulp_len = strlen (user_label_prefix);
+
+ if (ulp_len == 0)
+ ;
+ else if (strncmp (decl_str, user_label_prefix, ulp_len) == 0)
+ decl_str += ulp_len;
+ else
+ return false;
+
+ return strcmp (decl_str, IDENTIFIER_POINTER (asmname)) == 0;
+ }
+
+ return false;
+}
+
/* Compute the number of bytes occupied by a tree with code CODE.
This function cannot be used for TREE_VEC, PHI_NODE, or STRING_CST
codes, which are of variable length. */
return sizeof (struct tree_memory_tag);
case STRUCT_FIELD_TAG:
return sizeof (struct tree_struct_field_tag);
+ case MEMORY_PARTITION_TAG:
+ return sizeof (struct tree_memory_partition_tag);
default:
return sizeof (struct tree_decl_non_common);
}
return (sizeof (struct tree_exp)
+ (TREE_CODE_LENGTH (code) - 1) * sizeof (char *));
+ case tcc_gimple_stmt:
+ return (sizeof (struct gimple_stmt)
+ + (TREE_CODE_LENGTH (code) - 1) * sizeof (char *));
+
case tcc_constant: /* a constant */
switch (code)
{
kind = c_kind;
break;
+ case tcc_gimple_stmt:
+ kind = gimple_stmt_kind;
+ break;
+
case tcc_exceptional: /* something random, like an identifier. */
switch (code)
{
TYPE_ALIGN (t) = BITS_PER_UNIT;
TYPE_USER_ALIGN (t) = 0;
TYPE_MAIN_VARIANT (t) = t;
+ TYPE_CANONICAL (t) = t;
/* Default to no attributes for type, but let target change that. */
TYPE_ATTRIBUTES (t) = NULL_TREE;
}
break;
+ case tcc_gimple_stmt:
+ switch (code)
+ {
+ case GIMPLE_MODIFY_STMT:
+ TREE_SIDE_EFFECTS (t) = 1;
+ break;
+
+ default:
+ break;
+ }
+
default:
/* Other classes need no special treatment. */
break;
t = ggc_alloc_zone_pass_stat (length, &tree_zone);
memcpy (t, node, length);
- TREE_CHAIN (t) = 0;
+ if (!GIMPLE_TUPLE_P (node))
+ TREE_CHAIN (t) = 0;
TREE_ASM_WRITTEN (t) = 0;
TREE_VISITED (t) = 0;
- t->common.ann = 0;
+ t->base.ann = 0;
if (TREE_CODE_CLASS (code) == tcc_declaration)
{
tree
build_int_cst (tree type, HOST_WIDE_INT low)
{
+ /* Support legacy code. */
+ if (!type)
+ type = integer_type_node;
+
return build_int_cst_wide (type, low, low < 0 ? -1 : 0);
}
tree
build_int_cst_type (tree type, HOST_WIDE_INT low)
{
- unsigned HOST_WIDE_INT val = (unsigned HOST_WIDE_INT) low;
- unsigned HOST_WIDE_INT hi, mask;
- unsigned bits;
- bool signed_p;
- bool negative;
-
- if (!type)
- type = integer_type_node;
-
- bits = TYPE_PRECISION (type);
- signed_p = !TYPE_UNSIGNED (type);
-
- if (bits >= HOST_BITS_PER_WIDE_INT)
- negative = (low < 0);
- else
- {
- /* If the sign bit is inside precision of LOW, use it to determine
- the sign of the constant. */
- negative = ((val >> (bits - 1)) & 1) != 0;
+ unsigned HOST_WIDE_INT low1;
+ HOST_WIDE_INT hi;
- /* Mask out the bits outside of the precision of the constant. */
- mask = (((unsigned HOST_WIDE_INT) 2) << (bits - 1)) - 1;
+ gcc_assert (type);
- if (signed_p && negative)
- val |= ~mask;
- else
- val &= mask;
- }
+ fit_double_type (low, low < 0 ? -1 : 0, &low1, &hi, type);
- /* Determine the high bits. */
- hi = (negative ? ~(unsigned HOST_WIDE_INT) 0 : 0);
+ return build_int_cst_wide (type, low1, hi);
+}
- /* For unsigned type we need to mask out the bits outside of the type
- precision. */
- if (!signed_p)
- {
- if (bits <= HOST_BITS_PER_WIDE_INT)
- hi = 0;
- else
- {
- bits -= HOST_BITS_PER_WIDE_INT;
- mask = (((unsigned HOST_WIDE_INT) 2) << (bits - 1)) - 1;
- hi &= mask;
- }
- }
+/* Create an INT_CST node of TYPE and value HI:LOW. The value is truncated
+ and sign extended according to the value range of TYPE. */
- return build_int_cst_wide (type, val, hi);
+tree
+build_int_cst_wide_type (tree type,
+ unsigned HOST_WIDE_INT low, HOST_WIDE_INT high)
+{
+ fit_double_type (low, high, &low, &high, type);
+ return build_int_cst_wide (type, low, high);
}
/* These are the hash table functions for the hash table of INTEGER_CST
&& TREE_INT_CST_LOW (xt) == TREE_INT_CST_LOW (yt));
}
-/* Create an INT_CST node of TYPE and value HI:LOW. If TYPE is NULL,
- integer_type_node is used. The returned node is always shared.
- For small integers we use a per-type vector cache, for larger ones
- we use a single hash table. */
+/* Create an INT_CST node of TYPE and value HI:LOW.
+ The returned node is always shared. For small integers we use a
+ per-type vector cache, for larger ones we use a single hash table. */
tree
build_int_cst_wide (tree type, unsigned HOST_WIDE_INT low, HOST_WIDE_INT hi)
int ix = -1;
int limit = 0;
- if (!type)
- type = integer_type_node;
+ gcc_assert (type);
switch (TREE_CODE (type))
{
return size_zero_node;
}
- if (TREE_CODE (t) == INTEGER_CST)
- t = force_fit_type (t, 0, false, false);
-
return t;
}
align1 = TYPE_ALIGN (TREE_TYPE (t));
return MAX (align0, align1);
- case SAVE_EXPR: case COMPOUND_EXPR: case MODIFY_EXPR:
+ case MODIFY_EXPR:
+ /* FIXME tuples: It is unclear to me if this function, which
+ is only called from ADA, is called on gimple or non gimple
+ trees. Let's assume it's from gimple trees unless we hit
+ this abort. */
+ gcc_unreachable ();
+
+ case SAVE_EXPR: case COMPOUND_EXPR: case GIMPLE_MODIFY_STMT:
case INIT_EXPR: case TARGET_EXPR: case WITH_CLEANUP_EXPR:
case CLEANUP_POINT_EXPR:
/* These don't change the alignment of an object. */
case SYMBOL_MEMORY_TAG:
case NAME_MEMORY_TAG:
case STRUCT_FIELD_TAG:
+ case MEMORY_PARTITION_TAG:
return TS_MEMORY_TAG;
default:
return TS_DECL_NON_COMMON;
case tcc_expression:
case tcc_statement:
return TS_EXP;
+ case tcc_gimple_stmt:
+ return TS_GIMPLE_STATEMENT;
default: /* tcc_constant and tcc_exceptional */
break;
}
case VECTOR_CST: return TS_VECTOR;
case STRING_CST: return TS_STRING;
/* tcc_exceptional cases. */
+ /* FIXME tuples: eventually this should be TS_BASE. For now, nothing
+ returns TS_BASE. */
case ERROR_MARK: return TS_COMMON;
case IDENTIFIER_NODE: return TS_IDENTIFIER;
case TREE_LIST: return TS_LIST;
gcc_assert (TREE_CODE_LENGTH (code) == 2);
+ if (code == MODIFY_EXPR && cfun && cfun->gimplified)
+ {
+ /* We should be talking GIMPLE_MODIFY_STMT by now. */
+ gcc_unreachable ();
+ }
+
+ /* FIXME tuples: For now let's be lazy; later we must rewrite all
+ build2 calls to build2_gimple calls. */
+ if (TREE_CODE_CLASS (code) == tcc_gimple_stmt)
+ return build2_gimple (code, arg0, arg1);
+
t = make_node_stat (code PASS_MEM_STAT);
TREE_TYPE (t) = tt;
return t;
}
+
+/* Similar as build2_stat, but for GIMPLE tuples. For convenience's sake,
+ arguments and return type are trees. */
+
+tree
+build2_gimple_stat (enum tree_code code, tree arg0, tree arg1 MEM_STAT_DECL)
+{
+ bool side_effects;
+ tree t;
+
+ gcc_assert (TREE_CODE_LENGTH (code) == 2);
+
+ t = make_node_stat (code PASS_MEM_STAT);
+
+ side_effects = TREE_SIDE_EFFECTS (t);
+
+ /* ?? We don't care about setting flags for tuples... */
+ GIMPLE_STMT_OPERAND (t, 0) = arg0;
+ GIMPLE_STMT_OPERAND (t, 1) = arg1;
+
+ /* ...except perhaps side_effects and volatility. ?? */
+ TREE_SIDE_EFFECTS (t) = side_effects;
+ TREE_THIS_VOLATILE (t) = (TREE_CODE_CLASS (code) == tcc_reference
+ && arg0 && TREE_THIS_VOLATILE (arg0));
+
+
+ return t;
+}
+
tree
build3_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
tree arg2 MEM_STAT_DECL)
}
#endif
\f
+/* Source location accessor functions. */
+
+
+/* The source location of this expression. Non-tree_exp nodes such as
+ decls and constants can be shared among multiple locations, so
+ return nothing. */
+location_t
+expr_location (tree node)
+{
+#ifdef USE_MAPPED_LOCATION
+ if (GIMPLE_STMT_P (node))
+ return GIMPLE_STMT_LOCUS (node);
+ return EXPR_P (node) ? node->exp.locus : UNKNOWN_LOCATION;
+#else
+ if (GIMPLE_STMT_P (node))
+ return EXPR_HAS_LOCATION (node)
+ ? *GIMPLE_STMT_LOCUS (node) : UNKNOWN_LOCATION;
+ return EXPR_HAS_LOCATION (node) ? *node->exp.locus : UNKNOWN_LOCATION;
+#endif
+}
+
+void
+set_expr_location (tree node, location_t locus)
+{
+#ifdef USE_MAPPED_LOCATION
+ if (GIMPLE_STMT_P (node))
+ GIMPLE_STMT_LOCUS (node) = locus;
+ else
+ EXPR_CHECK (node)->exp.locus = locus;
+#else
+ annotate_with_locus (node, locus);
+#endif
+}
+
+bool
+expr_has_location (tree node)
+{
+#ifdef USE_MAPPED_LOCATION
+ return expr_location (node) != UNKNOWN_LOCATION;
+#else
+ return expr_locus (node) != NULL;
+#endif
+}
+
+#ifdef USE_MAPPED_LOCATION
+source_location *
+#else
+source_locus
+#endif
+expr_locus (tree node)
+{
+#ifdef USE_MAPPED_LOCATION
+ if (GIMPLE_STMT_P (node))
+ return &GIMPLE_STMT_LOCUS (node);
+ return EXPR_P (node) ? &node->exp.locus : (location_t *) NULL;
+#else
+ if (GIMPLE_STMT_P (node))
+ return GIMPLE_STMT_LOCUS (node);
+ /* ?? The cast below was originally "(location_t *)" in the macro,
+ but that makes no sense. ?? */
+ return EXPR_P (node) ? node->exp.locus : (source_locus) NULL;
+#endif
+}
+
+void
+set_expr_locus (tree node,
+#ifdef USE_MAPPED_LOCATION
+ source_location *loc
+#else
+ source_locus loc
+#endif
+ )
+{
+#ifdef USE_MAPPED_LOCATION
+ if (loc == NULL)
+ {
+ if (GIMPLE_STMT_P (node))
+ GIMPLE_STMT_LOCUS (node) = UNKNOWN_LOCATION;
+ else
+ EXPR_CHECK (node)->exp.locus = UNKNOWN_LOCATION;
+ }
+ else
+ {
+ if (GIMPLE_STMT_P (node))
+ GIMPLE_STMT_LOCUS (node) = *loc;
+ else
+ EXPR_CHECK (node)->exp.locus = *loc;
+ }
+#else
+ if (GIMPLE_STMT_P (node))
+ GIMPLE_STMT_LOCUS (node) = loc;
+ else
+ EXPR_CHECK (node)->exp.locus = loc;
+#endif
+}
+
+const char **
+expr_filename (tree node)
+{
+#ifdef USE_MAPPED_LOCATION
+ if (GIMPLE_STMT_P (node))
+ return &LOCATION_FILE (GIMPLE_STMT_LOCUS (node));
+ return &LOCATION_FILE (EXPR_CHECK (node)->exp.locus);
+#else
+ if (GIMPLE_STMT_P (node))
+ return &GIMPLE_STMT_LOCUS (node)->file;
+ return &(EXPR_CHECK (node)->exp.locus->file);
+#endif
+}
+
+int *
+expr_lineno (tree node)
+{
+#ifdef USE_MAPPED_LOCATION
+ if (GIMPLE_STMT_P (node))
+ return &LOCATION_LINE (GIMPLE_STMT_LOCUS (node));
+ return &LOCATION_LINE (EXPR_CHECK (node)->exp.locus);
+#else
+ if (GIMPLE_STMT_P (node))
+ return &GIMPLE_STMT_LOCUS (node)->line;
+ return &EXPR_CHECK (node)->exp.locus->line;
+#endif
+}
+\f
/* Return a declaration like DDECL except that its DECL_ATTRIBUTES
is ATTRIBUTE. */
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;
}
ntype = type_hash_canon (hashcode, ntype);
+
+ /* 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))
+ SET_TYPE_STRUCTURAL_EQUALITY (ntype);
+
ttype = build_qualified_type (ntype, quals);
}
{
t = build_variant_type_copy (type);
set_type_quals (t, type_quals);
+
+ if (TYPE_STRUCTURAL_EQUALITY_P (type))
+ /* Propagate structural equality. */
+ SET_TYPE_STRUCTURAL_EQUALITY (t);
+ else if (TYPE_CANONICAL (type) != type)
+ /* Build the underlying canonical type, since it is different
+ from TYPE. */
+ TYPE_CANONICAL (t) = build_qualified_type (TYPE_CANONICAL (type),
+ type_quals);
+ else
+ /* T is its own canonical type. */
+ TYPE_CANONICAL (t) = t;
+
}
return t;
}
/* Create a new distinct copy of TYPE. The new type is made its own
- MAIN_VARIANT. */
+ MAIN_VARIANT. If TYPE requires structural equality checks, the
+ resulting type requires structural equality checks; otherwise, its
+ TYPE_CANONICAL points to itself. */
tree
build_distinct_type_copy (tree type)
TYPE_POINTER_TO (t) = 0;
TYPE_REFERENCE_TO (t) = 0;
+ /* Set the canonical type either to a new equivalence class, or
+ propagate the need for structural equality checks. */
+ if (TYPE_STRUCTURAL_EQUALITY_P (type))
+ SET_TYPE_STRUCTURAL_EQUALITY (t);
+ else
+ TYPE_CANONICAL (t) = t;
+
/* Make it its own variant. */
TYPE_MAIN_VARIANT (t) = t;
TYPE_NEXT_VARIANT (t) = 0;
return t;
}
-/* Create a new variant of TYPE, equivalent but distinct.
- This is so the caller can modify it. */
+/* Create a new variant of TYPE, equivalent but distinct. This is so
+ the caller can modify it. TYPE_CANONICAL for the return type will
+ be equivalent to TYPE_CANONICAL of TYPE, indicating that the types
+ are considered equal by the language itself (or that both types
+ require structural equality checks). */
tree
build_variant_type_copy (tree type)
tree t, m = TYPE_MAIN_VARIANT (type);
t = build_distinct_type_copy (type);
+
+ /* Since we're building a variant, assume that it is a non-semantic
+ variant. This also propagates TYPE_STRUCTURAL_EQUALITY_P. */
+ TYPE_CANONICAL (t) = TYPE_CANONICAL (type);
/* Add the new type to the chain of variants of TYPE. */
TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m);
TYPE_NEXT_PTR_TO (t) = TYPE_POINTER_TO (to_type);
TYPE_POINTER_TO (to_type) = t;
+ if (TYPE_STRUCTURAL_EQUALITY_P (to_type))
+ SET_TYPE_STRUCTURAL_EQUALITY (t);
+ else if (TYPE_CANONICAL (to_type) != to_type)
+ TYPE_CANONICAL (t)
+ = build_pointer_type_for_mode (TYPE_CANONICAL (to_type),
+ mode, can_alias_all);
+
/* Lay out the type. This function has many callers that are concerned
with expression-construction, and this simplifies them all. */
layout_type (t);
TYPE_NEXT_REF_TO (t) = TYPE_REFERENCE_TO (to_type);
TYPE_REFERENCE_TO (to_type) = t;
+ if (TYPE_STRUCTURAL_EQUALITY_P (to_type))
+ SET_TYPE_STRUCTURAL_EQUALITY (t);
+ else if (TYPE_CANONICAL (to_type) != to_type)
+ TYPE_CANONICAL (t)
+ = build_reference_type_for_mode (TYPE_CANONICAL (to_type),
+ mode, can_alias_all);
+
layout_type (t);
return t;
if (host_integerp (maxval, 1))
return type_hash_canon (tree_low_cst (maxval, 1), itype);
else
- return itype;
+ {
+ /* Since we cannot hash this type, we need to compare it using
+ structural equality checks. */
+ SET_TYPE_STRUCTURAL_EQUALITY (itype);
+ return itype;
+ }
}
/* Builds a signed or unsigned integer type of precision PRECISION.
t = type_hash_canon (hashcode, t);
if (save == t)
layout_type (t);
+
+ if (TYPE_CANONICAL (t) == t)
+ {
+ if (TYPE_STRUCTURAL_EQUALITY_P (elt_type))
+ SET_TYPE_STRUCTURAL_EQUALITY (t);
+ else if (TYPE_CANONICAL (elt_type) != elt_type)
+ TYPE_CANONICAL (t)
+ = build_array_type (TYPE_CANONICAL (elt_type), index_type);
+ }
+
return t;
}
if (!COMPLETE_TYPE_P (t))
layout_type (t);
+
+ if (TYPE_CANONICAL (t) == t)
+ {
+ if (TYPE_STRUCTURAL_EQUALITY_P (elt_type)
+ || TYPE_STRUCTURAL_EQUALITY_P (index_type))
+ SET_TYPE_STRUCTURAL_EQUALITY (t);
+ else if (TYPE_CANONICAL (elt_type) != elt_type
+ || TYPE_CANONICAL (index_type) != index_type)
+ TYPE_CANONICAL (t)
+ = build_array_type (TYPE_CANONICAL (elt_type),
+ TYPE_CANONICAL (index_type));
+ }
+
return t;
}
TREE_TYPE (t) = value_type;
TYPE_ARG_TYPES (t) = arg_types;
+ /* We don't have canonicalization of function types, yet. */
+ SET_TYPE_STRUCTURAL_EQUALITY (t);
+
/* If we already have such a type, use the old one. */
hashcode = iterative_hash_object (TYPE_HASH (value_type), hashcode);
hashcode = type_hash_list (arg_types, hashcode);
argtypes = tree_cons (NULL_TREE, ptype, argtypes);
TYPE_ARG_TYPES (t) = argtypes;
+ /* We don't have canonicalization of method types yet. */
+ SET_TYPE_STRUCTURAL_EQUALITY (t);
+
/* If we already have such a type, use the old one. */
hashcode = iterative_hash_object (TYPE_HASH (basetype), hashcode);
hashcode = iterative_hash_object (TYPE_HASH (rettype), hashcode);
if (!COMPLETE_TYPE_P (t))
layout_type (t);
+ if (TYPE_CANONICAL (t) == t)
+ {
+ if (TYPE_STRUCTURAL_EQUALITY_P (basetype)
+ || TYPE_STRUCTURAL_EQUALITY_P (type))
+ SET_TYPE_STRUCTURAL_EQUALITY (t);
+ else if (TYPE_CANONICAL (basetype) != basetype
+ || TYPE_CANONICAL (type) != type)
+ TYPE_CANONICAL (t)
+ = build_offset_type (TYPE_CANONICAL (basetype),
+ TYPE_CANONICAL (type));
+ }
+
return t;
}
if (!COMPLETE_TYPE_P (t))
layout_type (t);
+ if (TYPE_CANONICAL (t) == t)
+ {
+ if (TYPE_STRUCTURAL_EQUALITY_P (component_type))
+ SET_TYPE_STRUCTURAL_EQUALITY (t);
+ else if (TYPE_CANONICAL (component_type) != component_type)
+ TYPE_CANONICAL (t)
+ = build_complex_type (TYPE_CANONICAL (component_type));
+ }
+
/* If we are writing Dwarf2 output we need to create a name,
since complex is a fundamental type. */
if ((write_symbols == DWARF2_DEBUG || write_symbols == VMS_AND_DWARF2_DEBUG)
{
if (first)
uns = DECL_UNSIGNED (TREE_OPERAND (op, 1));
- win = build3 (COMPONENT_REF, type, TREE_OPERAND (op, 0),
- TREE_OPERAND (op, 1), NULL_TREE);
- TREE_SIDE_EFFECTS (win) = TREE_SIDE_EFFECTS (op);
- TREE_THIS_VOLATILE (win) = TREE_THIS_VOLATILE (op);
+ win = fold_convert (type, op);
}
}
+
*unsignedp_ptr = uns;
return win;
}
tree type_low_bound = TYPE_MIN_VALUE (type);
tree type_high_bound = TYPE_MAX_VALUE (type);
bool ok_for_low_bound, ok_for_high_bound;
- tree tmp;
+ unsigned HOST_WIDE_INT low;
+ HOST_WIDE_INT high;
/* If at least one bound of the type is a constant integer, we can check
ourselves and maybe make a decision. If no such decision is possible, but
this type is a subtype, try checking against that. Otherwise, use
- force_fit_type, which checks against the precision.
+ fit_double_type, which checks against the precision.
Compute the status for each possibly constant bound, and return if we see
one does not match. Use ok_for_xxx_bound for this purpose, assigning -1
&& TYPE_PRECISION (type) == TYPE_PRECISION (TREE_TYPE (type)))
return int_fits_type_p (c, TREE_TYPE (type));
- /* Or to force_fit_type, if nothing else. */
- tmp = copy_node (c);
- TREE_TYPE (tmp) = type;
- tmp = force_fit_type (tmp, -1, false, false);
- return TREE_INT_CST_HIGH (tmp) == TREE_INT_CST_HIGH (c)
- && TREE_INT_CST_LOW (tmp) == TREE_INT_CST_LOW (c);
+ /* Or to fit_double_type, if nothing else. */
+ low = TREE_INT_CST_LOW (c);
+ high = TREE_INT_CST_HIGH (c);
+ return !fit_double_type (low, high, &low, &high, type);
}
/* Subprogram of following function. Called by walk_tree.
TYPE_READONLY (t) = TYPE_READONLY (innertype);
TYPE_VOLATILE (t) = TYPE_VOLATILE (innertype);
+ if (TYPE_STRUCTURAL_EQUALITY_P (innertype))
+ SET_TYPE_STRUCTURAL_EQUALITY (t);
+ else if (TYPE_CANONICAL (innertype) != innertype
+ || mode != VOIDmode)
+ TYPE_CANONICAL (t)
+ = make_vector_type (TYPE_CANONICAL (innertype), nunits, VOIDmode);
+
layout_type (t);
{
declare the type to be __builtin_va_list. */
if (TREE_CODE (t) != RECORD_TYPE)
t = build_variant_type_copy (t);
-
+
va_list_type_node = t;
}
}
bool
needs_to_live_in_memory (tree t)
{
+ if (TREE_CODE (t) == SSA_NAME)
+ t = SSA_NAME_VAR (t);
+
return (TREE_ADDRESSABLE (t)
|| is_global_var (t)
|| (TREE_CODE (t) == RESULT_DECL
/* FALLTHRU */
default:
- if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code)))
+ if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code))
+ || IS_GIMPLE_STMT_CODE_CLASS (TREE_CODE_CLASS (code)))
{
int i, len;
if (len)
{
for (i = 0; i < len - 1; ++i)
- WALK_SUBTREE (TREE_OPERAND (*tp, i));
- WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, len - 1));
+ WALK_SUBTREE (GENERIC_TREE_OPERAND (*tp, i));
+ WALK_SUBTREE_TAIL (GENERIC_TREE_OPERAND (*tp, len - 1));
}
}
-
/* 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 true;
}
+tree *
+tree_block (tree t)
+{
+ char const c = TREE_CODE_CLASS (TREE_CODE (t));
+
+ if (IS_EXPR_CODE_CLASS (c))
+ return &t->exp.block;
+ else if (IS_GIMPLE_STMT_CODE_CLASS (c))
+ return &GIMPLE_STMT_BLOCK (t);
+ gcc_unreachable ();
+ return NULL;
+}
+
+tree *
+generic_tree_operand (tree node, int i)
+{
+ if (GIMPLE_STMT_P (node))
+ return &GIMPLE_STMT_OPERAND (node, i);
+ return &TREE_OPERAND (node, i);
+}
+
+tree *
+generic_tree_type (tree node)
+{
+ if (GIMPLE_STMT_P (node))
+ return &void_type_node;
+ return &TREE_TYPE (node);
+}
+
#include "gt-tree.h"