aboutsummaryrefslogtreecommitdiff
path: root/gcc/gimplify.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/gimplify.c')
-rw-r--r--gcc/gimplify.c158
1 files changed, 125 insertions, 33 deletions
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 6a15daf4..8e1d400 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -983,6 +983,48 @@ unshare_expr_without_location (tree expr)
walk_tree (&expr, prune_expr_location, NULL, NULL);
return expr;
}
+
+/* Return the EXPR_LOCATION of EXPR, if it (maybe recursively) has
+ one, OR_ELSE otherwise. The location of a STATEMENT_LISTs
+ comprising at least one DEBUG_BEGIN_STMT followed by exactly one
+ EXPR is the location of the EXPR. */
+
+static location_t
+rexpr_location (tree expr, location_t or_else = UNKNOWN_LOCATION)
+{
+ if (!expr)
+ return or_else;
+
+ if (EXPR_HAS_LOCATION (expr))
+ return EXPR_LOCATION (expr);
+
+ if (TREE_CODE (expr) != STATEMENT_LIST)
+ return or_else;
+
+ tree_stmt_iterator i = tsi_start (expr);
+
+ bool found = false;
+ while (!tsi_end_p (i) && TREE_CODE (tsi_stmt (i)) == DEBUG_BEGIN_STMT)
+ {
+ found = true;
+ tsi_next (&i);
+ }
+
+ if (!found || !tsi_one_before_end_p (i))
+ return or_else;
+
+ return rexpr_location (tsi_stmt (i), or_else);
+}
+
+/* Return TRUE iff EXPR (maybe recursively) has a location; see
+ rexpr_location for the potential recursion. */
+
+static inline bool
+rexpr_has_location (tree expr)
+{
+ return rexpr_location (expr) != UNKNOWN_LOCATION;
+}
+
/* WRAPPER is a code such as BIND_EXPR or CLEANUP_POINT_EXPR which can both
contain statements and have a value. Assign its value to a temporary
@@ -1764,6 +1806,13 @@ warn_switch_unreachable_r (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
/* Walk the sub-statements. */
*handled_ops_p = false;
break;
+
+ case GIMPLE_DEBUG:
+ /* Ignore these. We may generate them before declarations that
+ are never executed. If there's something to warn about,
+ there will be non-debug stmts too, and we'll catch those. */
+ break;
+
case GIMPLE_CALL:
if (gimple_call_internal_p (stmt, IFN_ASAN_MARK))
{
@@ -3466,7 +3515,7 @@ shortcut_cond_r (tree pred, tree *true_label_p, tree *false_label_p,
append_to_statement_list (t, &expr);
/* Set the source location of the && on the second 'if'. */
- new_locus = EXPR_HAS_LOCATION (pred) ? EXPR_LOCATION (pred) : locus;
+ new_locus = rexpr_location (pred, locus);
t = shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p, false_label_p,
new_locus);
append_to_statement_list (t, &expr);
@@ -3489,7 +3538,7 @@ shortcut_cond_r (tree pred, tree *true_label_p, tree *false_label_p,
append_to_statement_list (t, &expr);
/* Set the source location of the || on the second 'if'. */
- new_locus = EXPR_HAS_LOCATION (pred) ? EXPR_LOCATION (pred) : locus;
+ new_locus = rexpr_location (pred, locus);
t = shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p, false_label_p,
new_locus);
append_to_statement_list (t, &expr);
@@ -3511,7 +3560,7 @@ shortcut_cond_r (tree pred, tree *true_label_p, tree *false_label_p,
/* Keep the original source location on the first 'if'. Set the source
location of the ? on the second 'if'. */
- new_locus = EXPR_HAS_LOCATION (pred) ? EXPR_LOCATION (pred) : locus;
+ new_locus = rexpr_location (pred, locus);
expr = build3 (COND_EXPR, void_type_node, TREE_OPERAND (pred, 0),
shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p,
false_label_p, locus),
@@ -3535,6 +3584,45 @@ shortcut_cond_r (tree pred, tree *true_label_p, tree *false_label_p,
return expr;
}
+/* If EXPR is a GOTO_EXPR, return it. If it is a STATEMENT_LIST, skip
+ any of its leading DEBUG_BEGIN_STMTS and recurse on the subsequent
+ statement, if it is the last one. Otherwise, return NULL. */
+
+static tree
+find_goto (tree expr)
+{
+ if (!expr)
+ return NULL_TREE;
+
+ if (TREE_CODE (expr) == GOTO_EXPR)
+ return expr;
+
+ if (TREE_CODE (expr) != STATEMENT_LIST)
+ return NULL_TREE;
+
+ tree_stmt_iterator i = tsi_start (expr);
+
+ while (!tsi_end_p (i) && TREE_CODE (tsi_stmt (i)) == DEBUG_BEGIN_STMT)
+ tsi_next (&i);
+
+ if (!tsi_one_before_end_p (i))
+ return NULL_TREE;
+
+ return find_goto (tsi_stmt (i));
+}
+
+/* Same as find_goto, except that it returns NULL if the destination
+ is not a LABEL_DECL. */
+
+static inline tree
+find_goto_label (tree expr)
+{
+ tree dest = find_goto (expr);
+ if (dest && TREE_CODE (GOTO_DESTINATION (dest)) == LABEL_DECL)
+ return dest;
+ return NULL_TREE;
+}
+
/* Given a conditional expression EXPR with short-circuit boolean
predicates using TRUTH_ANDIF_EXPR or TRUTH_ORIF_EXPR, break the
predicate apart into the equivalent sequence of conditionals. */
@@ -3565,8 +3653,8 @@ shortcut_cond_expr (tree expr)
location_t locus = EXPR_LOC_OR_LOC (expr, input_location);
TREE_OPERAND (expr, 0) = TREE_OPERAND (pred, 1);
/* Set the source location of the && on the second 'if'. */
- if (EXPR_HAS_LOCATION (pred))
- SET_EXPR_LOCATION (expr, EXPR_LOCATION (pred));
+ if (rexpr_has_location (pred))
+ SET_EXPR_LOCATION (expr, rexpr_location (pred));
then_ = shortcut_cond_expr (expr);
then_se = then_ && TREE_SIDE_EFFECTS (then_);
pred = TREE_OPERAND (pred, 0);
@@ -3587,8 +3675,8 @@ shortcut_cond_expr (tree expr)
location_t locus = EXPR_LOC_OR_LOC (expr, input_location);
TREE_OPERAND (expr, 0) = TREE_OPERAND (pred, 1);
/* Set the source location of the || on the second 'if'. */
- if (EXPR_HAS_LOCATION (pred))
- SET_EXPR_LOCATION (expr, EXPR_LOCATION (pred));
+ if (rexpr_has_location (pred))
+ SET_EXPR_LOCATION (expr, rexpr_location (pred));
else_ = shortcut_cond_expr (expr);
else_se = else_ && TREE_SIDE_EFFECTS (else_);
pred = TREE_OPERAND (pred, 0);
@@ -3615,20 +3703,16 @@ shortcut_cond_expr (tree expr)
/* If our arms just jump somewhere, hijack those labels so we don't
generate jumps to jumps. */
- if (then_
- && TREE_CODE (then_) == GOTO_EXPR
- && TREE_CODE (GOTO_DESTINATION (then_)) == LABEL_DECL)
+ if (tree then_goto = find_goto_label (then_))
{
- true_label = GOTO_DESTINATION (then_);
+ true_label = GOTO_DESTINATION (then_goto);
then_ = NULL;
then_se = false;
}
- if (else_
- && TREE_CODE (else_) == GOTO_EXPR
- && TREE_CODE (GOTO_DESTINATION (else_)) == LABEL_DECL)
+ if (tree else_goto = find_goto_label (else_))
{
- false_label = GOTO_DESTINATION (else_);
+ false_label = GOTO_DESTINATION (else_goto);
else_ = NULL;
else_se = false;
}
@@ -3692,8 +3776,8 @@ shortcut_cond_expr (tree expr)
{
tree last = expr_last (expr);
t = build_and_jump (&end_label);
- if (EXPR_HAS_LOCATION (last))
- SET_EXPR_LOCATION (t, EXPR_LOCATION (last));
+ if (rexpr_has_location (last))
+ SET_EXPR_LOCATION (t, rexpr_location (last));
append_to_statement_list (t, &expr);
}
if (emit_false)
@@ -3988,39 +4072,35 @@ gimplify_cond_expr (tree *expr_p, gimple_seq *pre_p, fallback_t fallback)
gimple_push_condition ();
have_then_clause_p = have_else_clause_p = false;
- if (TREE_OPERAND (expr, 1) != NULL
- && TREE_CODE (TREE_OPERAND (expr, 1)) == GOTO_EXPR
- && TREE_CODE (GOTO_DESTINATION (TREE_OPERAND (expr, 1))) == LABEL_DECL
- && (DECL_CONTEXT (GOTO_DESTINATION (TREE_OPERAND (expr, 1)))
- == current_function_decl)
+ label_true = find_goto_label (TREE_OPERAND (expr, 1));
+ if (label_true
+ && DECL_CONTEXT (GOTO_DESTINATION (label_true)) == current_function_decl
/* For -O0 avoid this optimization if the COND_EXPR and GOTO_EXPR
have different locations, otherwise we end up with incorrect
location information on the branches. */
&& (optimize
|| !EXPR_HAS_LOCATION (expr)
- || !EXPR_HAS_LOCATION (TREE_OPERAND (expr, 1))
- || EXPR_LOCATION (expr) == EXPR_LOCATION (TREE_OPERAND (expr, 1))))
+ || !rexpr_has_location (label_true)
+ || EXPR_LOCATION (expr) == rexpr_location (label_true)))
{
- label_true = GOTO_DESTINATION (TREE_OPERAND (expr, 1));
have_then_clause_p = true;
+ label_true = GOTO_DESTINATION (label_true);
}
else
label_true = create_artificial_label (UNKNOWN_LOCATION);
- if (TREE_OPERAND (expr, 2) != NULL
- && TREE_CODE (TREE_OPERAND (expr, 2)) == GOTO_EXPR
- && TREE_CODE (GOTO_DESTINATION (TREE_OPERAND (expr, 2))) == LABEL_DECL
- && (DECL_CONTEXT (GOTO_DESTINATION (TREE_OPERAND (expr, 2)))
- == current_function_decl)
+ label_false = find_goto_label (TREE_OPERAND (expr, 2));
+ if (label_false
+ && DECL_CONTEXT (GOTO_DESTINATION (label_false)) == current_function_decl
/* For -O0 avoid this optimization if the COND_EXPR and GOTO_EXPR
have different locations, otherwise we end up with incorrect
location information on the branches. */
&& (optimize
|| !EXPR_HAS_LOCATION (expr)
- || !EXPR_HAS_LOCATION (TREE_OPERAND (expr, 2))
- || EXPR_LOCATION (expr) == EXPR_LOCATION (TREE_OPERAND (expr, 2))))
+ || !rexpr_has_location (label_false)
+ || EXPR_LOCATION (expr) == rexpr_location (label_false)))
{
- label_false = GOTO_DESTINATION (TREE_OPERAND (expr, 2));
have_else_clause_p = true;
+ label_false = GOTO_DESTINATION (label_false);
}
else
label_false = create_artificial_label (UNKNOWN_LOCATION);
@@ -11809,6 +11889,18 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
ret = GS_ALL_DONE;
break;
+ case DEBUG_EXPR_DECL:
+ gcc_unreachable ();
+
+ case DEBUG_BEGIN_STMT:
+ gimplify_seq_add_stmt (pre_p,
+ gimple_build_debug_begin_stmt
+ (TREE_BLOCK (*expr_p),
+ EXPR_LOCATION (*expr_p)));
+ ret = GS_ALL_DONE;
+ *expr_p = NULL;
+ break;
+
case SSA_NAME:
/* Allow callbacks into the gimplifier during optimization. */
ret = GS_ALL_DONE;