gh-109627: duplicated smalll exit blocks need to be assigned jump target labels (#109630)

This commit is contained in:
Irit Katriel 2023-09-21 00:08:06 +01:00 committed by GitHub
parent 14cdefa667
commit 9ccf0545ef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 29 additions and 6 deletions

View File

@ -1252,6 +1252,15 @@ class TestSpecifics(unittest.TestCase):
return a, b return a, b
self.assertEqual(f(), (54, 96)) self.assertEqual(f(), (54, 96))
def test_duplicated_small_exit_block(self):
# See gh-109627
def f():
while element and something:
try:
return something
except:
pass
@requires_debug_ranges() @requires_debug_ranges()
class TestSourcePositions(unittest.TestCase): class TestSourcePositions(unittest.TestCase):

View File

@ -0,0 +1,2 @@
Fix bug where the compiler does not assign a new jump target label to a
duplicated small exit block.

View File

@ -575,16 +575,23 @@ check_cfg(cfg_builder *g) {
return SUCCESS; return SUCCESS;
} }
static int
get_max_label(basicblock *entryblock)
{
int lbl = -1;
for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
if (b->b_label.id > lbl) {
lbl = b->b_label.id;
}
}
return lbl;
}
/* Calculate the actual jump target from the target_label */ /* Calculate the actual jump target from the target_label */
static int static int
translate_jump_labels_to_targets(basicblock *entryblock) translate_jump_labels_to_targets(basicblock *entryblock)
{ {
int max_label = -1; int max_label = get_max_label(entryblock);
for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
if (b->b_label.id > max_label) {
max_label = b->b_label.id;
}
}
size_t mapsize = sizeof(basicblock *) * (max_label + 1); size_t mapsize = sizeof(basicblock *) * (max_label + 1);
basicblock **label2block = (basicblock **)PyMem_Malloc(mapsize); basicblock **label2block = (basicblock **)PyMem_Malloc(mapsize);
if (!label2block) { if (!label2block) {
@ -2229,6 +2236,7 @@ is_exit_without_lineno(basicblock *b) {
return true; return true;
} }
/* PEP 626 mandates that the f_lineno of a frame is correct /* PEP 626 mandates that the f_lineno of a frame is correct
* after a frame terminates. It would be prohibitively expensive * after a frame terminates. It would be prohibitively expensive
* to continuously update the f_lineno field at runtime, * to continuously update the f_lineno field at runtime,
@ -2242,6 +2250,9 @@ static int
duplicate_exits_without_lineno(cfg_builder *g) duplicate_exits_without_lineno(cfg_builder *g)
{ {
assert(no_empty_basic_blocks(g)); assert(no_empty_basic_blocks(g));
int next_lbl = get_max_label(g->g_entryblock) + 1;
/* Copy all exit blocks without line number that are targets of a jump. /* Copy all exit blocks without line number that are targets of a jump.
*/ */
basicblock *entryblock = g->g_entryblock; basicblock *entryblock = g->g_entryblock;
@ -2260,6 +2271,7 @@ duplicate_exits_without_lineno(cfg_builder *g)
target->b_predecessors--; target->b_predecessors--;
new_target->b_predecessors = 1; new_target->b_predecessors = 1;
new_target->b_next = target->b_next; new_target->b_next = target->b_next;
new_target->b_label.id = next_lbl++;
target->b_next = new_target; target->b_next = new_target;
} }
} }