aboutsummaryrefslogtreecommitdiff
path: root/gcc/final.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/final.c')
-rw-r--r--gcc/final.c109
1 files changed, 108 insertions, 1 deletions
diff --git a/gcc/final.c b/gcc/final.c
index fe1add2..f940b64 100644
--- a/gcc/final.c
+++ b/gcc/final.c
@@ -72,7 +72,6 @@ along with GCC; see the file COPYING3. If not see
#include "targhooks.h"
#include "debug.h"
#include "expr.h"
-#include "cfglayout.h" /* for reemit_insn_block_notes */
#include "tree-pass.h"
#include "tree-flow.h"
#include "timevar.h"
@@ -1515,6 +1514,114 @@ dwarf2_debug_info_emitted_p (tree decl)
return true;
}
+/* Return scope resulting from combination of S1 and S2. */
+static tree
+choose_inner_scope (tree s1, tree s2)
+{
+ if (!s1)
+ return s2;
+ if (!s2)
+ return s1;
+ if (BLOCK_NUMBER (s1) > BLOCK_NUMBER (s2))
+ return s1;
+ return s2;
+}
+
+/* Emit lexical block notes needed to change scope from S1 to S2. */
+
+static void
+change_scope (rtx orig_insn, tree s1, tree s2)
+{
+ rtx insn = orig_insn;
+ tree com = NULL_TREE;
+ tree ts1 = s1, ts2 = s2;
+ tree s;
+
+ while (ts1 != ts2)
+ {
+ gcc_assert (ts1 && ts2);
+ if (BLOCK_NUMBER (ts1) > BLOCK_NUMBER (ts2))
+ ts1 = BLOCK_SUPERCONTEXT (ts1);
+ else if (BLOCK_NUMBER (ts1) < BLOCK_NUMBER (ts2))
+ ts2 = BLOCK_SUPERCONTEXT (ts2);
+ else
+ {
+ ts1 = BLOCK_SUPERCONTEXT (ts1);
+ ts2 = BLOCK_SUPERCONTEXT (ts2);
+ }
+ }
+ com = ts1;
+
+ /* Close scopes. */
+ s = s1;
+ while (s != com)
+ {
+ rtx note = emit_note_before (NOTE_INSN_BLOCK_END, insn);
+ NOTE_BLOCK (note) = s;
+ s = BLOCK_SUPERCONTEXT (s);
+ }
+
+ /* Open scopes. */
+ s = s2;
+ while (s != com)
+ {
+ insn = emit_note_before (NOTE_INSN_BLOCK_BEG, insn);
+ NOTE_BLOCK (insn) = s;
+ s = BLOCK_SUPERCONTEXT (s);
+ }
+}
+
+/* Rebuild all the NOTE_INSN_BLOCK_BEG and NOTE_INSN_BLOCK_END notes based
+ on the scope tree and the newly reordered instructions. */
+
+static void
+reemit_insn_block_notes (void)
+{
+ tree cur_block = DECL_INITIAL (cfun->decl);
+ rtx insn, note;
+
+ insn = get_insns ();
+ if (!active_insn_p (insn))
+ insn = next_active_insn (insn);
+ for (; insn; insn = next_active_insn (insn))
+ {
+ tree this_block;
+
+ /* Avoid putting scope notes between jump table and its label. */
+ if (JUMP_TABLE_DATA_P (insn))
+ continue;
+
+ this_block = insn_scope (insn);
+ /* For sequences compute scope resulting from merging all scopes
+ of instructions nested inside. */
+ if (GET_CODE (PATTERN (insn)) == SEQUENCE)
+ {
+ int i;
+ rtx body = PATTERN (insn);
+
+ this_block = NULL;
+ for (i = 0; i < XVECLEN (body, 0); i++)
+ this_block = choose_inner_scope (this_block,
+ insn_scope (XVECEXP (body, 0, i)));
+ }
+ if (! this_block)
+ continue;
+
+ if (this_block != cur_block)
+ {
+ change_scope (insn, cur_block, this_block);
+ cur_block = this_block;
+ }
+ }
+
+ /* change_scope emits before the insn, not after. */
+ note = emit_note (NOTE_INSN_DELETED);
+ change_scope (note, cur_block, DECL_INITIAL (cfun->decl));
+ delete_insn (note);
+
+ reorder_blocks ();
+}
+
/* Output assembler code for the start of a function,
and initialize some of the variables in this file
for the new function. The label for the function and associated