/* 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, 2006, 2007, 2008
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
Free Software Foundation, Inc.
This file is part of GCC.
/* Since we cannot rehash a type after it is in the table, we have to
keep the hash code. */
-struct type_hash GTY(())
-{
+struct GTY(()) type_hash {
unsigned long hash;
tree type;
};
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[NAME_MEMORY_TAG][TS_DECL_MINIMAL] = 1;
- tree_contains_struct[SYMBOL_MEMORY_TAG][TS_DECL_MINIMAL] = 1;
- tree_contains_struct[MEMORY_PARTITION_TAG][TS_DECL_MINIMAL] = 1;
-
- tree_contains_struct[NAME_MEMORY_TAG][TS_MEMORY_TAG] = 1;
- tree_contains_struct[SYMBOL_MEMORY_TAG][TS_MEMORY_TAG] = 1;
- tree_contains_struct[MEMORY_PARTITION_TAG][TS_MEMORY_TAG] = 1;
-
- tree_contains_struct[MEMORY_PARTITION_TAG][TS_MEMORY_PARTITION_TAG] = 1;
tree_contains_struct[VAR_DECL][TS_DECL_WITH_VIS] = 1;
tree_contains_struct[FUNCTION_DECL][TS_DECL_WITH_VIS] = 1;
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;
lang_hooks.init_ts ();
}
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 MEMORY_PARTITION_TAG:
- return sizeof (struct tree_memory_partition_tag);
default:
return sizeof (struct tree_decl_non_common);
}
return chain;
}
+/* Return the node in a chain of nodes whose value is x, NULL if not found. */
+
+tree
+tree_find_value (tree chain, tree x)
+{
+ tree list;
+ for (list = chain; list; list = TREE_CHAIN (list))
+ if (TREE_VALUE (list) == x)
+ return list;
+ return NULL;
+}
+
/* Reverse the order of elements in the chain T,
and return the new head of the chain (old last element). */
case COMPONENT_REF:
/* If the thing being referenced is not a field, then it is
something language specific. */
- if (TREE_CODE (TREE_OPERAND (arg, 1)) != FIELD_DECL)
- return (*lang_hooks.staticp) (arg);
+ gcc_assert (TREE_CODE (TREE_OPERAND (arg, 1)) == FIELD_DECL);
/* If we are referencing a bitfield, we can't evaluate an
ADDR_EXPR at compile time and so it isn't a constant. */
&& TREE_CODE (TREE_OPERAND (arg, 1)) == INTEGER_CST)
return staticp (TREE_OPERAND (arg, 0));
else
- return false;
+ return NULL;
+
+ case COMPOUND_LITERAL_EXPR:
+ return TREE_STATIC (COMPOUND_LITERAL_EXPR_DECL (arg)) ? arg : NULL;
default:
- if ((unsigned int) TREE_CODE (arg)
- >= (unsigned int) LAST_AND_UNUSED_TREE_CODE)
- return lang_hooks.staticp (arg);
- else
- return NULL;
+ return NULL;
}
}
return false;
}
+/* Return whether OP is a DECL whose address is interprocedural-invariant. */
+
+bool
+decl_address_ip_invariant_p (const_tree op)
+{
+ /* The conditions below are slightly less strict than the one in
+ staticp. */
+
+ switch (TREE_CODE (op))
+ {
+ case LABEL_DECL:
+ case FUNCTION_DECL:
+ case STRING_CST:
+ return true;
+
+ case VAR_DECL:
+ if (((TREE_STATIC (op) || DECL_EXTERNAL (op))
+ && !DECL_DLLIMPORT_P (op))
+ || DECL_THREAD_LOCAL_P (op))
+ return true;
+ break;
+
+ case CONST_DECL:
+ if ((TREE_STATIC (op) || DECL_EXTERNAL (op)))
+ return true;
+ break;
+
+ default:
+ break;
+ }
+
+ return false;
+}
+
/* Return true if T is function-invariant (internal function, does
not handle arithmetic; that's handled in skip_simple_arithmetic and
return TS_TYPE_DECL;
case FUNCTION_DECL:
return TS_FUNCTION_DECL;
- case SYMBOL_MEMORY_TAG:
- case NAME_MEMORY_TAG:
- case MEMORY_PARTITION_TAG:
- return TS_MEMORY_TAG;
default:
return TS_DECL_NON_COMMON;
}
|| CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 1))
|| CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 2)));
+ case SAVE_EXPR:
+ /* The save_expr function never wraps anything containing
+ a PLACEHOLDER_EXPR. */
+ return 0;
+
default:
break;
}
gcc_assert (TREE_CODE_LENGTH (code) == 2);
if ((code == MINUS_EXPR || code == PLUS_EXPR || code == MULT_EXPR)
- && arg0 && arg1 && tt && POINTER_TYPE_P (tt))
- gcc_assert (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST);
+ && arg0 && arg1 && tt && POINTER_TYPE_P (tt)
+ /* When sizetype precision doesn't match that of pointers
+ we need to be able to build explicit extensions or truncations
+ of the offset argument. */
+ && TYPE_PRECISION (sizetype) == TYPE_PRECISION (tt))
+ gcc_assert (TREE_CODE (arg0) == INTEGER_CST
+ && TREE_CODE (arg1) == INTEGER_CST);
if (code == POINTER_PLUS_EXPR && arg0 && arg1 && tt)
gcc_assert (POINTER_TYPE_P (tt) && POINTER_TYPE_P (TREE_TYPE (arg0))
}
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)
+build6_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
+ tree arg2, tree arg3, tree arg4, tree arg5 MEM_STAT_DECL)
{
bool constant, read_only, side_effects;
tree t;
PROCESS_ARG(3);
PROCESS_ARG(4);
PROCESS_ARG(5);
- PROCESS_ARG(6);
TREE_SIDE_EFFECTS (t) = side_effects;
TREE_THIS_VOLATILE (t) = 0;
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. */
+
+void
+protected_set_expr_location (tree t, location_t loc)
+{
+ if (t && CAN_HAVE_LOCATION_P (t))
+ SET_EXPR_LOCATION (t, loc);
+}
\f
/* Return a declaration like DDECL except that its DECL_ATTRIBUTES
is ATTRIBUTE. */
return build_qualified_type (ttype, quals);
}
+ ttype = build_qualified_type (ttype, TYPE_UNQUALIFIED);
ntype = build_distinct_type_copy (ttype);
TYPE_ATTRIBUTES (ntype) = attribute;
- set_type_quals (ntype, TYPE_UNQUALIFIED);
hashcode = iterative_hash_object (code, hashcode);
if (TREE_TYPE (ntype))
/* If the target-dependent attributes make NTYPE different from
its canonical type, we will need to use structural equality
- checks for this qualified type. */
- ttype = build_qualified_type (ttype, TYPE_UNQUALIFIED);
+ checks for this type. */
if (TYPE_STRUCTURAL_EQUALITY_P (ttype)
|| !targetm.comp_type_attributes (ntype, ttype))
SET_TYPE_STRUCTURAL_EQUALITY (ntype);
- else
+ else if (TYPE_CANONICAL (ntype) == ntype)
TYPE_CANONICAL (ntype) = TYPE_CANONICAL (ttype);
ttype = build_qualified_type (ntype, quals);
|| !attribute_list_equal (TYPE_ATTRIBUTES (a->type),
TYPE_ATTRIBUTES (b->type))
|| TYPE_ALIGN (a->type) != TYPE_ALIGN (b->type)
- || TYPE_MODE (a->type) != TYPE_MODE (b->type))
+ || TYPE_MODE (a->type) != TYPE_MODE (b->type)
+ || (TREE_CODE (a->type) != COMPLEX_TYPE
+ && TYPE_NAME (a->type) != TYPE_NAME (b->type)))
return 0;
switch (TREE_CODE (a->type))
return 1;
}
+/* Return the minimum number of bits needed to represent VALUE in a
+ signed or unsigned type, UNSIGNEDP says which. */
+
+unsigned int
+tree_int_cst_min_precision (tree value, bool unsignedp)
+{
+ int log;
+
+ /* If the value is negative, compute its negative minus 1. The latter
+ adjustment is because the absolute value of the largest negative value
+ is one larger than the largest positive value. This is equivalent to
+ a bit-wise negation, so use that operation instead. */
+
+ if (tree_int_cst_sgn (value) < 0)
+ value = fold_build1 (BIT_NOT_EXPR, TREE_TYPE (value), value);
+
+ /* Return the number of bits needed, taking into account the fact
+ that we need one more bit for a signed than unsigned type. */
+
+ if (integer_zerop (value))
+ log = 0;
+ else
+ log = tree_floor_log2 (value);
+
+ return log + 1 + !unsignedp;
+}
+
/* Compare two constructor-element-type constants. Return 1 if the lists
are known to be equal; otherwise return 0. */
t = make_node (POINTER_TYPE);
TREE_TYPE (t) = to_type;
- TYPE_MODE (t) = mode;
+ SET_TYPE_MODE (t, mode);
TYPE_REF_CAN_ALIAS_ALL (t) = can_alias_all;
TYPE_NEXT_PTR_TO (t) = TYPE_POINTER_TO (to_type);
TYPE_POINTER_TO (to_type) = t;
t = make_node (REFERENCE_TYPE);
TREE_TYPE (t) = to_type;
- TYPE_MODE (t) = mode;
+ SET_TYPE_MODE (t, mode);
TYPE_REF_CAN_ALIAS_ALL (t) = can_alias_all;
TYPE_NEXT_REF_TO (t) = TYPE_REFERENCE_TO (to_type);
TYPE_REFERENCE_TO (to_type) = t;
TYPE_PRECISION (itype) = TYPE_PRECISION (sizetype);
TYPE_MIN_VALUE (itype) = size_zero_node;
TYPE_MAX_VALUE (itype) = fold_convert (sizetype, maxval);
- TYPE_MODE (itype) = TYPE_MODE (sizetype);
+ SET_TYPE_MODE (itype, TYPE_MODE (sizetype));
TYPE_SIZE (itype) = TYPE_SIZE (sizetype);
TYPE_SIZE_UNIT (itype) = TYPE_SIZE_UNIT (sizetype);
TYPE_ALIGN (itype) = TYPE_ALIGN (sizetype);
TYPE_MAX_VALUE (itype) = highval ? fold_convert (type, highval) : NULL;
TYPE_PRECISION (itype) = TYPE_PRECISION (type);
- TYPE_MODE (itype) = TYPE_MODE (type);
+ SET_TYPE_MODE (itype, TYPE_MODE (type));
TYPE_SIZE (itype) = TYPE_SIZE (type);
TYPE_SIZE_UNIT (itype) = TYPE_SIZE_UNIT (type);
TYPE_ALIGN (itype) = TYPE_ALIGN (type);
return t;
}
+/* Build variant of function type ORIG_TYPE skipping ARGS_TO_SKIP. */
+
+tree
+build_function_type_skip_args (tree orig_type, bitmap args_to_skip)
+{
+ tree new_type = NULL;
+ tree args, new_args = NULL, t;
+ tree new_reversed;
+ int i = 0;
+
+ for (args = TYPE_ARG_TYPES (orig_type); args && args != void_list_node;
+ args = TREE_CHAIN (args), i++)
+ if (!bitmap_bit_p (args_to_skip, i))
+ new_args = tree_cons (NULL_TREE, TREE_VALUE (args), new_args);
+
+ new_reversed = nreverse (new_args);
+ if (args)
+ {
+ if (new_reversed)
+ TREE_CHAIN (new_args) = void_list_node;
+ 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.)
+ Exception is METHOD_TYPEs must have THIS argument.
+ When we are asked to remove it, we need to build new FUNCTION_TYPE
+ instead. */
+ if (TREE_CODE (orig_type) != METHOD_TYPE
+ || !bitmap_bit_p (args_to_skip, 0))
+ {
+ new_type = copy_node (orig_type);
+ TYPE_ARG_TYPES (new_type) = new_reversed;
+ }
+ else
+ {
+ new_type
+ = build_distinct_type_copy (build_function_type (TREE_TYPE (orig_type),
+ new_reversed));
+ TYPE_CONTEXT (new_type) = TYPE_CONTEXT (orig_type);
+ }
+
+ /* This is a new type, not a copy of an old type. Need to reassociate
+ variants. We can handle everything except the main variant lazily. */
+ t = TYPE_MAIN_VARIANT (orig_type);
+ if (orig_type != t)
+ {
+ TYPE_MAIN_VARIANT (new_type) = t;
+ TYPE_NEXT_VARIANT (new_type) = TYPE_NEXT_VARIANT (t);
+ TYPE_NEXT_VARIANT (t) = new_type;
+ }
+ else
+ {
+ TYPE_MAIN_VARIANT (new_type) = new_type;
+ TYPE_NEXT_VARIANT (new_type) = NULL;
+ }
+ return new_type;
+}
+
+/* Build variant of function type ORIG_TYPE skipping ARGS_TO_SKIP.
+
+ Arguments from DECL_ARGUMENTS list can't be removed now, since they are
+ linked by TREE_CHAIN directly. It is caller responsibility to eliminate
+ them when they are being duplicated (i.e. copy_arguments_for_versioning). */
+
+tree
+build_function_decl_skip_args (tree orig_decl, bitmap args_to_skip)
+{
+ tree new_decl = copy_node (orig_decl);
+ tree new_type;
+
+ new_type = TREE_TYPE (orig_decl);
+ if (prototype_p (new_type))
+ new_type = build_function_type_skip_args (new_type, args_to_skip);
+ TREE_TYPE (new_decl) = new_type;
+
+ /* For declarations setting DECL_VINDEX (i.e. methods)
+ we expect first argument to be THIS pointer. */
+ if (bitmap_bit_p (args_to_skip, 0))
+ DECL_VINDEX (new_decl) = NULL_TREE;
+ return new_decl;
+}
+
/* Build a function type. The RETURN_TYPE is the type returned by the
function. If VAARGS is set, no void_type_node is appended to the
the list. ARGP muse be alway be terminated be a NULL_TREE. */
if (vaargs)
{
- last = args;
- if (args != NULL_TREE)
- args = nreverse (args);
+ last = args;
+ if (args != NULL_TREE)
+ args = nreverse (args);
gcc_assert (args != NULL_TREE && last != void_list_node);
}
else if (args == NULL_TREE)
tree t;
hashval_t hashcode;
+ gcc_assert (INTEGRAL_TYPE_P (component_type)
+ || SCALAR_FLOAT_TYPE_P (component_type)
+ || FIXED_POINT_TYPE_P (component_type));
+
/* Make a node of the sort we want. */
t = make_node (COMPLEX_TYPE);
return build_qualified_type (t, TYPE_QUALS (component_type));
}
+
+/* If TYPE is a real or complex floating-point type and the target
+ does not directly support arithmetic on TYPE then return the wider
+ type to be used for arithmetic on TYPE. Otherwise, return
+ NULL_TREE. */
+
+tree
+excess_precision_type (tree type)
+{
+ if (flag_excess_precision != EXCESS_PRECISION_FAST)
+ {
+ int flt_eval_method = TARGET_FLT_EVAL_METHOD;
+ switch (TREE_CODE (type))
+ {
+ case REAL_TYPE:
+ switch (flt_eval_method)
+ {
+ case 1:
+ if (TYPE_MODE (type) == TYPE_MODE (float_type_node))
+ return double_type_node;
+ break;
+ case 2:
+ if (TYPE_MODE (type) == TYPE_MODE (float_type_node)
+ || TYPE_MODE (type) == TYPE_MODE (double_type_node))
+ return long_double_type_node;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ break;
+ case COMPLEX_TYPE:
+ if (TREE_CODE (TREE_TYPE (type)) != REAL_TYPE)
+ return NULL_TREE;
+ switch (flt_eval_method)
+ {
+ case 1:
+ if (TYPE_MODE (TREE_TYPE (type)) == TYPE_MODE (float_type_node))
+ return complex_double_type_node;
+ break;
+ case 2:
+ if (TYPE_MODE (TREE_TYPE (type)) == TYPE_MODE (float_type_node)
+ || (TYPE_MODE (TREE_TYPE (type))
+ == TYPE_MODE (double_type_node)))
+ return complex_long_double_type_node;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ return NULL_TREE;
+}
\f
/* Return OP, stripped of any conversions to wider types as much as is safe.
Converting the value back to OP's type makes a value equivalent to OP.
int
int_fits_type_p (const_tree c, const_tree type)
{
- tree type_low_bound = TYPE_MIN_VALUE (type);
- tree type_high_bound = TYPE_MAX_VALUE (type);
- bool ok_for_low_bound, ok_for_high_bound;
- unsigned HOST_WIDE_INT low;
- HOST_WIDE_INT high;
+ tree type_low_bound, type_high_bound;
+ bool ok_for_low_bound, ok_for_high_bound, unsc;
+ double_int dc, dd;
+
+ dc = tree_to_double_int (c);
+ unsc = TYPE_UNSIGNED (TREE_TYPE (c));
+
+ if (TREE_CODE (TREE_TYPE (c)) == INTEGER_TYPE
+ && TYPE_IS_SIZETYPE (TREE_TYPE (c))
+ && unsc)
+ /* So c is an unsigned integer whose type is sizetype and type is not.
+ sizetype'd integers are sign extended even though they are
+ unsigned. If the integer value fits in the lower end word of c,
+ and if the higher end word has all its bits set to 1, that
+ means the higher end bits are set to 1 only for sign extension.
+ So let's convert c into an equivalent zero extended unsigned
+ integer. */
+ dc = double_int_zext (dc, TYPE_PRECISION (TREE_TYPE (c)));
+
+retry:
+ type_low_bound = TYPE_MIN_VALUE (type);
+ type_high_bound = TYPE_MAX_VALUE (type);
/* If at least one bound of the type is a constant integer, we can check
ourselves and maybe make a decision. If no such decision is possible, but
for "unknown if constant fits", 0 for "constant known *not* to fit" and 1
for "constant known to fit". */
- /* Check if C >= type_low_bound. */
+ /* Check if c >= type_low_bound. */
if (type_low_bound && TREE_CODE (type_low_bound) == INTEGER_CST)
{
- if (tree_int_cst_lt (c, type_low_bound))
+ dd = tree_to_double_int (type_low_bound);
+ if (TREE_CODE (type) == INTEGER_TYPE
+ && TYPE_IS_SIZETYPE (type)
+ && TYPE_UNSIGNED (type))
+ dd = double_int_zext (dd, TYPE_PRECISION (type));
+ if (unsc != TYPE_UNSIGNED (TREE_TYPE (type_low_bound)))
+ {
+ int c_neg = (!unsc && double_int_negative_p (dc));
+ int t_neg = (unsc && double_int_negative_p (dd));
+
+ if (c_neg && !t_neg)
+ return 0;
+ if ((c_neg || !t_neg) && double_int_ucmp (dc, dd) < 0)
+ return 0;
+ }
+ else if (double_int_cmp (dc, dd, unsc) < 0)
return 0;
ok_for_low_bound = true;
}
/* Check if c <= type_high_bound. */
if (type_high_bound && TREE_CODE (type_high_bound) == INTEGER_CST)
{
- if (tree_int_cst_lt (type_high_bound, c))
+ dd = tree_to_double_int (type_high_bound);
+ if (TREE_CODE (type) == INTEGER_TYPE
+ && TYPE_IS_SIZETYPE (type)
+ && TYPE_UNSIGNED (type))
+ dd = double_int_zext (dd, TYPE_PRECISION (type));
+ if (unsc != TYPE_UNSIGNED (TREE_TYPE (type_high_bound)))
+ {
+ int c_neg = (!unsc && double_int_negative_p (dc));
+ int t_neg = (unsc && double_int_negative_p (dd));
+
+ if (t_neg && !c_neg)
+ return 0;
+ if ((t_neg || !c_neg) && double_int_ucmp (dc, dd) > 0)
+ return 0;
+ }
+ else if (double_int_cmp (dc, dd, unsc) > 0)
return 0;
ok_for_high_bound = true;
}
/* Perform some generic filtering which may allow making a decision
even if the bounds are not constant. First, negative integers
never fit in unsigned types, */
- if (TYPE_UNSIGNED (type) && tree_int_cst_sgn (c) < 0)
+ if (TYPE_UNSIGNED (type) && !unsc && double_int_negative_p (dc))
return 0;
/* Second, narrower types always fit in wider ones. */
return 1;
/* Third, unsigned integers with top bit set never fit signed types. */
- if (! TYPE_UNSIGNED (type)
- && TYPE_UNSIGNED (TREE_TYPE (c))
- && tree_int_cst_msb (c))
- return 0;
+ if (! TYPE_UNSIGNED (type) && unsc)
+ {
+ int prec = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (c))) - 1;
+ if (prec < HOST_BITS_PER_WIDE_INT)
+ {
+ if (((((unsigned HOST_WIDE_INT) 1) << prec) & dc.low) != 0)
+ return 0;
+ }
+ else if (((((unsigned HOST_WIDE_INT) 1)
+ << (prec - HOST_BITS_PER_WIDE_INT)) & dc.high) != 0)
+ 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 and it
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));
+ {
+ type = TREE_TYPE (type);
+ goto retry;
+ }
/* Or to fit_double_type, if nothing else. */
- low = TREE_INT_CST_LOW (c);
- high = TREE_INT_CST_HIGH (c);
- return !fit_double_type (low, high, &low, &high, type);
+ return !fit_double_type (dc.low, dc.high, &dc.low, &dc.high, type);
}
/* Stores bounds of an integer TYPE in MIN and MAX. If TYPE has non-constant
&& TREE_CODE (TREE_OPERAND (addr, 0)) == FUNCTION_DECL)
return TREE_OPERAND (addr, 0);
- /* We couldn't figure out what was being called. Maybe the front
- end has some idea. */
- return lang_hooks.lang_get_callee_fndecl (call);
+ /* We couldn't figure out what was being called. */
+ return NULL_TREE;
}
/* Print debugging information about tree nodes generated during the compile,
/* If we already have a name we know to be unique, just use that. */
if (first_global_object_name)
- p = first_global_object_name;
+ p = q = ASTRDUP (first_global_object_name);
/* If the target is handling the constructors/destructors, they
will be local to this file and the name is only necessary for
debugging purposes. */
else
p = file;
p = q = ASTRDUP (p);
- clean_symbol_name (q);
}
else
{
len = strlen (file);
q = (char *) alloca (9 * 2 + len + 1);
memcpy (q, file, len + 1);
- clean_symbol_name (q);
sprintf (q + len, "_%08X_%08X", crc32_string (0, name),
crc32_string (0, get_random_seed (false)));
p = q;
}
+ clean_symbol_name (q);
buf = (char *) alloca (sizeof (FILE_FUNCTION_FORMAT) + strlen (p)
+ strlen (type));
t = make_node (VECTOR_TYPE);
TREE_TYPE (t) = TYPE_MAIN_VARIANT (innertype);
SET_TYPE_VECTOR_SUBPARTS (t, nunits);
- TYPE_MODE (t) = mode;
+ SET_TYPE_MODE (t, mode);
TYPE_READONLY (t) = TYPE_READONLY (innertype);
TYPE_VOLATILE (t) = TYPE_VOLATILE (innertype);
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;
+ SET_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;
+ SET_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;
+ SET_TYPE_MODE (dfloat128_type_node, TDmode);
dfloat128_ptr_type_node = build_pointer_type (dfloat128_type_node);
complex_integer_type_node = build_complex_type (integer_type_node);
tmp = tree_cons (NULL_TREE, inner_type, tmp);
ftype = build_function_type (type, tmp);
- mcode = BUILT_IN_COMPLEX_MUL_MIN + mode - MIN_MODE_COMPLEX_FLOAT;
- dcode = BUILT_IN_COMPLEX_DIV_MIN + mode - MIN_MODE_COMPLEX_FLOAT;
+ mcode = ((enum built_in_function)
+ (BUILT_IN_COMPLEX_MUL_MIN + mode - MIN_MODE_COMPLEX_FLOAT));
+ dcode = ((enum built_in_function)
+ (BUILT_IN_COMPLEX_DIV_MIN + mode - MIN_MODE_COMPLEX_FLOAT));
for (p = GET_MODE_NAME (mode), q = mode_name_buf; *p; p++, q++)
*q = TOLOWER (*p);
return make_vector_type (innertype, nunits, VOIDmode);
}
+/* Similarly, but takes the inner type and number of units, which must be
+ a power of two. */
+
+tree
+build_opaque_vector_type (tree innertype, int nunits)
+{
+ tree t;
+ innertype = build_distinct_type_copy (innertype);
+ t = make_vector_type (innertype, nunits, VOIDmode);
+ TYPE_VECTOR_OPAQUE (t) = true;
+ return t;
+}
+
/* Build RESX_EXPR with given REGION_NUMBER. */
tree
return (t != NULL_TREE);
}
-/* Return the number of arguments that a function has. */
-
-int
-function_args_count (tree fntype)
-{
- function_args_iterator args_iter;
- tree t;
- int num = 0;
-
- if (fntype)
- {
- FOREACH_FUNCTION_ARGS(fntype, t, args_iter)
- {
- num++;
- }
- }
-
- return num;
-}
-
/* If BLOCK is inlined from an __attribute__((__artificial__))
routine, return pointer to location from where it has been
called. */
{
tree ao = BLOCK_ABSTRACT_ORIGIN (block);
- while (TREE_CODE (ao) == BLOCK && BLOCK_ABSTRACT_ORIGIN (ao))
+ while (TREE_CODE (ao) == BLOCK
+ && BLOCK_ABSTRACT_ORIGIN (ao)
+ && BLOCK_ABSTRACT_ORIGIN (ao) != ao)
ao = BLOCK_ABSTRACT_ORIGIN (ao);
if (TREE_CODE (ao) == FUNCTION_DECL)
return ret;
}
+
+/* If EXP is inlined from an __attribute__((__artificial__))
+ function, return the location of the original call expression. */
+
+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);
+
+ 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);
+}
+
+
/* These are the hash table functions for the hash table of OPTIMIZATION_NODEq
nodes. */
return t;
}
+/* Determine the "ultimate origin" of a block. The block may be an inlined
+ instance of an inlined instance of a block which is local to an inline
+ function, so we have to trace all of the way back through the origin chain
+ to find out what sort of node actually served as the original seed for the
+ given block. */
+
+tree
+block_ultimate_origin (const_tree block)
+{
+ tree immediate_origin = BLOCK_ABSTRACT_ORIGIN (block);
+
+ /* output_inline_function sets BLOCK_ABSTRACT_ORIGIN for all the
+ nodes in the function to point to themselves; ignore that if
+ we're trying to output the abstract instance of this function. */
+ if (BLOCK_ABSTRACT (block) && immediate_origin == block)
+ return NULL_TREE;
+
+ if (immediate_origin == NULL_TREE)
+ return NULL_TREE;
+ else
+ {
+ tree ret_val;
+ tree lookahead = immediate_origin;
+
+ do
+ {
+ ret_val = lookahead;
+ lookahead = (TREE_CODE (ret_val) == BLOCK
+ ? BLOCK_ABSTRACT_ORIGIN (ret_val) : NULL);
+ }
+ while (lookahead != NULL && lookahead != ret_val);
+
+ /* The block's abstract origin chain may not be the *ultimate* origin of
+ the block. It could lead to a DECL that has an abstract origin set.
+ If so, we want that DECL's abstract origin (which is what DECL_ORIGIN
+ will give us if it has one). Note that DECL's abstract origins are
+ supposed to be the most distant ancestor (or so decl_ultimate_origin
+ claims), so we don't need to loop following the DECL origins. */
+ if (DECL_P (ret_val))
+ return DECL_ORIGIN (ret_val);
+
+ return ret_val;
+ }
+}
+
#include "gt-tree.h"