Handle movement of the final block.

Moving a final block caused segfaults and weird flow graph corruptions.
This commit is contained in:
Bill Currie 2012-05-04 19:48:32 +09:00
parent e8c17c68e6
commit 953e789db2

View file

@ -933,7 +933,7 @@ statement_label (sblock_t *sblock, expr_t *e)
e->e.label.next = sblock->labels; e->e.label.next = sblock->labels;
sblock->labels = &e->e.label; sblock->labels = &e->e.label;
} else { } else {
debug (e, "dropping unused label %s\n", e->e.label.name); debug (e, "dropping unused label %s", e->e.label.name);
} }
return sblock; return sblock;
} }
@ -1182,7 +1182,8 @@ merge_blocks (sblock_t *blocks)
} }
// the destiniation block must have only one label and one user for // the destiniation block must have only one label and one user for
// that label (ie, no other branch statement jumps to the block). // that label (ie, no other branch statement jumps to the block).
if (dest->labels->next || dest->labels->used > 1) // also, don't try to move a marker end-block
if (dest->labels->next || dest->labels->used > 1 || !dest->statements)
continue; continue;
// the destination block must be otherwise unreachable (preceeded by // the destination block must be otherwise unreachable (preceeded by
// an unconditional jump (goto or return)) // an unconditional jump (goto or return))
@ -1197,6 +1198,8 @@ merge_blocks (sblock_t *blocks)
if (!is_goto (s) && !is_return (s)) if (!is_goto (s) && !is_return (s))
continue; continue;
// desination block is reachable via only goto of the current block // desination block is reachable via only goto of the current block
if (!dest->next)
dest->next = new_sblock ();
sb->next = dest->next; // pull dest out of the chain sb->next = dest->next; // pull dest out of the chain
join_blocks (sblock, dest); join_blocks (sblock, dest);
did_something = 1; did_something = 1;