diff options
author | Alexandre Oliva <aoliva@redhat.com> | 2017-12-12 02:16:07 +0000 |
---|---|---|
committer | Alexandre Oliva <aoliva@gcc.gnu.org> | 2017-12-12 02:16:07 +0000 |
commit | 96a95ac18c2fe573d9c5039be18cf7c6cb26f171 (patch) | |
tree | b00f1071af75663b02d851d1219441346ab742ad /gcc/gimplify.c | |
parent | eb8b347423582a66758699748ffc3c499f6bdde2 (diff) | |
download | gcc-96a95ac18c2fe573d9c5039be18cf7c6cb26f171.zip gcc-96a95ac18c2fe573d9c5039be18cf7c6cb26f171.tar.gz gcc-96a95ac18c2fe573d9c5039be18cf7c6cb26f171.tar.bz2 |
[SFN] introduce statement frontier notes, still disabled
This patch completes the infrastructure for the introduction of
statement frontiers in C-family languages.
It brings in all the code remaining code needed to introduce and
transform begin stmt trees, gimple stmts, insns and notes, and
ultimately use them to generate the is_stmt column in DWARF2+ line
number tables/programs, however none of it is activated: the option
that would do so will be introduced in a subsequent patch.
This patch depends on an earlier patch with not-quite-boilerplate
changes towards SFN.
for gcc/c-family/ChangeLog
* c-semantics.c (pop_stmt_list): Move begin stmt marker into
subsequent statement list.
for gcc/c/ChangeLog
* c-objc-common.h (LANG_HOOKS_EMITS_BEGIN_STMT): Redefine as true.
* c-parser.c (add_debug_begin_stmt): New.
(c_parser_declaration_or_fndef): Call it.
(c_parser_compound_statement_nostart): Likewise.
(c_parser_statement_after_labels): Likewise.
* c-typeck (c_finish_stmt_expr): Skip begin stmts markers.
for gcc/cp/ChangeLog
* constexpr.c (check_constexpr_ctor_body_1): Skip begin stmt
markers.
(constexpr_fn_retval): Likewise.
(potential_constant_expression_1): Likewise.
(cxx_eval_statement_list): Check that a begin stmt marker is
not used as the value of a statement list.
(cxx_eval_constant_expression): Return begin stmt markers
unchanged.
* cp-array-notation.c (stmt_location): New.
(cp_expand_cond_array_notations): Use it.
* cp-objcp-common.h (LANG_HOOKS_EMITS_BEGIN_STMT): Redefine as true.
* parser.c (add_debug_begin_stmt): New.
(cp_parser_statement): Call it.
* pt.c (tsubst_copy): Handle begin stmt markers.
for gcc/ChangeLog
* cfgexpand.c (expand_gimple_basic_block): Handle begin stmt
markers. Integrate source bind into debug stmt expand loop.
(pass_expand::execute): Check debug marker limit. Avoid deep
TER and expand debug locations for debug bind insns only.
* cse.c (insn_live_p): Keep nonbind markers and debug bindings
followed by them.
* df-scan.c (df_insn_delete): Accept out-of-block debug insn.
* final.c (reemit_insn_block_notes): Take current block from
nonbind markers. Declare note where it's first set.
(final_scan_insn): Handle begin stmt notes. Emit is_stmt according to
begin stmt markers if enabled.
(notice_source_line): Handle nonbind markers. Fail if their
location is unknown or that of builtins.
(rest_of_handle_final): Convert begin stmt markers to notes if
var-tracking didn't run.
(rest_of_clean_state): Skip begin stmt markers.
* gimple-pretty-print.c (dump_gimple_debug): Handle begin stmt
markers.
* function.c (allocate_struct_function): Set begin_stmt_markers.
* function.h (struct function): Add debug_marker_count counter
and debug_nonbind_markers flag.
* gimple-iterator.c (gsi_remove): Adjust debug_marker_count.
* gimple-low.c (lower_function_body): Adjust
debug_nonbind_markers.
(lower_stmt): Drop or skip gimple debug stmts.
(lower_try_catch): Skip debug stmts.
* gimple.c (gimple_build_debug_begin_stmt): New.
(gimple_copy): Increment debug_marker_count if copying one.
* gimple.h (gimple_build_debug_begin_stmt): Declare.
* gimplify.c (rexpr_location): New.
(rexpr_has_location): New.
(warn_switch_unreachable_r): Handle gimple debug stmts.
(shortcut_cond_r): Call expr_location.
(find_goto): New.
(find_goto_label): New.
(shortcut_cond_expr): Call expr_has_location, expr_location, and
find_goto_label.
(gimplify_cond_expr): Call find_goto_label, expr_has_location, and
expr_location.
(gimplify_expr): Handle begin stmt markers. Reject debug expr decls.
* langhooks-def.h (LANG_HOOKS_EMITS_BEGIN_STMT): New. Add to...
(LANG_HOOKS_INITIALIZER): ... this.
* langhooks.h (struct lang_hooks): Add emits_begin_stmt.
* lra-contraints.c (inherit_reload_reg): Tolerate between-blocks
debug insns.
(update_ebb_live_info): Skip debug insn markers.
* lra.c (debug_insn_static_data): Rename to...
(debug_bind_static_data): ... this.
(debug_marker_static_data): New.
(lra_set_insn_recog_data): Select one of the above depending
on debug insn kind.
(lra_update_isn_regno_info): Don't assume debug insns have
freqs.
(push_insns): Skip debug insns.
* lto-streamer-in.c (input_function): Drop debug stmts
depending on active options. Adjust debug_nonbind_markers.
* params.def (PARAM_MAX_DEBUG_MARKER_COUNT): New.
* print-rtl.c (rtx_writer::print_rtx_operand_code_0): Handle
begin stmt marker notes.
(print_insn): Likewise.
* recog.c (extract_insn): Recognize rtl for debug markers.
* rtl.def (DEBUG_MARKER): New.
* tree-inline.c: Include params.h.
(remap_gimple_stmt): Handle nonbind markers.
(maybe_move_debug_stmts_to_successors): Likewise.
(copy_debug_stmt): Likewise.
* tree-iterator.c (append_to_statement_list_1): Append begin stmt
markers regardless of no side effects.
(tsi_link_before): Don't update container's side effects when adding
a begin stmt marker.
(tsi_link_after): Likewise.
(expr_first): Skip begin stmt markers.
(expr_last): Likewise.
* tree-pretty-print (dump_generic_node): Handle begin stmt markers.
* tree-ssa-threadedge.c (propagate_threaded_block_debug_info):
Disregard nonbind markers.
* tree.c (make_node_stat): Don't set side effects for begin stmt
markers.
(build1_stat): Likewise.
* tree.def (DEBUG_BEGIN_STMT): New.
* tree.h (GOTO_DESTINATION): Require a GOTO_EXPR.
* var-tracking.c (delete_debug_insns): Renamed to...
(delete_vta_debug_insns): ... this.
(reemit_marker_as_note): New.
(vt_initialize): Reemit markers.
(delete_vta_debug_insns): Likewise.
(vt_debug_insns_local): Reemit or delete markers.
(variable_tracking_main_1): Likewise.
* doc/generic.texi (DEBUG_BEGIN_STMT): Document.
* doc/gimple.texi (gimple_debug_begin_stmt_p): New.
(gimple_debug_nonbind_marker_p): New.
(gimple_build_debug_bind): Adjust.
(gimple_build_debug_begin_stmt): New.
* doc/invoke.texi (max-debug-marker-count): New param.
* doc/rtl.texi (debug_implicit_ptr, entry_value): New.
(debug_parameter_ref, debug_marker): New.
(NOTE_INSN_BEGIN_STMT): New.
(DEBUG_INSN): Describe begin stmt markers.
From-SVN: r255568
Diffstat (limited to 'gcc/gimplify.c')
-rw-r--r-- | gcc/gimplify.c | 158 |
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; |