/* Language-independent node constructors for parse phase of GNU compiler.
Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
This file is part of GCC.
"binfos",
"phi_nodes",
"ssa names",
+ "constructors",
"random kinds",
"lang_decl kinds",
- "lang_type kinds"
+ "lang_type kinds",
+ "omp clauses"
};
#endif /* GATHER_STATISTICS */
/* General tree->tree mapping structure for use in hash tables. */
-struct tree_map GTY(())
-{
- hashval_t hash;
- tree from;
- tree to;
-};
static GTY ((if_marked ("tree_map_marked_p"), param_is (struct tree_map)))
htab_t debug_expr_for_decl;
static GTY ((if_marked ("tree_map_marked_p"), param_is (struct tree_map)))
htab_t value_expr_for_decl;
+static GTY ((if_marked ("tree_int_map_marked_p"), param_is (struct tree_int_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;
+
+struct tree_int_map GTY(())
+{
+ tree from;
+ unsigned short to;
+};
+static unsigned int tree_int_map_hash (const void *);
+static int tree_int_map_eq (const void *, const void *);
+static int tree_int_map_marked_p (const void *);
static void set_type_quals (tree, int);
static int type_hash_eq (const void *, const void *);
static hashval_t type_hash_hash (const void *);
-static int tree_map_eq (const void *, const void *);
-static hashval_t tree_map_hash (const void *);
static hashval_t int_cst_hash_hash (const void *);
static int int_cst_hash_eq (const void *, const void *);
static void print_type_hash_statistics (void);
static void print_value_expr_statistics (void);
static tree make_vector_type (tree, int, enum machine_mode);
static int type_hash_marked_p (const void *);
-static int tree_map_marked_p (const void *);
static unsigned int type_hash_list (tree, hashval_t);
static unsigned int attribute_hash_list (tree, hashval_t);
tree global_trees[TI_MAX];
tree integer_types[itk_none];
+unsigned char tree_contains_struct[256][64];
+
+/* Number of operands for each OpenMP clause. */
+unsigned const char omp_clause_num_ops[] =
+{
+ 0, /* OMP_CLAUSE_ERROR */
+ 1, /* OMP_CLAUSE_PRIVATE */
+ 1, /* OMP_CLAUSE_SHARED */
+ 1, /* OMP_CLAUSE_FIRSTPRIVATE */
+ 1, /* OMP_CLAUSE_LASTPRIVATE */
+ 4, /* OMP_CLAUSE_REDUCTION */
+ 1, /* OMP_CLAUSE_COPYIN */
+ 1, /* OMP_CLAUSE_COPYPRIVATE */
+ 1, /* OMP_CLAUSE_IF */
+ 1, /* OMP_CLAUSE_NUM_THREADS */
+ 1, /* OMP_CLAUSE_SCHEDULE */
+ 0, /* OMP_CLAUSE_NOWAIT */
+ 0, /* OMP_CLAUSE_ORDERED */
+ 0 /* OMP_CLAUSE_DEFAULT */
+};
+
+const char * const omp_clause_code_name[] =
+{
+ "error_clause",
+ "private",
+ "shared",
+ "firstprivate",
+ "lastprivate",
+ "reduction",
+ "copyin",
+ "copyprivate",
+ "if",
+ "num_threads",
+ "schedule",
+ "nowait",
+ "ordered",
+ "default"
+};
\f
/* Init tree.c. */
value_expr_for_decl = htab_create_ggc (512, tree_map_hash,
tree_map_eq, 0);
+ init_priority_for_decl = htab_create_ggc (512, tree_int_map_hash,
+ tree_int_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);
int_cst_node = make_node (INTEGER_CST);
+ 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[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[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[STRUCT_FIELD_TAG][TS_STRUCT_FIELD_TAG] = 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;
+
+ lang_hooks.init_ts ();
}
\f
{
if (!DECL_ASSEMBLER_NAME_SET_P (decl))
lang_hooks.set_decl_assembler_name (decl);
- return DECL_CHECK (decl)->decl.assembler_name;
+ return DECL_WITH_VIS_CHECK (decl)->decl_with_vis.assembler_name;
}
/* Compute the number of bytes occupied by a tree with code CODE.
switch (TREE_CODE_CLASS (code))
{
case tcc_declaration: /* A decl node */
- return sizeof (struct tree_decl);
+ {
+ switch (code)
+ {
+ case FIELD_DECL:
+ return sizeof (struct tree_field_decl);
+ case PARM_DECL:
+ return sizeof (struct tree_parm_decl);
+ case VAR_DECL:
+ return sizeof (struct tree_var_decl);
+ case LABEL_DECL:
+ return sizeof (struct tree_label_decl);
+ case RESULT_DECL:
+ return sizeof (struct tree_result_decl);
+ case CONST_DECL:
+ return sizeof (struct tree_const_decl);
+ case TYPE_DECL:
+ return sizeof (struct tree_type_decl);
+ case FUNCTION_DECL:
+ return sizeof (struct tree_function_decl);
+ case NAME_MEMORY_TAG:
+ case SYMBOL_MEMORY_TAG:
+ return sizeof (struct tree_memory_tag);
+ case STRUCT_FIELD_TAG:
+ return sizeof (struct tree_struct_field_tag);
+ default:
+ return sizeof (struct tree_decl_non_common);
+ }
+ }
case tcc_type: /* a type node */
return sizeof (struct tree_type);
case PLACEHOLDER_EXPR: return sizeof (struct tree_common);
case TREE_VEC:
+ case OMP_CLAUSE:
case PHI_NODE: gcc_unreachable ();
case SSA_NAME: return sizeof (struct tree_ssa_name);
case STATEMENT_LIST: return sizeof (struct tree_statement_list);
case BLOCK: return sizeof (struct tree_block);
case VALUE_HANDLE: return sizeof (struct tree_value_handle);
+ case CONSTRUCTOR: return sizeof (struct tree_constructor);
default:
return lang_hooks.tree_size (code);
+ (TREE_VEC_LENGTH (node) - 1) * sizeof(char *));
case STRING_CST:
- return sizeof (struct tree_string) + TREE_STRING_LENGTH (node) - 1;
+ return TREE_STRING_LENGTH (node) + offsetof (struct tree_string, str) + 1;
+
+ case OMP_CLAUSE:
+ return (sizeof (struct tree_omp_clause)
+ + (omp_clause_num_ops[OMP_CLAUSE_CODE (node)] - 1)
+ * sizeof (tree));
default:
return tree_code_size (code);
/* Return a newly allocated node of code CODE. For decl and type
nodes, some other fields are initialized. The rest of the node is
- initialized to zero. This function cannot be used for PHI_NODE or
- TREE_VEC nodes, which is enforced by asserts in tree_code_size.
+ initialized to zero. This function cannot be used for PHI_NODE,
+ TREE_VEC or OMP_CLAUSE nodes, which is enforced by asserts in
+ tree_code_size.
Achoo! I got a code in the node. */
kind = id_kind;
break;
- case TREE_VEC:;
+ case TREE_VEC:
kind = vec_kind;
break;
kind = b_kind;
break;
+ case CONSTRUCTOR:
+ kind = constr_kind;
+ break;
+
default:
kind = x_kind;
break;
break;
case tcc_declaration:
- if (code != FUNCTION_DECL)
- DECL_ALIGN (t) = 1;
- DECL_USER_ALIGN (t) = 0;
- DECL_IN_SYSTEM_HEADER (t) = in_system_header;
+ if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS))
+ DECL_IN_SYSTEM_HEADER (t) = in_system_header;
+ if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
+ {
+ if (code != FUNCTION_DECL)
+ DECL_ALIGN (t) = 1;
+ DECL_USER_ALIGN (t) = 0;
+ /* 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++;
- /* We have not yet computed the alias set for this declaration. */
- DECL_POINTER_ALIAS_SET (t) = -1;
break;
case tcc_type:
TYPE_UID (t) = next_type_uid++;
- TYPE_ALIGN (t) = char_type_node ? TYPE_ALIGN (char_type_node) : 0;
+ TYPE_ALIGN (t) = BITS_PER_UNIT;
TYPE_USER_ALIGN (t) = 0;
TYPE_MAIN_VARIANT (t) = t;
SET_DECL_VALUE_EXPR (t, DECL_VALUE_EXPR (node));
DECL_HAS_VALUE_EXPR_P (t) = 1;
}
-
+ if (TREE_CODE (node) == VAR_DECL && DECL_HAS_INIT_PRIORITY_P (node))
+ {
+ 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)
{
break;
case INTEGER_TYPE:
- case CHAR_TYPE:
case OFFSET_TYPE:
if (TYPE_UNSIGNED (type))
{
}
/* Return a new VECTOR_CST node whose type is TYPE and whose values
- are in a list pointed by VALS. */
+ are in a list pointed to by VALS. */
tree
build_vector (tree type, tree vals)
return v;
}
+/* Return a new VECTOR_CST node whose type is TYPE and whose values
+ are extracted from V, a vector of CONSTRUCTOR_ELT. */
+
+tree
+build_vector_from_ctor (tree type, VEC(constructor_elt,gc) *v)
+{
+ tree list = NULL_TREE;
+ unsigned HOST_WIDE_INT idx;
+ tree value;
+
+ FOR_EACH_CONSTRUCTOR_VALUE (v, idx, value)
+ list = tree_cons (NULL_TREE, value, list);
+ return build_vector (type, nreverse (list));
+}
+
/* Return a new CONSTRUCTOR node whose type is TYPE and whose values
- are in a list pointed to by VALS. */
+ are in the VEC pointed to by VALS. */
tree
-build_constructor (tree type, tree vals)
+build_constructor (tree type, VEC(constructor_elt,gc) *vals)
{
tree c = make_node (CONSTRUCTOR);
TREE_TYPE (c) = type;
CONSTRUCTOR_ELTS (c) = vals;
+ return c;
+}
+
+/* Build a CONSTRUCTOR node made of a single initializer, with the specified
+ INDEX and VALUE. */
+tree
+build_constructor_single (tree type, tree index, tree value)
+{
+ VEC(constructor_elt,gc) *v;
+ constructor_elt *elt;
+ tree t;
+
+ v = VEC_alloc (constructor_elt, gc, 1);
+ elt = VEC_quick_push (constructor_elt, v, NULL);
+ elt->index = index;
+ elt->value = value;
+
+ t = build_constructor (type, v);
+ TREE_CONSTANT (t) = TREE_CONSTANT (value);
+ return t;
+}
+
+
+/* Return a new CONSTRUCTOR node whose type is TYPE and whose values
+ are in a list pointed to by VALS. */
+tree
+build_constructor_from_list (tree type, tree vals)
+{
+ tree t, val;
+ VEC(constructor_elt,gc) *v = NULL;
+ bool constant_p = true;
- /* ??? May not be necessary. Mirrors what build does. */
if (vals)
{
- TREE_SIDE_EFFECTS (c) = TREE_SIDE_EFFECTS (vals);
- TREE_READONLY (c) = TREE_READONLY (vals);
- TREE_CONSTANT (c) = TREE_CONSTANT (vals);
- TREE_INVARIANT (c) = TREE_INVARIANT (vals);
+ v = VEC_alloc (constructor_elt, gc, list_length (vals));
+ for (t = vals; t; t = TREE_CHAIN (t))
+ {
+ constructor_elt *elt = VEC_quick_push (constructor_elt, v, NULL);
+ val = TREE_VALUE (t);
+ elt->index = TREE_PURPOSE (t);
+ elt->value = val;
+ if (!TREE_CONSTANT (val))
+ constant_p = false;
+ }
}
- return c;
+ t = build_constructor (type, v);
+ TREE_CONSTANT (t) = constant_p;
+ return t;
}
+
/* Return a new REAL_CST node whose type is TYPE and value is D. */
tree
{
tree s;
size_t length;
-
- length = len + sizeof (struct tree_string);
+
+ /* Do not waste bytes provided by padding of struct tree_string. */
+ length = len + offsetof (struct tree_string, str) + 1;
#ifdef GATHER_STATISTICS
tree_node_counts[(int) c_kind]++;
memset (s, 0, sizeof (struct tree_common));
TREE_SET_CODE (s, STRING_CST);
+ 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';
return t;
}
+/* Return a constant of arithmetic type TYPE which is the
+ multiplicative identity of the set TYPE. */
+
+tree
+build_one_cst (tree type)
+{
+ switch (TREE_CODE (type))
+ {
+ case INTEGER_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE:
+ case POINTER_TYPE: case REFERENCE_TYPE:
+ case OFFSET_TYPE:
+ return build_int_cst (type, 1);
+
+ case REAL_TYPE:
+ return build_real (type, dconst1);
+
+ case VECTOR_TYPE:
+ {
+ tree scalar, cst;
+ int i;
+
+ scalar = build_one_cst (TREE_TYPE (type));
+
+ /* Create 'vect_cst_ = {cst,cst,...,cst}' */
+ cst = NULL_TREE;
+ for (i = TYPE_VECTOR_SUBPARTS (type); --i >= 0; )
+ cst = tree_cons (NULL_TREE, scalar, cst);
+
+ return build_vector (type, cst);
+ }
+
+ case COMPLEX_TYPE:
+ return build_complex (type,
+ build_one_cst (TREE_TYPE (type)),
+ fold_convert (TREE_TYPE (type), integer_zero_node));
+
+ default:
+ gcc_unreachable ();
+ }
+}
+
/* Build a BINFO with LEN language slots. */
tree
STRIP_NOPS (expr);
return ((TREE_CODE (expr) == INTEGER_CST
- && ! TREE_CONSTANT_OVERFLOW (expr)
&& TREE_INT_CST_LOW (expr) == 0
&& TREE_INT_CST_HIGH (expr) == 0)
|| (TREE_CODE (expr) == COMPLEX_CST
STRIP_NOPS (expr);
return ((TREE_CODE (expr) == INTEGER_CST
- && ! TREE_CONSTANT_OVERFLOW (expr)
&& TREE_INT_CST_LOW (expr) == 1
&& TREE_INT_CST_HIGH (expr) == 0)
|| (TREE_CODE (expr) == COMPLEX_CST
&& integer_zerop (TREE_IMAGPART (expr)))
return 1;
- else if (TREE_CODE (expr) != INTEGER_CST
- || TREE_CONSTANT_OVERFLOW (expr))
+ else if (TREE_CODE (expr) != INTEGER_CST)
return 0;
uns = TYPE_UNSIGNED (TREE_TYPE (expr));
+ if (TREE_INT_CST_LOW (expr) == ~(unsigned HOST_WIDE_INT) 0
+ && TREE_INT_CST_HIGH (expr) == -1)
+ return 1;
if (!uns)
- return (TREE_INT_CST_LOW (expr) == ~(unsigned HOST_WIDE_INT) 0
- && TREE_INT_CST_HIGH (expr) == -1);
+ return 0;
/* Note that using TYPE_PRECISION here is wrong. We care about the
actual bits, not the (arbitrary) range of the type. */
&& integer_zerop (TREE_IMAGPART (expr)))
return 1;
- if (TREE_CODE (expr) != INTEGER_CST || TREE_CONSTANT_OVERFLOW (expr))
+ if (TREE_CODE (expr) != INTEGER_CST)
return 0;
prec = (POINTER_TYPE_P (TREE_TYPE (expr))
STRIP_NOPS (expr);
return ((TREE_CODE (expr) == INTEGER_CST
- && ! TREE_CONSTANT_OVERFLOW (expr)
&& (TREE_INT_CST_LOW (expr) != 0
|| TREE_INT_CST_HIGH (expr) != 0))
|| (TREE_CODE (expr) == COMPLEX_CST
STRIP_NOPS (expr);
return ((TREE_CODE (expr) == REAL_CST
- && ! TREE_CONSTANT_OVERFLOW (expr)
&& REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconst0))
|| (TREE_CODE (expr) == COMPLEX_CST
&& real_zerop (TREE_REALPART (expr))
STRIP_NOPS (expr);
return ((TREE_CODE (expr) == REAL_CST
- && ! TREE_CONSTANT_OVERFLOW (expr)
&& REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconst1))
|| (TREE_CODE (expr) == COMPLEX_CST
&& real_onep (TREE_REALPART (expr))
STRIP_NOPS (expr);
return ((TREE_CODE (expr) == REAL_CST
- && ! TREE_CONSTANT_OVERFLOW (expr)
&& REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconst2))
|| (TREE_CODE (expr) == COMPLEX_CST
&& real_twop (TREE_REALPART (expr))
STRIP_NOPS (expr);
return ((TREE_CODE (expr) == REAL_CST
- && ! TREE_CONSTANT_OVERFLOW (expr)
&& REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconstm1))
|| (TREE_CODE (expr) == COMPLEX_CST
&& real_minus_onep (TREE_REALPART (expr))
t = TYPE_SIZE_UNIT (type);
if (t == 0
|| TREE_CODE (t) != INTEGER_CST
- || TREE_OVERFLOW (t)
|| TREE_INT_CST_HIGH (t) != 0
/* If the result would appear negative, it's too big to represent. */
|| (HOST_WIDE_INT) TREE_INT_CST_LOW (t) < 0)
return TREE_INT_CST_LOW (t);
}
+
+/* Return the maximum size of TYPE (in bytes) as a wide integer
+ or return -1 if the size can vary or is larger than an integer. */
+
+HOST_WIDE_INT
+max_int_size_in_bytes (tree type)
+{
+ HOST_WIDE_INT size = -1;
+ tree size_tree;
+
+ /* If this is an array type, check for a possible MAX_SIZE attached. */
+
+ if (TREE_CODE (type) == ARRAY_TYPE)
+ {
+ size_tree = TYPE_ARRAY_MAX_SIZE (type);
+
+ if (size_tree && host_integerp (size_tree, 1))
+ size = tree_low_cst (size_tree, 1);
+ }
+
+ /* If we still haven't been able to get a size, see if the language
+ can compute a maximum size. */
+
+ if (size == -1)
+ {
+ size_tree = lang_hooks.types.max_size (type);
+
+ if (size_tree && host_integerp (size_tree, 1))
+ size = tree_low_cst (size_tree, 1);
+ }
+
+ return size;
+}
\f
/* Return the bit position of FIELD, in bits from the start of the record.
This is a tree of type bitsizetype. */
case VAR_DECL:
return ((TREE_STATIC (arg) || DECL_EXTERNAL (arg))
&& ! DECL_THREAD_LOCAL_P (arg)
- && ! DECL_NON_ADDR_CONST_P (arg)
+ && ! DECL_DLLIMPORT_P (arg)
? arg : NULL);
case CONST_DECL:
enum tree_code code = TREE_CODE (t);
switch (TREE_CODE_CLASS (code))
- {
+ {
case tcc_declaration:
- return TS_DECL;
+ {
+ 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;
+ case SYMBOL_MEMORY_TAG:
+ case NAME_MEMORY_TAG:
+ case STRUCT_FIELD_TAG:
+ return TS_MEMORY_TAG;
+ default:
+ return TS_DECL_NON_COMMON;
+ }
+ }
case tcc_type:
return TS_TYPE;
case tcc_reference:
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 VALUE_HANDLE: return TS_VALUE_HANDLE;
+ case OMP_CLAUSE: return TS_OMP_CLAUSE;
default:
gcc_unreachable ();
|| CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 1))
|| CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 2)));
+ case CALL_EXPR:
+ return CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 1));
+
default:
break;
}
case COMPLEX_TYPE:
case ENUMERAL_TYPE:
case BOOLEAN_TYPE:
- case CHAR_TYPE:
case POINTER_TYPE:
case OFFSET_TYPE:
case REFERENCE_TYPE:
substitute_in_expr (tree exp, tree f, tree r)
{
enum tree_code code = TREE_CODE (exp);
- tree op0, op1, op2;
+ tree op0, op1, op2, op3;
tree new;
tree inner;
new = fold_build3 (code, TREE_TYPE (exp), op0, op1, op2);
break;
+ case 4:
+ op0 = SUBSTITUTE_IN_EXPR (TREE_OPERAND (exp, 0), f, r);
+ op1 = SUBSTITUTE_IN_EXPR (TREE_OPERAND (exp, 1), f, r);
+ op2 = SUBSTITUTE_IN_EXPR (TREE_OPERAND (exp, 2), f, r);
+ op3 = SUBSTITUTE_IN_EXPR (TREE_OPERAND (exp, 3), f, r);
+
+ if (op0 == TREE_OPERAND (exp, 0) && op1 == TREE_OPERAND (exp, 1)
+ && op2 == TREE_OPERAND (exp, 2)
+ && op3 == TREE_OPERAND (exp, 3))
+ return exp;
+
+ new = fold (build4 (code, TREE_TYPE (exp), op0, op1, op2, op3));
+ break;
+
default:
gcc_unreachable ();
}
TREE_INVARIANT, and TREE_SIDE_EFFECTS for an ADDR_EXPR. */
void
-recompute_tree_invarant_for_addr_expr (tree t)
+recompute_tree_invariant_for_addr_expr (tree t)
{
tree node;
bool tc = true, ti = true, se = false;
UPDATE_TITCSE (TREE_OPERAND (node, 2));
}
+ node = lang_hooks.expr_to_decl (node, &tc, &ti, &se);
+
/* Now see what's inside. If it's an INDIRECT_REF, copy our properties from
the address, since &(*a)->b is a form of addition. If it's a decl, it's
invariant and constant if the decl is static. It's also invariant if it's
Constants, decls, types and misc nodes cannot be.
We define 5 non-variadic functions, from 0 to 4 arguments. This is
- enough for all extant tree codes. These functions can be called
- directly (preferably!), but can also be obtained via GCC preprocessor
- magic within the build macro. */
+ enough for all extant tree codes. */
tree
build0_stat (enum tree_code code, tree tt MEM_STAT_DECL)
case ADDR_EXPR:
if (node)
- recompute_tree_invarant_for_addr_expr (t);
+ recompute_tree_invariant_for_addr_expr (t);
break;
default:
- if (TREE_CODE_CLASS (code) == tcc_unary
+ if ((TREE_CODE_CLASS (code) == tcc_unary || code == VIEW_CONVERT_EXPR)
&& node && !TYPE_P (node)
&& TREE_CONSTANT (node))
TREE_CONSTANT (t) = 1;
- if (TREE_CODE_CLASS (code) == tcc_unary
+ if ((TREE_CODE_CLASS (code) == tcc_unary || code == VIEW_CONVERT_EXPR)
&& node && TREE_INVARIANT (node))
TREE_INVARIANT (t) = 1;
if (TREE_CODE_CLASS (code) == tcc_reference
}
tree
-build7_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
- tree arg2, tree arg3, tree arg4, tree arg5,
- tree arg6 MEM_STAT_DECL)
+build5_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
+ tree arg2, tree arg3, tree arg4 MEM_STAT_DECL)
{
bool constant, read_only, side_effects, invariant;
tree t;
- gcc_assert (code == TARGET_MEM_REF);
+ gcc_assert (TREE_CODE_LENGTH (code) == 5);
t = make_node_stat (code PASS_MEM_STAT);
TREE_TYPE (t) = tt;
PROCESS_ARG(2);
PROCESS_ARG(3);
PROCESS_ARG(4);
- PROCESS_ARG(5);
- PROCESS_ARG(6);
TREE_SIDE_EFFECTS (t) = side_effects;
- TREE_THIS_VOLATILE (t) = 0;
+ TREE_THIS_VOLATILE (t)
+ = (TREE_CODE_CLASS (code) == tcc_reference
+ && arg0 && TREE_THIS_VOLATILE (arg0));
return t;
}
-/* Backup definition for non-gcc build compilers. */
-
tree
-(build) (enum tree_code code, tree tt, ...)
+build7_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
+ tree arg2, tree arg3, tree arg4, tree arg5,
+ tree arg6 MEM_STAT_DECL)
{
- tree t, arg0, arg1, arg2, arg3, arg4, arg5, arg6;
- int length = TREE_CODE_LENGTH (code);
- va_list p;
+ bool constant, read_only, side_effects, invariant;
+ tree t;
- va_start (p, tt);
- switch (length)
- {
- case 0:
- t = build0 (code, tt);
- break;
- case 1:
- arg0 = va_arg (p, tree);
- t = build1 (code, tt, arg0);
- break;
- case 2:
- arg0 = va_arg (p, tree);
- arg1 = va_arg (p, tree);
- t = build2 (code, tt, arg0, arg1);
- break;
- case 3:
- arg0 = va_arg (p, tree);
- arg1 = va_arg (p, tree);
- arg2 = va_arg (p, tree);
- t = build3 (code, tt, arg0, arg1, arg2);
- break;
- case 4:
- arg0 = va_arg (p, tree);
- arg1 = va_arg (p, tree);
- arg2 = va_arg (p, tree);
- arg3 = va_arg (p, tree);
- t = build4 (code, tt, arg0, arg1, arg2, arg3);
- break;
- case 7:
- arg0 = va_arg (p, tree);
- arg1 = va_arg (p, tree);
- arg2 = va_arg (p, tree);
- arg3 = va_arg (p, tree);
- arg4 = va_arg (p, tree);
- arg5 = va_arg (p, tree);
- arg6 = va_arg (p, tree);
- t = build7 (code, tt, arg0, arg1, arg2, arg3, arg4, arg5, arg6);
- break;
- default:
- gcc_unreachable ();
- }
- va_end (p);
+ gcc_assert (code == TARGET_MEM_REF);
+
+ t = make_node_stat (code PASS_MEM_STAT);
+ TREE_TYPE (t) = tt;
+
+ side_effects = TREE_SIDE_EFFECTS (t);
+
+ PROCESS_ARG(0);
+ PROCESS_ARG(1);
+ PROCESS_ARG(2);
+ PROCESS_ARG(3);
+ PROCESS_ARG(4);
+ PROCESS_ARG(5);
+ PROCESS_ARG(6);
+
+ TREE_SIDE_EFFECTS (t) = side_effects;
+ TREE_THIS_VOLATILE (t) = 0;
return t;
}
else if (code == FUNCTION_DECL)
DECL_MODE (t) = FUNCTION_MODE;
- /* Set default visibility to whatever the user supplied with
- visibility_specified depending on #pragma GCC visibility. */
- DECL_VISIBILITY (t) = default_visibility;
- DECL_VISIBILITY_SPECIFIED (t) = visibility_options.inpragma;
-
return t;
}
#if 1 /* ! defined(USE_MAPPED_LOCATION) */
/* ??? gengtype doesn't handle conditionals */
-static GTY(()) tree last_annotated_node;
+static GTY(()) source_locus last_annotated_node;
#endif
#ifdef USE_MAPPED_LOCATION
a node with the same information already attached to that node!
Just return instead of wasting memory. */
if (EXPR_LOCUS (node)
+ && EXPR_LINENO (node) == line
&& (EXPR_FILENAME (node) == file
- || ! strcmp (EXPR_FILENAME (node), file))
- && EXPR_LINENO (node) == line)
+ || !strcmp (EXPR_FILENAME (node), file)))
{
- last_annotated_node = node;
+ last_annotated_node = EXPR_LOCUS (node);
return;
}
entry cache can reduce the number of allocations by more
than half. */
if (last_annotated_node
- && EXPR_LOCUS (last_annotated_node)
- && (EXPR_FILENAME (last_annotated_node) == file
- || ! strcmp (EXPR_FILENAME (last_annotated_node), file))
- && EXPR_LINENO (last_annotated_node) == line)
+ && last_annotated_node->line == line
+ && (last_annotated_node->file == file
+ || !strcmp (last_annotated_node->file, file)))
{
- SET_EXPR_LOCUS (node, EXPR_LOCUS (last_annotated_node));
+ SET_EXPR_LOCUS (node, last_annotated_node);
return;
}
SET_EXPR_LOCUS (node, ggc_alloc (sizeof (location_t)));
EXPR_LINENO (node) = line;
EXPR_FILENAME (node) = file;
- last_annotated_node = node;
+ last_annotated_node = EXPR_LOCUS (node);
}
void
gcc_assert (attr[1] == '_');
gcc_assert (attr[attr_len - 2] == '_');
gcc_assert (attr[attr_len - 1] == '_');
- gcc_assert (attr[1] == '_');
if (ident_len == attr_len - 4
&& strncmp (attr + 2, p, attr_len - 4) == 0)
return 1;
return NULL_TREE;
}
+/* Remove any instances of attribute ATTR_NAME in LIST and return the
+ modified list. */
+
+tree
+remove_attribute (const char *attr_name, tree list)
+{
+ tree *p;
+ size_t attr_len = strlen (attr_name);
+
+ for (p = &list; *p; )
+ {
+ tree l = *p;
+ gcc_assert (TREE_CODE (TREE_PURPOSE (l)) == IDENTIFIER_NODE);
+ if (is_attribute_with_length_p (attr_name, attr_len, TREE_PURPOSE (l)))
+ *p = TREE_CHAIN (l);
+ else
+ p = &TREE_CHAIN (l);
+ }
+
+ return list;
+}
+
/* Return an attribute list that is the union of a1 and a2. */
tree
a = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (a2)),
TREE_CHAIN (a)))
{
- if (simple_cst_equal (TREE_VALUE (a), TREE_VALUE (a2)) == 1)
+ if (TREE_VALUE (a) != NULL
+ && TREE_CODE (TREE_VALUE (a)) == TREE_LIST
+ && TREE_VALUE (a2) != NULL
+ && TREE_CODE (TREE_VALUE (a2)) == TREE_LIST)
+ {
+ if (simple_cst_list_equal (TREE_VALUE (a),
+ TREE_VALUE (a2)) == 1)
+ break;
+ }
+ else if (simple_cst_equal (TREE_VALUE (a),
+ TREE_VALUE (a2)) == 1)
break;
}
if (a == NULL_TREE)
merge_dllimport_decl_attributes (tree old, tree new)
{
tree a;
- int delete_dllimport_p;
-
- old = DECL_ATTRIBUTES (old);
- new = DECL_ATTRIBUTES (new);
+ int delete_dllimport_p = 1;
/* What we need to do here is remove from `old' dllimport if it doesn't
appear in `new'. dllimport behaves like extern: if a declaration is
marked dllimport and a definition appears later, then the object
- is not dllimport'd. */
- if (lookup_attribute ("dllimport", old) != NULL_TREE
- && lookup_attribute ("dllimport", new) == NULL_TREE)
- delete_dllimport_p = 1;
+ is not dllimport'd. We also remove a `new' dllimport if the old list
+ contains dllexport: dllexport always overrides dllimport, regardless
+ of the order of declaration. */
+ if (!VAR_OR_FUNCTION_DECL_P (new))
+ delete_dllimport_p = 0;
+ else if (DECL_DLLIMPORT_P (new)
+ && lookup_attribute ("dllexport", DECL_ATTRIBUTES (old)))
+ {
+ DECL_DLLIMPORT_P (new) = 0;
+ warning (OPT_Wattributes, "%q+D already declared with dllexport attribute: "
+ "dllimport ignored", new);
+ }
+ else if (DECL_DLLIMPORT_P (old) && !DECL_DLLIMPORT_P (new))
+ {
+ /* Warn about overriding a symbol that has already been used. eg:
+ extern int __attribute__ ((dllimport)) foo;
+ int* bar () {return &foo;}
+ int foo;
+ */
+ if (TREE_USED (old))
+ {
+ warning (0, "%q+D redeclared without dllimport attribute "
+ "after being referenced with dll linkage", new);
+ /* If we have used a variable's address with dllimport linkage,
+ keep the old DECL_DLLIMPORT_P flag: the ADDR_EXPR using the
+ decl may already have had TREE_INVARIANT and TREE_CONSTANT
+ computed.
+ We still remove the attribute so that assembler code refers
+ to '&foo rather than '_imp__foo'. */
+ if (TREE_CODE (old) == VAR_DECL && TREE_ADDRESSABLE (old))
+ DECL_DLLIMPORT_P (new) = 1;
+ }
+
+ /* Let an inline definition silently override the external reference,
+ but otherwise warn about attribute inconsistency. */
+ else if (TREE_CODE (new) == VAR_DECL
+ || !DECL_DECLARED_INLINE_P (new))
+ warning (OPT_Wattributes, "%q+D redeclared without dllimport attribute: "
+ "previous dllimport ignored", new);
+ }
else
delete_dllimport_p = 0;
- a = merge_attributes (old, new);
+ a = merge_attributes (DECL_ATTRIBUTES (old), DECL_ATTRIBUTES (new));
- if (delete_dllimport_p)
+ if (delete_dllimport_p)
{
tree prev, t;
-
+ const size_t attr_len = strlen ("dllimport");
+
/* Scan the list for dllimport and delete it. */
for (prev = NULL_TREE, t = a; t; prev = t, t = TREE_CHAIN (t))
{
- if (is_attribute_p ("dllimport", TREE_PURPOSE (t)))
+ if (is_attribute_with_length_p ("dllimport", attr_len,
+ TREE_PURPOSE (t)))
{
if (prev == NULL_TREE)
a = TREE_CHAIN (a);
return NULL_TREE;
}
+ if (TREE_CODE (node) != FUNCTION_DECL
+ && TREE_CODE (node) != VAR_DECL)
+ {
+ *no_add_attrs = true;
+ warning (OPT_Wattributes, "%qs attribute ignored",
+ IDENTIFIER_POINTER (name));
+ return NULL_TREE;
+ }
+
/* Report error on dllimport ambiguities seen now before they cause
any damage. */
- if (is_attribute_p ("dllimport", name))
+ else if (is_attribute_p ("dllimport", name))
{
+ /* Honor any target-specific overrides. */
+ if (!targetm.valid_dllimport_attribute_p (node))
+ *no_add_attrs = true;
+
+ else if (TREE_CODE (node) == FUNCTION_DECL
+ && DECL_DECLARED_INLINE_P (node))
+ {
+ warning (OPT_Wattributes, "inline function %q+D declared as "
+ " dllimport: attribute ignored", node);
+ *no_add_attrs = true;
+ }
/* Like MS, treat definition of dllimported variables and
- non-inlined functions on declaration as syntax errors. We
- allow the attribute for function definitions if declared
- inline. */
- if (TREE_CODE (node) == FUNCTION_DECL && DECL_INITIAL (node)
- && !DECL_DECLARED_INLINE_P (node))
+ non-inlined functions on declaration as syntax errors. */
+ else if (TREE_CODE (node) == FUNCTION_DECL && DECL_INITIAL (node))
{
- error ("%Jfunction %qD definition is marked dllimport.", node, node);
+ error ("function %q+D definition is marked dllimport", node);
*no_add_attrs = true;
}
- else if (TREE_CODE (node) == VAR_DECL)
+ else if (TREE_CODE (node) == VAR_DECL)
{
if (DECL_INITIAL (node))
{
- error ("%Jvariable %qD definition is marked dllimport.",
- node, node);
+ error ("variable %q+D definition is marked dllimport",
+ node);
*no_add_attrs = true;
}
if (current_function_decl != NULL_TREE && !TREE_STATIC (node))
TREE_PUBLIC (node) = 1;
}
+
+ if (*no_add_attrs == false)
+ DECL_DLLIMPORT_P (node) = 1;
}
/* Report error if symbol is not accessible at global scope. */
&& (TREE_CODE (node) == VAR_DECL
|| TREE_CODE (node) == FUNCTION_DECL))
{
- error ("%Jexternal linkage required for symbol %qD because of "
- "%qs attribute.", node, node, IDENTIFIER_POINTER (name));
+ error ("external linkage required for symbol %q+D because of "
+ "%qs attribute", node, IDENTIFIER_POINTER (name));
*no_add_attrs = true;
}
\f
/* Return true if the from tree in both tree maps are equal. */
-static int
+int
tree_map_eq (const void *va, const void *vb)
{
const struct tree_map *a = va, *b = vb;
/* Hash a from tree in a tree_map. */
-static hashval_t
+unsigned int
tree_map_hash (const void *item)
{
return (((const struct tree_map *) item)->hash);
purposes. We simply return true if the from tree is marked, so that this
structure goes away when the from tree goes away. */
-static int
+int
tree_map_marked_p (const void *p)
{
tree from = ((struct tree_map *) p)->from;
return ggc_marked_p (from);
}
-/* Print out the statistics for the DECL_DEBUG_EXPR hash table. */
+/* Return true if the trees in the tree_int_map *'s VA and VB are equal. */
-static void
-print_debug_expr_statistics (void)
+static int
+tree_int_map_eq (const void *va, const void *vb)
{
- fprintf (stderr, "DECL_DEBUG_EXPR hash: size %ld, %ld elements, %f collisions\n",
- (long) htab_size (debug_expr_for_decl),
- (long) htab_elements (debug_expr_for_decl),
- htab_collisions (debug_expr_for_decl));
+ const struct tree_int_map *a = va, *b = vb;
+ return (a->from == b->from);
}
-/* Print out the statistics for the DECL_VALUE_EXPR hash table. */
+/* Hash a from tree in the tree_int_map * ITEM. */
-static void
-print_value_expr_statistics (void)
+static unsigned int
+tree_int_map_hash (const void *item)
{
- fprintf (stderr, "DECL_VALUE_EXPR hash: size %ld, %ld elements, %f collisions\n",
- (long) htab_size (value_expr_for_decl),
- (long) htab_elements (value_expr_for_decl),
- htab_collisions (value_expr_for_decl));
+ return htab_hash_pointer (((const struct tree_int_map *)item)->from);
}
-/* Lookup a debug expression for FROM, and return it if we find one. */
-tree
-decl_debug_expr_lookup (tree from)
+/* Return true if this tree int map structure is marked for garbage collection
+ purposes. We simply return true if the from tree_int_map *P's from tree is marked, so that this
+ structure goes away when the from tree goes away. */
+
+static int
+tree_int_map_marked_p (const void *p)
{
- struct tree_map *h, in;
+ tree from = ((struct tree_int_map *) p)->from;
+
+ return ggc_marked_p (from);
+}
+/* Lookup an init priority for FROM, and return it if we find one. */
+
+unsigned short
+decl_init_priority_lookup (tree from)
+{
+ struct tree_int_map *h, in;
in.from = from;
- h = htab_find_with_hash (debug_expr_for_decl, &in, htab_hash_pointer (from));
+ h = htab_find_with_hash (init_priority_for_decl,
+ &in, htab_hash_pointer (from));
if (h)
return h->to;
- return NULL_TREE;
+ return 0;
}
-/* Insert a mapping FROM->TO in the debug expression hashtable. */
+/* Insert a mapping FROM->TO in the init priority hashtable. */
void
-decl_debug_expr_insert (tree from, tree to)
+decl_init_priority_insert (tree from, unsigned short to)
{
- struct tree_map *h;
+ struct tree_int_map *h;
void **loc;
- h = ggc_alloc (sizeof (struct tree_map));
- h->hash = htab_hash_pointer (from);
+ h = ggc_alloc (sizeof (struct tree_int_map));
h->from = from;
h->to = to;
- loc = htab_find_slot_with_hash (debug_expr_for_decl, h, h->hash, INSERT);
+ loc = htab_find_slot_with_hash (init_priority_for_decl, h,
+ htab_hash_pointer (from), INSERT);
+ *(struct tree_int_map **) loc = h;
+}
+
+/* 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.from = from;
+ h = 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_alloc (sizeof (struct tree_map));
+ h->hash = htab_hash_pointer (from);
+ h->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
+print_debug_expr_statistics (void)
+{
+ fprintf (stderr, "DECL_DEBUG_EXPR hash: size %ld, %ld elements, %f collisions\n",
+ (long) htab_size (debug_expr_for_decl),
+ (long) htab_elements (debug_expr_for_decl),
+ htab_collisions (debug_expr_for_decl));
+}
+
+/* Print out the statistics for the DECL_VALUE_EXPR hash table. */
+
+static void
+print_value_expr_statistics (void)
+{
+ fprintf (stderr, "DECL_VALUE_EXPR hash: size %ld, %ld elements, %f collisions\n",
+ (long) htab_size (value_expr_for_decl),
+ (long) htab_elements (value_expr_for_decl),
+ 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
+decl_debug_expr_lookup (tree from)
+{
+ struct tree_map *h, in;
+ in.from = from;
+
+ h = htab_find_with_hash (debug_expr_for_decl, &in, htab_hash_pointer (from));
+ if (h)
+ return h->to;
+ return NULL_TREE;
+}
+
+/* Insert a mapping FROM->TO in the debug expression hashtable. */
+
+void
+decl_debug_expr_insert (tree from, tree to)
+{
+ struct tree_map *h;
+ void **loc;
+
+ h = ggc_alloc (sizeof (struct tree_map));
+ h->hash = htab_hash_pointer (from);
+ h->from = from;
+ h->to = to;
+ loc = htab_find_slot_with_hash (debug_expr_for_decl, h, h->hash, INSERT);
*(struct tree_map **) loc = h;
}
case INTEGER_TYPE:
case REAL_TYPE:
case BOOLEAN_TYPE:
- case CHAR_TYPE:
return ((TYPE_MAX_VALUE (a->type) == TYPE_MAX_VALUE (b->type)
|| tree_int_cst_equal (TYPE_MAX_VALUE (a->type),
TYPE_MAX_VALUE (b->type)))
attr = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (t2)),
TREE_CHAIN (attr)))
{
- if (simple_cst_equal (TREE_VALUE (t2), TREE_VALUE (attr)) == 1)
+ if (TREE_VALUE (t2) != NULL
+ && TREE_CODE (TREE_VALUE (t2)) == TREE_LIST
+ && TREE_VALUE (attr) != NULL
+ && TREE_CODE (TREE_VALUE (attr)) == TREE_LIST)
+ {
+ if (simple_cst_list_equal (TREE_VALUE (t2),
+ TREE_VALUE (attr)) == 1)
+ break;
+ }
+ else if (simple_cst_equal (TREE_VALUE (t2), TREE_VALUE (attr)) == 1)
break;
}
if (attr == 0)
return 0;
-
- if (simple_cst_equal (TREE_VALUE (t2), TREE_VALUE (attr)) != 1)
- return 0;
}
return 1;
/* Return 1 if T is an INTEGER_CST that can be manipulated efficiently on
the host. If POS is zero, the value can be represented in a single
- HOST_WIDE_INT. If POS is nonzero, the value must be positive and can
+ HOST_WIDE_INT. If POS is nonzero, the value must be non-negative and can
be represented in a single unsigned HOST_WIDE_INT. */
int
host_integerp (tree t, int pos)
{
return (TREE_CODE (t) == INTEGER_CST
- && ! TREE_OVERFLOW (t)
&& ((TREE_INT_CST_HIGH (t) == 0
&& (HOST_WIDE_INT) TREE_INT_CST_LOW (t) >= 0)
|| (! pos && TREE_INT_CST_HIGH (t) == -1
/* Return the HOST_WIDE_INT least significant bits of T if it is an
INTEGER_CST and there is no overflow. POS is nonzero if the result must
- be positive. We must be able to satisfy the above conditions. */
+ be non-negative. We must be able to satisfy the above conditions. */
HOST_WIDE_INT
tree_low_cst (tree t, int pos)
/* Return an indication of the sign of the integer constant T.
The return value is -1 if T < 0, 0 if T == 0, and 1 if T > 0.
- Note that -1 will never be returned it T's type is unsigned. */
+ Note that -1 will never be returned if T's type is unsigned. */
int
tree_int_cst_sgn (tree t)
TREE_STRING_LENGTH (t1)));
case CONSTRUCTOR:
- return simple_cst_list_equal (CONSTRUCTOR_ELTS (t1),
- CONSTRUCTOR_ELTS (t2));
+ {
+ unsigned HOST_WIDE_INT idx;
+ VEC(constructor_elt, gc) *v1 = CONSTRUCTOR_ELTS (t1);
+ VEC(constructor_elt, gc) *v2 = CONSTRUCTOR_ELTS (t2);
+
+ if (VEC_length (constructor_elt, v1) != VEC_length (constructor_elt, v2))
+ return false;
+
+ for (idx = 0; idx < VEC_length (constructor_elt, v1); ++idx)
+ /* ??? Should we handle also fields here? */
+ if (!simple_cst_equal (VEC_index (constructor_elt, v1, idx)->value,
+ VEC_index (constructor_elt, v2, idx)->value))
+ return false;
+ return true;
+ }
case SAVE_EXPR:
return simple_cst_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
for (; t; t = TREE_CHAIN (t))
val = iterative_hash_expr (TREE_VALUE (t), val);
return val;
+ case CONSTRUCTOR:
+ {
+ unsigned HOST_WIDE_INT idx;
+ tree field, value;
+ FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (t), idx, field, value)
+ {
+ val = iterative_hash_expr (field, val);
+ val = iterative_hash_expr (value, val);
+ }
+ return val;
+ }
case FUNCTION_DECL:
/* When referring to a built-in FUNCTION_DECL, use the
__builtin__ form. Otherwise nodes that compare equal
if (class == tcc_declaration)
{
- /* Otherwise, we can just compare decls by pointer. */
- val = iterative_hash_pointer (t, val);
+ /* DECL's have a unique ID */
+ val = iterative_hash_host_wide_int (DECL_UID (t), val);
}
else
{
{
tree t;
+ if (to_type == error_mark_node)
+ return error_mark_node;
+
/* In some cases, languages will have things that aren't a POINTER_TYPE
(such as a RECORD_TYPE for fat pointers in Ada) as TYPE_POINTER_TO.
In that case, return that type without regard to the rest of our
}
/* Create a range of some discrete type TYPE (an INTEGER_TYPE,
- ENUMERAL_TYPE, BOOLEAN_TYPE, or CHAR_TYPE), with
- low bound LOWVAL and high bound HIGHVAL.
- if TYPE==NULL_TREE, sizetype is used. */
+ ENUMERAL_TYPE or BOOLEAN_TYPE), with low bound LOWVAL and
+ high bound HIGHVAL. If TYPE is NULL, sizetype is used. */
tree
build_range_type (tree type, tree lowval, tree highval)
if (type == NULL_TREE)
type = sizetype;
- TYPE_MIN_VALUE (itype) = convert (type, lowval);
- TYPE_MAX_VALUE (itype) = highval ? convert (type, highval) : NULL;
+ TYPE_MIN_VALUE (itype) = fold_convert (type, lowval);
+ TYPE_MAX_VALUE (itype) = highval ? fold_convert (type, highval) : NULL;
TYPE_PRECISION (itype) = TYPE_PRECISION (type);
TYPE_MODE (itype) = TYPE_MODE (type);
if (index_type == 0)
{
- layout_type (t);
+ tree save = t;
+ hashcode = iterative_hash_object (TYPE_HASH (elt_type), hashcode);
+ t = type_hash_canon (hashcode, t);
+ if (save == t)
+ layout_type (t);
return t;
}
return 0;
/* If we haven't been able to decide at this point, there nothing more we
- can check ourselves here. Look at the base type if we have one. */
- if (TREE_CODE (type) == INTEGER_TYPE && TREE_TYPE (type) != 0)
+ can check ourselves here. Look at the base type if we have one and it
+ has the same precision. */
+ if (TREE_CODE (type) == INTEGER_TYPE
+ && TREE_TYPE (type) != 0
+ && 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. */
}
/* Returns true if T is, contains, or refers to a type with variable
- size. If FN is nonzero, only return true if a modifier of the type
- or position of FN is a variable or parameter inside FN.
+ size. For METHOD_TYPEs and FUNCTION_TYPEs we exclude the
+ arguments, but not the return type. If FN is nonzero, only return
+ true if a modifier of the type or position of FN is a variable or
+ parameter inside FN.
This concept is more general than that of C99 'variably modified types':
in C99, a struct type is never variably modified because a VLA may not
if (type == error_mark_node)
return false;
- /* If TYPE itself has variable size, it is variably modified.
-
- We do not yet have a representation of the C99 '[*]' syntax.
- When a representation is chosen, this function should be modified
- to test for that case as well. */
+ /* If TYPE itself has variable size, it is variably modified. */
RETURN_TRUE_IF_VAR (TYPE_SIZE (type));
- RETURN_TRUE_IF_VAR (TYPE_SIZE_UNIT(type));
+ RETURN_TRUE_IF_VAR (TYPE_SIZE_UNIT (type));
switch (TREE_CODE (type))
{
case POINTER_TYPE:
case REFERENCE_TYPE:
- case ARRAY_TYPE:
case VECTOR_TYPE:
if (variably_modified_type_p (TREE_TYPE (type), fn))
return true;
case FUNCTION_TYPE:
case METHOD_TYPE:
- /* If TYPE is a function type, it is variably modified if any of the
- parameters or the return type are variably modified. */
+ /* If TYPE is a function type, it is variably modified if the
+ return type is variably modified. */
if (variably_modified_type_p (TREE_TYPE (type), fn))
return true;
-
- for (t = TYPE_ARG_TYPES (type);
- t && t != void_list_node;
- t = TREE_CHAIN (t))
- if (variably_modified_type_p (TREE_VALUE (t), fn))
- return true;
break;
case INTEGER_TYPE:
case REAL_TYPE:
case ENUMERAL_TYPE:
case BOOLEAN_TYPE:
- case CHAR_TYPE:
/* Scalar types are variably modified if their end points
aren't constant. */
RETURN_TRUE_IF_VAR (TYPE_MIN_VALUE (type));
case RECORD_TYPE:
case UNION_TYPE:
case QUAL_UNION_TYPE:
- /* We can't see if any of the field are variably-modified by the
+ /* We can't see if any of the fields are variably-modified by the
definition we normally use, since that would produce infinite
recursion via pointers. */
/* This is variably modified if some field's type is. */
}
break;
+ case ARRAY_TYPE:
+ /* Do not call ourselves to avoid infinite recursion. This is
+ variably modified if the element type is. */
+ RETURN_TRUE_IF_VAR (TYPE_SIZE (TREE_TYPE (type)));
+ RETURN_TRUE_IF_VAR (TYPE_SIZE_UNIT (TREE_TYPE (type)));
+ break;
+
default:
break;
}
{
tree addr;
+ if (call == error_mark_node)
+ return call;
+
/* It's invalid to call this function with anything but a
CALL_EXPR. */
gcc_assert (TREE_CODE (call) == CALL_EXPR);
print_type_hash_statistics ();
print_debug_expr_statistics ();
print_value_expr_statistics ();
+ print_restrict_base_statistics ();
lang_hooks.print_statistics ();
}
\f
char *q;
if (first_global_object_name)
- p = first_global_object_name;
+ {
+ p = first_global_object_name;
+
+ /* For type 'F', the generated name must be unique not only to this
+ translation unit but also to any given link. Since global names
+ can be overloaded, we concatenate the first global object name
+ with a string derived from the file name of this object. */
+ if (!strcmp (type, "F"))
+ {
+ const char *file = main_input_filename;
+
+ if (! file)
+ file = input_filename;
+
+ q = alloca (strlen (p) + 10);
+ sprintf (q, "%s_%08X", p, crc32_string (0, file));
+
+ p = q;
+ }
+ }
else
{
/* We don't have anything that we know to be unique to this translation
tree_code_name[TREE_CODE (node)], function, trim_filename (file), line);
}
+/* Similar to tree_check_failed, except that instead of specifying a
+ dozen codes, use the knowledge that they're all sequential. */
+
+void
+tree_range_check_failed (const tree node, const char *file, int line,
+ const char *function, enum tree_code c1,
+ enum tree_code c2)
+{
+ char *buffer;
+ unsigned length = 0;
+ enum tree_code c;
+
+ for (c = c1; c <= c2; ++c)
+ length += 4 + strlen (tree_code_name[c]);
+
+ length += strlen ("expected ");
+ buffer = alloca (length);
+ length = 0;
+
+ for (c = c1; c <= c2; ++c)
+ {
+ const char *prefix = length ? " or " : "expected ";
+
+ strcpy (buffer + length, prefix);
+ length += strlen (prefix);
+ strcpy (buffer + length, tree_code_name[c]);
+ length += strlen (tree_code_name[c]);
+ }
+
+ internal_error ("tree check: %s, have %s in %s, at %s:%d",
+ buffer, tree_code_name[TREE_CODE (node)],
+ function, trim_filename (file), line);
+}
+
+
+/* Similar to tree_check_failed, except that we check that a tree does
+ not have the specified code, given in CL. */
+
+void
+tree_not_class_check_failed (const tree node, const enum tree_code_class cl,
+ const char *file, int line, const char *function)
+{
+ internal_error
+ ("tree check: did not expect class %qs, have %qs (%s) in %s, at %s:%d",
+ TREE_CODE_CLASS_STRING (cl),
+ TREE_CODE_CLASS_STRING (TREE_CODE_CLASS (TREE_CODE (node))),
+ tree_code_name[TREE_CODE (node)], function, trim_filename (file), line);
+}
+
+
+/* Similar to tree_check_failed but applied to OMP_CLAUSE codes. */
+
+void
+omp_clause_check_failed (const tree node, const char *file, int line,
+ const char *function, enum omp_clause_code code)
+{
+ internal_error ("tree check: expected omp_clause %s, have %s in %s, at %s:%d",
+ omp_clause_code_name[code], tree_code_name[TREE_CODE (node)],
+ function, trim_filename (file), line);
+}
+
+
+/* Similar to tree_range_check_failed but applied to OMP_CLAUSE codes. */
+
+void
+omp_clause_range_check_failed (const tree node, const char *file, int line,
+ const char *function, enum omp_clause_code c1,
+ enum omp_clause_code c2)
+{
+ char *buffer;
+ unsigned length = 0;
+ enum omp_clause_code c;
+
+ for (c = c1; c <= c2; ++c)
+ length += 4 + strlen (omp_clause_code_name[c]);
+
+ length += strlen ("expected ");
+ buffer = alloca (length);
+ length = 0;
+
+ for (c = c1; c <= c2; ++c)
+ {
+ const char *prefix = length ? " or " : "expected ";
+
+ strcpy (buffer + length, prefix);
+ length += strlen (prefix);
+ strcpy (buffer + length, omp_clause_code_name[c]);
+ length += strlen (omp_clause_code_name[c]);
+ }
+
+ internal_error ("tree check: %s, have %s in %s, at %s:%d",
+ buffer, omp_clause_code_name[TREE_CODE (node)],
+ function, trim_filename (file), line);
+}
+
+
+#undef DEFTREESTRUCT
+#define DEFTREESTRUCT(VAL, NAME) NAME,
+
+static const char *ts_enum_names[] = {
+#include "treestruct.def"
+};
+#undef DEFTREESTRUCT
+
+#define TS_ENUM_NAME(EN) (ts_enum_names[(EN)])
+
+/* Similar to tree_class_check_failed, except that we check for
+ whether CODE contains the tree structure identified by EN. */
+
+void
+tree_contains_struct_check_failed (const tree node,
+ const enum tree_node_structure_enum en,
+ const char *file, int line,
+ const char *function)
+{
+ internal_error
+ ("tree check: expected tree that contains %qs structure, have %qs in %s, at %s:%d",
+ TS_ENUM_NAME(en),
+ tree_code_name[TREE_CODE (node)], function, trim_filename (file), line);
+}
+
+
/* Similar to above, except that the check is for the bounds of a TREE_VEC's
(dynamically sized) vector. */
idx + 1, tree_code_name[code], TREE_CODE_LENGTH (code),
function, trim_filename (file), line);
}
+
+/* Similar to above, except that the check is for the number of
+ operands of an OMP_CLAUSE node. */
+
+void
+omp_clause_operand_check_failed (int idx, tree t, const char *file,
+ int line, const char *function)
+{
+ internal_error
+ ("tree check: accessed operand %d of omp_clause %s with %d operands "
+ "in %s, at %s:%d", idx + 1, omp_clause_code_name[OMP_CLAUSE_CODE (t)],
+ omp_clause_num_ops [OMP_CLAUSE_CODE (t)], function,
+ trim_filename (file), line);
+}
#endif /* ENABLE_TREE_CHECKING */
\f
/* Create a new vector type node holding SUBPARTS units of type INNERTYPE,
/* Define both `signed char' and `unsigned char'. */
signed_char_type_node = make_signed_type (CHAR_TYPE_SIZE);
+ TYPE_STRING_FLAG (signed_char_type_node) = 1;
unsigned_char_type_node = make_unsigned_type (CHAR_TYPE_SIZE);
+ TYPE_STRING_FLAG (unsigned_char_type_node) = 1;
/* Define `char', which is like either `signed char' or `unsigned char'
but not the same as either. */
= (signed_char
? make_signed_type (CHAR_TYPE_SIZE)
: make_unsigned_type (CHAR_TYPE_SIZE));
+ TYPE_STRING_FLAG (char_type_node) = 1;
short_integer_type_node = make_signed_type (SHORT_TYPE_SIZE);
short_unsigned_type_node = make_unsigned_type (SHORT_TYPE_SIZE);
long_double_ptr_type_node = build_pointer_type (long_double_type_node);
integer_ptr_type_node = build_pointer_type (integer_type_node);
+ /* Decimal float types. */
+ dfloat32_type_node = make_node (REAL_TYPE);
+ TYPE_PRECISION (dfloat32_type_node) = DECIMAL32_TYPE_SIZE;
+ layout_type (dfloat32_type_node);
+ TYPE_MODE (dfloat32_type_node) = SDmode;
+ dfloat32_ptr_type_node = build_pointer_type (dfloat32_type_node);
+
+ dfloat64_type_node = make_node (REAL_TYPE);
+ TYPE_PRECISION (dfloat64_type_node) = DECIMAL64_TYPE_SIZE;
+ layout_type (dfloat64_type_node);
+ TYPE_MODE (dfloat64_type_node) = DDmode;
+ dfloat64_ptr_type_node = build_pointer_type (dfloat64_type_node);
+
+ dfloat128_type_node = make_node (REAL_TYPE);
+ TYPE_PRECISION (dfloat128_type_node) = DECIMAL128_TYPE_SIZE;
+ layout_type (dfloat128_type_node);
+ TYPE_MODE (dfloat128_type_node) = TDmode;
+ dfloat128_ptr_type_node = build_pointer_type (dfloat128_type_node);
+
complex_integer_type_node = make_node (COMPLEX_TYPE);
TREE_TYPE (complex_integer_type_node) = integer_type_node;
layout_type (complex_integer_type_node);
"__builtin_nonlocal_goto",
ECF_NORETURN | ECF_NOTHROW);
+ tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
+ tmp = tree_cons (NULL_TREE, ptr_type_node, tmp);
+ ftype = build_function_type (void_type_node, tmp);
+ local_define_builtin ("__builtin_setjmp_setup", ftype,
+ BUILT_IN_SETJMP_SETUP,
+ "__builtin_setjmp_setup", ECF_NOTHROW);
+
+ tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
+ ftype = build_function_type (ptr_type_node, tmp);
+ local_define_builtin ("__builtin_setjmp_dispatcher", ftype,
+ BUILT_IN_SETJMP_DISPATCHER,
+ "__builtin_setjmp_dispatcher",
+ ECF_PURE | ECF_NOTHROW);
+
+ tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
+ ftype = build_function_type (void_type_node, tmp);
+ local_define_builtin ("__builtin_setjmp_receiver", ftype,
+ BUILT_IN_SETJMP_RECEIVER,
+ "__builtin_setjmp_receiver", ECF_NOTHROW);
+
ftype = build_function_type (ptr_type_node, void_list_node);
local_define_builtin ("__builtin_stack_save", ftype, BUILT_IN_STACK_SAVE,
"__builtin_stack_save", ECF_NOTHROW);
return true;
case CONSTRUCTOR:
- elt = CONSTRUCTOR_ELTS (init);
- if (elt == NULL_TREE)
- return true;
+ {
+ unsigned HOST_WIDE_INT idx;
- for (; elt ; elt = TREE_CHAIN (elt))
- if (! initializer_zerop (TREE_VALUE (elt)))
- return false;
- return true;
+ FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (init), idx, elt)
+ if (!initializer_zerop (elt))
+ return false;
+ return true;
+ }
default:
return false;
}
}
-void
-add_var_to_bind_expr (tree bind_expr, tree var)
-{
- BIND_EXPR_VARS (bind_expr)
- = chainon (BIND_EXPR_VARS (bind_expr), var);
- if (BIND_EXPR_BLOCK (bind_expr))
- BLOCK_VARS (BIND_EXPR_BLOCK (bind_expr))
- = BIND_EXPR_VARS (bind_expr);
-}
-
/* Build an empty statement. */
tree
}
+/* Build an OpenMP clause with code CODE. */
+
+tree
+build_omp_clause (enum omp_clause_code code)
+{
+ tree t;
+ int size, length;
+
+ length = omp_clause_num_ops[code];
+ size = (sizeof (struct tree_omp_clause) + (length - 1) * sizeof (tree));
+
+ t = ggc_alloc (size);
+ memset (t, 0, size);
+ TREE_SET_CODE (t, OMP_CLAUSE);
+ OMP_CLAUSE_SET_CODE (t, code);
+
+#ifdef GATHER_STATISTICS
+ tree_node_counts[(int) omp_clause_kind]++;
+ tree_node_sizes[(int) omp_clause_kind] += size;
+#endif
+
+ return t;
+}
+
+
/* Returns true if it is possible to prove that the index of
an array access REF (an ARRAY_REF expression) falls into the
array bounds. */
return true;
}
+/* Returns true if it is possible to prove that the range of
+ an array access REF (an ARRAY_RANGE_REF expression) falls
+ into the array bounds. */
+
+bool
+range_in_array_bounds_p (tree ref)
+{
+ tree domain_type = TYPE_DOMAIN (TREE_TYPE (ref));
+ tree range_min, range_max, min, max;
+
+ range_min = TYPE_MIN_VALUE (domain_type);
+ range_max = TYPE_MAX_VALUE (domain_type);
+ if (!range_min
+ || !range_max
+ || TREE_CODE (range_min) != INTEGER_CST
+ || TREE_CODE (range_max) != INTEGER_CST)
+ return false;
+
+ min = array_ref_low_bound (ref);
+ max = array_ref_up_bound (ref);
+ if (!min
+ || !max
+ || TREE_CODE (min) != INTEGER_CST
+ || TREE_CODE (max) != INTEGER_CST)
+ return false;
+
+ if (tree_int_cst_lt (range_min, min)
+ || tree_int_cst_lt (max, range_max))
+ return false;
+
+ return true;
+}
+
/* Return true if T (assumed to be a DECL) is a global variable. */
bool
is_global_var (tree t)
{
- return (TREE_STATIC (t) || DECL_EXTERNAL (t));
+ if (MTAG_P (t))
+ return (TREE_STATIC (t) || MTAG_GLOBAL (t));
+ else
+ return (TREE_STATIC (t) || DECL_EXTERNAL (t));
}
/* Return true if T (assumed to be a DECL) must be assigned a memory
if (tree_int_cst_sgn (a) == -1)
a = fold_build2 (MULT_EXPR, type, a,
- convert (type, integer_minus_one_node));
+ build_int_cst (type, -1));
if (tree_int_cst_sgn (b) == -1)
b = fold_build2 (MULT_EXPR, type, b,
- convert (type, integer_minus_one_node));
+ build_int_cst (type, -1));
while (1)
{
tree
unsigned_type_for (tree type)
{
+ if (POINTER_TYPE_P (type))
+ return lang_hooks.types.unsigned_type (size_type_node);
return lang_hooks.types.unsigned_type (type);
}
tree
signed_type_for (tree type)
{
+ if (POINTER_TYPE_P (type))
+ return lang_hooks.types.signed_type (size_type_node);
return lang_hooks.types.signed_type (type);
}
upper_bound_in_type (tree outer, tree inner)
{
unsigned HOST_WIDE_INT lo, hi;
- unsigned bits = TYPE_PRECISION (inner);
+ unsigned int det = 0;
+ unsigned oprec = TYPE_PRECISION (outer);
+ unsigned iprec = TYPE_PRECISION (inner);
+ unsigned prec;
+
+ /* Compute a unique number for every combination. */
+ det |= (oprec > iprec) ? 4 : 0;
+ det |= TYPE_UNSIGNED (outer) ? 2 : 0;
+ det |= TYPE_UNSIGNED (inner) ? 1 : 0;
+
+ /* Determine the exponent to use. */
+ switch (det)
+ {
+ case 0:
+ case 1:
+ /* oprec <= iprec, outer: signed, inner: don't care. */
+ prec = oprec - 1;
+ break;
+ case 2:
+ case 3:
+ /* oprec <= iprec, outer: unsigned, inner: don't care. */
+ prec = oprec;
+ break;
+ case 4:
+ /* oprec > iprec, outer: signed, inner: signed. */
+ prec = iprec - 1;
+ break;
+ case 5:
+ /* oprec > iprec, outer: signed, inner: unsigned. */
+ prec = iprec;
+ break;
+ case 6:
+ /* oprec > iprec, outer: unsigned, inner: signed. */
+ prec = oprec;
+ break;
+ case 7:
+ /* oprec > iprec, outer: unsigned, inner: unsigned. */
+ prec = iprec;
+ break;
+ default:
+ gcc_unreachable ();
+ }
- if (TYPE_UNSIGNED (outer) || TYPE_UNSIGNED (inner))
+ /* Compute 2^^prec - 1. */
+ if (prec <= HOST_BITS_PER_WIDE_INT)
{
- /* Zero extending in these cases. */
- if (bits <= HOST_BITS_PER_WIDE_INT)
- {
- hi = 0;
- lo = (~(unsigned HOST_WIDE_INT) 0)
- >> (HOST_BITS_PER_WIDE_INT - bits);
- }
- else
- {
- hi = (~(unsigned HOST_WIDE_INT) 0)
- >> (2 * HOST_BITS_PER_WIDE_INT - bits);
- lo = ~(unsigned HOST_WIDE_INT) 0;
- }
+ hi = 0;
+ lo = ((~(unsigned HOST_WIDE_INT) 0)
+ >> (HOST_BITS_PER_WIDE_INT - prec));
}
else
{
- /* Sign extending in these cases. */
- if (bits <= HOST_BITS_PER_WIDE_INT)
- {
- hi = 0;
- lo = (~(unsigned HOST_WIDE_INT) 0)
- >> (HOST_BITS_PER_WIDE_INT - bits) >> 1;
- }
- else
- {
- hi = (~(unsigned HOST_WIDE_INT) 0)
- >> (2 * HOST_BITS_PER_WIDE_INT - bits) >> 1;
- lo = ~(unsigned HOST_WIDE_INT) 0;
- }
+ hi = ((~(unsigned HOST_WIDE_INT) 0)
+ >> (2 * HOST_BITS_PER_WIDE_INT - prec));
+ lo = ~(unsigned HOST_WIDE_INT) 0;
}
- return fold_convert (outer,
- build_int_cst_wide (inner, lo, hi));
+ return build_int_cst_wide (outer, lo, hi);
}
/* Returns the smallest value obtainable by casting something in INNER type to
lower_bound_in_type (tree outer, tree inner)
{
unsigned HOST_WIDE_INT lo, hi;
- unsigned bits = TYPE_PRECISION (inner);
-
- if (TYPE_UNSIGNED (outer) || TYPE_UNSIGNED (inner))
+ unsigned oprec = TYPE_PRECISION (outer);
+ unsigned iprec = TYPE_PRECISION (inner);
+
+ /* If OUTER type is unsigned, we can definitely cast 0 to OUTER type
+ and obtain 0. */
+ if (TYPE_UNSIGNED (outer)
+ /* If we are widening something of an unsigned type, OUTER type
+ contains all values of INNER type. In particular, both INNER
+ and OUTER types have zero in common. */
+ || (oprec > iprec && TYPE_UNSIGNED (inner)))
lo = hi = 0;
- else if (bits <= HOST_BITS_PER_WIDE_INT)
- {
- hi = ~(unsigned HOST_WIDE_INT) 0;
- lo = (~(unsigned HOST_WIDE_INT) 0) << (bits - 1);
- }
else
{
- hi = (~(unsigned HOST_WIDE_INT) 0) << (bits - HOST_BITS_PER_WIDE_INT - 1);
- lo = 0;
+ /* If we are widening a signed type to another signed type, we
+ want to obtain -2^^(iprec-1). If we are keeping the
+ precision or narrowing to a signed type, we want to obtain
+ -2^(oprec-1). */
+ unsigned prec = oprec > iprec ? iprec : oprec;
+
+ if (prec <= HOST_BITS_PER_WIDE_INT)
+ {
+ hi = ~(unsigned HOST_WIDE_INT) 0;
+ lo = (~(unsigned HOST_WIDE_INT) 0) << (prec - 1);
+ }
+ else
+ {
+ hi = ((~(unsigned HOST_WIDE_INT) 0)
+ << (prec - HOST_BITS_PER_WIDE_INT - 1));
+ lo = 0;
+ }
}
- return fold_convert (outer,
- build_int_cst_wide (inner, lo, hi));
+ return build_int_cst_wide (outer, lo, hi);
}
/* Return nonzero if two operands that are suitable for PHI nodes are
case BOOLEAN_TYPE:
case ENUMERAL_TYPE:
case INTEGER_TYPE:
- case CHAR_TYPE:
case REAL_TYPE:
WALK_SUBTREE (TYPE_MIN_VALUE (type));
WALK_SUBTREE (TYPE_MAX_VALUE (type));
interesting below this point in the tree. */
if (!walk_subtrees)
{
+ /* But we still need to check our siblings. */
if (code == TREE_LIST)
- /* But we still need to check our siblings. */
WALK_SUBTREE_TAIL (TREE_CHAIN (*tp));
+ else if (code == OMP_CLAUSE)
+ WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp));
else
return NULL_TREE;
}
if (result || ! walk_subtrees)
return result;
- /* If this is a DECL_EXPR, walk into various fields of the type that it's
- defining. We only want to walk into these fields of a type in this
- case. Note that decls get walked as part of the processing of a
- BIND_EXPR.
-
- ??? Precisely which fields of types that we are supposed to walk in
- this case vs. the normal case aren't well defined. */
- if (code == DECL_EXPR
- && TREE_CODE (DECL_EXPR_DECL (*tp)) == TYPE_DECL
- && TREE_CODE (TREE_TYPE (DECL_EXPR_DECL (*tp))) != ERROR_MARK)
+ switch (code)
{
- tree *type_p = &TREE_TYPE (DECL_EXPR_DECL (*tp));
+ case ERROR_MARK:
+ case IDENTIFIER_NODE:
+ case INTEGER_CST:
+ case REAL_CST:
+ case VECTOR_CST:
+ case STRING_CST:
+ case BLOCK:
+ case PLACEHOLDER_EXPR:
+ case SSA_NAME:
+ case FIELD_DECL:
+ case RESULT_DECL:
+ /* None of these have subtrees other than those already walked
+ above. */
+ break;
- /* Call the function for the type. See if it returns anything or
- doesn't want us to continue. If we are to continue, walk both
- the normal fields and those for the declaration case. */
- result = (*func) (type_p, &walk_subtrees, data);
- if (result || !walk_subtrees)
- return NULL_TREE;
+ case TREE_LIST:
+ WALK_SUBTREE (TREE_VALUE (*tp));
+ WALK_SUBTREE_TAIL (TREE_CHAIN (*tp));
+ break;
- result = walk_type_fields (*type_p, func, data, pset);
- if (result)
- return result;
+ case TREE_VEC:
+ {
+ int len = TREE_VEC_LENGTH (*tp);
- WALK_SUBTREE (TYPE_SIZE (*type_p));
- WALK_SUBTREE (TYPE_SIZE_UNIT (*type_p));
+ if (len == 0)
+ break;
- /* If this is a record type, also walk the fields. */
- if (TREE_CODE (*type_p) == RECORD_TYPE
- || TREE_CODE (*type_p) == UNION_TYPE
- || TREE_CODE (*type_p) == QUAL_UNION_TYPE)
- {
- tree field;
+ /* Walk all elements but the first. */
+ while (--len)
+ WALK_SUBTREE (TREE_VEC_ELT (*tp, len));
- for (field = TYPE_FIELDS (*type_p); field;
- field = TREE_CHAIN (field))
- {
- /* We'd like to look at the type of the field, but we can easily
- get infinite recursion. So assume it's pointed to elsewhere
- in the tree. Also, ignore things that aren't fields. */
- if (TREE_CODE (field) != FIELD_DECL)
- continue;
-
- WALK_SUBTREE (DECL_FIELD_OFFSET (field));
- WALK_SUBTREE (DECL_SIZE (field));
- WALK_SUBTREE (DECL_SIZE_UNIT (field));
- if (TREE_CODE (*type_p) == QUAL_UNION_TYPE)
- WALK_SUBTREE (DECL_QUALIFIER (field));
- }
- }
- }
+ /* Now walk the first one as a tail call. */
+ WALK_SUBTREE_TAIL (TREE_VEC_ELT (*tp, 0));
+ }
- else if (code != SAVE_EXPR
- && code != BIND_EXPR
- && IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code)))
- {
- int i, len;
-
- /* Walk over all the sub-trees of this operand. */
- len = TREE_CODE_LENGTH (code);
- /* TARGET_EXPRs are peculiar: operands 1 and 3 can be the same.
- But, we only want to walk once. */
- if (code == TARGET_EXPR
- && TREE_OPERAND (*tp, 3) == TREE_OPERAND (*tp, 1))
- --len;
-
- /* Go through the subtrees. We need to do this in forward order so
- that the scope of a FOR_EXPR is handled properly. */
-#ifdef DEBUG_WALK_TREE
- for (i = 0; i < len; ++i)
- WALK_SUBTREE (TREE_OPERAND (*tp, i));
-#else
- for (i = 0; i < len - 1; ++i)
- WALK_SUBTREE (TREE_OPERAND (*tp, i));
+ case COMPLEX_CST:
+ WALK_SUBTREE (TREE_REALPART (*tp));
+ WALK_SUBTREE_TAIL (TREE_IMAGPART (*tp));
- if (len)
- {
- /* The common case is that we may tail recurse here. */
- if (code != BIND_EXPR
- && !TREE_CHAIN (*tp))
- WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, len - 1));
- else
- WALK_SUBTREE (TREE_OPERAND (*tp, len - 1));
- }
-#endif
- }
+ case CONSTRUCTOR:
+ {
+ unsigned HOST_WIDE_INT idx;
+ constructor_elt *ce;
- /* If this is a type, walk the needed fields in the type. */
- else if (TYPE_P (*tp))
- {
- result = walk_type_fields (*tp, func, data, pset);
- if (result)
- return result;
- }
- else
- {
- /* Not one of the easy cases. We must explicitly go through the
- children. */
- switch (code)
- {
- case ERROR_MARK:
- case IDENTIFIER_NODE:
- case INTEGER_CST:
- case REAL_CST:
- case VECTOR_CST:
- case STRING_CST:
- case BLOCK:
- case PLACEHOLDER_EXPR:
- case SSA_NAME:
- case FIELD_DECL:
- case RESULT_DECL:
- /* None of these have subtrees other than those already walked
- above. */
- break;
+ for (idx = 0;
+ VEC_iterate(constructor_elt, CONSTRUCTOR_ELTS (*tp), idx, ce);
+ idx++)
+ WALK_SUBTREE (ce->value);
+ }
+ break;
- case TREE_LIST:
- WALK_SUBTREE (TREE_VALUE (*tp));
- WALK_SUBTREE_TAIL (TREE_CHAIN (*tp));
- break;
+ case SAVE_EXPR:
+ WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, 0));
- case TREE_VEC:
+ case BIND_EXPR:
+ {
+ tree decl;
+ for (decl = BIND_EXPR_VARS (*tp); decl; decl = TREE_CHAIN (decl))
{
- int len = TREE_VEC_LENGTH (*tp);
-
- if (len == 0)
- break;
+ /* Walk the DECL_INITIAL and DECL_SIZE. We don't want to walk
+ into declarations that are just mentioned, rather than
+ declared; they don't really belong to this part of the tree.
+ And, we can see cycles: the initializer for a declaration
+ can refer to the declaration itself. */
+ WALK_SUBTREE (DECL_INITIAL (decl));
+ WALK_SUBTREE (DECL_SIZE (decl));
+ WALK_SUBTREE (DECL_SIZE_UNIT (decl));
+ }
+ WALK_SUBTREE_TAIL (BIND_EXPR_BODY (*tp));
+ }
- /* Walk all elements but the first. */
- while (--len)
- WALK_SUBTREE (TREE_VEC_ELT (*tp, len));
+ case STATEMENT_LIST:
+ {
+ tree_stmt_iterator i;
+ for (i = tsi_start (*tp); !tsi_end_p (i); tsi_next (&i))
+ WALK_SUBTREE (*tsi_stmt_ptr (i));
+ }
+ break;
- /* Now walk the first one as a tail call. */
- WALK_SUBTREE_TAIL (TREE_VEC_ELT (*tp, 0));
+ case OMP_CLAUSE:
+ switch (OMP_CLAUSE_CODE (*tp))
+ {
+ case OMP_CLAUSE_PRIVATE:
+ case OMP_CLAUSE_SHARED:
+ case OMP_CLAUSE_FIRSTPRIVATE:
+ case OMP_CLAUSE_LASTPRIVATE:
+ case OMP_CLAUSE_COPYIN:
+ case OMP_CLAUSE_COPYPRIVATE:
+ case OMP_CLAUSE_IF:
+ case OMP_CLAUSE_NUM_THREADS:
+ case OMP_CLAUSE_SCHEDULE:
+ WALK_SUBTREE (OMP_CLAUSE_OPERAND (*tp, 0));
+ /* FALLTHRU */
+
+ case OMP_CLAUSE_NOWAIT:
+ case OMP_CLAUSE_ORDERED:
+ case OMP_CLAUSE_DEFAULT:
+ WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp));
+
+ case OMP_CLAUSE_REDUCTION:
+ {
+ int i;
+ for (i = 0; i < 4; i++)
+ WALK_SUBTREE (OMP_CLAUSE_OPERAND (*tp, i));
+ WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp));
}
- case COMPLEX_CST:
- WALK_SUBTREE (TREE_REALPART (*tp));
- WALK_SUBTREE_TAIL (TREE_IMAGPART (*tp));
+ default:
+ gcc_unreachable ();
+ }
+ break;
- case CONSTRUCTOR:
- WALK_SUBTREE_TAIL (CONSTRUCTOR_ELTS (*tp));
+ case TARGET_EXPR:
+ {
+ int i, len;
+
+ /* TARGET_EXPRs are peculiar: operands 1 and 3 can be the same.
+ But, we only want to walk once. */
+ len = (TREE_OPERAND (*tp, 3) == TREE_OPERAND (*tp, 1)) ? 2 : 3;
+ for (i = 0; i < len; ++i)
+ WALK_SUBTREE (TREE_OPERAND (*tp, i));
+ WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, len));
+ }
- case SAVE_EXPR:
- WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, 0));
+ case DECL_EXPR:
+ /* Walk into various fields of the type that it's defining. We only
+ want to walk into these fields of a type in this case. Note that
+ decls get walked as part of the processing of a BIND_EXPR.
- case BIND_EXPR:
- {
- tree decl;
- for (decl = BIND_EXPR_VARS (*tp); decl; decl = TREE_CHAIN (decl))
- {
- /* Walk the DECL_INITIAL and DECL_SIZE. We don't want to walk
- into declarations that are just mentioned, rather than
- declared; they don't really belong to this part of the tree.
- And, we can see cycles: the initializer for a declaration
- can refer to the declaration itself. */
- WALK_SUBTREE (DECL_INITIAL (decl));
- WALK_SUBTREE (DECL_SIZE (decl));
- WALK_SUBTREE (DECL_SIZE_UNIT (decl));
- }
- WALK_SUBTREE_TAIL (BIND_EXPR_BODY (*tp));
- }
+ ??? Precisely which fields of types that we are supposed to walk in
+ this case vs. the normal case aren't well defined. */
+ if (TREE_CODE (DECL_EXPR_DECL (*tp)) == TYPE_DECL
+ && TREE_CODE (TREE_TYPE (DECL_EXPR_DECL (*tp))) != ERROR_MARK)
+ {
+ tree *type_p = &TREE_TYPE (DECL_EXPR_DECL (*tp));
- case STATEMENT_LIST:
- {
- tree_stmt_iterator i;
- for (i = tsi_start (*tp); !tsi_end_p (i); tsi_next (&i))
- WALK_SUBTREE (*tsi_stmt_ptr (i));
- }
- break;
+ /* Call the function for the type. See if it returns anything or
+ doesn't want us to continue. If we are to continue, walk both
+ the normal fields and those for the declaration case. */
+ result = (*func) (type_p, &walk_subtrees, data);
+ if (result || !walk_subtrees)
+ return NULL_TREE;
- default:
- /* ??? This could be a language-defined node. We really should make
- a hook for it, but right now just ignore it. */
- break;
+ result = walk_type_fields (*type_p, func, data, pset);
+ if (result)
+ return result;
+
+ /* If this is a record type, also walk the fields. */
+ if (TREE_CODE (*type_p) == RECORD_TYPE
+ || TREE_CODE (*type_p) == UNION_TYPE
+ || TREE_CODE (*type_p) == QUAL_UNION_TYPE)
+ {
+ tree field;
+
+ for (field = TYPE_FIELDS (*type_p); field;
+ field = TREE_CHAIN (field))
+ {
+ /* We'd like to look at the type of the field, but we can
+ easily get infinite recursion. So assume it's pointed
+ to elsewhere in the tree. Also, ignore things that
+ aren't fields. */
+ if (TREE_CODE (field) != FIELD_DECL)
+ continue;
+
+ WALK_SUBTREE (DECL_FIELD_OFFSET (field));
+ WALK_SUBTREE (DECL_SIZE (field));
+ WALK_SUBTREE (DECL_SIZE_UNIT (field));
+ if (TREE_CODE (*type_p) == QUAL_UNION_TYPE)
+ WALK_SUBTREE (DECL_QUALIFIER (field));
+ }
+ }
+
+ WALK_SUBTREE (TYPE_SIZE (*type_p));
+ WALK_SUBTREE_TAIL (TYPE_SIZE_UNIT (*type_p));
}
+ /* FALLTHRU */
+
+ default:
+ if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code)))
+ {
+ int i, len;
+
+ /* Walk over all the sub-trees of this operand. */
+ len = TREE_CODE_LENGTH (code);
+
+ /* Go through the subtrees. We need to do this in forward order so
+ that the scope of a FOR_EXPR is handled properly. */
+ if (len)
+ {
+ for (i = 0; i < len - 1; ++i)
+ WALK_SUBTREE (TREE_OPERAND (*tp, i));
+ WALK_SUBTREE_TAIL (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);
+ break;
}
/* We didn't find what we were looking for. */
return result;
}
+
+/* Return true if STMT is an empty statement or contains nothing but
+ empty statements. */
+
+bool
+empty_body_p (tree stmt)
+{
+ tree_stmt_iterator i;
+ tree body;
+
+ if (IS_EMPTY_STMT (stmt))
+ return true;
+ else if (TREE_CODE (stmt) == BIND_EXPR)
+ body = BIND_EXPR_BODY (stmt);
+ else if (TREE_CODE (stmt) == STATEMENT_LIST)
+ body = stmt;
+ else
+ return false;
+
+ for (i = tsi_start (body); !tsi_end_p (i); tsi_next (&i))
+ if (!empty_body_p (tsi_stmt (i)))
+ return false;
+
+ return true;
+}
+
#include "gt-tree.h"