#include "output.h"
#include "target.h"
#include "langhooks.h"
+#include "tree-inline.h"
#include "tree-iterator.h"
#include "basic-block.h"
#include "tree-flow.h"
param_is (struct tree_priority_map)))
htab_t init_priority_for_decl;
-static GTY ((if_marked ("tree_map_marked_p"), param_is (struct tree_map)))
- htab_t restrict_base_for_decl;
-
static void set_type_quals (tree, int);
static int type_hash_eq (const void *, const void *);
static hashval_t type_hash_hash (const void *);
"collapse",
"untied"
};
-\f
+
+
+/* Return the tree node structure used by tree code CODE. */
+
+static inline enum tree_node_structure_enum
+tree_node_structure_for_code (enum tree_code code)
+{
+ switch (TREE_CODE_CLASS (code))
+ {
+ case tcc_declaration:
+ {
+ switch (code)
+ {
+ case FIELD_DECL:
+ return TS_FIELD_DECL;
+ case PARM_DECL:
+ return TS_PARM_DECL;
+ case VAR_DECL:
+ return TS_VAR_DECL;
+ case LABEL_DECL:
+ return TS_LABEL_DECL;
+ case RESULT_DECL:
+ return TS_RESULT_DECL;
+ case CONST_DECL:
+ return TS_CONST_DECL;
+ case TYPE_DECL:
+ return TS_TYPE_DECL;
+ case FUNCTION_DECL:
+ return TS_FUNCTION_DECL;
+ default:
+ return TS_DECL_NON_COMMON;
+ }
+ }
+ case tcc_type:
+ return TS_TYPE;
+ case tcc_reference:
+ case tcc_comparison:
+ case tcc_unary:
+ case tcc_binary:
+ case tcc_expression:
+ case tcc_statement:
+ case tcc_vl_exp:
+ return TS_EXP;
+ default: /* tcc_constant and tcc_exceptional */
+ break;
+ }
+ switch (code)
+ {
+ /* 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;
+ /* tcc_exceptional cases. */
+ case ERROR_MARK: return TS_COMMON;
+ case IDENTIFIER_NODE: return TS_IDENTIFIER;
+ case TREE_LIST: return TS_LIST;
+ case TREE_VEC: return TS_VEC;
+ case SSA_NAME: return TS_SSA_NAME;
+ case PLACEHOLDER_EXPR: return TS_COMMON;
+ case STATEMENT_LIST: return TS_STATEMENT_LIST;
+ case BLOCK: return TS_BLOCK;
+ case CONSTRUCTOR: return TS_CONSTRUCTOR;
+ case TREE_BINFO: return TS_BINFO;
+ case OMP_CLAUSE: return TS_OMP_CLAUSE;
+ case OPTIMIZATION_NODE: return TS_OPTIMIZATION;
+ case TARGET_OPTION_NODE: return TS_TARGET_OPTION;
+
+ default:
+ gcc_unreachable ();
+ }
+}
+
+
+/* Initialize tree_contains_struct to describe the hierarchy of tree
+ nodes. */
+
+static void
+initialize_tree_contains_struct (void)
+{
+ unsigned i;
+
+#define MARK_TS_BASE(C) \
+ do { \
+ tree_contains_struct[C][TS_BASE] = 1; \
+ } while (0)
+
+#define MARK_TS_COMMON(C) \
+ do { \
+ MARK_TS_BASE (C); \
+ tree_contains_struct[C][TS_COMMON] = 1; \
+ } while (0)
+
+#define MARK_TS_DECL_MINIMAL(C) \
+ do { \
+ MARK_TS_COMMON (C); \
+ tree_contains_struct[C][TS_DECL_MINIMAL] = 1; \
+ } while (0)
+
+#define MARK_TS_DECL_COMMON(C) \
+ do { \
+ MARK_TS_DECL_MINIMAL (C); \
+ tree_contains_struct[C][TS_DECL_COMMON] = 1; \
+ } while (0)
+
+#define MARK_TS_DECL_WRTL(C) \
+ do { \
+ MARK_TS_DECL_COMMON (C); \
+ tree_contains_struct[C][TS_DECL_WRTL] = 1; \
+ } while (0)
+
+#define MARK_TS_DECL_WITH_VIS(C) \
+ do { \
+ MARK_TS_DECL_WRTL (C); \
+ tree_contains_struct[C][TS_DECL_WITH_VIS] = 1; \
+ } while (0)
+
+#define MARK_TS_DECL_NON_COMMON(C) \
+ do { \
+ MARK_TS_DECL_WITH_VIS (C); \
+ tree_contains_struct[C][TS_DECL_NON_COMMON] = 1; \
+ } while (0)
+
+ for (i = ERROR_MARK; i < LAST_AND_UNUSED_TREE_CODE; i++)
+ {
+ enum tree_code code;
+ enum tree_node_structure_enum ts_code;
+
+ code = (enum tree_code) i;
+ ts_code = tree_node_structure_for_code (code);
+
+ /* Mark the TS structure itself. */
+ tree_contains_struct[code][ts_code] = 1;
+
+ /* Mark all the structures that TS is derived from. */
+ switch (ts_code)
+ {
+ case TS_COMMON:
+ MARK_TS_BASE (code);
+ break;
+
+ case TS_INT_CST:
+ case TS_REAL_CST:
+ case TS_FIXED_CST:
+ case TS_VECTOR:
+ case TS_STRING:
+ case TS_COMPLEX:
+ case TS_IDENTIFIER:
+ case TS_DECL_MINIMAL:
+ case TS_TYPE:
+ case TS_LIST:
+ case TS_VEC:
+ case TS_EXP:
+ case TS_SSA_NAME:
+ case TS_BLOCK:
+ case TS_BINFO:
+ case TS_STATEMENT_LIST:
+ case TS_CONSTRUCTOR:
+ case TS_OMP_CLAUSE:
+ case TS_OPTIMIZATION:
+ case TS_TARGET_OPTION:
+ MARK_TS_COMMON (code);
+ break;
+
+ case TS_DECL_COMMON:
+ MARK_TS_DECL_MINIMAL (code);
+ break;
+
+ case TS_DECL_WRTL:
+ MARK_TS_DECL_COMMON (code);
+ break;
+
+ case TS_DECL_NON_COMMON:
+ MARK_TS_DECL_WITH_VIS (code);
+ break;
+
+ case TS_DECL_WITH_VIS:
+ case TS_PARM_DECL:
+ case TS_LABEL_DECL:
+ case TS_RESULT_DECL:
+ case TS_CONST_DECL:
+ MARK_TS_DECL_WRTL (code);
+ break;
+
+ case TS_FIELD_DECL:
+ MARK_TS_DECL_COMMON (code);
+ break;
+
+ case TS_VAR_DECL:
+ MARK_TS_DECL_WITH_VIS (code);
+ break;
+
+ case TS_TYPE_DECL:
+ case TS_FUNCTION_DECL:
+ MARK_TS_DECL_NON_COMMON (code);
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+ }
+
+ /* Basic consistency checks for attributes used in fold. */
+ gcc_assert (tree_contains_struct[FUNCTION_DECL][TS_DECL_NON_COMMON]);
+ gcc_assert (tree_contains_struct[TRANSLATION_UNIT_DECL][TS_DECL_NON_COMMON]);
+ gcc_assert (tree_contains_struct[TYPE_DECL][TS_DECL_NON_COMMON]);
+ gcc_assert (tree_contains_struct[CONST_DECL][TS_DECL_COMMON]);
+ gcc_assert (tree_contains_struct[VAR_DECL][TS_DECL_COMMON]);
+ gcc_assert (tree_contains_struct[PARM_DECL][TS_DECL_COMMON]);
+ gcc_assert (tree_contains_struct[RESULT_DECL][TS_DECL_COMMON]);
+ gcc_assert (tree_contains_struct[FUNCTION_DECL][TS_DECL_COMMON]);
+ gcc_assert (tree_contains_struct[TYPE_DECL][TS_DECL_COMMON]);
+ gcc_assert (tree_contains_struct[TRANSLATION_UNIT_DECL][TS_DECL_COMMON]);
+ gcc_assert (tree_contains_struct[LABEL_DECL][TS_DECL_COMMON]);
+ gcc_assert (tree_contains_struct[FIELD_DECL][TS_DECL_COMMON]);
+ gcc_assert (tree_contains_struct[CONST_DECL][TS_DECL_WRTL]);
+ gcc_assert (tree_contains_struct[VAR_DECL][TS_DECL_WRTL]);
+ gcc_assert (tree_contains_struct[PARM_DECL][TS_DECL_WRTL]);
+ gcc_assert (tree_contains_struct[RESULT_DECL][TS_DECL_WRTL]);
+ gcc_assert (tree_contains_struct[FUNCTION_DECL][TS_DECL_WRTL]);
+ gcc_assert (tree_contains_struct[LABEL_DECL][TS_DECL_WRTL]);
+ gcc_assert (tree_contains_struct[CONST_DECL][TS_DECL_MINIMAL]);
+ gcc_assert (tree_contains_struct[VAR_DECL][TS_DECL_MINIMAL]);
+ gcc_assert (tree_contains_struct[PARM_DECL][TS_DECL_MINIMAL]);
+ gcc_assert (tree_contains_struct[RESULT_DECL][TS_DECL_MINIMAL]);
+ gcc_assert (tree_contains_struct[FUNCTION_DECL][TS_DECL_MINIMAL]);
+ gcc_assert (tree_contains_struct[TYPE_DECL][TS_DECL_MINIMAL]);
+ gcc_assert (tree_contains_struct[TRANSLATION_UNIT_DECL][TS_DECL_MINIMAL]);
+ gcc_assert (tree_contains_struct[LABEL_DECL][TS_DECL_MINIMAL]);
+ gcc_assert (tree_contains_struct[FIELD_DECL][TS_DECL_MINIMAL]);
+ gcc_assert (tree_contains_struct[VAR_DECL][TS_DECL_WITH_VIS]);
+ gcc_assert (tree_contains_struct[FUNCTION_DECL][TS_DECL_WITH_VIS]);
+ gcc_assert (tree_contains_struct[TYPE_DECL][TS_DECL_WITH_VIS]);
+ gcc_assert (tree_contains_struct[TRANSLATION_UNIT_DECL][TS_DECL_WITH_VIS]);
+ gcc_assert (tree_contains_struct[VAR_DECL][TS_VAR_DECL]);
+ gcc_assert (tree_contains_struct[FIELD_DECL][TS_FIELD_DECL]);
+ gcc_assert (tree_contains_struct[PARM_DECL][TS_PARM_DECL]);
+ gcc_assert (tree_contains_struct[LABEL_DECL][TS_LABEL_DECL]);
+ gcc_assert (tree_contains_struct[RESULT_DECL][TS_RESULT_DECL]);
+ gcc_assert (tree_contains_struct[CONST_DECL][TS_CONST_DECL]);
+ gcc_assert (tree_contains_struct[TYPE_DECL][TS_TYPE_DECL]);
+ gcc_assert (tree_contains_struct[FUNCTION_DECL][TS_FUNCTION_DECL]);
+ gcc_assert (tree_contains_struct[IMPORTED_DECL][TS_DECL_MINIMAL]);
+ gcc_assert (tree_contains_struct[IMPORTED_DECL][TS_DECL_COMMON]);
+
+#undef MARK_TS_BASE
+#undef MARK_TS_COMMON
+#undef MARK_TS_DECL_MINIMAL
+#undef MARK_TS_DECL_COMMON
+#undef MARK_TS_DECL_WRTL
+#undef MARK_TS_DECL_WITH_VIS
+#undef MARK_TS_DECL_NON_COMMON
+}
+
+
/* Init tree.c. */
void
tree_map_eq, 0);
init_priority_for_decl = htab_create_ggc (512, tree_priority_map_hash,
tree_priority_map_eq, 0);
- restrict_base_for_decl = htab_create_ggc (256, tree_map_hash,
- tree_map_eq, 0);
int_cst_hash_table = htab_create_ggc (1024, int_cst_hash_hash,
int_cst_hash_eq, NULL);
cl_optimization_node = make_node (OPTIMIZATION_NODE);
cl_target_option_node = make_node (TARGET_OPTION_NODE);
- tree_contains_struct[FUNCTION_DECL][TS_DECL_NON_COMMON] = 1;
- tree_contains_struct[TRANSLATION_UNIT_DECL][TS_DECL_NON_COMMON] = 1;
- tree_contains_struct[TYPE_DECL][TS_DECL_NON_COMMON] = 1;
-
-
- tree_contains_struct[CONST_DECL][TS_DECL_COMMON] = 1;
- tree_contains_struct[VAR_DECL][TS_DECL_COMMON] = 1;
- tree_contains_struct[PARM_DECL][TS_DECL_COMMON] = 1;
- tree_contains_struct[RESULT_DECL][TS_DECL_COMMON] = 1;
- tree_contains_struct[FUNCTION_DECL][TS_DECL_COMMON] = 1;
- tree_contains_struct[TYPE_DECL][TS_DECL_COMMON] = 1;
- tree_contains_struct[TRANSLATION_UNIT_DECL][TS_DECL_COMMON] = 1;
- tree_contains_struct[LABEL_DECL][TS_DECL_COMMON] = 1;
- tree_contains_struct[FIELD_DECL][TS_DECL_COMMON] = 1;
-
-
- tree_contains_struct[CONST_DECL][TS_DECL_WRTL] = 1;
- tree_contains_struct[VAR_DECL][TS_DECL_WRTL] = 1;
- tree_contains_struct[PARM_DECL][TS_DECL_WRTL] = 1;
- tree_contains_struct[RESULT_DECL][TS_DECL_WRTL] = 1;
- tree_contains_struct[FUNCTION_DECL][TS_DECL_WRTL] = 1;
- tree_contains_struct[LABEL_DECL][TS_DECL_WRTL] = 1;
-
- tree_contains_struct[CONST_DECL][TS_DECL_MINIMAL] = 1;
- tree_contains_struct[VAR_DECL][TS_DECL_MINIMAL] = 1;
- tree_contains_struct[PARM_DECL][TS_DECL_MINIMAL] = 1;
- tree_contains_struct[RESULT_DECL][TS_DECL_MINIMAL] = 1;
- tree_contains_struct[FUNCTION_DECL][TS_DECL_MINIMAL] = 1;
- tree_contains_struct[TYPE_DECL][TS_DECL_MINIMAL] = 1;
- tree_contains_struct[TRANSLATION_UNIT_DECL][TS_DECL_MINIMAL] = 1;
- tree_contains_struct[LABEL_DECL][TS_DECL_MINIMAL] = 1;
- tree_contains_struct[FIELD_DECL][TS_DECL_MINIMAL] = 1;
-
- tree_contains_struct[VAR_DECL][TS_DECL_WITH_VIS] = 1;
- tree_contains_struct[FUNCTION_DECL][TS_DECL_WITH_VIS] = 1;
- tree_contains_struct[TYPE_DECL][TS_DECL_WITH_VIS] = 1;
- tree_contains_struct[TRANSLATION_UNIT_DECL][TS_DECL_WITH_VIS] = 1;
-
- tree_contains_struct[VAR_DECL][TS_VAR_DECL] = 1;
- tree_contains_struct[FIELD_DECL][TS_FIELD_DECL] = 1;
- tree_contains_struct[PARM_DECL][TS_PARM_DECL] = 1;
- tree_contains_struct[LABEL_DECL][TS_LABEL_DECL] = 1;
- tree_contains_struct[RESULT_DECL][TS_RESULT_DECL] = 1;
- tree_contains_struct[CONST_DECL][TS_CONST_DECL] = 1;
- tree_contains_struct[TYPE_DECL][TS_TYPE_DECL] = 1;
- tree_contains_struct[FUNCTION_DECL][TS_FUNCTION_DECL] = 1;
- tree_contains_struct[IMPORTED_DECL][TS_DECL_MINIMAL] = 1;
- tree_contains_struct[IMPORTED_DECL][TS_DECL_COMMON] = 1;
-
+ /* Initialize the tree_contains_struct array. */
+ initialize_tree_contains_struct ();
lang_hooks.init_ts ();
}
}
else
DECL_ALIGN (t) = 1;
- /* We have not yet computed the alias set for this declaration. */
- DECL_POINTER_ALIAS_SET (t) = -1;
}
DECL_SOURCE_LOCATION (t) = input_location;
DECL_UID (t) = next_decl_uid++;
+ if (TREE_CODE (t) == LABEL_DECL)
+ LABEL_DECL_UID (t) = -1;
break;
SET_DECL_INIT_PRIORITY (t, DECL_INIT_PRIORITY (node));
DECL_HAS_INIT_PRIORITY_P (t) = 1;
}
- if (TREE_CODE (node) == VAR_DECL && DECL_BASED_ON_RESTRICT_P (node))
- {
- SET_DECL_RESTRICT_BASE (t, DECL_GET_RESTRICT_BASE (node));
- DECL_BASED_ON_RESTRICT_P (t) = 1;
- }
}
else if (TREE_CODE_CLASS (code) == tcc_type)
{
: floor_log2 (low));
}
-/* Return 1 if EXPR is the real constant zero. */
+/* Return 1 if EXPR is the real constant zero. Trailing zeroes matter for
+ decimal float constants, so don't return 1 for them. */
int
real_zerop (const_tree expr)
STRIP_NOPS (expr);
return ((TREE_CODE (expr) == REAL_CST
- && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconst0))
+ && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconst0)
+ && !(DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (expr)))))
|| (TREE_CODE (expr) == COMPLEX_CST
&& real_zerop (TREE_REALPART (expr))
&& real_zerop (TREE_IMAGPART (expr))));
}
-/* Return 1 if EXPR is the real constant one in real or complex form. */
+/* Return 1 if EXPR is the real constant one in real or complex form.
+ Trailing zeroes matter for decimal float constants, so don't return
+ 1 for them. */
int
real_onep (const_tree expr)
STRIP_NOPS (expr);
return ((TREE_CODE (expr) == REAL_CST
- && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconst1))
+ && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconst1)
+ && !(DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (expr)))))
|| (TREE_CODE (expr) == COMPLEX_CST
&& real_onep (TREE_REALPART (expr))
&& real_zerop (TREE_IMAGPART (expr))));
}
-/* Return 1 if EXPR is the real constant two. */
+/* Return 1 if EXPR is the real constant two. Trailing zeroes matter
+ for decimal float constants, so don't return 1 for them. */
int
real_twop (const_tree expr)
STRIP_NOPS (expr);
return ((TREE_CODE (expr) == REAL_CST
- && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconst2))
+ && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconst2)
+ && !(DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (expr)))))
|| (TREE_CODE (expr) == COMPLEX_CST
&& real_twop (TREE_REALPART (expr))
&& real_zerop (TREE_IMAGPART (expr))));
}
-/* Return 1 if EXPR is the real constant minus one. */
+/* Return 1 if EXPR is the real constant minus one. Trailing zeroes
+ matter for decimal float constants, so don't return 1 for them. */
int
real_minus_onep (const_tree expr)
STRIP_NOPS (expr);
return ((TREE_CODE (expr) == REAL_CST
- && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconstm1))
+ && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconstm1)
+ && !(DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (expr)))))
|| (TREE_CODE (expr) == COMPLEX_CST
&& real_minus_onep (TREE_REALPART (expr))
&& real_zerop (TREE_IMAGPART (expr))));
return t;
}
+/* Build a chain of TREE_LIST nodes from a vector. */
+
+tree
+build_tree_list_vec_stat (const VEC(tree,gc) *vec MEM_STAT_DECL)
+{
+ tree ret = NULL_TREE;
+ tree *pp = &ret;
+ unsigned int i;
+ tree t;
+ for (i = 0; VEC_iterate (tree, vec, i, t); ++i)
+ {
+ *pp = build_tree_list_stat (NULL, t PASS_MEM_STAT);
+ pp = &TREE_CHAIN (*pp);
+ }
+ return ret;
+}
+
/* Return a newly created TREE_LIST node whose
purpose and value fields are PURPOSE and VALUE
and whose TREE_CHAIN is CHAIN. */
return list;
}
+
+/* Return the values of the elements of a CONSTRUCTOR as a vector of
+ trees. */
+
+VEC(tree,gc) *
+ctor_to_vec (tree ctor)
+{
+ VEC(tree, gc) *vec = VEC_alloc (tree, gc, CONSTRUCTOR_NELTS (ctor));
+ unsigned int ix;
+ tree val;
+
+ FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (ctor), ix, val)
+ VEC_quick_push (tree, vec, val);
+
+ return vec;
+}
\f
/* Return the size nominally occupied by an object of type TYPE
when it resides in memory. The value is measured in units of bytes,
return t;
t = build1 (SAVE_EXPR, TREE_TYPE (expr), t);
+ SET_EXPR_LOCATION (t, EXPR_LOCATION (expr));
/* This expression might be placed ahead of a jump to ensure that the
value was computed on both sides of the jump. So make sure it isn't
return inner;
}
+
/* Return which tree structure is used by T. */
enum tree_node_structure_enum
tree_node_structure (const_tree t)
{
const enum tree_code code = TREE_CODE (t);
+ return tree_node_structure_for_code (code);
+}
- switch (TREE_CODE_CLASS (code))
- {
- case tcc_declaration:
+/* Set various status flags when building a CALL_EXPR object T. */
+
+static void
+process_call_operands (tree t)
+{
+ bool side_effects = TREE_SIDE_EFFECTS (t);
+ bool read_only = false;
+ int i = call_expr_flags (t);
+
+ /* Calls have side-effects, except those to const or pure functions. */
+ if ((i & ECF_LOOPING_CONST_OR_PURE) || !(i & (ECF_CONST | ECF_PURE)))
+ side_effects = true;
+ /* Propagate TREE_READONLY of arguments for const functions. */
+ if (i & ECF_CONST)
+ read_only = true;
+
+ if (!side_effects || read_only)
+ for (i = 1; i < TREE_OPERAND_LENGTH (t); i++)
{
- switch (code)
- {
- case FIELD_DECL:
- return TS_FIELD_DECL;
- case PARM_DECL:
- return TS_PARM_DECL;
- case VAR_DECL:
- return TS_VAR_DECL;
- case LABEL_DECL:
- return TS_LABEL_DECL;
- case RESULT_DECL:
- return TS_RESULT_DECL;
- case CONST_DECL:
- return TS_CONST_DECL;
- case TYPE_DECL:
- return TS_TYPE_DECL;
- case FUNCTION_DECL:
- return TS_FUNCTION_DECL;
- default:
- return TS_DECL_NON_COMMON;
- }
+ tree op = TREE_OPERAND (t, i);
+ if (op && TREE_SIDE_EFFECTS (op))
+ side_effects = true;
+ if (op && !TREE_READONLY (op) && !CONSTANT_CLASS_P (op))
+ read_only = false;
}
- case tcc_type:
- return TS_TYPE;
- case tcc_reference:
- case tcc_comparison:
- case tcc_unary:
- case tcc_binary:
- case tcc_expression:
- case tcc_statement:
- case tcc_vl_exp:
- return TS_EXP;
- default: /* tcc_constant and tcc_exceptional */
- break;
- }
- switch (code)
- {
- /* 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;
- /* tcc_exceptional cases. */
- case ERROR_MARK: return TS_COMMON;
- case IDENTIFIER_NODE: return TS_IDENTIFIER;
- case TREE_LIST: return TS_LIST;
- case TREE_VEC: return TS_VEC;
- case SSA_NAME: return TS_SSA_NAME;
- case PLACEHOLDER_EXPR: return TS_COMMON;
- case STATEMENT_LIST: return TS_STATEMENT_LIST;
- case BLOCK: return TS_BLOCK;
- case CONSTRUCTOR: return TS_CONSTRUCTOR;
- case TREE_BINFO: return TS_BINFO;
- case OMP_CLAUSE: return TS_OMP_CLAUSE;
- case OPTIMIZATION_NODE: return TS_OPTIMIZATION;
- case TARGET_OPTION_NODE: return TS_TARGET_OPTION;
- default:
- gcc_unreachable ();
- }
+ TREE_SIDE_EFFECTS (t) = side_effects;
+ TREE_READONLY (t) = read_only;
}
\f
/* Return 1 if EXP contains a PLACEHOLDER_EXPR; i.e., if it represents a size
return result;
}
\f
+/* Push tree EXP onto vector QUEUE if it is not already present. */
+
+static void
+push_without_duplicates (tree exp, VEC (tree, heap) **queue)
+{
+ unsigned int i;
+ tree iter;
+
+ for (i = 0; VEC_iterate (tree, *queue, i, iter); i++)
+ if (simple_cst_equal (iter, exp) == 1)
+ break;
+
+ if (!iter)
+ VEC_safe_push (tree, heap, *queue, exp);
+}
+
+/* Given a tree EXP, find all occurences of references to fields
+ in a PLACEHOLDER_EXPR and place them in vector REFS without
+ duplicates. Also record VAR_DECLs and CONST_DECLs. Note that
+ we assume here that EXP contains only arithmetic expressions
+ or CALL_EXPRs with PLACEHOLDER_EXPRs occurring only in their
+ argument list. */
+
+void
+find_placeholder_in_expr (tree exp, VEC (tree, heap) **refs)
+{
+ enum tree_code code = TREE_CODE (exp);
+ tree inner;
+ int i;
+
+ /* We handle TREE_LIST and COMPONENT_REF separately. */
+ if (code == TREE_LIST)
+ {
+ FIND_PLACEHOLDER_IN_EXPR (TREE_CHAIN (exp), refs);
+ FIND_PLACEHOLDER_IN_EXPR (TREE_VALUE (exp), refs);
+ }
+ else if (code == COMPONENT_REF)
+ {
+ for (inner = TREE_OPERAND (exp, 0);
+ REFERENCE_CLASS_P (inner);
+ inner = TREE_OPERAND (inner, 0))
+ ;
+
+ if (TREE_CODE (inner) == PLACEHOLDER_EXPR)
+ push_without_duplicates (exp, refs);
+ else
+ FIND_PLACEHOLDER_IN_EXPR (TREE_OPERAND (exp, 0), refs);
+ }
+ else
+ switch (TREE_CODE_CLASS (code))
+ {
+ case tcc_constant:
+ break;
+
+ case tcc_declaration:
+ /* Variables allocated to static storage can stay. */
+ if (!TREE_STATIC (exp))
+ push_without_duplicates (exp, refs);
+ break;
+
+ case tcc_expression:
+ /* This is the pattern built in ada/make_aligning_type. */
+ if (code == ADDR_EXPR
+ && TREE_CODE (TREE_OPERAND (exp, 0)) == PLACEHOLDER_EXPR)
+ {
+ push_without_duplicates (exp, refs);
+ break;
+ }
+
+ /* Fall through... */
+
+ case tcc_exceptional:
+ case tcc_unary:
+ case tcc_binary:
+ case tcc_comparison:
+ case tcc_reference:
+ for (i = 0; i < TREE_CODE_LENGTH (code); i++)
+ FIND_PLACEHOLDER_IN_EXPR (TREE_OPERAND (exp, i), refs);
+ break;
+
+ case tcc_vl_exp:
+ for (i = 1; i < TREE_OPERAND_LENGTH (exp); i++)
+ FIND_PLACEHOLDER_IN_EXPR (TREE_OPERAND (exp, i), refs);
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+}
+
/* Given a tree EXP, a FIELD_DECL F, and a replacement value R,
return a tree with all occurrences of references to F in a
- PLACEHOLDER_EXPR replaced by R. Note that we assume here that EXP
- contains only arithmetic expressions or a CALL_EXPR with a
- PLACEHOLDER_EXPR occurring only in its arglist. */
+ PLACEHOLDER_EXPR replaced by R. Also handle VAR_DECLs and
+ CONST_DECLs. Note that we assume here that EXP contains only
+ arithmetic expressions or CALL_EXPRs with PLACEHOLDER_EXPRs
+ occurring only in their argument list. */
tree
substitute_in_expr (tree exp, tree f, tree r)
{
enum tree_code code = TREE_CODE (exp);
tree op0, op1, op2, op3;
- tree new_tree, inner;
+ tree new_tree;
/* We handle TREE_LIST and COMPONENT_REF separately. */
if (code == TREE_LIST)
return tree_cons (TREE_PURPOSE (exp), op1, op0);
}
else if (code == COMPONENT_REF)
- {
- /* If this expression is getting a value from a PLACEHOLDER_EXPR
- and it is the right field, replace it with R. */
- for (inner = TREE_OPERAND (exp, 0);
- REFERENCE_CLASS_P (inner);
- inner = TREE_OPERAND (inner, 0))
- ;
- if (TREE_CODE (inner) == PLACEHOLDER_EXPR
- && TREE_OPERAND (exp, 1) == f)
- return r;
-
- /* If this expression hasn't been completed let, leave it alone. */
- if (TREE_CODE (inner) == PLACEHOLDER_EXPR && TREE_TYPE (inner) == 0)
- return exp;
-
- op0 = SUBSTITUTE_IN_EXPR (TREE_OPERAND (exp, 0), f, r);
- if (op0 == TREE_OPERAND (exp, 0))
- return exp;
-
- new_tree = fold_build3 (COMPONENT_REF, TREE_TYPE (exp),
- op0, TREE_OPERAND (exp, 1), NULL_TREE);
+ {
+ tree inner;
+
+ /* If this expression is getting a value from a PLACEHOLDER_EXPR
+ and it is the right field, replace it with R. */
+ for (inner = TREE_OPERAND (exp, 0);
+ REFERENCE_CLASS_P (inner);
+ inner = TREE_OPERAND (inner, 0))
+ ;
+
+ /* The field. */
+ op1 = TREE_OPERAND (exp, 1);
+
+ if (TREE_CODE (inner) == PLACEHOLDER_EXPR && op1 == f)
+ return r;
+
+ /* If this expression hasn't been completed let, leave it alone. */
+ if (TREE_CODE (inner) == PLACEHOLDER_EXPR && !TREE_TYPE (inner))
+ return exp;
+
+ op0 = SUBSTITUTE_IN_EXPR (TREE_OPERAND (exp, 0), f, r);
+ if (op0 == TREE_OPERAND (exp, 0))
+ return exp;
+
+ new_tree
+ = fold_build3 (COMPONENT_REF, TREE_TYPE (exp), op0, op1, NULL_TREE);
}
else
switch (TREE_CODE_CLASS (code))
{
case tcc_constant:
- case tcc_declaration:
return exp;
+ case tcc_declaration:
+ if (exp == f)
+ return r;
+ else
+ return exp;
+
+ case tcc_expression:
+ if (exp == f)
+ return r;
+
+ /* Fall through... */
+
case tcc_exceptional:
case tcc_unary:
case tcc_binary:
case tcc_comparison:
- case tcc_expression:
case tcc_reference:
switch (TREE_CODE_LENGTH (code))
{
&& op3 == TREE_OPERAND (exp, 3))
return exp;
- new_tree = fold (build4 (code, TREE_TYPE (exp), op0, op1, op2, op3));
+ new_tree
+ = fold (build4 (code, TREE_TYPE (exp), op0, op1, op2, op3));
break;
default:
case tcc_vl_exp:
{
- tree copy = NULL_TREE;
int i;
+ new_tree = NULL_TREE;
+
+ /* If we are trying to replace F with a constant, inline back
+ functions which do nothing else than computing a value from
+ the arguments they are passed. This makes it possible to
+ fold partially or entirely the replacement expression. */
+ if (CONSTANT_CLASS_P (r) && code == CALL_EXPR)
+ {
+ tree t = maybe_inline_call_in_expr (exp);
+ if (t)
+ return SUBSTITUTE_IN_EXPR (t, f, r);
+ }
+
for (i = 1; i < TREE_OPERAND_LENGTH (exp); i++)
{
tree op = TREE_OPERAND (exp, i);
tree new_op = SUBSTITUTE_IN_EXPR (op, f, r);
if (new_op != op)
{
- if (!copy)
- copy = copy_node (exp);
- TREE_OPERAND (copy, i) = new_op;
+ if (!new_tree)
+ new_tree = copy_node (exp);
+ TREE_OPERAND (new_tree, i) = new_op;
}
}
- if (copy)
- new_tree = fold (copy);
+ if (new_tree)
+ {
+ new_tree = fold (new_tree);
+ if (TREE_CODE (new_tree) == CALL_EXPR)
+ process_call_operands (new_tree);
+ }
else
return exp;
}
gcc_unreachable ();
}
- TREE_READONLY (new_tree) = TREE_READONLY (exp);
+ TREE_READONLY (new_tree) |= TREE_READONLY (exp);
return new_tree;
}
{
enum tree_code code = TREE_CODE (exp);
tree op0, op1, op2, op3;
+ tree new_tree;
/* If this is a PLACEHOLDER_EXPR, see if we find a corresponding type
in the chain of OBJ. */
op0 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (TREE_OPERAND (exp, 0), obj);
if (op0 == TREE_OPERAND (exp, 0))
return exp;
- else
- return fold_build1 (code, TREE_TYPE (exp), op0);
+
+ new_tree = fold_build1 (code, TREE_TYPE (exp), op0);
+ break;
case 2:
op0 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (TREE_OPERAND (exp, 0), obj);
if (op0 == TREE_OPERAND (exp, 0) && op1 == TREE_OPERAND (exp, 1))
return exp;
- else
- return fold_build2 (code, TREE_TYPE (exp), op0, op1);
+
+ new_tree = fold_build2 (code, TREE_TYPE (exp), op0, op1);
+ break;
case 3:
op0 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (TREE_OPERAND (exp, 0), obj);
if (op0 == TREE_OPERAND (exp, 0) && op1 == TREE_OPERAND (exp, 1)
&& op2 == TREE_OPERAND (exp, 2))
return exp;
- else
- return fold_build3 (code, TREE_TYPE (exp), op0, op1, op2);
+
+ new_tree = fold_build3 (code, TREE_TYPE (exp), op0, op1, op2);
+ break;
case 4:
op0 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (TREE_OPERAND (exp, 0), obj);
&& op2 == TREE_OPERAND (exp, 2)
&& op3 == TREE_OPERAND (exp, 3))
return exp;
- else
- return fold (build4 (code, TREE_TYPE (exp), op0, op1, op2, op3));
+
+ new_tree
+ = fold (build4 (code, TREE_TYPE (exp), op0, op1, op2, op3));
+ break;
default:
gcc_unreachable ();
case tcc_vl_exp:
{
- tree copy = NULL_TREE;
int i;
+ new_tree = NULL_TREE;
+
for (i = 1; i < TREE_OPERAND_LENGTH (exp); i++)
{
tree op = TREE_OPERAND (exp, i);
tree new_op = SUBSTITUTE_PLACEHOLDER_IN_EXPR (op, obj);
if (new_op != op)
{
- if (!copy)
- copy = copy_node (exp);
- TREE_OPERAND (copy, i) = new_op;
+ if (!new_tree)
+ new_tree = copy_node (exp);
+ TREE_OPERAND (new_tree, i) = new_op;
}
}
- if (copy)
- return fold (copy);
+ if (new_tree)
+ {
+ new_tree = fold (new_tree);
+ if (TREE_CODE (new_tree) == CALL_EXPR)
+ process_call_operands (new_tree);
+ }
else
return exp;
}
+ break;
default:
gcc_unreachable ();
}
+
+ TREE_READONLY (new_tree) |= TREE_READONLY (exp);
+ return new_tree;
}
\f
/* Stabilize a reference so that we can use it any number of times
return t;
}
-#define PROCESS_ARG(N) \
- do { \
- TREE_OPERAND (t, N) = arg##N; \
- if (arg##N &&!TYPE_P (arg##N)) \
- { \
- if (TREE_SIDE_EFFECTS (arg##N)) \
- side_effects = 1; \
- if (!TREE_READONLY (arg##N)) \
- read_only = 0; \
- if (!TREE_CONSTANT (arg##N)) \
- constant = 0; \
- } \
+#define PROCESS_ARG(N) \
+ do { \
+ TREE_OPERAND (t, N) = arg##N; \
+ if (arg##N &&!TYPE_P (arg##N)) \
+ { \
+ if (TREE_SIDE_EFFECTS (arg##N)) \
+ side_effects = 1; \
+ if (!TREE_READONLY (arg##N) \
+ && !CONSTANT_CLASS_P (arg##N)) \
+ read_only = 0; \
+ if (!TREE_CONSTANT (arg##N)) \
+ constant = 0; \
+ } \
} while (0)
tree
t = make_node_stat (code PASS_MEM_STAT);
TREE_TYPE (t) = tt;
+ read_only = 1;
+
/* As a special exception, if COND_EXPR has NULL branches, we
assume that it is a gimple statement and always consider
it to have side effects. */
PROCESS_ARG(1);
PROCESS_ARG(2);
+ if (code == COND_EXPR)
+ TREE_READONLY (t) = read_only;
+
TREE_SIDE_EFFECTS (t) = side_effects;
TREE_THIS_VOLATILE (t)
= (TREE_CODE_CLASS (code) == tcc_reference
CALL_EXPR_ARG (t, i) = TREE_VALUE (arglist);
return t;
}
+
+/* Similar to build_nt, but for creating a CALL_EXPR object with a
+ tree VEC. */
+
+tree
+build_nt_call_vec (tree fn, VEC(tree,gc) *args)
+{
+ tree ret, t;
+ unsigned int ix;
+
+ ret = build_vl_exp (CALL_EXPR, VEC_length (tree, args) + 3);
+ CALL_EXPR_FN (ret) = fn;
+ CALL_EXPR_STATIC_CHAIN (ret) = NULL_TREE;
+ for (ix = 0; VEC_iterate (tree, args, ix, t); ++ix)
+ CALL_EXPR_ARG (ret, ix) = t;
+ return ret;
+}
\f
/* Create a DECL_... node of code CODE, name NAME and data type TYPE.
We do NOT enter this node in any sort of symbol table.
+ LOC is the location of the decl.
+
layout_decl is used to set up the decl's storage layout.
Other slots are initialized to 0 or null pointers. */
tree
-build_decl_stat (enum tree_code code, tree name, tree type MEM_STAT_DECL)
+build_decl_stat (location_t loc, enum tree_code code, tree name,
+ tree type MEM_STAT_DECL)
{
tree t;
t = make_node_stat (code PASS_MEM_STAT);
+ DECL_SOURCE_LOCATION (t) = loc;
/* if (type == error_mark_node)
type = integer_type_node; */
build_fn_decl (const char *name, tree type)
{
tree id = get_identifier (name);
- tree decl = build_decl (FUNCTION_DECL, id, type);
+ tree decl = build_decl (input_location, FUNCTION_DECL, id, type);
DECL_EXTERNAL (decl) = 1;
TREE_PUBLIC (decl) = 1;
}
\f
-/* Source location accessor functions. */
-
-
-void
-set_expr_locus (tree node, source_location *loc)
-{
- if (loc == NULL)
- EXPR_CHECK (node)->exp.locus = UNKNOWN_LOCATION;
- else
- EXPR_CHECK (node)->exp.locus = *loc;
-}
-
/* Like SET_EXPR_LOCATION, but make sure the tree can have a location.
LOC is the location to use in tree T. */
bool *no_add_attrs)
{
tree node = *pnode;
+ bool is_dllimport;
/* These attributes may apply to structure and union types being created,
but otherwise should pass to the declaration involved. */
return NULL_TREE;
}
+ is_dllimport = is_attribute_p ("dllimport", name);
+
/* Report error on dllimport ambiguities seen now before they cause
any damage. */
- else if (is_attribute_p ("dllimport", name))
+ if (is_dllimport)
{
/* Honor any target-specific overrides. */
if (!targetm.valid_dllimport_attribute_p (node))
if (*no_add_attrs == false)
DECL_DLLIMPORT_P (node) = 1;
}
+ else if (TREE_CODE (node) == FUNCTION_DECL
+ && DECL_DECLARED_INLINE_P (node))
+ /* An exported function, even if inline, must be emitted. */
+ DECL_EXTERNAL (node) = 0;
/* Report error if symbol is not accessible at global scope. */
if (!TREE_PUBLIC (node)
h->fini = priority;
}
-/* Look up a restrict qualified base decl for FROM. */
-
-tree
-decl_restrict_base_lookup (tree from)
-{
- struct tree_map *h;
- struct tree_map in;
-
- in.base.from = from;
- h = (struct tree_map *) htab_find_with_hash (restrict_base_for_decl, &in,
- htab_hash_pointer (from));
- return h ? h->to : NULL_TREE;
-}
-
-/* Record the restrict qualified base TO for FROM. */
-
-void
-decl_restrict_base_insert (tree from, tree to)
-{
- struct tree_map *h;
- void **loc;
-
- h = GGC_NEW (struct tree_map);
- h->hash = htab_hash_pointer (from);
- h->base.from = from;
- h->to = to;
- loc = htab_find_slot_with_hash (restrict_base_for_decl, h, h->hash, INSERT);
- *(struct tree_map **) loc = h;
-}
-
/* Print out the statistics for the DECL_DEBUG_EXPR hash table. */
static void
htab_collisions (value_expr_for_decl));
}
-/* Print out statistics for the RESTRICT_BASE_FOR_DECL hash table, but
- don't print anything if the table is empty. */
-
-static void
-print_restrict_base_statistics (void)
-{
- if (htab_elements (restrict_base_for_decl) != 0)
- fprintf (stderr,
- "RESTRICT_BASE hash: size %ld, %ld elements, %f collisions\n",
- (long) htab_size (restrict_base_for_decl),
- (long) htab_elements (restrict_base_for_decl),
- htab_collisions (restrict_base_for_decl));
-}
-
/* Lookup a debug expression for FROM, and return it if we find one. */
tree
return val;
}
case FUNCTION_DECL:
- /* When referring to a built-in FUNCTION_DECL, use the
- __builtin__ form. Otherwise nodes that compare equal
- according to operand_equal_p might get different
- hash codes. */
- if (DECL_BUILT_IN (t) && built_in_decls[DECL_FUNCTION_CODE (t)])
+ /* When referring to a built-in FUNCTION_DECL, use the __builtin__ form.
+ Otherwise nodes that compare equal according to operand_equal_p might
+ get different hash codes. However, don't do this for machine specific
+ or front end builtins, since the function code is overloaded in those
+ cases. */
+ if (DECL_BUILT_IN_CLASS (t) == BUILT_IN_NORMAL
+ && built_in_decls[DECL_FUNCTION_CODE (t)])
{
t = built_in_decls[DECL_FUNCTION_CODE (t)];
code = TREE_CODE (t);
else
new_reversed = void_list_node;
}
- gcc_assert (new_reversed);
/* Use copy_node to preserve as much as possible from original type
(debug info, attribute lists etc.)
name = 0;
if (name != 0)
- TYPE_NAME (t) = build_decl (TYPE_DECL, get_identifier (name), t);
+ TYPE_NAME (t) = build_decl (UNKNOWN_LOCATION, TYPE_DECL,
+ get_identifier (name), t);
}
return build_qualified_type (t, TYPE_QUALS (component_type));
print_type_hash_statistics ();
print_debug_expr_statistics ();
print_value_expr_statistics ();
- print_restrict_base_statistics ();
lang_hooks.print_statistics ();
}
\f
{
tree index = build_int_cst (NULL_TREE, nunits - 1);
- tree array = build_array_type (innertype, build_index_type (index));
+ tree array = build_array_type (TYPE_MAIN_VARIANT (innertype),
+ build_index_type (index));
tree rt = make_node (RECORD_TYPE);
- TYPE_FIELDS (rt) = build_decl (FIELD_DECL, get_identifier ("f"), array);
+ TYPE_FIELDS (rt) = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
+ get_identifier ("f"), array);
DECL_CONTEXT (TYPE_FIELDS (rt)) = rt;
layout_type (rt);
TYPE_DEBUG_REPRESENTATION_TYPE (t) = rt;
}
}
-/* Build an empty statement. */
+/* Build an empty statement at location LOC. */
tree
-build_empty_stmt (void)
+build_empty_stmt (location_t loc)
{
- return build1 (NOP_EXPR, void_type_node, size_zero_node);
+ tree t = build1 (NOP_EXPR, void_type_node, size_zero_node);
+ SET_EXPR_LOCATION (t, loc);
+ return t;
}
-/* Build an OpenMP clause with code CODE. */
+/* Build an OpenMP clause with code CODE. LOC is the location of the
+ clause. */
tree
-build_omp_clause (enum omp_clause_code code)
+build_omp_clause (location_t loc, enum omp_clause_code code)
{
tree t;
int size, length;
memset (t, 0, size);
TREE_SET_CODE (t, OMP_CLAUSE);
OMP_CLAUSE_SET_CODE (t, code);
+ OMP_CLAUSE_LOCATION (t) = loc;
#ifdef GATHER_STATISTICS
tree_node_counts[(int) omp_clause_kind]++;
return t;
}
-/* Set various status flags when building a CALL_EXPR object T. */
-
-static void
-process_call_operands (tree t)
-{
- bool side_effects;
-
- side_effects = TREE_SIDE_EFFECTS (t);
- if (!side_effects)
- {
- int i, n;
- n = TREE_OPERAND_LENGTH (t);
- for (i = 1; i < n; i++)
- {
- tree op = TREE_OPERAND (t, i);
- if (op && TREE_SIDE_EFFECTS (op))
- {
- side_effects = 1;
- break;
- }
- }
- }
- if (!side_effects)
- {
- int i;
-
- /* Calls have side-effects, except those to const or
- pure functions. */
- i = call_expr_flags (t);
- if ((i & ECF_LOOPING_CONST_OR_PURE) || !(i & (ECF_CONST | ECF_PURE)))
- side_effects = 1;
- }
- TREE_SIDE_EFFECTS (t) = side_effects;
-}
-
/* Build a tcc_vl_exp object with code CODE and room for LEN operands. LEN
includes the implicit operand count in TREE_OPERAND 0, and so must be >= 1.
Except for the CODE and operand count field, other storage for the
which are specified as a tree array ARGS. */
tree
-build_call_array (tree return_type, tree fn, int nargs, tree *args)
+build_call_array_loc (location_t loc, tree return_type, tree fn,
+ int nargs, const tree *args)
{
tree t;
int i;
for (i = 0; i < nargs; i++)
CALL_EXPR_ARG (t, i) = args[i];
process_call_operands (t);
+ SET_EXPR_LOCATION (t, loc);
return t;
}
+/* Like build_call_array, but takes a VEC. */
+
+tree
+build_call_vec (tree return_type, tree fn, VEC(tree,gc) *args)
+{
+ tree ret, t;
+ unsigned int ix;
+
+ ret = build_vl_exp (CALL_EXPR, VEC_length (tree, args) + 3);
+ TREE_TYPE (ret) = return_type;
+ CALL_EXPR_FN (ret) = fn;
+ CALL_EXPR_STATIC_CHAIN (ret) = NULL_TREE;
+ for (ix = 0; VEC_iterate (tree, args, ix, t); ++ix)
+ CALL_EXPR_ARG (ret, ix) = t;
+ process_call_operands (ret);
+ return ret;
+}
+
/* Returns true if it is possible to prove that the index of
an array access REF (an ARRAY_REF expression) falls into the
return val;
}
+/* Return value of a constant X and sign-extend it. */
+
+HOST_WIDEST_INT
+widest_int_cst_value (const_tree x)
+{
+ unsigned bits = TYPE_PRECISION (TREE_TYPE (x));
+ unsigned HOST_WIDEST_INT val = TREE_INT_CST_LOW (x);
+
+#if HOST_BITS_PER_WIDEST_INT > HOST_BITS_PER_WIDE_INT
+ gcc_assert (HOST_BITS_PER_WIDEST_INT >= 2 * HOST_BITS_PER_WIDE_INT);
+ val |= (((unsigned HOST_WIDEST_INT) TREE_INT_CST_HIGH (x))
+ << HOST_BITS_PER_WIDE_INT);
+#else
+ /* Make sure the sign-extended value will fit in a HOST_WIDE_INT. */
+ gcc_assert (TREE_INT_CST_HIGH (x) == 0
+ || TREE_INT_CST_HIGH (x) == -1);
+#endif
+
+ if (bits < HOST_BITS_PER_WIDEST_INT)
+ {
+ bool negative = ((val >> (bits - 1)) & 1) != 0;
+ if (negative)
+ val |= (~(unsigned HOST_WIDEST_INT) 0) << (bits - 1) << 1;
+ else
+ val &= ~((~(unsigned HOST_WIDEST_INT) 0) << (bits - 1) << 1);
+ }
+
+ return val;
+}
+
/* If TYPE is an integral type, return an equivalent type which is
unsigned iff UNSIGNEDP is true. If TYPE is not an integral type,
return TYPE itself. */
WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, len));
}
- case CHANGE_DYNAMIC_TYPE_EXPR:
- WALK_SUBTREE (CHANGE_DYNAMIC_TYPE_NEW_TYPE (*tp));
- WALK_SUBTREE_TAIL (CHANGE_DYNAMIC_TYPE_LOCATION (*tp));
-
case DECL_EXPR:
/* If this is a TYPE_DECL, walk into the fields of the type that it's
defining. We only want to walk into these fields of a type in this
}
-/* Create a nameless artificial label and put it in the current function
- context. Returns the newly created label. */
+/* Create a nameless artificial label and put it in the current
+ function context. The label has a location of LOC. Returns the
+ newly created label. */
tree
-create_artificial_label (void)
+create_artificial_label (location_t loc)
{
- tree lab = build_decl (LABEL_DECL, NULL_TREE, void_type_node);
+ tree lab = build_decl (loc,
+ LABEL_DECL, NULL_TREE, void_type_node);
DECL_ARTIFICIAL (lab) = 1;
DECL_IGNORED_P (lab) = 1;
location_t
tree_nonartificial_location (tree exp)
{
- tree block = TREE_BLOCK (exp);
-
- while (block
- && TREE_CODE (block) == BLOCK
- && BLOCK_ABSTRACT_ORIGIN (block))
- {
- tree ao = BLOCK_ABSTRACT_ORIGIN (block);
+ location_t *loc = block_nonartificial_location (TREE_BLOCK (exp));
- do
- {
- if (TREE_CODE (ao) == FUNCTION_DECL
- && DECL_DECLARED_INLINE_P (ao)
- && lookup_attribute ("artificial", DECL_ATTRIBUTES (ao)))
- return BLOCK_SOURCE_LOCATION (block);
- else if (TREE_CODE (ao) == BLOCK
- && BLOCK_SUPERCONTEXT (ao) != ao)
- ao = BLOCK_SUPERCONTEXT (ao);
- else
- break;
- }
- while (ao);
-
- block = BLOCK_SUPERCONTEXT (block);
- }
-
- return EXPR_LOCATION (exp);
+ if (loc)
+ return *loc;
+ else
+ return EXPR_LOCATION (exp);
}
return !t1 && !t2;
}
+/* Return true iff conversion in EXP generates no instruction. Mark
+ it inline so that we fully inline into the stripping functions even
+ though we have two uses of this function. */
+
+static inline bool
+tree_nop_conversion (const_tree exp)
+{
+ tree outer_type, inner_type;
+
+ if (!CONVERT_EXPR_P (exp)
+ && TREE_CODE (exp) != NON_LVALUE_EXPR)
+ return false;
+ if (TREE_OPERAND (exp, 0) == error_mark_node)
+ return false;
+
+ outer_type = TREE_TYPE (exp);
+ inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
+
+ /* Use precision rather then machine mode when we can, which gives
+ the correct answer even for submode (bit-field) types. */
+ if ((INTEGRAL_TYPE_P (outer_type)
+ || POINTER_TYPE_P (outer_type)
+ || TREE_CODE (outer_type) == OFFSET_TYPE)
+ && (INTEGRAL_TYPE_P (inner_type)
+ || POINTER_TYPE_P (inner_type)
+ || TREE_CODE (inner_type) == OFFSET_TYPE))
+ return TYPE_PRECISION (outer_type) == TYPE_PRECISION (inner_type);
+
+ /* Otherwise fall back on comparing machine modes (e.g. for
+ aggregate types, floats). */
+ return TYPE_MODE (outer_type) == TYPE_MODE (inner_type);
+}
+
+/* Return true iff conversion in EXP generates no instruction. Don't
+ consider conversions changing the signedness. */
+
+static bool
+tree_sign_nop_conversion (const_tree exp)
+{
+ tree outer_type, inner_type;
+
+ if (!tree_nop_conversion (exp))
+ return false;
+
+ outer_type = TREE_TYPE (exp);
+ inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
+
+ return (TYPE_UNSIGNED (outer_type) == TYPE_UNSIGNED (inner_type)
+ && POINTER_TYPE_P (outer_type) == POINTER_TYPE_P (inner_type));
+}
+
+/* Strip conversions from EXP according to tree_nop_conversion and
+ return the resulting expression. */
+
+tree
+tree_strip_nop_conversions (tree exp)
+{
+ while (tree_nop_conversion (exp))
+ exp = TREE_OPERAND (exp, 0);
+ return exp;
+}
+
+/* Strip conversions from EXP according to tree_sign_nop_conversion
+ and return the resulting expression. */
+
+tree
+tree_strip_sign_nop_conversions (tree exp)
+{
+ while (tree_sign_nop_conversion (exp))
+ exp = TREE_OPERAND (exp, 0);
+ return exp;
+}
+
#include "gt-tree.h"