/* Forward declarations. */
static enum gimplify_status gimplify_compound_expr (tree *, tree *, bool);
+#ifdef ENABLE_CHECKING
+static bool cpt_same_type (tree a, tree b);
+#endif
/* Return a hash value for a formal temporary table entry. */
/* Only allow them to compare equal if they also hash equal; otherwise
results are nondeterminate, and we fail bootstrap comparison. */
- if (gimple_tree_hash (p1) != gimple_tree_hash (p2))
- abort ();
+ gcc_assert (gimple_tree_hash (p1) == gimple_tree_hash (p2));
return 1;
}
void
push_gimplify_context (void)
{
- if (gimplify_ctxp)
- abort ();
+ gcc_assert (!gimplify_ctxp);
gimplify_ctxp
= (struct gimplify_ctx *) xcalloc (1, sizeof (struct gimplify_ctx));
if (optimize)
{
tree t;
- if (!gimplify_ctxp || gimplify_ctxp->current_bind_expr)
- abort ();
+ gcc_assert (gimplify_ctxp && !gimplify_ctxp->current_bind_expr);
for (t = gimplify_ctxp->temps; t ; t = TREE_CHAIN (t))
DECL_GIMPLE_FORMAL_TEMP_P (t) = 0;
static void
gimple_push_condition (void)
{
+#ifdef ENABLE_CHECKING
+ if (gimplify_ctxp->conditions == 0)
+ gcc_assert (!gimplify_ctxp->conditional_cleanups);
+#endif
++(gimplify_ctxp->conditions);
}
{
int conds = --(gimplify_ctxp->conditions);
+ gcc_assert (conds >= 0);
if (conds == 0)
{
append_to_statement_list (gimplify_ctxp->conditional_cleanups, pre_p);
gimplify_ctxp->conditional_cleanups = NULL_TREE;
}
- else if (conds < 0)
- abort ();
}
/* A subroutine of append_to_statement_list{,_force}. */
new_type = build_type_variant (type, 0, 0);
TYPE_ATTRIBUTES (new_type) = TYPE_ATTRIBUTES (type);
- tmp_var = build_decl (VAR_DECL, create_tmp_var_name (prefix), type);
+ tmp_var = build_decl (VAR_DECL, prefix ? create_tmp_var_name (prefix) : NULL,
+ type);
/* The variable was declared by the compiler. */
DECL_ARTIFICIAL (tmp_var) = 1;
{
tree tmp_var;
-#if defined ENABLE_CHECKING
/* We don't allow types that are addressable (meaning we can't make copies),
incomplete, or of variable size. */
- if (TREE_ADDRESSABLE (type)
- || !COMPLETE_TYPE_P (type)
- || TREE_CODE (TYPE_SIZE_UNIT (type)) != INTEGER_CST)
- abort ();
-#endif
+ gcc_assert (!TREE_ADDRESSABLE (type)
+ && COMPLETE_TYPE_P (type)
+ && TREE_CODE (TYPE_SIZE_UNIT (type)) == INTEGER_CST);
tmp_var = create_tmp_var_raw (type, prefix);
gimple_add_tmp_var (tmp_var);
while (TREE_CODE (scope) == COMPOUND_EXPR)
scope = TREE_OPERAND (scope, 0);
- if (TREE_CODE (scope) != BIND_EXPR)
- abort ();
+ gcc_assert (TREE_CODE (scope) == BIND_EXPR);
temps = nreverse (last);
TREE_CHAIN (last) = BIND_EXPR_VARS (scope);
void
gimple_add_tmp_var (tree tmp)
{
- if (TREE_CHAIN (tmp) || DECL_SEEN_IN_BIND_EXPR_P (tmp))
- abort ();
+ gcc_assert (!TREE_CHAIN (tmp) && !DECL_SEEN_IN_BIND_EXPR_P (tmp));
DECL_CONTEXT (tmp) = current_function_decl;
DECL_SEEN_IN_BIND_EXPR_P (tmp) = 1;
static void
annotate_one_with_locus (tree t, location_t locus)
{
- if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (t)))
- && ! EXPR_HAS_LOCATION (t)
- && should_carry_locus_p (t))
+ if (EXPR_P (t) && ! EXPR_HAS_LOCATION (t) && should_carry_locus_p (t))
SET_EXPR_LOCATION (t, locus);
}
{
tree t = tsi_stmt (i);
-#ifdef ENABLE_CHECKING
- /* Assuming we've already been gimplified, we shouldn't
- see nested chaining constructs anymore. */
- if (TREE_CODE (t) == STATEMENT_LIST
- || TREE_CODE (t) == COMPOUND_EXPR)
- abort ();
-#endif
+ /* Assuming we've already been gimplified, we shouldn't
+ see nested chaining constructs anymore. */
+ gcc_assert (TREE_CODE (t) != STATEMENT_LIST
+ && TREE_CODE (t) != COMPOUND_EXPR);
annotate_one_with_locus (t, locus);
}
{
enum tree_code code = TREE_CODE (*tp);
/* Don't unshare types, decls, constants and SAVE_EXPR nodes. */
- if (TREE_CODE_CLASS (code) == 't'
- || TREE_CODE_CLASS (code) == 'd'
- || TREE_CODE_CLASS (code) == 'c'
+ if (TREE_CODE_CLASS (code) == tcc_type
+ || TREE_CODE_CLASS (code) == tcc_declaration
+ || TREE_CODE_CLASS (code) == tcc_constant
|| code == SAVE_EXPR || code == TARGET_EXPR
/* We can't do anything sensible with a BLOCK used as an expression,
but we also can't abort when we see it because of non-expression
uses. So just avert our eyes and cross our fingers. Silly Java. */
|| code == BLOCK)
*walk_subtrees = 0;
- else if (code == BIND_EXPR)
- abort ();
else
- copy_tree_r (tp, walk_subtrees, data);
+ {
+ gcc_assert (code != BIND_EXPR);
+ copy_tree_r (tp, walk_subtrees, data);
+ }
return NULL_TREE;
}
types and the bounds of types. Mark them as visited so we properly
unmark their subtrees on the unmark pass. If we've already seen them,
don't look down further. */
- if (TREE_CODE_CLASS (code) == 't'
- || TREE_CODE_CLASS (code) == 'd'
- || TREE_CODE_CLASS (code) == 'c')
+ if (TREE_CODE_CLASS (code) == tcc_type
+ || TREE_CODE_CLASS (code) == tcc_declaration
+ || TREE_CODE_CLASS (code) == tcc_constant)
{
if (TREE_VISITED (t))
*walk_subtrees = 0;
return expr;
}
-/* A terser interface for building a representation of a exception
+/* A terser interface for building a representation of an exception
specification. */
tree
p = tsi_end_p (i) ? NULL : tsi_stmt_ptr (i);
}
else
- {
+ {
for (; TREE_CODE (*p) == COMPOUND_EXPR; p = &TREE_OPERAND (*p, 1))
{
TREE_SIDE_EFFECTS (*p) = 1;
if (TREE_CODE (result_decl) == INDIRECT_REF)
/* See through a return by reference. */
result_decl = TREE_OPERAND (result_decl, 0);
-#ifdef ENABLE_CHECKING
- if ((TREE_CODE (ret_expr) != MODIFY_EXPR
- && TREE_CODE (ret_expr) != INIT_EXPR)
- || TREE_CODE (result_decl) != RESULT_DECL)
- abort ();
-#endif
+
+ gcc_assert ((TREE_CODE (ret_expr) == MODIFY_EXPR
+ || TREE_CODE (ret_expr) == INIT_EXPR)
+ && TREE_CODE (result_decl) == RESULT_DECL);
}
/* If aggregate_value_p is true, then we can return the bare RESULT_DECL.
Recall that aggregate_value_p is FALSE for any aggregate type that is
returned in registers. If we're returning values in registers, then
we don't want to extend the lifetime of the RESULT_DECL, particularly
- across another call. In addition, for those aggregates for which
+ across another call. In addition, for those aggregates for which
hard_function_value generates a PARALLEL, we'll abort during normal
expansion of structure assignments; there's special code in expand_return
to handle this case that does not exist in expand_expr. */
/* All occurrences of this decl in final gimplified code will be
replaced by indirection. Setting DECL_VALUE_EXPR does two
things: First, it lets the rest of the gimplifier know what
- replacement to use. Second, it lets the debug info know
+ replacement to use. Second, it lets the debug info know
where to find the value. */
ptr_type = build_pointer_type (TREE_TYPE (decl));
addr = create_tmp_var (ptr_type, get_name (decl));
/* If someone can be bothered to fill in the labels, they can
be bothered to null out the body too. */
- if (SWITCH_LABELS (switch_expr))
- abort ();
+ gcc_assert (!SWITCH_LABELS (switch_expr));
saved_labels = gimplify_ctxp->case_labels;
VARRAY_TREE_INIT (gimplify_ctxp->case_labels, 8, "case_labels");
SWITCH_BODY (switch_expr) = NULL;
}
- else if (!SWITCH_LABELS (switch_expr))
- abort ();
+ else
+ gcc_assert (SWITCH_LABELS (switch_expr));
return ret;
}
gimplify_case_label_expr (tree *expr_p)
{
tree expr = *expr_p;
- if (gimplify_ctxp->case_labels)
- VARRAY_PUSH_TREE (gimplify_ctxp->case_labels, expr);
- else
- abort ();
+
+ gcc_assert (gimplify_ctxp->case_labels);
+ VARRAY_PUSH_TREE (gimplify_ctxp->case_labels, expr);
*expr_p = build (LABEL_EXPR, void_type_node, CASE_LABEL (expr));
return GS_ALL_DONE;
}
/* First operand must be a LABELED_BLOCK_EXPR, which should
already be lowered (or partially lowered) when we get here. */
-#if defined ENABLE_CHECKING
- if (TREE_CODE (labeled_block) != LABELED_BLOCK_EXPR)
- abort ();
-#endif
+ gcc_assert (TREE_CODE (labeled_block) == LABELED_BLOCK_EXPR);
label = LABELED_BLOCK_LABEL (labeled_block);
*expr_p = build1 (GOTO_EXPR, void_type_node, label);
tree expr = *expr_p;
tree type;
- if (TREE_CODE (expr) != COMPONENT_REF)
- abort ();
+ gcc_assert (TREE_CODE (expr) == COMPONENT_REF);
if (INTEGRAL_TYPE_P (TREE_TYPE (expr)))
type = TREE_TYPE (get_unwidened (expr, NULL_TREE));
}
/* If a NOP conversion is changing a pointer to array of foo to a pointer
- to foo, embed that change in the ADDR_EXPR by converting
+ to foo, embed that change in the ADDR_EXPR by converting
T array[U];
(T *)&array
==>
static enum gimplify_status
gimplify_conversion (tree *expr_p)
-{
+{
/* If we still have a conversion at the toplevel, then strip
away all but the outermost conversion. */
if (TREE_CODE (*expr_p) == NOP_EXPR || TREE_CODE (*expr_p) == CONVERT_EXPR)
int i;
/* Create a stack of the subexpressions so later we can walk them in
- order from inner to outer.
+ order from inner to outer.
This array is very memory consuming. Don't even think of making
it VARRAY_TREE. */
p = &TREE_OPERAND (*p, 0))
VARRAY_PUSH_GENERIC_PTR_NOGC (stack, *p);
-#if defined ENABLE_CHECKING
- if (VARRAY_ACTIVE_SIZE (stack) == 0)
- abort ();
-#endif
+ gcc_assert (VARRAY_ACTIVE_SIZE (stack));
/* Now STACK is a stack of pointers to all the refs we've walked through
and P points to the innermost expression.
code = TREE_CODE (*expr_p);
-#if defined ENABLE_CHECKING
- if (code != POSTINCREMENT_EXPR
- && code != POSTDECREMENT_EXPR
- && code != PREINCREMENT_EXPR
- && code != PREDECREMENT_EXPR)
- abort ();
-#endif
+ gcc_assert (code == POSTINCREMENT_EXPR || code == POSTDECREMENT_EXPR
+ || code == PREINCREMENT_EXPR || code == PREDECREMENT_EXPR);
/* Prefix or postfix? */
if (code == POSTINCREMENT_EXPR || code == POSTDECREMENT_EXPR)
tree arglist;
enum gimplify_status ret;
-#if defined ENABLE_CHECKING
- if (TREE_CODE (*expr_p) != CALL_EXPR)
- abort ();
-#endif
+ gcc_assert (TREE_CODE (*expr_p) == CALL_EXPR);
- /* For reliable diagnostics during inlining, it is necessary that
+ /* For reliable diagnostics during inlining, it is necessary that
every call_expr be annotated with file and line. */
if (! EXPR_HAS_LOCATION (*expr_p))
SET_EXPR_LOCATION (*expr_p, input_location);
decl = get_callee_fndecl (*expr_p);
if (decl && DECL_BUILT_IN (decl))
{
- tree new = simplify_builtin (*expr_p, !want_value);
+ tree new = fold_builtin (*expr_p, !want_value);
if (new && new != *expr_p)
{
/* Try this again in case gimplification exposed something. */
if (ret != GS_ERROR && decl && DECL_BUILT_IN (decl))
{
- tree new = simplify_builtin (*expr_p, !want_value);
+ tree new = fold_builtin (*expr_p, !want_value);
if (new && new != *expr_p)
{
/* These expressions always produce boolean results. */
TREE_TYPE (expr) = boolean_type_node;
return expr;
-
+
default:
/* Other expressions that get here must have boolean values, but
might need to be converted to the appropriate mode. */
&& alias_sets_conflict_p (data->lhs_alias_set, get_alias_set (t)))
return t;
- if (DECL_P (t) || TYPE_P (t))
+ if (IS_TYPE_OR_DECL_P (t))
*walk_subtrees = 0;
return NULL;
}
/* Gimplify the constructor element to something appropriate for the rhs
of a MODIFY_EXPR. Given that we know the lhs is an aggregate, we know
- the gimplifier will consider this a store to memory. Doing this
+ the gimplifier will consider this a store to memory. Doing this
gimplification now means that we won't have to deal with complicated
language-specific trees, nor trees like SAVE_EXPR that can induce
- exponential search behaviour. */
+ exponential search behavior. */
one = gimplify_expr (expr_p, pre_p, post_p, is_gimple_mem_rhs, fb_rvalue);
if (one == GS_ERROR)
{
{
/* ??? Here's to hoping the front end fills in all of the indicies,
so we don't have to figure out what's missing ourselves. */
- if (!purpose)
- abort ();
+ gcc_assert (purpose);
/* ??? Need to handle this. */
- if (TREE_CODE (purpose) == RANGE_EXPR)
- abort ();
+ gcc_assert (TREE_CODE (purpose) != RANGE_EXPR);
cref = build (ARRAY_REF, array_elt_type, unshare_expr (object),
purpose, NULL_TREE, NULL_TREE);
}
/* If there are "lots" of initialized elements, even discounting
- those that are not address constants (and thus *must* be
+ those that are not address constants (and thus *must* be
computed at runtime), then partition the constructor into
constant and non-constant parts. Block copy the constant
parts in, then generate code for the non-constant parts. */
if (elt_list)
{
i = TREE_VALUE (elt_list);
- if (TREE_CHAIN (elt_list))
- abort ();
+ gcc_assert (!TREE_CHAIN (elt_list));
}
}
if (r == NULL || i == NULL)
default:
/* So how did we get a CONSTRUCTOR for a scalar type? */
- abort ();
+ gcc_unreachable ();
}
if (ret == GS_ERROR)
case COND_EXPR:
/* If we're assigning to a non-register type, push the assignment
down into the branches. This is mandatory for ADDRESSABLE types,
- since we cannot generate temporaries for such, but it saves a
+ since we cannot generate temporaries for such, but it saves a
copy in other cases as well. */
if (!is_gimple_reg_type (TREE_TYPE (*from_p)))
{
tree *to_p = &TREE_OPERAND (*expr_p, 0);
enum gimplify_status ret = GS_UNHANDLED;
-#if defined ENABLE_CHECKING
- if (TREE_CODE (*expr_p) != MODIFY_EXPR && TREE_CODE (*expr_p) != INIT_EXPR)
- abort ();
-#endif
+ gcc_assert (TREE_CODE (*expr_p) == MODIFY_EXPR
+ || TREE_CODE (*expr_p) == INIT_EXPR);
/* The distinction between MODIFY_EXPR and INIT_EXPR is no longer useful. */
if (TREE_CODE (*expr_p) == INIT_EXPR)
{
/* If we've somehow already got an SSA_NAME on the LHS, then
we're probably modifying it twice. Not good. */
- if (TREE_CODE (*to_p) == SSA_NAME)
- abort ();
+ gcc_assert (TREE_CODE (*to_p) != SSA_NAME);
*to_p = make_ssa_name (*to_p, *expr_p);
}
PRE_P points to the list where the side effects for all the
expressions in the sequence will be emitted.
-
+
WANT_VALUE is true when the result of the last COMPOUND_EXPR is used. */
/* ??? Should rearrange to share the pre-queue with all the indirect
- invocations of gimplify_expr. Would probably save on creations
+ invocations of gimplify_expr. Would probably save on creations
of statement_list nodes. */
static enum gimplify_status
enum gimplify_status ret = GS_ALL_DONE;
tree val;
-#if defined ENABLE_CHECKING
- if (TREE_CODE (*expr_p) != SAVE_EXPR)
- abort ();
-#endif
-
+ gcc_assert (TREE_CODE (*expr_p) == SAVE_EXPR);
val = TREE_OPERAND (*expr_p, 0);
/* If the SAVE_EXPR has not been resolved, then evaluate it once. */
switch (TREE_CODE (op0))
{
case INDIRECT_REF:
+ case MISALIGNED_INDIRECT_REF:
+ do_indirect_ref:
/* Check if we are dealing with an expression of the form '&*ptr'.
While the front end folds away '&*ptr' into 'ptr', these
expressions may be generated internally by the compiler (e.g.,
builtins like __builtin_va_end). */
- *expr_p = TREE_OPERAND (op0, 0);
- ret = GS_OK;
+ /* Caution: the silent array decomposition semantics we allow for
+ ADDR_EXPR means we can't always discard the pair. */
+ {
+ tree op00 = TREE_OPERAND (op0, 0);
+ tree t_expr = TREE_TYPE (expr);
+ tree t_op00 = TREE_TYPE (op00);
+
+ if (!lang_hooks.types_compatible_p (t_expr, t_op00))
+ {
+#ifdef ENABLE_CHECKING
+ tree t_op0 = TREE_TYPE (op0);
+ gcc_assert (TREE_CODE (t_op0) == ARRAY_TYPE
+ && POINTER_TYPE_P (t_expr)
+ && cpt_same_type (TREE_TYPE (t_op0),
+ TREE_TYPE (t_expr))
+ && POINTER_TYPE_P (t_op00)
+ && cpt_same_type (t_op0, TREE_TYPE (t_op00)));
+#endif
+ op00 = fold_convert (TREE_TYPE (expr), op00);
+ }
+ *expr_p = op00;
+ ret = GS_OK;
+ }
break;
case VIEW_CONVERT_EXPR:
??? The interactions of VIEW_CONVERT_EXPR and aliasing is not at
all clear. The impact of this transformation is even less clear. */
+
+ /* If the operand is a useless conversion, look through it. Doing so
+ guarantees that the ADDR_EXPR and its operand will remain of the
+ same type. */
+ if (tree_ssa_useless_type_conversion (TREE_OPERAND (op0, 0)))
+ op0 = TREE_OPERAND (op0, 0);
+
*expr_p = fold_convert (TREE_TYPE (expr),
build_fold_addr_expr (TREE_OPERAND (op0, 0)));
ret = GS_OK;
is_gimple_addressable, fb_either);
if (ret != GS_ERROR)
{
- /* The above may have made an INDIRECT_REF (e.g, Ada's NULL_EXPR),
- so check for it here. It's not worth checking for the other
- cases above. */
- if (TREE_CODE (TREE_OPERAND (expr, 0)) == INDIRECT_REF)
- {
- *expr_p = TREE_OPERAND (TREE_OPERAND (expr, 0), 0);
- break;
- }
+ op0 = TREE_OPERAND (expr, 0);
+
+ /* For various reasons, the gimplification of the expression
+ may have made a new INDIRECT_REF. */
+ if (TREE_CODE (op0) == INDIRECT_REF)
+ goto do_indirect_ref;
/* Make sure TREE_INVARIANT, TREE_CONSTANT, and TREE_SIDE_EFFECTS
is set properly. */
else
{
tret = gimplify_expr (&TREE_VALUE (link), pre_p, post_p,
- is_gimple_val, fb_rvalue);
+ is_gimple_asm_val, fb_rvalue);
if (tret == GS_ERROR)
ret = tret;
}
TREE_OPERAND (targ, 3) = init;
TARGET_EXPR_INITIAL (targ) = NULL_TREE;
}
- else if (!DECL_SEEN_IN_BIND_EXPR_P (temp))
+ else
/* We should have expanded this before. */
- abort ();
+ gcc_assert (DECL_SEEN_IN_BIND_EXPR_P (temp));
*expr_p = temp;
return GS_OK;
break;
case TREE_LIST:
- abort ();
+ gcc_unreachable ();
case COMPOUND_EXPR:
ret = gimplify_compound_expr (expr_p, pre_p, fallback != fb_none);
recalculate_side_effects (*expr_p);
break;
+ case ALIGN_INDIRECT_REF:
+ case MISALIGNED_INDIRECT_REF:
case INDIRECT_REF:
ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
is_gimple_reg, fb_rvalue);
case LABEL_EXPR:
ret = GS_ALL_DONE;
-#ifdef ENABLE_CHECKING
- if (decl_function_context (LABEL_EXPR_LABEL (*expr_p)) != current_function_decl)
- abort ();
-#endif
+ gcc_assert (decl_function_context (LABEL_EXPR_LABEL (*expr_p))
+ == current_function_decl);
break;
case CASE_LABEL_EXPR:
*expr_p = NULL_TREE;
}
-
+
ret = GS_ALL_DONE;
break;
case NON_LVALUE_EXPR:
/* This should have been stripped above. */
- abort ();
- break;
+ gcc_unreachable ();
case ASM_EXPR:
ret = gimplify_asm_expr (expr_p, pre_p, post_p);
case WITH_SIZE_EXPR:
{
enum gimplify_status r0, r1;
- r0 = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
+ r0 = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
post_p == &internal_post ? NULL : post_p,
gimple_test_f, fallback);
r1 = gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p, post_p,
/* ??? If this is a local variable, and it has not been seen in any
outer BIND_EXPR, then it's probably the result of a duplicate
declaration, for which we've already issued an error. It would
- be really nice if the front end wouldn't leak these at all.
+ be really nice if the front end wouldn't leak these at all.
Currently the only known culprit is C++ destructors, as seen
in g++.old-deja/g++.jason/binding.C. */
tmp = *expr_p;
&& decl_function_context (tmp) == current_function_decl
&& !DECL_SEEN_IN_BIND_EXPR_P (tmp))
{
-#ifdef ENABLE_CHECKING
- if (!errorcount && !sorrycount)
- abort ();
-#endif
+ gcc_assert (errorcount || sorrycount);
ret = GS_ERROR;
break;
}
break;
default:
- /* If this is a comparison of objects of aggregate type, handle
- it specially (by converting to a call to memcmp). It would be
- nice to only have to do this for variable-sized objects, but
- then we'd have to allow the same nest of reference nodes we
- allow for MODIFY_EXPR and that's too complex. */
- if (TREE_CODE_CLASS (TREE_CODE (*expr_p)) == '<'
- && (AGGREGATE_TYPE_P (TREE_TYPE (TREE_OPERAND (*expr_p, 1)))))
- ret = gimplify_variable_sized_compare (expr_p);
-
- /* If *EXPR_P does not need to be special-cased, handle it
- according to its class. */
- else if (TREE_CODE_CLASS (TREE_CODE (*expr_p)) == '1')
- ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
- post_p, is_gimple_val, fb_rvalue);
- else if (TREE_CODE_CLASS (TREE_CODE (*expr_p)) == '2'
- || TREE_CODE_CLASS (TREE_CODE (*expr_p)) == '<'
- || TREE_CODE (*expr_p) == TRUTH_AND_EXPR
- || TREE_CODE (*expr_p) == TRUTH_OR_EXPR
- || TREE_CODE (*expr_p) == TRUTH_XOR_EXPR)
+ switch (TREE_CODE_CLASS (TREE_CODE (*expr_p)))
{
- enum gimplify_status r0, r1;
+ case tcc_comparison:
+ /* If this is a comparison of objects of aggregate type,
+ handle it specially (by converting to a call to
+ memcmp). It would be nice to only have to do this
+ for variable-sized objects, but then we'd have to
+ allow the same nest of reference nodes we allow for
+ MODIFY_EXPR and that's too complex. */
+ if (!AGGREGATE_TYPE_P (TREE_TYPE (TREE_OPERAND (*expr_p, 1))))
+ goto expr_2;
+ ret = gimplify_variable_sized_compare (expr_p);
+ break;
- r0 = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
- post_p, is_gimple_val, fb_rvalue);
- r1 = gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p,
- post_p, is_gimple_val, fb_rvalue);
+ /* If *EXPR_P does not need to be special-cased, handle it
+ according to its class. */
+ case tcc_unary:
+ ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
+ post_p, is_gimple_val, fb_rvalue);
+ break;
- ret = MIN (r0, r1);
- }
- else if (TREE_CODE_CLASS (TREE_CODE (*expr_p)) == 'd'
- || TREE_CODE_CLASS (TREE_CODE (*expr_p)) == 'c')
- {
+ case tcc_binary:
+ expr_2:
+ {
+ enum gimplify_status r0, r1;
+
+ r0 = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
+ post_p, is_gimple_val, fb_rvalue);
+ r1 = gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p,
+ post_p, is_gimple_val, fb_rvalue);
+
+ ret = MIN (r0, r1);
+ break;
+ }
+
+ case tcc_declaration:
+ case tcc_constant:
ret = GS_ALL_DONE;
- break;
+ goto dont_recalculate;
+
+ default:
+ gcc_assert (TREE_CODE (*expr_p) == TRUTH_AND_EXPR
+ || TREE_CODE (*expr_p) == TRUTH_OR_EXPR
+ || TREE_CODE (*expr_p) == TRUTH_XOR_EXPR);
+ goto expr_2;
}
- else
- /* Fail if we don't know how to handle this tree code. */
- abort ();
recalculate_side_effects (*expr_p);
+ dont_recalculate:
break;
}
goto out;
}
-#ifdef ENABLE_CHECKING
/* This was only valid as a return value from the langhook, which
we handled. Make sure it doesn't escape from any other context. */
- if (ret == GS_UNHANDLED)
- abort ();
-#endif
+ gcc_assert (ret != GS_UNHANDLED);
if (fallback == fb_none && *expr_p && !is_gimple_stmt (*expr_p))
{
has side effects. Recurse through the operands to find it. */
enum tree_code code = TREE_CODE (*expr_p);
- if (code == COMPONENT_REF
- || code == REALPART_EXPR || code == IMAGPART_EXPR)
- gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
- gimple_test_f, fallback);
- else if (code == ARRAY_REF || code == ARRAY_RANGE_REF)
+ switch (code)
{
+ case COMPONENT_REF:
+ case REALPART_EXPR: case IMAGPART_EXPR:
+ gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
+ gimple_test_f, fallback);
+ break;
+
+ case ARRAY_REF: case ARRAY_RANGE_REF:
gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
gimple_test_f, fallback);
gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p, post_p,
- gimple_test_f, fallback);
+ gimple_test_f, fallback);
+ break;
+
+ default:
+ /* Anything else with side-effects must be converted to
+ a valid statement before we get here. */
+ gcc_unreachable ();
}
- else
- /* Anything else with side-effects
- must be converted to a valid statement before we get here. */
- abort ();
*expr_p = NULL;
}
}
else if ((fallback & fb_rvalue) && is_gimple_formal_tmp_rhs (*expr_p))
{
-#if defined ENABLE_CHECKING
- if (VOID_TYPE_P (TREE_TYPE (*expr_p)))
- abort ();
-#endif
+ gcc_assert (!VOID_TYPE_P (TREE_TYPE (*expr_p)));
/* An rvalue will do. Assign the gimplified expression into a new
temporary TMP and replace the original expression with TMP. */
if (TREE_CODE (*expr_p) != SSA_NAME)
DECL_GIMPLE_FORMAL_TEMP_P (*expr_p) = 1;
}
- else if (fallback & fb_mayfail)
+ else
{
- /* If this is an asm statement, and the user asked for the impossible,
- don't abort. Fail and let gimplify_asm_expr issue an error. */
+#ifdef ENABLE_CHECKING
+ if (!(fallback & fb_mayfail))
+ {
+ fprintf (stderr, "gimplification failed:\n");
+ print_generic_expr (stderr, *expr_p, 0);
+ debug_tree (*expr_p);
+ internal_error ("gimplification failed");
+ }
+#endif
+ gcc_assert (fallback & fb_mayfail);
+ /* If this is an asm statement, and the user asked for the
+ impossible, don't abort. Fail and let gimplify_asm_expr
+ issue an error. */
ret = GS_ERROR;
goto out;
}
- else
- {
- fprintf (stderr, "gimplification failed:\n");
- print_generic_expr (stderr, *expr_p, 0);
- debug_tree (*expr_p);
- abort ();
- }
-#if defined ENABLE_CHECKING
/* Make sure the temporary matches our predicate. */
- if (!(*gimple_test_f) (*expr_p))
- abort ();
-#endif
+ gcc_assert ((*gimple_test_f) (*expr_p));
if (internal_post)
{
otype = TREE_TYPE (t);
ptype = TREE_TYPE (TREE_OPERAND (t, 0));
dtype = TREE_TYPE (ptype);
- if (!cpt_same_type (otype, dtype))
- abort ();
+ gcc_assert (cpt_same_type (otype, dtype));
break;
case ADDR_EXPR:
a pointer to the array type. We must allow this in order to
properly represent assigning the address of an array in C into
pointer to the element type. */
- if (TREE_CODE (otype) == ARRAY_TYPE
- && POINTER_TYPE_P (ptype)
- && cpt_same_type (TREE_TYPE (otype), dtype))
- break;
- abort ();
+ gcc_assert (TREE_CODE (otype) == ARRAY_TYPE
+ && POINTER_TYPE_P (ptype)
+ && cpt_same_type (TREE_TYPE (otype), dtype));
+ break;
}
break;
ret = gimplify_expr (&expr, stmts, NULL,
gimple_test_f, fb_rvalue);
- if (ret == GS_ERROR)
- abort ();
+ gcc_assert (ret != GS_ERROR);
for (t = gimplify_ctxp->temps; t ; t = TREE_CHAIN (t))
add_referenced_tmp_var (t);