#include "function.h"
#include "expr.h"
#include "output.h"
+#include "diagnostic-core.h"
#include "toplev.h"
#include "ggc.h"
#include "target.h"
/* An array of functions used for self-referential size computation. */
static GTY(()) VEC (tree, gc) *size_functions;
+/* Look inside EXPR into simple arithmetic operations involving constants.
+ Return the outermost non-arithmetic or non-constant node. */
+
+static tree
+skip_simple_constant_arithmetic (tree expr)
+{
+ while (true)
+ {
+ if (UNARY_CLASS_P (expr))
+ expr = TREE_OPERAND (expr, 0);
+ else if (BINARY_CLASS_P (expr))
+ {
+ if (TREE_CONSTANT (TREE_OPERAND (expr, 1)))
+ expr = TREE_OPERAND (expr, 0);
+ else if (TREE_CONSTANT (TREE_OPERAND (expr, 0)))
+ expr = TREE_OPERAND (expr, 1);
+ else
+ break;
+ }
+ else
+ break;
+ }
+
+ return expr;
+}
+
/* Similar to copy_tree_r but do not copy component references involving
PLACEHOLDER_EXPRs. These nodes are spotted in find_placeholder_in_expr
and substituted in substitute_in_expr. */
{
static unsigned HOST_WIDE_INT fnno = 0;
VEC (tree, heap) *self_refs = NULL;
- tree param_type_list = NULL, param_decl_list = NULL, arg_list = NULL;
+ tree param_type_list = NULL, param_decl_list = NULL;
tree t, ref, return_type, fntype, fnname, fndecl;
unsigned int i;
char buf[128];
+ VEC(tree,gc) *args = NULL;
/* Do not factor out simple operations. */
- t = skip_simple_arithmetic (size);
+ t = skip_simple_constant_arithmetic (size);
if (TREE_CODE (t) == CALL_EXPR)
return size;
/* Build the parameter and argument lists in parallel; also
substitute the former for the latter in the expression. */
- for (i = 0; VEC_iterate (tree, self_refs, i, ref); i++)
+ args = VEC_alloc (tree, gc, VEC_length (tree, self_refs));
+ FOR_EACH_VEC_ELT (tree, self_refs, i, ref)
{
tree subst, param_name, param_type, param_decl;
param_type_list = tree_cons (NULL_TREE, param_type, param_type_list);
param_decl_list = chainon (param_decl, param_decl_list);
- arg_list = tree_cons (NULL_TREE, ref, arg_list);
+ VEC_quick_push (tree, args, ref);
}
VEC_free (tree, heap, self_refs);
/* The 3 lists have been created in reverse order. */
param_type_list = nreverse (param_type_list);
param_decl_list = nreverse (param_decl_list);
- arg_list = nreverse (arg_list);
/* Build the function type. */
return_type = TREE_TYPE (size);
sprintf (buf, "SZ"HOST_WIDE_INT_PRINT_UNSIGNED, fnno++);
fnname = get_file_function_name (buf);
fndecl = build_decl (input_location, FUNCTION_DECL, fnname, fntype);
- for (t = param_decl_list; t; t = TREE_CHAIN (t))
+ for (t = param_decl_list; t; t = DECL_CHAIN (t))
DECL_CONTEXT (t) = fndecl;
DECL_ARGUMENTS (fndecl) = param_decl_list;
DECL_RESULT (fndecl)
VEC_safe_push (tree, gc, size_functions, fndecl);
/* Replace the original expression with a call to the size function. */
- return build_function_call_expr (UNKNOWN_LOCATION, fndecl, arg_list);
+ return build_call_expr_loc_vec (input_location, fndecl, args);
}
/* Take, queue and compile all the size functions. It is essential that
return mode;
}
+/* Find a mode that is suitable for representing a vector with
+ NUNITS elements of mode INNERMODE. Returns BLKmode if there
+ is no suitable mode. */
+
+enum machine_mode
+mode_for_vector (enum machine_mode innermode, unsigned nunits)
+{
+ enum machine_mode mode;
+
+ /* First, look for a supported vector type. */
+ if (SCALAR_FLOAT_MODE_P (innermode))
+ mode = MIN_MODE_VECTOR_FLOAT;
+ else if (SCALAR_FRACT_MODE_P (innermode))
+ mode = MIN_MODE_VECTOR_FRACT;
+ else if (SCALAR_UFRACT_MODE_P (innermode))
+ mode = MIN_MODE_VECTOR_UFRACT;
+ else if (SCALAR_ACCUM_MODE_P (innermode))
+ mode = MIN_MODE_VECTOR_ACCUM;
+ else if (SCALAR_UACCUM_MODE_P (innermode))
+ mode = MIN_MODE_VECTOR_UACCUM;
+ else
+ mode = MIN_MODE_VECTOR_INT;
+
+ /* Do not check vector_mode_supported_p here. We'll do that
+ later in vector_type_mode. */
+ for (; mode != VOIDmode ; mode = GET_MODE_WIDER_MODE (mode))
+ if (GET_MODE_NUNITS (mode) == nunits
+ && GET_MODE_INNER (mode) == innermode)
+ break;
+
+ /* For integers, try mapping it to a same-sized scalar mode. */
+ if (mode == VOIDmode
+ && GET_MODE_CLASS (innermode) == MODE_INT)
+ mode = mode_for_size (nunits * GET_MODE_BITSIZE (innermode),
+ MODE_INT, 0);
+
+ if (mode == VOIDmode
+ || (GET_MODE_CLASS (mode) == MODE_INT
+ && !have_regs_of_mode[mode]))
+ return BLKmode;
+
+ return mode;
+}
+
/* Return the alignment of MODE. This will be bounded by 1 and
BIGGEST_ALIGNMENT. */
int size_as_int = TREE_INT_CST_LOW (size);
if (compare_tree_int (size, size_as_int) == 0)
- warning (OPT_Wlarger_than_eq, "size of %q+D is %d bytes", decl, size_as_int);
+ warning (OPT_Wlarger_than_, "size of %q+D is %d bytes", decl, size_as_int);
else
- warning (OPT_Wlarger_than_eq, "size of %q+D is larger than %wd bytes",
+ warning (OPT_Wlarger_than_, "size of %q+D is larger than %wd bytes",
decl, larger_than_size);
}
}
if (!VEC_empty (tree, rli->pending_statics))
{
- unsigned ix;
- tree t;
fprintf (stderr, "pending statics:\n");
debug_vec_tree (rli->pending_statics);
}
/* If we ended a bitfield before the full length of the type then
pad the struct out to the full length of the last type. */
- if ((TREE_CHAIN (field) == NULL
- || TREE_CODE (TREE_CHAIN (field)) != FIELD_DECL)
+ if ((DECL_CHAIN (field) == NULL
+ || TREE_CODE (DECL_CHAIN (field)) != FIELD_DECL)
&& DECL_BIT_FIELD_TYPE (field)
&& !integer_zerop (DECL_SIZE (field)))
rli->bitpos = size_binop (PLUS_EXPR, rli->bitpos,
/* A record which has any BLKmode members must itself be
BLKmode; it can't go in a register. Unless the member is
BLKmode only because it isn't aligned. */
- for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+ for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
{
if (TREE_CODE (field) != FIELD_DECL)
continue;
for (tail = NULL_TREE; fields; tail = fields, fields = next)
{
DECL_FIELD_CONTEXT (fields) = type;
- next = TREE_CHAIN (fields);
- TREE_CHAIN (fields) = tail;
+ next = DECL_CHAIN (fields);
+ DECL_CHAIN (fields) = tail;
}
TYPE_FIELDS (type) = tail;
/* Find an appropriate mode for the vector type. */
if (TYPE_MODE (type) == VOIDmode)
- {
- enum machine_mode innermode = TYPE_MODE (innertype);
- enum machine_mode mode;
-
- /* First, look for a supported vector type. */
- if (SCALAR_FLOAT_MODE_P (innermode))
- mode = MIN_MODE_VECTOR_FLOAT;
- else if (SCALAR_FRACT_MODE_P (innermode))
- mode = MIN_MODE_VECTOR_FRACT;
- else if (SCALAR_UFRACT_MODE_P (innermode))
- mode = MIN_MODE_VECTOR_UFRACT;
- else if (SCALAR_ACCUM_MODE_P (innermode))
- mode = MIN_MODE_VECTOR_ACCUM;
- else if (SCALAR_UACCUM_MODE_P (innermode))
- mode = MIN_MODE_VECTOR_UACCUM;
- else
- mode = MIN_MODE_VECTOR_INT;
-
- /* Do not check vector_mode_supported_p here. We'll do that
- later in vector_type_mode. */
- for (; mode != VOIDmode ; mode = GET_MODE_WIDER_MODE (mode))
- if (GET_MODE_NUNITS (mode) == nunits
- && GET_MODE_INNER (mode) == innermode)
- break;
-
- /* For integers, try mapping it to a same-sized scalar mode. */
- if (mode == VOIDmode
- && GET_MODE_CLASS (innermode) == MODE_INT)
- mode = mode_for_size (nunits * GET_MODE_BITSIZE (innermode),
- MODE_INT, 0);
-
- if (mode == VOIDmode ||
- (GET_MODE_CLASS (mode) == MODE_INT
- && !have_regs_of_mode[mode]))
- SET_TYPE_MODE (type, BLKmode);
- else
- SET_TYPE_MODE (type, mode);
- }
+ SET_TYPE_MODE (type,
+ mode_for_vector (TYPE_MODE (innertype), nunits));
TYPE_SATURATING (type) = TYPE_SATURATING (TREE_TYPE (type));
TYPE_UNSIGNED (type) = TYPE_UNSIGNED (TREE_TYPE (type));
TYPE_FIELDS (type) = nreverse (TYPE_FIELDS (type));
/* Place all the fields. */
- for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+ for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
place_field (rli, field);
if (TREE_CODE (type) == QUAL_UNION_TYPE)