From 717f1b4ee76648e22a596f32e483f4e88b55049b Mon Sep 17 00:00:00 2001 From: Irit Katriel <iritkatriel@yahoo.com> Date: Thu, 28 Jul 2022 19:57:18 +0100 Subject: [PATCH 01/14] gh-87092: create a 'jump target label' abstraction so that the compiler's codegen stage does not work directly with basic blocks --- Python/compile.c | 313 ++++++++++++++--------------------------------- 1 file changed, 95 insertions(+), 218 deletions(-) diff --git a/Python/compile.c b/Python/compile.c index 975efa7e23ecdf..db3fe70519876b 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -139,11 +139,19 @@ struct location { static struct location NO_LOCATION = {-1, -1, -1, -1}; +typedef struct basicblock_* jump_target_label; + +#define NEW_JUMP_TARGET_LABEL(C, NAME) \ + jump_target_label NAME = compiler_new_block(C); \ + if (NAME == NULL) { \ + return 0; \ + } + struct instr { int i_opcode; int i_oparg; /* target block (if jump instruction) */ - struct basicblock_ *i_target; + jump_target_label i_target; /* target block when exception is raised, should not be set by front-end. */ struct basicblock_ *i_except; struct location i_loc; @@ -418,7 +426,7 @@ typedef struct { // fail_pop[2]: POP_TOP // fail_pop[1]: POP_TOP // fail_pop[0]: NOP - basicblock **fail_pop; + jump_target_label *fail_pop; // The current length of fail_pop. Py_ssize_t fail_pop_size; // The number of items on top of the stack that need to *stay* on top of the @@ -1900,13 +1908,9 @@ compiler_call_exit_with_nones(struct compiler *c) { static int compiler_add_yield_from(struct compiler *c, int await) { - basicblock *start, *resume, *exit; - start = compiler_new_block(c); - resume = compiler_new_block(c); - exit = compiler_new_block(c); - if (start == NULL || resume == NULL || exit == NULL) { - return 0; - } + NEW_JUMP_TARGET_LABEL(c, start); + NEW_JUMP_TARGET_LABEL(c, resume); + NEW_JUMP_TARGET_LABEL(c, exit); compiler_use_next_block(c, start); ADDOP_JUMP(c, SEND, exit); compiler_use_next_block(c, resume); @@ -2816,7 +2820,7 @@ static int compiler_addcompare(struct compiler *c, cmpop_ty op) static int -compiler_jump_if(struct compiler *c, expr_ty e, basicblock *next, int cond) +compiler_jump_if(struct compiler *c, expr_ty e, jump_target_label next, int cond) { switch (e->kind) { case UnaryOp_kind: @@ -2829,11 +2833,10 @@ compiler_jump_if(struct compiler *c, expr_ty e, basicblock *next, int cond) Py_ssize_t i, n = asdl_seq_LEN(s) - 1; assert(n >= 0); int cond2 = e->v.BoolOp.op == Or; - basicblock *next2 = next; + jump_target_label next2 = next; if (!cond2 != !cond) { - next2 = compiler_new_block(c); - if (next2 == NULL) - return 0; + NEW_JUMP_TARGET_LABEL(c, new_next2); + next2 = new_next2; } for (i = 0; i < n; ++i) { if (!compiler_jump_if(c, (expr_ty)asdl_seq_GET(s, i), next2, cond2)) @@ -2846,13 +2849,8 @@ compiler_jump_if(struct compiler *c, expr_ty e, basicblock *next, int cond) return 1; } case IfExp_kind: { - basicblock *end, *next2; - end = compiler_new_block(c); - if (end == NULL) - return 0; - next2 = compiler_new_block(c); - if (next2 == NULL) - return 0; + NEW_JUMP_TARGET_LABEL(c, end); + NEW_JUMP_TARGET_LABEL(c, next2); if (!compiler_jump_if(c, e->v.IfExp.test, next2, 0)) return 0; if (!compiler_jump_if(c, e->v.IfExp.body, next, cond)) @@ -2870,9 +2868,7 @@ compiler_jump_if(struct compiler *c, expr_ty e, basicblock *next, int cond) if (!check_compare(c, e)) { return 0; } - basicblock *cleanup = compiler_new_block(c); - if (cleanup == NULL) - return 0; + NEW_JUMP_TARGET_LABEL(c, cleanup); VISIT(c, expr, e->v.Compare.left); for (i = 0; i < n; i++) { VISIT(c, expr, @@ -2885,9 +2881,7 @@ compiler_jump_if(struct compiler *c, expr_ty e, basicblock *next, int cond) VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Compare.comparators, n)); ADDOP_COMPARE(c, asdl_seq_GET(e->v.Compare.ops, n)); ADDOP_JUMP(c, cond ? POP_JUMP_IF_TRUE : POP_JUMP_IF_FALSE, next); - basicblock *end = compiler_new_block(c); - if (end == NULL) - return 0; + NEW_JUMP_TARGET_LABEL(c, end); ADDOP_JUMP_NOLINE(c, JUMP, end); compiler_use_next_block(c, cleanup); ADDOP(c, POP_TOP); @@ -2914,15 +2908,9 @@ compiler_jump_if(struct compiler *c, expr_ty e, basicblock *next, int cond) static int compiler_ifexp(struct compiler *c, expr_ty e) { - basicblock *end, *next; - assert(e->kind == IfExp_kind); - end = compiler_new_block(c); - if (end == NULL) - return 0; - next = compiler_new_block(c); - if (next == NULL) - return 0; + NEW_JUMP_TARGET_LABEL(c, end); + NEW_JUMP_TARGET_LABEL(c, next); if (!compiler_jump_if(c, e->v.IfExp.test, next, 0)) return 0; VISIT(c, expr, e->v.IfExp.body); @@ -2993,17 +2981,12 @@ compiler_lambda(struct compiler *c, expr_ty e) static int compiler_if(struct compiler *c, stmt_ty s) { - basicblock *end, *next; + jump_target_label next; assert(s->kind == If_kind); - end = compiler_new_block(c); - if (end == NULL) { - return 0; - } + NEW_JUMP_TARGET_LABEL(c, end); if (asdl_seq_LEN(s->v.If.orelse)) { - next = compiler_new_block(c); - if (next == NULL) { - return 0; - } + NEW_JUMP_TARGET_LABEL(c, orelse); + next = orelse; } else { next = end; @@ -3024,15 +3007,11 @@ compiler_if(struct compiler *c, stmt_ty s) static int compiler_for(struct compiler *c, stmt_ty s) { - basicblock *start, *body, *cleanup, *end; + NEW_JUMP_TARGET_LABEL(c, start); + NEW_JUMP_TARGET_LABEL(c, body); + NEW_JUMP_TARGET_LABEL(c, cleanup); + NEW_JUMP_TARGET_LABEL(c, end); - start = compiler_new_block(c); - body = compiler_new_block(c); - cleanup = compiler_new_block(c); - end = compiler_new_block(c); - if (start == NULL || body == NULL || end == NULL || cleanup == NULL) { - return 0; - } if (!compiler_push_fblock(c, FOR_LOOP, start, end, NULL)) { return 0; } @@ -3059,20 +3038,16 @@ compiler_for(struct compiler *c, stmt_ty s) static int compiler_async_for(struct compiler *c, stmt_ty s) { - basicblock *start, *except, *end; if (IS_TOP_LEVEL_AWAIT(c)){ c->u->u_ste->ste_coroutine = 1; } else if (c->u->u_scope_type != COMPILER_SCOPE_ASYNC_FUNCTION) { return compiler_error(c, "'async for' outside async function"); } - start = compiler_new_block(c); - except = compiler_new_block(c); - end = compiler_new_block(c); + NEW_JUMP_TARGET_LABEL(c, start); + NEW_JUMP_TARGET_LABEL(c, except); + NEW_JUMP_TARGET_LABEL(c, end); - if (start == NULL || except == NULL || end == NULL) { - return 0; - } VISIT(c, expr, s->v.AsyncFor.iter); ADDOP(c, GET_AITER); @@ -3115,14 +3090,11 @@ compiler_async_for(struct compiler *c, stmt_ty s) static int compiler_while(struct compiler *c, stmt_ty s) { - basicblock *loop, *body, *end, *anchor = NULL; - loop = compiler_new_block(c); - body = compiler_new_block(c); - anchor = compiler_new_block(c); - end = compiler_new_block(c); - if (loop == NULL || body == NULL || anchor == NULL || end == NULL) { - return 0; - } + NEW_JUMP_TARGET_LABEL(c, loop); + NEW_JUMP_TARGET_LABEL(c, body); + NEW_JUMP_TARGET_LABEL(c, end); + NEW_JUMP_TARGET_LABEL(c, anchor); + compiler_use_next_block(c, loop); if (!compiler_push_fblock(c, WHILE_LOOP, loop, end, NULL)) { return 0; @@ -3257,15 +3229,11 @@ compiler_continue(struct compiler *c) static int compiler_try_finally(struct compiler *c, stmt_ty s) { - basicblock *body, *end, *exit, *cleanup; + NEW_JUMP_TARGET_LABEL(c, body); + NEW_JUMP_TARGET_LABEL(c, end); + NEW_JUMP_TARGET_LABEL(c, exit); + NEW_JUMP_TARGET_LABEL(c, cleanup); - body = compiler_new_block(c); - end = compiler_new_block(c); - exit = compiler_new_block(c); - cleanup = compiler_new_block(c); - if (body == NULL || end == NULL || exit == NULL || cleanup == NULL) { - return 0; - } /* `try` block */ ADDOP_JUMP(c, SETUP_FINALLY, end); compiler_use_next_block(c, body); @@ -3302,22 +3270,10 @@ compiler_try_finally(struct compiler *c, stmt_ty s) static int compiler_try_star_finally(struct compiler *c, stmt_ty s) { - basicblock *body = compiler_new_block(c); - if (body == NULL) { - return 0; - } - basicblock *end = compiler_new_block(c); - if (!end) { - return 0; - } - basicblock *exit = compiler_new_block(c); - if (!exit) { - return 0; - } - basicblock *cleanup = compiler_new_block(c); - if (!cleanup) { - return 0; - } + NEW_JUMP_TARGET_LABEL(c, body); + NEW_JUMP_TARGET_LABEL(c, end); + NEW_JUMP_TARGET_LABEL(c, exit); + NEW_JUMP_TARGET_LABEL(c, cleanup); /* `try` block */ ADDOP_JUMP(c, SETUP_FINALLY, end); compiler_use_next_block(c, body); @@ -3386,15 +3342,13 @@ compiler_try_star_finally(struct compiler *c, stmt_ty s) static int compiler_try_except(struct compiler *c, stmt_ty s) { - basicblock *body, *except, *end, *cleanup; Py_ssize_t i, n; - body = compiler_new_block(c); - except = compiler_new_block(c); - end = compiler_new_block(c); - cleanup = compiler_new_block(c); - if (body == NULL || except == NULL || end == NULL || cleanup == NULL) - return 0; + NEW_JUMP_TARGET_LABEL(c, body); + NEW_JUMP_TARGET_LABEL(c, except); + NEW_JUMP_TARGET_LABEL(c, end); + NEW_JUMP_TARGET_LABEL(c, cleanup); + ADDOP_JUMP(c, SETUP_FINALLY, except); compiler_use_next_block(c, body); if (!compiler_push_fblock(c, TRY_EXCEPT, body, NULL, NULL)) @@ -3422,22 +3376,16 @@ compiler_try_except(struct compiler *c, stmt_ty s) if (!handler->v.ExceptHandler.type && i < n-1) { return compiler_error(c, "default 'except:' must be last"); } - except = compiler_new_block(c); - if (except == NULL) - return 0; + NEW_JUMP_TARGET_LABEL(c, next_except); + except = next_except; if (handler->v.ExceptHandler.type) { VISIT(c, expr, handler->v.ExceptHandler.type); ADDOP(c, CHECK_EXC_MATCH); ADDOP_JUMP(c, POP_JUMP_IF_FALSE, except); } if (handler->v.ExceptHandler.name) { - basicblock *cleanup_end, *cleanup_body; - - cleanup_end = compiler_new_block(c); - cleanup_body = compiler_new_block(c); - if (cleanup_end == NULL || cleanup_body == NULL) { - return 0; - } + NEW_JUMP_TARGET_LABEL(c, cleanup_end); + NEW_JUMP_TARGET_LABEL(c, cleanup_body); compiler_nameop(c, handler->v.ExceptHandler.name, Store); @@ -3484,11 +3432,7 @@ compiler_try_except(struct compiler *c, stmt_ty s) ADDOP_I(c, RERAISE, 1); } else { - basicblock *cleanup_body; - - cleanup_body = compiler_new_block(c); - if (!cleanup_body) - return 0; + NEW_JUMP_TARGET_LABEL(c, cleanup_body); ADDOP(c, POP_TOP); /* exc_value */ compiler_use_next_block(c, cleanup_body); @@ -3565,30 +3509,12 @@ compiler_try_except(struct compiler *c, stmt_ty s) static int compiler_try_star_except(struct compiler *c, stmt_ty s) { - basicblock *body = compiler_new_block(c); - if (body == NULL) { - return 0; - } - basicblock *except = compiler_new_block(c); - if (except == NULL) { - return 0; - } - basicblock *orelse = compiler_new_block(c); - if (orelse == NULL) { - return 0; - } - basicblock *end = compiler_new_block(c); - if (end == NULL) { - return 0; - } - basicblock *cleanup = compiler_new_block(c); - if (cleanup == NULL) { - return 0; - } - basicblock *reraise_star = compiler_new_block(c); - if (reraise_star == NULL) { - return 0; - } + NEW_JUMP_TARGET_LABEL(c, body); + NEW_JUMP_TARGET_LABEL(c, except); + NEW_JUMP_TARGET_LABEL(c, orelse); + NEW_JUMP_TARGET_LABEL(c, end); + NEW_JUMP_TARGET_LABEL(c, cleanup); + NEW_JUMP_TARGET_LABEL(c, reraise_star); ADDOP_JUMP(c, SETUP_FINALLY, except); compiler_use_next_block(c, body); @@ -3614,14 +3540,9 @@ compiler_try_star_except(struct compiler *c, stmt_ty s) excepthandler_ty handler = (excepthandler_ty)asdl_seq_GET( s->v.TryStar.handlers, i); SET_LOC(c, handler); - except = compiler_new_block(c); - if (except == NULL) { - return 0; - } - basicblock *handle_match = compiler_new_block(c); - if (handle_match == NULL) { - return 0; - } + NEW_JUMP_TARGET_LABEL(c, next_except); + except = next_except; + NEW_JUMP_TARGET_LABEL(c, handle_match); if (i == 0) { /* Push the original EG into the stack */ /* @@ -3650,14 +3571,8 @@ compiler_try_star_except(struct compiler *c, stmt_ty s) compiler_use_next_block(c, handle_match); - basicblock *cleanup_end = compiler_new_block(c); - if (cleanup_end == NULL) { - return 0; - } - basicblock *cleanup_body = compiler_new_block(c); - if (cleanup_body == NULL) { - return 0; - } + NEW_JUMP_TARGET_LABEL(c, cleanup_end); + NEW_JUMP_TARGET_LABEL(c, cleanup_body); if (handler->v.ExceptHandler.name) { compiler_nameop(c, handler->v.ExceptHandler.name, Store); @@ -3723,10 +3638,7 @@ compiler_try_star_except(struct compiler *c, stmt_ty s) /* Mark as artificial */ UNSET_LOC(c); compiler_pop_fblock(c, EXCEPTION_GROUP_HANDLER, NULL); - basicblock *reraise = compiler_new_block(c); - if (!reraise) { - return 0; - } + NEW_JUMP_TARGET_LABEL(c, reraise); compiler_use_next_block(c, reraise_star); ADDOP(c, PREP_RERAISE_STAR); @@ -3917,8 +3829,6 @@ compiler_from_import(struct compiler *c, stmt_ty s) static int compiler_assert(struct compiler *c, stmt_ty s) { - basicblock *end; - /* Always emit a warning if the test is a non-zero length tuple */ if ((s->v.Assert.test->kind == Tuple_kind && asdl_seq_LEN(s->v.Assert.test->v.Tuple.elts) > 0) || @@ -3934,9 +3844,7 @@ compiler_assert(struct compiler *c, stmt_ty s) } if (c->c_optimize) return 1; - end = compiler_new_block(c); - if (end == NULL) - return 0; + NEW_JUMP_TARGET_LABEL(c, end); if (!compiler_jump_if(c, s->v.Assert.test, end, 1)) return 0; ADDOP(c, LOAD_ASSERTION_ERROR); @@ -4243,7 +4151,6 @@ compiler_nameop(struct compiler *c, identifier name, expr_context_ty ctx) static int compiler_boolop(struct compiler *c, expr_ty e) { - basicblock *end; int jumpi; Py_ssize_t i, n; asdl_expr_seq *s; @@ -4253,19 +4160,14 @@ compiler_boolop(struct compiler *c, expr_ty e) jumpi = JUMP_IF_FALSE_OR_POP; else jumpi = JUMP_IF_TRUE_OR_POP; - end = compiler_new_block(c); - if (end == NULL) - return 0; + NEW_JUMP_TARGET_LABEL(c, end); s = e->v.BoolOp.values; n = asdl_seq_LEN(s) - 1; assert(n >= 0); for (i = 0; i < n; ++i) { VISIT(c, expr, (expr_ty)asdl_seq_GET(s, i)); ADDOP_JUMP(c, jumpi, end); - basicblock *next = compiler_new_block(c); - if (next == NULL) { - return 0; - } + NEW_JUMP_TARGET_LABEL(c, next); compiler_use_next_block(c, next); } VISIT(c, expr, (expr_ty)asdl_seq_GET(s, n)); @@ -4563,9 +4465,7 @@ compiler_compare(struct compiler *c, expr_ty e) ADDOP_COMPARE(c, asdl_seq_GET(e->v.Compare.ops, 0)); } else { - basicblock *cleanup = compiler_new_block(c); - if (cleanup == NULL) - return 0; + NEW_JUMP_TARGET_LABEL(c, cleanup); for (i = 0; i < n; i++) { VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Compare.comparators, i)); @@ -4576,9 +4476,7 @@ compiler_compare(struct compiler *c, expr_ty e) } VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Compare.comparators, n)); ADDOP_COMPARE(c, asdl_seq_GET(e->v.Compare.ops, n)); - basicblock *end = compiler_new_block(c); - if (end == NULL) - return 0; + NEW_JUMP_TARGET_LABEL(c, end); ADDOP_JUMP_NOLINE(c, JUMP, end); compiler_use_next_block(c, cleanup); ADDOP_I(c, SWAP, 2); @@ -5138,16 +5036,11 @@ compiler_sync_comprehension_generator(struct compiler *c, and then write to the element */ comprehension_ty gen; - basicblock *start, *anchor, *if_cleanup; Py_ssize_t i, n; - start = compiler_new_block(c); - if_cleanup = compiler_new_block(c); - anchor = compiler_new_block(c); - - if (start == NULL || if_cleanup == NULL || anchor == NULL) { - return 0; - } + NEW_JUMP_TARGET_LABEL(c, start); + NEW_JUMP_TARGET_LABEL(c, if_cleanup); + NEW_JUMP_TARGET_LABEL(c, anchor); gen = (comprehension_ty)asdl_seq_GET(generators, gen_index); @@ -5249,11 +5142,10 @@ compiler_async_comprehension_generator(struct compiler *c, expr_ty elt, expr_ty val, int type) { comprehension_ty gen; - basicblock *start, *if_cleanup, *except; Py_ssize_t i, n; - start = compiler_new_block(c); - except = compiler_new_block(c); - if_cleanup = compiler_new_block(c); + NEW_JUMP_TARGET_LABEL(c, start); + NEW_JUMP_TARGET_LABEL(c, except); + NEW_JUMP_TARGET_LABEL(c, if_cleanup); if (start == NULL || if_cleanup == NULL || except == NULL) { return 0; @@ -5494,12 +5386,9 @@ compiler_visit_keyword(struct compiler *c, keyword_ty k) static int -compiler_with_except_finish(struct compiler *c, basicblock * cleanup) { +compiler_with_except_finish(struct compiler *c, jump_target_label cleanup) { UNSET_LOC(c); - basicblock *suppress = compiler_new_block(c); - if (suppress == NULL) { - return 0; - } + NEW_JUMP_TARGET_LABEL(c, suppress); ADDOP_JUMP(c, POP_JUMP_IF_TRUE, suppress); ADDOP_I(c, RERAISE, 2); compiler_use_next_block(c, suppress); @@ -5508,10 +5397,7 @@ compiler_with_except_finish(struct compiler *c, basicblock * cleanup) { ADDOP(c, POP_EXCEPT); ADDOP(c, POP_TOP); ADDOP(c, POP_TOP); - basicblock *exit = compiler_new_block(c); - if (exit == NULL) { - return 0; - } + NEW_JUMP_TARGET_LABEL(c, exit); ADDOP_JUMP(c, JUMP, exit); compiler_use_next_block(c, cleanup); POP_EXCEPT_AND_RERAISE(c); @@ -5546,7 +5432,6 @@ compiler_with_except_finish(struct compiler *c, basicblock * cleanup) { static int compiler_async_with(struct compiler *c, stmt_ty s, int pos) { - basicblock *block, *final, *exit, *cleanup; withitem_ty item = asdl_seq_GET(s->v.AsyncWith.items, pos); assert(s->kind == AsyncWith_kind); @@ -5556,12 +5441,10 @@ compiler_async_with(struct compiler *c, stmt_ty s, int pos) return compiler_error(c, "'async with' outside async function"); } - block = compiler_new_block(c); - final = compiler_new_block(c); - exit = compiler_new_block(c); - cleanup = compiler_new_block(c); - if (!block || !final || !exit || !cleanup) - return 0; + NEW_JUMP_TARGET_LABEL(c, block); + NEW_JUMP_TARGET_LABEL(c, final); + NEW_JUMP_TARGET_LABEL(c, exit); + NEW_JUMP_TARGET_LABEL(c, cleanup); /* Evaluate EXPR */ VISIT(c, expr, item->context_expr); @@ -5652,17 +5535,14 @@ compiler_async_with(struct compiler *c, stmt_ty s, int pos) static int compiler_with(struct compiler *c, stmt_ty s, int pos) { - basicblock *block, *final, *exit, *cleanup; withitem_ty item = asdl_seq_GET(s->v.With.items, pos); assert(s->kind == With_kind); - block = compiler_new_block(c); - final = compiler_new_block(c); - exit = compiler_new_block(c); - cleanup = compiler_new_block(c); - if (!block || !final || !exit || !cleanup) - return 0; + NEW_JUMP_TARGET_LABEL(c, block); + NEW_JUMP_TARGET_LABEL(c, final); + NEW_JUMP_TARGET_LABEL(c, exit); + NEW_JUMP_TARGET_LABEL(c, cleanup); /* Evaluate EXPR */ VISIT(c, expr, item->context_expr); @@ -6243,7 +6123,7 @@ ensure_fail_pop(struct compiler *c, pattern_context *pc, Py_ssize_t n) if (size <= pc->fail_pop_size) { return 1; } - Py_ssize_t needed = sizeof(basicblock*) * size; + Py_ssize_t needed = sizeof(jump_target_label) * size; basicblock **resized = PyObject_Realloc(pc->fail_pop, needed); if (resized == NULL) { PyErr_NoMemory(); @@ -6251,8 +6131,7 @@ ensure_fail_pop(struct compiler *c, pattern_context *pc, Py_ssize_t n) } pc->fail_pop = resized; while (pc->fail_pop_size < size) { - basicblock *new_block; - RETURN_IF_FALSE(new_block = compiler_new_block(c)); + NEW_JUMP_TARGET_LABEL(c, new_block); pc->fail_pop[pc->fail_pop_size++] = new_block; } return 1; @@ -6689,8 +6568,7 @@ static int compiler_pattern_or(struct compiler *c, pattern_ty p, pattern_context *pc) { assert(p->kind == MatchOr_kind); - basicblock *end; - RETURN_IF_FALSE(end = compiler_new_block(c)); + NEW_JUMP_TARGET_LABEL(c, end); Py_ssize_t size = asdl_seq_LEN(p->v.MatchOr.patterns); assert(size > 1); // We're going to be messing with pc. Keep the original info handy: @@ -6952,8 +6830,7 @@ static int compiler_match_inner(struct compiler *c, stmt_ty s, pattern_context *pc) { VISIT(c, expr, s->v.Match.subject); - basicblock *end; - RETURN_IF_FALSE(end = compiler_new_block(c)); + NEW_JUMP_TARGET_LABEL(c, end); Py_ssize_t cases = asdl_seq_LEN(s->v.Match.cases); assert(cases > 0); match_case_ty m = asdl_seq_GET(s->v.Match.cases, cases - 1); From bce36a17805f22f8fcd9382981e214f3a0ad6061 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Thu, 28 Jul 2022 19:07:08 +0000 Subject: [PATCH 02/14] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20b?= =?UTF-8?q?lurb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../2022-07-28-19-07-06.gh-issue-87092.73IPS1.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2022-07-28-19-07-06.gh-issue-87092.73IPS1.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-07-28-19-07-06.gh-issue-87092.73IPS1.rst b/Misc/NEWS.d/next/Core and Builtins/2022-07-28-19-07-06.gh-issue-87092.73IPS1.rst new file mode 100644 index 00000000000000..d4cc4bb9afc2ef --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-07-28-19-07-06.gh-issue-87092.73IPS1.rst @@ -0,0 +1 @@ +Create a 'jump target label' abstraction in the compiler so that the compiler's codegen stage does not work directly with basic blocks. This prepares the code for changes to the underlying CFG generation mechanism. From 863f188ebd503b7861ae4c86b39b79b3e57689a4 Mon Sep 17 00:00:00 2001 From: Irit Katriel <iritkatriel@yahoo.com> Date: Thu, 28 Jul 2022 20:31:20 +0100 Subject: [PATCH 03/14] added SET_LABEL alias for compiler_use_next_block and replaced all codegen calls --- Python/compile.c | 206 +++++++++++++++++++++++++++++------------------ 1 file changed, 129 insertions(+), 77 deletions(-) diff --git a/Python/compile.c b/Python/compile.c index db3fe70519876b..730ea14a22dfd6 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -147,6 +147,8 @@ typedef struct basicblock_* jump_target_label; return 0; \ } +#define SET_LABEL(C, LBL) compiler_use_next_block(C, LBL) + struct instr { int i_opcode; int i_oparg; @@ -1911,13 +1913,16 @@ compiler_add_yield_from(struct compiler *c, int await) NEW_JUMP_TARGET_LABEL(c, start); NEW_JUMP_TARGET_LABEL(c, resume); NEW_JUMP_TARGET_LABEL(c, exit); - compiler_use_next_block(c, start); + + SET_LABEL(c, start); ADDOP_JUMP(c, SEND, exit); - compiler_use_next_block(c, resume); + + SET_LABEL(c, resume); ADDOP_I(c, YIELD_VALUE, 0); ADDOP_I(c, RESUME, await ? 3 : 2); ADDOP_JUMP(c, JUMP_NO_INTERRUPT, start); - compiler_use_next_block(c, exit); + + SET_LABEL(c, exit); return 1; } @@ -2844,8 +2849,9 @@ compiler_jump_if(struct compiler *c, expr_ty e, jump_target_label next, int cond } if (!compiler_jump_if(c, (expr_ty)asdl_seq_GET(s, n), next, cond)) return 0; - if (next2 != next) - compiler_use_next_block(c, next2); + if (next2 != next) { + SET_LABEL(c, next2); + } return 1; } case IfExp_kind: { @@ -2856,10 +2862,12 @@ compiler_jump_if(struct compiler *c, expr_ty e, jump_target_label next, int cond if (!compiler_jump_if(c, e->v.IfExp.body, next, cond)) return 0; ADDOP_JUMP_NOLINE(c, JUMP, end); - compiler_use_next_block(c, next2); + + SET_LABEL(c, next2); if (!compiler_jump_if(c, e->v.IfExp.orelse, next, cond)) return 0; - compiler_use_next_block(c, end); + + SET_LABEL(c, end); return 1; } case Compare_kind: { @@ -2883,12 +2891,14 @@ compiler_jump_if(struct compiler *c, expr_ty e, jump_target_label next, int cond ADDOP_JUMP(c, cond ? POP_JUMP_IF_TRUE : POP_JUMP_IF_FALSE, next); NEW_JUMP_TARGET_LABEL(c, end); ADDOP_JUMP_NOLINE(c, JUMP, end); - compiler_use_next_block(c, cleanup); + + SET_LABEL(c, cleanup); ADDOP(c, POP_TOP); if (!cond) { ADDOP_JUMP_NOLINE(c, JUMP, next); } - compiler_use_next_block(c, end); + + SET_LABEL(c, end); return 1; } /* fallback to general implementation */ @@ -2911,13 +2921,16 @@ compiler_ifexp(struct compiler *c, expr_ty e) assert(e->kind == IfExp_kind); NEW_JUMP_TARGET_LABEL(c, end); NEW_JUMP_TARGET_LABEL(c, next); + if (!compiler_jump_if(c, e->v.IfExp.test, next, 0)) return 0; VISIT(c, expr, e->v.IfExp.body); ADDOP_JUMP_NOLINE(c, JUMP, end); - compiler_use_next_block(c, next); + + SET_LABEL(c, next); VISIT(c, expr, e->v.IfExp.orelse); - compiler_use_next_block(c, end); + + SET_LABEL(c, end); return 1; } @@ -2997,10 +3010,12 @@ compiler_if(struct compiler *c, stmt_ty s) VISIT_SEQ(c, stmt, s->v.If.body); if (asdl_seq_LEN(s->v.If.orelse)) { ADDOP_JUMP_NOLINE(c, JUMP, end); - compiler_use_next_block(c, next); + + SET_LABEL(c, next); VISIT_SEQ(c, stmt, s->v.If.orelse); } - compiler_use_next_block(c, end); + + SET_LABEL(c, end); return 1; } @@ -3017,20 +3032,24 @@ compiler_for(struct compiler *c, stmt_ty s) } VISIT(c, expr, s->v.For.iter); ADDOP(c, GET_ITER); - compiler_use_next_block(c, start); + + SET_LABEL(c, start); ADDOP_JUMP(c, FOR_ITER, cleanup); - compiler_use_next_block(c, body); + + SET_LABEL(c, body); VISIT(c, expr, s->v.For.target); VISIT_SEQ(c, stmt, s->v.For.body); /* Mark jump as artificial */ UNSET_LOC(c); ADDOP_JUMP(c, JUMP, start); - compiler_use_next_block(c, cleanup); + + SET_LABEL(c, cleanup); compiler_pop_fblock(c, FOR_LOOP, start); VISIT_SEQ(c, stmt, s->v.For.orelse); - compiler_use_next_block(c, end); + + SET_LABEL(c, end); return 1; } @@ -3051,7 +3070,7 @@ compiler_async_for(struct compiler *c, stmt_ty s) VISIT(c, expr, s->v.AsyncFor.iter); ADDOP(c, GET_AITER); - compiler_use_next_block(c, start); + SET_LABEL(c, start); if (!compiler_push_fblock(c, FOR_LOOP, start, end, NULL)) { return 0; } @@ -3072,7 +3091,7 @@ compiler_async_for(struct compiler *c, stmt_ty s) compiler_pop_fblock(c, FOR_LOOP, start); /* Except block for __anext__ */ - compiler_use_next_block(c, except); + SET_LABEL(c, except); /* Use same line number as the iterator, * as the END_ASYNC_FOR succeeds the `for`, not the body. */ @@ -3082,8 +3101,7 @@ compiler_async_for(struct compiler *c, stmt_ty s) /* `else` block */ VISIT_SEQ(c, stmt, s->v.For.orelse); - compiler_use_next_block(c, end); - + SET_LABEL(c, end); return 1; } @@ -3095,7 +3113,7 @@ compiler_while(struct compiler *c, stmt_ty s) NEW_JUMP_TARGET_LABEL(c, end); NEW_JUMP_TARGET_LABEL(c, anchor); - compiler_use_next_block(c, loop); + SET_LABEL(c, loop); if (!compiler_push_fblock(c, WHILE_LOOP, loop, end, NULL)) { return 0; } @@ -3103,7 +3121,7 @@ compiler_while(struct compiler *c, stmt_ty s) return 0; } - compiler_use_next_block(c, body); + SET_LABEL(c, body); VISIT_SEQ(c, stmt, s->v.While.body); SET_LOC(c, s); if (!compiler_jump_if(c, s->v.While.test, body, 1)) { @@ -3112,12 +3130,12 @@ compiler_while(struct compiler *c, stmt_ty s) compiler_pop_fblock(c, WHILE_LOOP, loop); - compiler_use_next_block(c, anchor); + SET_LABEL(c, anchor); if (s->v.While.orelse) { VISIT_SEQ(c, stmt, s->v.While.orelse); } - compiler_use_next_block(c, end); + SET_LABEL(c, end); return 1; } @@ -3236,7 +3254,8 @@ compiler_try_finally(struct compiler *c, stmt_ty s) /* `try` block */ ADDOP_JUMP(c, SETUP_FINALLY, end); - compiler_use_next_block(c, body); + + SET_LABEL(c, body); if (!compiler_push_fblock(c, FINALLY_TRY, body, end, s->v.Try.finalbody)) return 0; if (s->v.Try.handlers && asdl_seq_LEN(s->v.Try.handlers)) { @@ -3251,7 +3270,8 @@ compiler_try_finally(struct compiler *c, stmt_ty s) VISIT_SEQ(c, stmt, s->v.Try.finalbody); ADDOP_JUMP_NOLINE(c, JUMP, exit); /* `finally` block */ - compiler_use_next_block(c, end); + + SET_LABEL(c, end); UNSET_LOC(c); ADDOP_JUMP(c, SETUP_CLEANUP, cleanup); @@ -3261,9 +3281,11 @@ compiler_try_finally(struct compiler *c, stmt_ty s) VISIT_SEQ(c, stmt, s->v.Try.finalbody); compiler_pop_fblock(c, FINALLY_END, end); ADDOP_I(c, RERAISE, 0); - compiler_use_next_block(c, cleanup); + + SET_LABEL(c, cleanup); POP_EXCEPT_AND_RERAISE(c); - compiler_use_next_block(c, exit); + + SET_LABEL(c, exit); return 1; } @@ -3276,7 +3298,8 @@ compiler_try_star_finally(struct compiler *c, stmt_ty s) NEW_JUMP_TARGET_LABEL(c, cleanup); /* `try` block */ ADDOP_JUMP(c, SETUP_FINALLY, end); - compiler_use_next_block(c, body); + + SET_LABEL(c, body); if (!compiler_push_fblock(c, FINALLY_TRY, body, end, s->v.TryStar.finalbody)) { return 0; } @@ -3292,8 +3315,9 @@ compiler_try_star_finally(struct compiler *c, stmt_ty s) compiler_pop_fblock(c, FINALLY_TRY, body); VISIT_SEQ(c, stmt, s->v.TryStar.finalbody); ADDOP_JUMP_NOLINE(c, JUMP, exit); + /* `finally` block */ - compiler_use_next_block(c, end); + SET_LABEL(c, end); UNSET_LOC(c); ADDOP_JUMP(c, SETUP_CLEANUP, cleanup); @@ -3304,9 +3328,11 @@ compiler_try_star_finally(struct compiler *c, stmt_ty s) VISIT_SEQ(c, stmt, s->v.TryStar.finalbody); compiler_pop_fblock(c, FINALLY_END, end); ADDOP_I(c, RERAISE, 0); - compiler_use_next_block(c, cleanup); + + SET_LABEL(c, cleanup); POP_EXCEPT_AND_RERAISE(c); - compiler_use_next_block(c, exit); + + SET_LABEL(c, exit); return 1; } @@ -3350,7 +3376,8 @@ compiler_try_except(struct compiler *c, stmt_ty s) NEW_JUMP_TARGET_LABEL(c, cleanup); ADDOP_JUMP(c, SETUP_FINALLY, except); - compiler_use_next_block(c, body); + + SET_LABEL(c, body); if (!compiler_push_fblock(c, TRY_EXCEPT, body, NULL, NULL)) return 0; VISIT_SEQ(c, stmt, s->v.Try.body); @@ -3361,7 +3388,8 @@ compiler_try_except(struct compiler *c, stmt_ty s) } ADDOP_JUMP_NOLINE(c, JUMP, end); n = asdl_seq_LEN(s->v.Try.handlers); - compiler_use_next_block(c, except); + + SET_LABEL(c, except); UNSET_LOC(c); ADDOP_JUMP(c, SETUP_CLEANUP, cleanup); @@ -3402,7 +3430,8 @@ compiler_try_except(struct compiler *c, stmt_ty s) /* second try: */ ADDOP_JUMP(c, SETUP_CLEANUP, cleanup_end); - compiler_use_next_block(c, cleanup_body); + + SET_LABEL(c, cleanup_body); if (!compiler_push_fblock(c, HANDLER_CLEANUP, cleanup_body, NULL, handler->v.ExceptHandler.name)) return 0; @@ -3420,7 +3449,7 @@ compiler_try_except(struct compiler *c, stmt_ty s) ADDOP_JUMP(c, JUMP, end); /* except: */ - compiler_use_next_block(c, cleanup_end); + SET_LABEL(c, cleanup_end); /* name = None; del name; # Mark as artificial */ UNSET_LOC(c); @@ -3435,7 +3464,8 @@ compiler_try_except(struct compiler *c, stmt_ty s) NEW_JUMP_TARGET_LABEL(c, cleanup_body); ADDOP(c, POP_TOP); /* exc_value */ - compiler_use_next_block(c, cleanup_body); + + SET_LABEL(c, cleanup_body); if (!compiler_push_fblock(c, HANDLER_CLEANUP, cleanup_body, NULL, NULL)) return 0; VISIT_SEQ(c, stmt, handler->v.ExceptHandler.body); @@ -3445,15 +3475,18 @@ compiler_try_except(struct compiler *c, stmt_ty s) ADDOP(c, POP_EXCEPT); ADDOP_JUMP(c, JUMP, end); } - compiler_use_next_block(c, except); + + SET_LABEL(c, except); } /* Mark as artificial */ UNSET_LOC(c); compiler_pop_fblock(c, EXCEPTION_HANDLER, NULL); ADDOP_I(c, RERAISE, 0); - compiler_use_next_block(c, cleanup); + + SET_LABEL(c, cleanup); POP_EXCEPT_AND_RERAISE(c); - compiler_use_next_block(c, end); + + SET_LABEL(c, end); return 1; } @@ -3517,7 +3550,8 @@ compiler_try_star_except(struct compiler *c, stmt_ty s) NEW_JUMP_TARGET_LABEL(c, reraise_star); ADDOP_JUMP(c, SETUP_FINALLY, except); - compiler_use_next_block(c, body); + + SET_LABEL(c, body); if (!compiler_push_fblock(c, TRY_EXCEPT, body, NULL, NULL)) { return 0; } @@ -3526,7 +3560,8 @@ compiler_try_star_except(struct compiler *c, stmt_ty s) ADDOP_NOLINE(c, POP_BLOCK); ADDOP_JUMP_NOLINE(c, JUMP, orelse); Py_ssize_t n = asdl_seq_LEN(s->v.TryStar.handlers); - compiler_use_next_block(c, except); + + SET_LABEL(c, except); UNSET_LOC(c); ADDOP_JUMP(c, SETUP_CLEANUP, cleanup); @@ -3569,7 +3604,7 @@ compiler_try_star_except(struct compiler *c, stmt_ty s) ADDOP_JUMP(c, JUMP, except); } - compiler_use_next_block(c, handle_match); + SET_LABEL(c, handle_match); NEW_JUMP_TARGET_LABEL(c, cleanup_end); NEW_JUMP_TARGET_LABEL(c, cleanup_body); @@ -3593,7 +3628,8 @@ compiler_try_star_except(struct compiler *c, stmt_ty s) */ /* second try: */ ADDOP_JUMP(c, SETUP_CLEANUP, cleanup_end); - compiler_use_next_block(c, cleanup_body); + + SET_LABEL(c, cleanup_body); if (!compiler_push_fblock(c, HANDLER_CLEANUP, cleanup_body, NULL, handler->v.ExceptHandler.name)) return 0; @@ -3611,7 +3647,7 @@ compiler_try_star_except(struct compiler *c, stmt_ty s) ADDOP_JUMP(c, JUMP, except); /* except: */ - compiler_use_next_block(c, cleanup_end); + SET_LABEL(c, cleanup_end); /* name = None; del name; # Mark as artificial */ UNSET_LOC(c); @@ -3625,9 +3661,9 @@ compiler_try_star_except(struct compiler *c, stmt_ty s) /* add exception raised to the res list */ ADDOP_I(c, LIST_APPEND, 3); // exc ADDOP(c, POP_TOP); // lasti - ADDOP_JUMP(c, JUMP, except); - compiler_use_next_block(c, except); + + SET_LABEL(c, except); if (i == n - 1) { /* Add exc to the list (if not None it's the unhandled part of the EG) */ @@ -3640,7 +3676,7 @@ compiler_try_star_except(struct compiler *c, stmt_ty s) compiler_pop_fblock(c, EXCEPTION_GROUP_HANDLER, NULL); NEW_JUMP_TARGET_LABEL(c, reraise); - compiler_use_next_block(c, reraise_star); + SET_LABEL(c, reraise_star); ADDOP(c, PREP_RERAISE_STAR); ADDOP_I(c, COPY, 1); ADDOP_JUMP(c, POP_JUMP_IF_NOT_NONE, reraise); @@ -3650,16 +3686,20 @@ compiler_try_star_except(struct compiler *c, stmt_ty s) ADDOP(c, POP_BLOCK); ADDOP(c, POP_EXCEPT); ADDOP_JUMP(c, JUMP, end); - compiler_use_next_block(c, reraise); + + SET_LABEL(c, reraise); ADDOP(c, POP_BLOCK); ADDOP_I(c, SWAP, 2); ADDOP(c, POP_EXCEPT); ADDOP_I(c, RERAISE, 0); - compiler_use_next_block(c, cleanup); + + SET_LABEL(c, cleanup); POP_EXCEPT_AND_RERAISE(c); - compiler_use_next_block(c, orelse); + + SET_LABEL(c, orelse); VISIT_SEQ(c, stmt, s->v.TryStar.orelse); - compiler_use_next_block(c, end); + + SET_LABEL(c, end); return 1; } @@ -3853,7 +3893,8 @@ compiler_assert(struct compiler *c, stmt_ty s) ADDOP_I(c, CALL, 0); } ADDOP_I(c, RAISE_VARARGS, 1); - compiler_use_next_block(c, end); + + SET_LABEL(c, end); return 1; } @@ -4168,10 +4209,12 @@ compiler_boolop(struct compiler *c, expr_ty e) VISIT(c, expr, (expr_ty)asdl_seq_GET(s, i)); ADDOP_JUMP(c, jumpi, end); NEW_JUMP_TARGET_LABEL(c, next); - compiler_use_next_block(c, next); + + SET_LABEL(c, next); } VISIT(c, expr, (expr_ty)asdl_seq_GET(s, n)); - compiler_use_next_block(c, end); + + SET_LABEL(c, end); return 1; } @@ -4478,10 +4521,12 @@ compiler_compare(struct compiler *c, expr_ty e) ADDOP_COMPARE(c, asdl_seq_GET(e->v.Compare.ops, n)); NEW_JUMP_TARGET_LABEL(c, end); ADDOP_JUMP_NOLINE(c, JUMP, end); - compiler_use_next_block(c, cleanup); + + SET_LABEL(c, cleanup); ADDOP_I(c, SWAP, 2); ADDOP(c, POP_TOP); - compiler_use_next_block(c, end); + + SET_LABEL(c, end); } return 1; } @@ -5079,7 +5124,7 @@ compiler_sync_comprehension_generator(struct compiler *c, } if (start) { depth++; - compiler_use_next_block(c, start); + SET_LABEL(c, start); ADDOP_JUMP(c, FOR_ITER, anchor); } VISIT(c, expr, gen->target); @@ -5126,10 +5171,12 @@ compiler_sync_comprehension_generator(struct compiler *c, return 0; } } - compiler_use_next_block(c, if_cleanup); + + SET_LABEL(c, if_cleanup); if (start) { ADDOP_JUMP(c, JUMP, start); - compiler_use_next_block(c, anchor); + + SET_LABEL(c, anchor); } return 1; @@ -5164,7 +5211,7 @@ compiler_async_comprehension_generator(struct compiler *c, ADDOP(c, GET_AITER); } - compiler_use_next_block(c, start); + SET_LABEL(c, start); /* Runtime will push a block here, so we need to account for that */ if (!compiler_push_fblock(c, ASYNC_COMPREHENSION_GENERATOR, start, NULL, NULL)) { @@ -5220,12 +5267,13 @@ compiler_async_comprehension_generator(struct compiler *c, return 0; } } - compiler_use_next_block(c, if_cleanup); + + SET_LABEL(c, if_cleanup); ADDOP_JUMP(c, JUMP, start); compiler_pop_fblock(c, ASYNC_COMPREHENSION_GENERATOR, start); - compiler_use_next_block(c, except); + SET_LABEL(c, except); //UNSET_LOC(c); ADDOP(c, END_ASYNC_FOR); @@ -5391,7 +5439,8 @@ compiler_with_except_finish(struct compiler *c, jump_target_label cleanup) { NEW_JUMP_TARGET_LABEL(c, suppress); ADDOP_JUMP(c, POP_JUMP_IF_TRUE, suppress); ADDOP_I(c, RERAISE, 2); - compiler_use_next_block(c, suppress); + + SET_LABEL(c, suppress); ADDOP(c, POP_TOP); /* exc_value */ ADDOP(c, POP_BLOCK); ADDOP(c, POP_EXCEPT); @@ -5399,9 +5448,11 @@ compiler_with_except_finish(struct compiler *c, jump_target_label cleanup) { ADDOP(c, POP_TOP); NEW_JUMP_TARGET_LABEL(c, exit); ADDOP_JUMP(c, JUMP, exit); - compiler_use_next_block(c, cleanup); + + SET_LABEL(c, cleanup); POP_EXCEPT_AND_RERAISE(c); - compiler_use_next_block(c, exit); + + SET_LABEL(c, exit); return 1; } @@ -5457,7 +5508,7 @@ compiler_async_with(struct compiler *c, stmt_ty s, int pos) ADDOP_JUMP(c, SETUP_WITH, final); /* SETUP_WITH pushes a finally block. */ - compiler_use_next_block(c, block); + SET_LABEL(c, block); if (!compiler_push_fblock(c, ASYNC_WITH, block, final, s)) { return 0; } @@ -5496,7 +5547,7 @@ compiler_async_with(struct compiler *c, stmt_ty s, int pos) ADDOP_JUMP(c, JUMP, exit); /* For exceptional outcome: */ - compiler_use_next_block(c, final); + SET_LABEL(c, final); ADDOP_JUMP(c, SETUP_CLEANUP, cleanup); ADDOP(c, PUSH_EXC_INFO); @@ -5506,7 +5557,7 @@ compiler_async_with(struct compiler *c, stmt_ty s, int pos) ADD_YIELD_FROM(c, 1); compiler_with_except_finish(c, cleanup); - compiler_use_next_block(c, exit); + SET_LABEL(c, exit); return 1; } @@ -5551,7 +5602,7 @@ compiler_with(struct compiler *c, stmt_ty s, int pos) ADDOP_JUMP(c, SETUP_WITH, final); /* SETUP_WITH pushes a finally block. */ - compiler_use_next_block(c, block); + SET_LABEL(c, block); if (!compiler_push_fblock(c, WITH, block, final, s)) { return 0; } @@ -5589,14 +5640,14 @@ compiler_with(struct compiler *c, stmt_ty s, int pos) ADDOP_JUMP(c, JUMP, exit); /* For exceptional outcome: */ - compiler_use_next_block(c, final); + SET_LABEL(c, final); ADDOP_JUMP(c, SETUP_CLEANUP, cleanup); ADDOP(c, PUSH_EXC_INFO); ADDOP(c, WITH_EXCEPT_START); compiler_with_except_finish(c, cleanup); - compiler_use_next_block(c, exit); + SET_LABEL(c, exit); return 1; } @@ -6158,7 +6209,7 @@ emit_and_reset_fail_pop(struct compiler *c, pattern_context *pc) return 1; } while (--pc->fail_pop_size) { - compiler_use_next_block(c, pc->fail_pop[pc->fail_pop_size]); + SET_LABEL(c, pc->fail_pop[pc->fail_pop_size]); if (!cfg_builder_addop_noarg(CFG_BUILDER(c), POP_TOP, COMPILER_LOC(c))) { pc->fail_pop_size = 0; PyObject_Free(pc->fail_pop); @@ -6166,7 +6217,7 @@ emit_and_reset_fail_pop(struct compiler *c, pattern_context *pc) return 0; } } - compiler_use_next_block(c, pc->fail_pop[0]); + SET_LABEL(c, pc->fail_pop[0]); PyObject_Free(pc->fail_pop); pc->fail_pop = NULL; return 1; @@ -6671,7 +6722,8 @@ compiler_pattern_or(struct compiler *c, pattern_ty p, pattern_context *pc) if (!cfg_builder_addop_noarg(CFG_BUILDER(c), POP_TOP, COMPILER_LOC(c)) || !jump_to_fail_pop(c, pc, JUMP)) { goto error; } - compiler_use_next_block(c, end); + + SET_LABEL(c, end); Py_ssize_t nstores = PyList_GET_SIZE(control); // There's a bunch of stuff on the stack between where the new stores // are and where they need to be: @@ -6899,7 +6951,7 @@ compiler_match_inner(struct compiler *c, stmt_ty s, pattern_context *pc) } VISIT_SEQ(c, stmt, m->body); } - compiler_use_next_block(c, end); + SET_LABEL(c, end); return 1; } From 1a59e4d39e075c1c48d54546ac9269a988c51098 Mon Sep 17 00:00:00 2001 From: Irit Katriel <iritkatriel@yahoo.com> Date: Fri, 29 Jul 2022 12:58:33 +0100 Subject: [PATCH 04/14] SET_LABEL --> USE_LABEL. fblockinfo also has labels rather than blocks --- Python/compile.c | 192 ++++++++++++++++++++++++----------------------- 1 file changed, 97 insertions(+), 95 deletions(-) diff --git a/Python/compile.c b/Python/compile.c index 730ea14a22dfd6..79cd0f8ca41cce 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -147,7 +147,9 @@ typedef struct basicblock_* jump_target_label; return 0; \ } -#define SET_LABEL(C, LBL) compiler_use_next_block(C, LBL) +#define USE_LABEL(C, LBL) compiler_use_next_block(C, LBL) + +#define NO_LABEL NULL struct instr { int i_opcode; @@ -319,9 +321,9 @@ enum fblocktype { WHILE_LOOP, FOR_LOOP, TRY_EXCEPT, FINALLY_TRY, FINALLY_END, struct fblockinfo { enum fblocktype fb_type; - basicblock *fb_block; + jump_target_label fb_block; /* (optional) type-specific exit or cleanup block */ - basicblock *fb_exit; + jump_target_label fb_exit; /* (optional) additional information required for unwinding */ void *fb_datum; }; @@ -1873,8 +1875,8 @@ find_ann(asdl_stmt_seq *stmts) */ static int -compiler_push_fblock(struct compiler *c, enum fblocktype t, basicblock *b, - basicblock *exit, void *datum) +compiler_push_fblock(struct compiler *c, enum fblocktype t, jump_target_label b, + jump_target_label exit, void *datum) { struct fblockinfo *f; if (c->u->u_nfblocks >= CO_MAXBLOCKS) { @@ -1889,7 +1891,7 @@ compiler_push_fblock(struct compiler *c, enum fblocktype t, basicblock *b, } static void -compiler_pop_fblock(struct compiler *c, enum fblocktype t, basicblock *b) +compiler_pop_fblock(struct compiler *c, enum fblocktype t, jump_target_label b) { struct compiler_unit *u = c->u; assert(u->u_nfblocks > 0); @@ -1914,15 +1916,15 @@ compiler_add_yield_from(struct compiler *c, int await) NEW_JUMP_TARGET_LABEL(c, resume); NEW_JUMP_TARGET_LABEL(c, exit); - SET_LABEL(c, start); + USE_LABEL(c, start); ADDOP_JUMP(c, SEND, exit); - SET_LABEL(c, resume); + USE_LABEL(c, resume); ADDOP_I(c, YIELD_VALUE, 0); ADDOP_I(c, RESUME, await ? 3 : 2); ADDOP_JUMP(c, JUMP_NO_INTERRUPT, start); - SET_LABEL(c, exit); + USE_LABEL(c, exit); return 1; } @@ -1974,14 +1976,14 @@ compiler_unwind_fblock(struct compiler *c, struct fblockinfo *info, /* This POP_BLOCK gets the line number of the unwinding statement */ ADDOP(c, POP_BLOCK); if (preserve_tos) { - if (!compiler_push_fblock(c, POP_VALUE, NULL, NULL, NULL)) { + if (!compiler_push_fblock(c, POP_VALUE, NO_LABEL, NO_LABEL, NULL)) { return 0; } } /* Emit the finally block */ VISIT_SEQ(c, stmt, info->fb_datum); if (preserve_tos) { - compiler_pop_fblock(c, POP_VALUE, NULL); + compiler_pop_fblock(c, POP_VALUE, NO_LABEL); } /* The finally block should appear to execute after the * statement causing the unwinding, so make the unwinding @@ -2850,7 +2852,7 @@ compiler_jump_if(struct compiler *c, expr_ty e, jump_target_label next, int cond if (!compiler_jump_if(c, (expr_ty)asdl_seq_GET(s, n), next, cond)) return 0; if (next2 != next) { - SET_LABEL(c, next2); + USE_LABEL(c, next2); } return 1; } @@ -2863,11 +2865,11 @@ compiler_jump_if(struct compiler *c, expr_ty e, jump_target_label next, int cond return 0; ADDOP_JUMP_NOLINE(c, JUMP, end); - SET_LABEL(c, next2); + USE_LABEL(c, next2); if (!compiler_jump_if(c, e->v.IfExp.orelse, next, cond)) return 0; - SET_LABEL(c, end); + USE_LABEL(c, end); return 1; } case Compare_kind: { @@ -2892,13 +2894,13 @@ compiler_jump_if(struct compiler *c, expr_ty e, jump_target_label next, int cond NEW_JUMP_TARGET_LABEL(c, end); ADDOP_JUMP_NOLINE(c, JUMP, end); - SET_LABEL(c, cleanup); + USE_LABEL(c, cleanup); ADDOP(c, POP_TOP); if (!cond) { ADDOP_JUMP_NOLINE(c, JUMP, next); } - SET_LABEL(c, end); + USE_LABEL(c, end); return 1; } /* fallback to general implementation */ @@ -2927,10 +2929,10 @@ compiler_ifexp(struct compiler *c, expr_ty e) VISIT(c, expr, e->v.IfExp.body); ADDOP_JUMP_NOLINE(c, JUMP, end); - SET_LABEL(c, next); + USE_LABEL(c, next); VISIT(c, expr, e->v.IfExp.orelse); - SET_LABEL(c, end); + USE_LABEL(c, end); return 1; } @@ -3011,11 +3013,11 @@ compiler_if(struct compiler *c, stmt_ty s) if (asdl_seq_LEN(s->v.If.orelse)) { ADDOP_JUMP_NOLINE(c, JUMP, end); - SET_LABEL(c, next); + USE_LABEL(c, next); VISIT_SEQ(c, stmt, s->v.If.orelse); } - SET_LABEL(c, end); + USE_LABEL(c, end); return 1; } @@ -3033,23 +3035,23 @@ compiler_for(struct compiler *c, stmt_ty s) VISIT(c, expr, s->v.For.iter); ADDOP(c, GET_ITER); - SET_LABEL(c, start); + USE_LABEL(c, start); ADDOP_JUMP(c, FOR_ITER, cleanup); - SET_LABEL(c, body); + USE_LABEL(c, body); VISIT(c, expr, s->v.For.target); VISIT_SEQ(c, stmt, s->v.For.body); /* Mark jump as artificial */ UNSET_LOC(c); ADDOP_JUMP(c, JUMP, start); - SET_LABEL(c, cleanup); + USE_LABEL(c, cleanup); compiler_pop_fblock(c, FOR_LOOP, start); VISIT_SEQ(c, stmt, s->v.For.orelse); - SET_LABEL(c, end); + USE_LABEL(c, end); return 1; } @@ -3070,7 +3072,7 @@ compiler_async_for(struct compiler *c, stmt_ty s) VISIT(c, expr, s->v.AsyncFor.iter); ADDOP(c, GET_AITER); - SET_LABEL(c, start); + USE_LABEL(c, start); if (!compiler_push_fblock(c, FOR_LOOP, start, end, NULL)) { return 0; } @@ -3091,7 +3093,7 @@ compiler_async_for(struct compiler *c, stmt_ty s) compiler_pop_fblock(c, FOR_LOOP, start); /* Except block for __anext__ */ - SET_LABEL(c, except); + USE_LABEL(c, except); /* Use same line number as the iterator, * as the END_ASYNC_FOR succeeds the `for`, not the body. */ @@ -3101,7 +3103,7 @@ compiler_async_for(struct compiler *c, stmt_ty s) /* `else` block */ VISIT_SEQ(c, stmt, s->v.For.orelse); - SET_LABEL(c, end); + USE_LABEL(c, end); return 1; } @@ -3113,7 +3115,7 @@ compiler_while(struct compiler *c, stmt_ty s) NEW_JUMP_TARGET_LABEL(c, end); NEW_JUMP_TARGET_LABEL(c, anchor); - SET_LABEL(c, loop); + USE_LABEL(c, loop); if (!compiler_push_fblock(c, WHILE_LOOP, loop, end, NULL)) { return 0; } @@ -3121,7 +3123,7 @@ compiler_while(struct compiler *c, stmt_ty s) return 0; } - SET_LABEL(c, body); + USE_LABEL(c, body); VISIT_SEQ(c, stmt, s->v.While.body); SET_LOC(c, s); if (!compiler_jump_if(c, s->v.While.test, body, 1)) { @@ -3130,12 +3132,12 @@ compiler_while(struct compiler *c, stmt_ty s) compiler_pop_fblock(c, WHILE_LOOP, loop); - SET_LABEL(c, anchor); + USE_LABEL(c, anchor); if (s->v.While.orelse) { VISIT_SEQ(c, stmt, s->v.While.orelse); } - SET_LABEL(c, end); + USE_LABEL(c, end); return 1; } @@ -3255,7 +3257,7 @@ compiler_try_finally(struct compiler *c, stmt_ty s) /* `try` block */ ADDOP_JUMP(c, SETUP_FINALLY, end); - SET_LABEL(c, body); + USE_LABEL(c, body); if (!compiler_push_fblock(c, FINALLY_TRY, body, end, s->v.Try.finalbody)) return 0; if (s->v.Try.handlers && asdl_seq_LEN(s->v.Try.handlers)) { @@ -3271,21 +3273,21 @@ compiler_try_finally(struct compiler *c, stmt_ty s) ADDOP_JUMP_NOLINE(c, JUMP, exit); /* `finally` block */ - SET_LABEL(c, end); + USE_LABEL(c, end); UNSET_LOC(c); ADDOP_JUMP(c, SETUP_CLEANUP, cleanup); ADDOP(c, PUSH_EXC_INFO); - if (!compiler_push_fblock(c, FINALLY_END, end, NULL, NULL)) + if (!compiler_push_fblock(c, FINALLY_END, end, NO_LABEL, NULL)) return 0; VISIT_SEQ(c, stmt, s->v.Try.finalbody); compiler_pop_fblock(c, FINALLY_END, end); ADDOP_I(c, RERAISE, 0); - SET_LABEL(c, cleanup); + USE_LABEL(c, cleanup); POP_EXCEPT_AND_RERAISE(c); - SET_LABEL(c, exit); + USE_LABEL(c, exit); return 1; } @@ -3299,7 +3301,7 @@ compiler_try_star_finally(struct compiler *c, stmt_ty s) /* `try` block */ ADDOP_JUMP(c, SETUP_FINALLY, end); - SET_LABEL(c, body); + USE_LABEL(c, body); if (!compiler_push_fblock(c, FINALLY_TRY, body, end, s->v.TryStar.finalbody)) { return 0; } @@ -3317,22 +3319,22 @@ compiler_try_star_finally(struct compiler *c, stmt_ty s) ADDOP_JUMP_NOLINE(c, JUMP, exit); /* `finally` block */ - SET_LABEL(c, end); + USE_LABEL(c, end); UNSET_LOC(c); ADDOP_JUMP(c, SETUP_CLEANUP, cleanup); ADDOP(c, PUSH_EXC_INFO); - if (!compiler_push_fblock(c, FINALLY_END, end, NULL, NULL)) { + if (!compiler_push_fblock(c, FINALLY_END, end, NO_LABEL, NULL)) { return 0; } VISIT_SEQ(c, stmt, s->v.TryStar.finalbody); compiler_pop_fblock(c, FINALLY_END, end); ADDOP_I(c, RERAISE, 0); - SET_LABEL(c, cleanup); + USE_LABEL(c, cleanup); POP_EXCEPT_AND_RERAISE(c); - SET_LABEL(c, exit); + USE_LABEL(c, exit); return 1; } @@ -3377,8 +3379,8 @@ compiler_try_except(struct compiler *c, stmt_ty s) ADDOP_JUMP(c, SETUP_FINALLY, except); - SET_LABEL(c, body); - if (!compiler_push_fblock(c, TRY_EXCEPT, body, NULL, NULL)) + USE_LABEL(c, body); + if (!compiler_push_fblock(c, TRY_EXCEPT, body, NO_LABEL, NULL)) return 0; VISIT_SEQ(c, stmt, s->v.Try.body); compiler_pop_fblock(c, TRY_EXCEPT, body); @@ -3389,13 +3391,13 @@ compiler_try_except(struct compiler *c, stmt_ty s) ADDOP_JUMP_NOLINE(c, JUMP, end); n = asdl_seq_LEN(s->v.Try.handlers); - SET_LABEL(c, except); + USE_LABEL(c, except); UNSET_LOC(c); ADDOP_JUMP(c, SETUP_CLEANUP, cleanup); ADDOP(c, PUSH_EXC_INFO); /* Runtime will push a block here, so we need to account for that */ - if (!compiler_push_fblock(c, EXCEPTION_HANDLER, NULL, NULL, NULL)) + if (!compiler_push_fblock(c, EXCEPTION_HANDLER, NO_LABEL, NO_LABEL, NULL)) return 0; for (i = 0; i < n; i++) { excepthandler_ty handler = (excepthandler_ty)asdl_seq_GET( @@ -3431,8 +3433,8 @@ compiler_try_except(struct compiler *c, stmt_ty s) /* second try: */ ADDOP_JUMP(c, SETUP_CLEANUP, cleanup_end); - SET_LABEL(c, cleanup_body); - if (!compiler_push_fblock(c, HANDLER_CLEANUP, cleanup_body, NULL, handler->v.ExceptHandler.name)) + USE_LABEL(c, cleanup_body); + if (!compiler_push_fblock(c, HANDLER_CLEANUP, cleanup_body, NO_LABEL, handler->v.ExceptHandler.name)) return 0; /* second # body */ @@ -3449,7 +3451,7 @@ compiler_try_except(struct compiler *c, stmt_ty s) ADDOP_JUMP(c, JUMP, end); /* except: */ - SET_LABEL(c, cleanup_end); + USE_LABEL(c, cleanup_end); /* name = None; del name; # Mark as artificial */ UNSET_LOC(c); @@ -3465,8 +3467,8 @@ compiler_try_except(struct compiler *c, stmt_ty s) ADDOP(c, POP_TOP); /* exc_value */ - SET_LABEL(c, cleanup_body); - if (!compiler_push_fblock(c, HANDLER_CLEANUP, cleanup_body, NULL, NULL)) + USE_LABEL(c, cleanup_body); + if (!compiler_push_fblock(c, HANDLER_CLEANUP, cleanup_body, NO_LABEL, NULL)) return 0; VISIT_SEQ(c, stmt, handler->v.ExceptHandler.body); compiler_pop_fblock(c, HANDLER_CLEANUP, cleanup_body); @@ -3476,17 +3478,17 @@ compiler_try_except(struct compiler *c, stmt_ty s) ADDOP_JUMP(c, JUMP, end); } - SET_LABEL(c, except); + USE_LABEL(c, except); } /* Mark as artificial */ UNSET_LOC(c); - compiler_pop_fblock(c, EXCEPTION_HANDLER, NULL); + compiler_pop_fblock(c, EXCEPTION_HANDLER, NO_LABEL); ADDOP_I(c, RERAISE, 0); - SET_LABEL(c, cleanup); + USE_LABEL(c, cleanup); POP_EXCEPT_AND_RERAISE(c); - SET_LABEL(c, end); + USE_LABEL(c, end); return 1; } @@ -3551,8 +3553,8 @@ compiler_try_star_except(struct compiler *c, stmt_ty s) ADDOP_JUMP(c, SETUP_FINALLY, except); - SET_LABEL(c, body); - if (!compiler_push_fblock(c, TRY_EXCEPT, body, NULL, NULL)) { + USE_LABEL(c, body); + if (!compiler_push_fblock(c, TRY_EXCEPT, body, NO_LABEL, NULL)) { return 0; } VISIT_SEQ(c, stmt, s->v.TryStar.body); @@ -3561,14 +3563,14 @@ compiler_try_star_except(struct compiler *c, stmt_ty s) ADDOP_JUMP_NOLINE(c, JUMP, orelse); Py_ssize_t n = asdl_seq_LEN(s->v.TryStar.handlers); - SET_LABEL(c, except); + USE_LABEL(c, except); UNSET_LOC(c); ADDOP_JUMP(c, SETUP_CLEANUP, cleanup); ADDOP(c, PUSH_EXC_INFO); /* Runtime will push a block here, so we need to account for that */ if (!compiler_push_fblock(c, EXCEPTION_GROUP_HANDLER, - NULL, NULL, "except handler")) { + NO_LABEL, NO_LABEL, "except handler")) { return 0; } for (Py_ssize_t i = 0; i < n; i++) { @@ -3604,7 +3606,7 @@ compiler_try_star_except(struct compiler *c, stmt_ty s) ADDOP_JUMP(c, JUMP, except); } - SET_LABEL(c, handle_match); + USE_LABEL(c, handle_match); NEW_JUMP_TARGET_LABEL(c, cleanup_end); NEW_JUMP_TARGET_LABEL(c, cleanup_body); @@ -3629,8 +3631,8 @@ compiler_try_star_except(struct compiler *c, stmt_ty s) /* second try: */ ADDOP_JUMP(c, SETUP_CLEANUP, cleanup_end); - SET_LABEL(c, cleanup_body); - if (!compiler_push_fblock(c, HANDLER_CLEANUP, cleanup_body, NULL, handler->v.ExceptHandler.name)) + USE_LABEL(c, cleanup_body); + if (!compiler_push_fblock(c, HANDLER_CLEANUP, cleanup_body, NO_LABEL, handler->v.ExceptHandler.name)) return 0; /* second # body */ @@ -3647,7 +3649,7 @@ compiler_try_star_except(struct compiler *c, stmt_ty s) ADDOP_JUMP(c, JUMP, except); /* except: */ - SET_LABEL(c, cleanup_end); + USE_LABEL(c, cleanup_end); /* name = None; del name; # Mark as artificial */ UNSET_LOC(c); @@ -3663,7 +3665,7 @@ compiler_try_star_except(struct compiler *c, stmt_ty s) ADDOP(c, POP_TOP); // lasti ADDOP_JUMP(c, JUMP, except); - SET_LABEL(c, except); + USE_LABEL(c, except); if (i == n - 1) { /* Add exc to the list (if not None it's the unhandled part of the EG) */ @@ -3673,10 +3675,10 @@ compiler_try_star_except(struct compiler *c, stmt_ty s) } /* Mark as artificial */ UNSET_LOC(c); - compiler_pop_fblock(c, EXCEPTION_GROUP_HANDLER, NULL); + compiler_pop_fblock(c, EXCEPTION_GROUP_HANDLER, NO_LABEL); NEW_JUMP_TARGET_LABEL(c, reraise); - SET_LABEL(c, reraise_star); + USE_LABEL(c, reraise_star); ADDOP(c, PREP_RERAISE_STAR); ADDOP_I(c, COPY, 1); ADDOP_JUMP(c, POP_JUMP_IF_NOT_NONE, reraise); @@ -3687,19 +3689,19 @@ compiler_try_star_except(struct compiler *c, stmt_ty s) ADDOP(c, POP_EXCEPT); ADDOP_JUMP(c, JUMP, end); - SET_LABEL(c, reraise); + USE_LABEL(c, reraise); ADDOP(c, POP_BLOCK); ADDOP_I(c, SWAP, 2); ADDOP(c, POP_EXCEPT); ADDOP_I(c, RERAISE, 0); - SET_LABEL(c, cleanup); + USE_LABEL(c, cleanup); POP_EXCEPT_AND_RERAISE(c); - SET_LABEL(c, orelse); + USE_LABEL(c, orelse); VISIT_SEQ(c, stmt, s->v.TryStar.orelse); - SET_LABEL(c, end); + USE_LABEL(c, end); return 1; } @@ -3894,7 +3896,7 @@ compiler_assert(struct compiler *c, stmt_ty s) } ADDOP_I(c, RAISE_VARARGS, 1); - SET_LABEL(c, end); + USE_LABEL(c, end); return 1; } @@ -4210,11 +4212,11 @@ compiler_boolop(struct compiler *c, expr_ty e) ADDOP_JUMP(c, jumpi, end); NEW_JUMP_TARGET_LABEL(c, next); - SET_LABEL(c, next); + USE_LABEL(c, next); } VISIT(c, expr, (expr_ty)asdl_seq_GET(s, n)); - SET_LABEL(c, end); + USE_LABEL(c, end); return 1; } @@ -4522,11 +4524,11 @@ compiler_compare(struct compiler *c, expr_ty e) NEW_JUMP_TARGET_LABEL(c, end); ADDOP_JUMP_NOLINE(c, JUMP, end); - SET_LABEL(c, cleanup); + USE_LABEL(c, cleanup); ADDOP_I(c, SWAP, 2); ADDOP(c, POP_TOP); - SET_LABEL(c, end); + USE_LABEL(c, end); } return 1; } @@ -5124,7 +5126,7 @@ compiler_sync_comprehension_generator(struct compiler *c, } if (start) { depth++; - SET_LABEL(c, start); + USE_LABEL(c, start); ADDOP_JUMP(c, FOR_ITER, anchor); } VISIT(c, expr, gen->target); @@ -5172,11 +5174,11 @@ compiler_sync_comprehension_generator(struct compiler *c, } } - SET_LABEL(c, if_cleanup); + USE_LABEL(c, if_cleanup); if (start) { ADDOP_JUMP(c, JUMP, start); - SET_LABEL(c, anchor); + USE_LABEL(c, anchor); } return 1; @@ -5211,10 +5213,10 @@ compiler_async_comprehension_generator(struct compiler *c, ADDOP(c, GET_AITER); } - SET_LABEL(c, start); + USE_LABEL(c, start); /* Runtime will push a block here, so we need to account for that */ if (!compiler_push_fblock(c, ASYNC_COMPREHENSION_GENERATOR, start, - NULL, NULL)) { + NO_LABEL, NULL)) { return 0; } @@ -5268,12 +5270,12 @@ compiler_async_comprehension_generator(struct compiler *c, } } - SET_LABEL(c, if_cleanup); + USE_LABEL(c, if_cleanup); ADDOP_JUMP(c, JUMP, start); compiler_pop_fblock(c, ASYNC_COMPREHENSION_GENERATOR, start); - SET_LABEL(c, except); + USE_LABEL(c, except); //UNSET_LOC(c); ADDOP(c, END_ASYNC_FOR); @@ -5440,7 +5442,7 @@ compiler_with_except_finish(struct compiler *c, jump_target_label cleanup) { ADDOP_JUMP(c, POP_JUMP_IF_TRUE, suppress); ADDOP_I(c, RERAISE, 2); - SET_LABEL(c, suppress); + USE_LABEL(c, suppress); ADDOP(c, POP_TOP); /* exc_value */ ADDOP(c, POP_BLOCK); ADDOP(c, POP_EXCEPT); @@ -5449,10 +5451,10 @@ compiler_with_except_finish(struct compiler *c, jump_target_label cleanup) { NEW_JUMP_TARGET_LABEL(c, exit); ADDOP_JUMP(c, JUMP, exit); - SET_LABEL(c, cleanup); + USE_LABEL(c, cleanup); POP_EXCEPT_AND_RERAISE(c); - SET_LABEL(c, exit); + USE_LABEL(c, exit); return 1; } @@ -5508,7 +5510,7 @@ compiler_async_with(struct compiler *c, stmt_ty s, int pos) ADDOP_JUMP(c, SETUP_WITH, final); /* SETUP_WITH pushes a finally block. */ - SET_LABEL(c, block); + USE_LABEL(c, block); if (!compiler_push_fblock(c, ASYNC_WITH, block, final, s)) { return 0; } @@ -5547,7 +5549,7 @@ compiler_async_with(struct compiler *c, stmt_ty s, int pos) ADDOP_JUMP(c, JUMP, exit); /* For exceptional outcome: */ - SET_LABEL(c, final); + USE_LABEL(c, final); ADDOP_JUMP(c, SETUP_CLEANUP, cleanup); ADDOP(c, PUSH_EXC_INFO); @@ -5557,7 +5559,7 @@ compiler_async_with(struct compiler *c, stmt_ty s, int pos) ADD_YIELD_FROM(c, 1); compiler_with_except_finish(c, cleanup); - SET_LABEL(c, exit); + USE_LABEL(c, exit); return 1; } @@ -5602,7 +5604,7 @@ compiler_with(struct compiler *c, stmt_ty s, int pos) ADDOP_JUMP(c, SETUP_WITH, final); /* SETUP_WITH pushes a finally block. */ - SET_LABEL(c, block); + USE_LABEL(c, block); if (!compiler_push_fblock(c, WITH, block, final, s)) { return 0; } @@ -5640,14 +5642,14 @@ compiler_with(struct compiler *c, stmt_ty s, int pos) ADDOP_JUMP(c, JUMP, exit); /* For exceptional outcome: */ - SET_LABEL(c, final); + USE_LABEL(c, final); ADDOP_JUMP(c, SETUP_CLEANUP, cleanup); ADDOP(c, PUSH_EXC_INFO); ADDOP(c, WITH_EXCEPT_START); compiler_with_except_finish(c, cleanup); - SET_LABEL(c, exit); + USE_LABEL(c, exit); return 1; } @@ -6175,7 +6177,7 @@ ensure_fail_pop(struct compiler *c, pattern_context *pc, Py_ssize_t n) return 1; } Py_ssize_t needed = sizeof(jump_target_label) * size; - basicblock **resized = PyObject_Realloc(pc->fail_pop, needed); + jump_target_label *resized = PyObject_Realloc(pc->fail_pop, needed); if (resized == NULL) { PyErr_NoMemory(); return 0; @@ -6209,7 +6211,7 @@ emit_and_reset_fail_pop(struct compiler *c, pattern_context *pc) return 1; } while (--pc->fail_pop_size) { - SET_LABEL(c, pc->fail_pop[pc->fail_pop_size]); + USE_LABEL(c, pc->fail_pop[pc->fail_pop_size]); if (!cfg_builder_addop_noarg(CFG_BUILDER(c), POP_TOP, COMPILER_LOC(c))) { pc->fail_pop_size = 0; PyObject_Free(pc->fail_pop); @@ -6217,7 +6219,7 @@ emit_and_reset_fail_pop(struct compiler *c, pattern_context *pc) return 0; } } - SET_LABEL(c, pc->fail_pop[0]); + USE_LABEL(c, pc->fail_pop[0]); PyObject_Free(pc->fail_pop); pc->fail_pop = NULL; return 1; @@ -6723,7 +6725,7 @@ compiler_pattern_or(struct compiler *c, pattern_ty p, pattern_context *pc) goto error; } - SET_LABEL(c, end); + USE_LABEL(c, end); Py_ssize_t nstores = PyList_GET_SIZE(control); // There's a bunch of stuff on the stack between where the new stores // are and where they need to be: @@ -6951,7 +6953,7 @@ compiler_match_inner(struct compiler *c, stmt_ty s, pattern_context *pc) } VISIT_SEQ(c, stmt, m->body); } - SET_LABEL(c, end); + USE_LABEL(c, end); return 1; } From ac8b7b31552a878efbc34161d4c3f1dd2ffd1e32 Mon Sep 17 00:00:00 2001 From: Irit Katriel <iritkatriel@yahoo.com> Date: Fri, 29 Jul 2022 16:58:18 +0100 Subject: [PATCH 05/14] instr has both target_label and target. Front end sets target_label and backend calculates target from it --- Python/compile.c | 74 +++++++++++++++++++++++++++++++++++------------- 1 file changed, 55 insertions(+), 19 deletions(-) diff --git a/Python/compile.c b/Python/compile.c index 79cd0f8ca41cce..33a324334cdad1 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -154,8 +154,11 @@ typedef struct basicblock_* jump_target_label; struct instr { int i_opcode; int i_oparg; - /* target block (if jump instruction) */ - jump_target_label i_target; + /* target block (if jump instruction) -- we temporarily have both the label + and the block in the instr. The label is set by front end, and the block + is calculated by backend. */ + jump_target_label i_target_label; + struct basicblock_ *i_target; /* target block when exception is raised, should not be set by front-end. */ struct basicblock_ *i_except; struct location i_loc; @@ -1266,7 +1269,7 @@ PyCompile_OpcodeStackEffect(int opcode, int oparg) static int basicblock_addop(basicblock *b, int opcode, int oparg, - basicblock *target, struct location loc) + jump_target_label target, struct location loc) { assert(IS_WITHIN_OPCODE_RANGE(opcode)); assert(!IS_ASSEMBLER_OPCODE(opcode)); @@ -1284,14 +1287,15 @@ basicblock_addop(basicblock *b, int opcode, int oparg, struct instr *i = &b->b_instr[off]; i->i_opcode = opcode; i->i_oparg = oparg; - i->i_target = target; + i->i_target_label = target; + i->i_target = NULL; i->i_loc = loc; return 1; } static int -cfg_builder_addop(cfg_builder *g, int opcode, int oparg, basicblock *target, +cfg_builder_addop(cfg_builder *g, int opcode, int oparg, jump_target_label target, struct location loc) { struct instr *last = basicblock_last_instr(g->curblock); @@ -1309,7 +1313,7 @@ static int cfg_builder_addop_noarg(cfg_builder *g, int opcode, struct location loc) { assert(!HAS_ARG(opcode)); - return cfg_builder_addop(g, opcode, 0, NULL, loc); + return cfg_builder_addop(g, opcode, 0, NO_LABEL, loc); } static Py_ssize_t @@ -1521,7 +1525,7 @@ cfg_builder_addop_i(cfg_builder *g, int opcode, Py_ssize_t oparg, struct locatio EXTENDED_ARG is used for 16, 24, and 32-bit arguments. */ int oparg_ = Py_SAFE_DOWNCAST(oparg, Py_ssize_t, int); - return cfg_builder_addop(g, opcode, oparg_, NULL, loc); + return cfg_builder_addop(g, opcode, oparg_, NO_LABEL, loc); } static int @@ -5116,15 +5120,15 @@ compiler_sync_comprehension_generator(struct compiler *c, expr_ty elt = asdl_seq_GET(elts, 0); if (elt->kind != Starred_kind) { VISIT(c, expr, elt); - start = NULL; + start = NO_LABEL; } } - if (start) { + if (start != NO_LABEL) { VISIT(c, expr, gen->iter); ADDOP(c, GET_ITER); } } - if (start) { + if (start != NO_LABEL) { depth++; USE_LABEL(c, start); ADDOP_JUMP(c, FOR_ITER, anchor); @@ -5175,7 +5179,7 @@ compiler_sync_comprehension_generator(struct compiler *c, } USE_LABEL(c, if_cleanup); - if (start) { + if (start != NO_LABEL) { ADDOP_JUMP(c, JUMP, start); USE_LABEL(c, anchor); @@ -5196,10 +5200,6 @@ compiler_async_comprehension_generator(struct compiler *c, NEW_JUMP_TARGET_LABEL(c, except); NEW_JUMP_TARGET_LABEL(c, if_cleanup); - if (start == NULL || if_cleanup == NULL || except == NULL) { - return 0; - } - gen = (comprehension_ty)asdl_seq_GET(generators, gen_index); if (gen_index == 0) { @@ -7370,10 +7370,15 @@ push_cold_blocks_to_end(cfg_builder *g, int code_flags) { return -1; } basicblock_addop(explicit_jump, JUMP, 0, b->b_next, NO_LOCATION); - explicit_jump->b_cold = 1; explicit_jump->b_next = b->b_next; b->b_next = explicit_jump; + + /* calculate target from target_label */ + /* TODO: formalize an API for adding jumps in the backend */ + struct instr *last = basicblock_last_instr(explicit_jump); + last->i_target = last->i_target_label; + last->i_target_label = NULL; } } @@ -8210,6 +8215,9 @@ dump_basicblock(const basicblock *b) static int normalize_basic_block(basicblock *bb); +static int +calculate_jump_targets(basicblock *entryblock); + static int optimize_cfg(basicblock *entryblock, PyObject *consts, PyObject *const_cache); @@ -8428,7 +8436,7 @@ static void eliminate_empty_basic_blocks(basicblock *entryblock); -static void +static int remove_redundant_jumps(basicblock *entryblock) { /* If a non-empty block ends with a jump instruction, check if the next * non-empty block reached through normal flow control is the target @@ -8442,6 +8450,10 @@ remove_redundant_jumps(basicblock *entryblock) { assert(!IS_ASSEMBLER_OPCODE(b_last_instr->i_opcode)); if (b_last_instr->i_opcode == JUMP || b_last_instr->i_opcode == JUMP_NO_INTERRUPT) { + if (b_last_instr->i_target == NULL) { + PyErr_SetString(PyExc_SystemError, "jump with NULL target"); + return -1; + } if (b_last_instr->i_target == b->b_next) { assert(b->b_next->b_iused); b_last_instr->i_opcode = NOP; @@ -8453,6 +8465,7 @@ remove_redundant_jumps(basicblock *entryblock) { if (removed) { eliminate_empty_basic_blocks(entryblock); } + return 0; } static PyCodeObject * @@ -8530,7 +8543,9 @@ assemble(struct compiler *c, int addNone) if (consts == NULL) { goto error; } - + if (calculate_jump_targets(entryblock)) { + goto error; + } if (optimize_cfg(entryblock, consts, c->c_const_cache)) { goto error; } @@ -8558,7 +8573,9 @@ assemble(struct compiler *c, int addNone) goto error; } - remove_redundant_jumps(entryblock); + if (remove_redundant_jumps(entryblock) < 0) { + goto error; + } for (basicblock *b = entryblock; b != NULL; b = b->b_next) { clean_basic_block(b); } @@ -9372,6 +9389,25 @@ propagate_line_numbers(basicblock *entryblock) { } } + +/* Calculate the actual jump target from the target_label */ +static int +calculate_jump_targets(basicblock *entryblock) +{ + for (basicblock *b = entryblock; b != NULL; b = b->b_next) { + for (int i = 0; i < b->b_iused; i++) { + struct instr *instr = &b->b_instr[i]; + assert(instr->i_target == NULL); + instr->i_target = instr->i_target_label; + instr->i_target_label = NULL; + if (is_jump(instr) || is_block_push(instr)) { + assert(instr->i_target != NULL); + } + } + } + return 0; +} + /* Perform optimizations on a control flow graph. The consts object should still be in list form to allow new constants to be appended. From 0b8075efbbb8508adab9a43082377b6eacce46e1 Mon Sep 17 00:00:00 2001 From: Irit Katriel <iritkatriel@yahoo.com> Date: Fri, 29 Jul 2022 17:24:18 +0100 Subject: [PATCH 06/14] make jump_target_label have a different type than basicblock*, so we can see it all works with the split between frontend and backend responsibilities --- Python/compile.c | 52 +++++++++++++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/Python/compile.c b/Python/compile.c index 33a324334cdad1..f72d5342317609 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -139,17 +139,22 @@ struct location { static struct location NO_LOCATION = {-1, -1, -1, -1}; -typedef struct basicblock_* jump_target_label; +typedef struct jump_target_label_ { + struct basicblock_ *block; +} jump_target_label; + +static struct jump_target_label_ NO_LABEL = {NULL}; + +#define SAME_LABEL(L1, L2) ((L1).block == (L2).block) +#define IS_LABEL(L) (!SAME_LABEL((L), (NO_LABEL))) #define NEW_JUMP_TARGET_LABEL(C, NAME) \ - jump_target_label NAME = compiler_new_block(C); \ - if (NAME == NULL) { \ + jump_target_label NAME = {compiler_new_block(C)}; \ + if (!IS_LABEL(NAME)) { \ return 0; \ } -#define USE_LABEL(C, LBL) compiler_use_next_block(C, LBL) - -#define NO_LABEL NULL +#define USE_LABEL(C, LBL) compiler_use_next_block(C, (LBL).block) struct instr { int i_opcode; @@ -1275,10 +1280,10 @@ basicblock_addop(basicblock *b, int opcode, int oparg, assert(!IS_ASSEMBLER_OPCODE(opcode)); assert(HAS_ARG(opcode) || oparg == 0); assert(0 <= oparg && oparg < (1 << 30)); - assert((target == NULL) || + assert(!IS_LABEL(target) || IS_JUMP_OPCODE(opcode) || IS_BLOCK_PUSH_OPCODE(opcode)); - assert(oparg == 0 || target == NULL); + assert(oparg == 0 || !IS_LABEL(target)); int off = basicblock_next_instr(b); if (off < 0) { @@ -1529,9 +1534,9 @@ cfg_builder_addop_i(cfg_builder *g, int opcode, Py_ssize_t oparg, struct locatio } static int -cfg_builder_addop_j(cfg_builder *g, int opcode, basicblock *target, struct location loc) +cfg_builder_addop_j(cfg_builder *g, int opcode, jump_target_label target, struct location loc) { - assert(target != NULL); + assert(IS_LABEL(target)); assert(IS_JUMP_OPCODE(opcode) || IS_BLOCK_PUSH_OPCODE(opcode)); return cfg_builder_addop(g, opcode, 0, target, loc); } @@ -1879,7 +1884,7 @@ find_ann(asdl_stmt_seq *stmts) */ static int -compiler_push_fblock(struct compiler *c, enum fblocktype t, jump_target_label b, +compiler_push_fblock(struct compiler *c, enum fblocktype t, jump_target_label block_label, jump_target_label exit, void *datum) { struct fblockinfo *f; @@ -1888,20 +1893,20 @@ compiler_push_fblock(struct compiler *c, enum fblocktype t, jump_target_label b, } f = &c->u->u_fblock[c->u->u_nfblocks++]; f->fb_type = t; - f->fb_block = b; + f->fb_block = block_label; f->fb_exit = exit; f->fb_datum = datum; return 1; } static void -compiler_pop_fblock(struct compiler *c, enum fblocktype t, jump_target_label b) +compiler_pop_fblock(struct compiler *c, enum fblocktype t, jump_target_label block_label) { struct compiler_unit *u = c->u; assert(u->u_nfblocks > 0); u->u_nfblocks--; assert(u->u_fblock[u->u_nfblocks].fb_type == t); - assert(u->u_fblock[u->u_nfblocks].fb_block == b); + assert(SAME_LABEL(u->u_fblock[u->u_nfblocks].fb_block, block_label)); } static int @@ -2855,7 +2860,7 @@ compiler_jump_if(struct compiler *c, expr_ty e, jump_target_label next, int cond } if (!compiler_jump_if(c, (expr_ty)asdl_seq_GET(s, n), next, cond)) return 0; - if (next2 != next) { + if (!SAME_LABEL(next2, next)) { USE_LABEL(c, next2); } return 1; @@ -5123,12 +5128,12 @@ compiler_sync_comprehension_generator(struct compiler *c, start = NO_LABEL; } } - if (start != NO_LABEL) { + if (IS_LABEL(start)) { VISIT(c, expr, gen->iter); ADDOP(c, GET_ITER); } } - if (start != NO_LABEL) { + if (IS_LABEL(start)) { depth++; USE_LABEL(c, start); ADDOP_JUMP(c, FOR_ITER, anchor); @@ -5179,7 +5184,7 @@ compiler_sync_comprehension_generator(struct compiler *c, } USE_LABEL(c, if_cleanup); - if (start != NO_LABEL) { + if (IS_LABEL(start)) { ADDOP_JUMP(c, JUMP, start); USE_LABEL(c, anchor); @@ -7369,7 +7374,8 @@ push_cold_blocks_to_end(cfg_builder *g, int code_flags) { if (explicit_jump == NULL) { return -1; } - basicblock_addop(explicit_jump, JUMP, 0, b->b_next, NO_LOCATION); + jump_target_label next_label = {b->b_next}; + basicblock_addop(explicit_jump, JUMP, 0, next_label, NO_LOCATION); explicit_jump->b_cold = 1; explicit_jump->b_next = b->b_next; b->b_next = explicit_jump; @@ -7377,8 +7383,8 @@ push_cold_blocks_to_end(cfg_builder *g, int code_flags) { /* calculate target from target_label */ /* TODO: formalize an API for adding jumps in the backend */ struct instr *last = basicblock_last_instr(explicit_jump); - last->i_target = last->i_target_label; - last->i_target_label = NULL; + last->i_target = last->i_target_label.block; + last->i_target_label = NO_LABEL; } } @@ -9398,8 +9404,8 @@ calculate_jump_targets(basicblock *entryblock) for (int i = 0; i < b->b_iused; i++) { struct instr *instr = &b->b_instr[i]; assert(instr->i_target == NULL); - instr->i_target = instr->i_target_label; - instr->i_target_label = NULL; + instr->i_target = instr->i_target_label.block; + instr->i_target_label = NO_LABEL; if (is_jump(instr) || is_block_push(instr)) { assert(instr->i_target != NULL); } From c2050f67e9ec2231fcd13646e7f18adba5b6d012 Mon Sep 17 00:00:00 2001 From: Irit Katriel <iritkatriel@yahoo.com> Date: Tue, 2 Aug 2022 18:41:15 +0100 Subject: [PATCH 07/14] added g_current_label, set by USE_LABEL --- Python/compile.c | 56 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 40 insertions(+), 16 deletions(-) diff --git a/Python/compile.c b/Python/compile.c index f72d5342317609..88c107956f125c 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -149,12 +149,12 @@ static struct jump_target_label_ NO_LABEL = {NULL}; #define IS_LABEL(L) (!SAME_LABEL((L), (NO_LABEL))) #define NEW_JUMP_TARGET_LABEL(C, NAME) \ - jump_target_label NAME = {compiler_new_block(C)}; \ + jump_target_label NAME = {cfg_builder_new_block(CFG_BUILDER(C))}; \ if (!IS_LABEL(NAME)) { \ return 0; \ } -#define USE_LABEL(C, LBL) compiler_use_next_block(C, (LBL).block) +#define USE_LABEL(C, LBL) cfg_builder_use_label(CFG_BUILDER(C), LBL) struct instr { int i_opcode; @@ -354,6 +354,8 @@ typedef struct cfg_builder_ { basicblock *block_list; /* pointer to the block currently being constructed */ basicblock *curblock; + /* label for the next instruction to be placed */ + jump_target_label g_current_label; } cfg_builder; /* The following items change on entry and exit of code blocks. @@ -449,6 +451,7 @@ typedef struct { static int basicblock_next_instr(basicblock *); +static int cfg_builder_maybe_start_new_block(cfg_builder *g); static int cfg_builder_addop_i(cfg_builder *g, int opcode, Py_ssize_t oparg, struct location loc); static void compiler_free(struct compiler *); @@ -886,16 +889,11 @@ cfg_builder_use_next_block(cfg_builder *g, basicblock *block) return block; } -static basicblock * -compiler_new_block(struct compiler *c) -{ - return cfg_builder_new_block(CFG_BUILDER(c)); -} - -static basicblock * -compiler_use_next_block(struct compiler *c, basicblock *block) +static int +cfg_builder_use_label(cfg_builder *g, jump_target_label lbl) { - return cfg_builder_use_next_block(CFG_BUILDER(c), block); + g->g_current_label = lbl; + return cfg_builder_maybe_start_new_block(g); } static basicblock * @@ -1299,18 +1297,43 @@ basicblock_addop(basicblock *b, int opcode, int oparg, return 1; } -static int -cfg_builder_addop(cfg_builder *g, int opcode, int oparg, jump_target_label target, - struct location loc) +static bool +cfg_builder_current_block_is_terminated(cfg_builder *g) { + if (IS_LABEL(g->g_current_label)) { + return true; + } struct instr *last = basicblock_last_instr(g->curblock); - if (last && IS_TERMINATOR_OPCODE(last->i_opcode)) { - basicblock *b = cfg_builder_new_block(g); + return last && IS_TERMINATOR_OPCODE(last->i_opcode); +} + +static int +cfg_builder_maybe_start_new_block(cfg_builder *g) +{ + if (cfg_builder_current_block_is_terminated(g)) { + basicblock *b; + if (IS_LABEL(g->g_current_label)) { + b = g->g_current_label.block; + g->g_current_label = NO_LABEL; + } + else { + b = cfg_builder_new_block(g); + } if (b == NULL) { return -1; } cfg_builder_use_next_block(g, b); } + return 0; +} + +static int +cfg_builder_addop(cfg_builder *g, int opcode, int oparg, jump_target_label target, + struct location loc) +{ + if (cfg_builder_maybe_start_new_block(g) != 0) { + return -1; + } return basicblock_addop(g->curblock, opcode, oparg, target, loc); } @@ -1765,6 +1788,7 @@ compiler_enter_scope(struct compiler *c, identifier name, if (block == NULL) return 0; g->curblock = g->cfg_entryblock = block; + g->g_current_label = NO_LABEL; if (u->u_scope_type == COMPILER_SCOPE_MODULE) { c->u->u_loc.lineno = 0; From 558b04cad21df765203cdd6171d3b254d89f1c6e Mon Sep 17 00:00:00 2001 From: Irit Katriel <iritkatriel@yahoo.com> Date: Wed, 3 Aug 2022 10:24:48 +0100 Subject: [PATCH 08/14] add id to jump_target_label and use it to calculate i_target --- Python/compile.c | 47 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/Python/compile.c b/Python/compile.c index 88c107956f125c..46267b53f41e2a 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -140,16 +140,17 @@ struct location { static struct location NO_LOCATION = {-1, -1, -1, -1}; typedef struct jump_target_label_ { + int id; struct basicblock_ *block; } jump_target_label; -static struct jump_target_label_ NO_LABEL = {NULL}; +static struct jump_target_label_ NO_LABEL = {-1, NULL}; -#define SAME_LABEL(L1, L2) ((L1).block == (L2).block) +#define SAME_LABEL(L1, L2) ((L1).id == (L2).id) #define IS_LABEL(L) (!SAME_LABEL((L), (NO_LABEL))) #define NEW_JUMP_TARGET_LABEL(C, NAME) \ - jump_target_label NAME = {cfg_builder_new_block(CFG_BUILDER(C))}; \ + jump_target_label NAME = {cfg_new_label_id(CFG_BUILDER(C)), cfg_builder_new_block(CFG_BUILDER(C))}; \ if (!IS_LABEL(NAME)) { \ return 0; \ } @@ -255,6 +256,8 @@ typedef struct basicblock_ { reverse order that the block are allocated. b_list points to the next block, not to be confused with b_next, which is next by control flow. */ struct basicblock_ *b_list; + /* The label of this block if it is a jump target, -1 otherwise */ + int b_label; /* Exception stack at start of block, used by assembler to create the exception handling table */ ExceptStack *b_exceptstack; /* pointer to an array of instructions, initially NULL */ @@ -356,6 +359,8 @@ typedef struct cfg_builder_ { basicblock *curblock; /* label for the next instruction to be placed */ jump_target_label g_current_label; + /* next free label id */ + int g_next_free_label; } cfg_builder; /* The following items change on entry and exit of code blocks. @@ -862,6 +867,11 @@ compiler_set_qualname(struct compiler *c) return 1; } +static int +cfg_new_label_id(cfg_builder *g) +{ + return g->g_next_free_label++; +} /* Allocate a new block and return a pointer to it. Returns NULL on error. @@ -877,6 +887,7 @@ cfg_builder_new_block(cfg_builder *g) /* Extend the singly linked list of blocks with new block. */ b->b_list = g->block_list; g->block_list = b; + b->b_label = -1; return b; } @@ -1314,6 +1325,7 @@ cfg_builder_maybe_start_new_block(cfg_builder *g) basicblock *b; if (IS_LABEL(g->g_current_label)) { b = g->g_current_label.block; + b->b_label = g->g_current_label.id; g->g_current_label = NO_LABEL; } else { @@ -7398,7 +7410,7 @@ push_cold_blocks_to_end(cfg_builder *g, int code_flags) { if (explicit_jump == NULL) { return -1; } - jump_target_label next_label = {b->b_next}; + jump_target_label next_label = {b->b_next->b_label, b->b_next}; basicblock_addop(explicit_jump, JUMP, 0, next_label, NO_LOCATION); explicit_jump->b_cold = 1; explicit_jump->b_next = b->b_next; @@ -8228,8 +8240,8 @@ static void dump_basicblock(const basicblock *b) { const char *b_return = basicblock_returns(b) ? "return " : ""; - fprintf(stderr, "[%d %d %d %p] used: %d, depth: %d, offset: %d %s\n", - b->b_cold, b->b_warm, BB_NO_FALLTHROUGH(b), b, b->b_iused, + fprintf(stderr, "%d: [%d %d %d %p] used: %d, depth: %d, offset: %d %s\n", + b->b_label, b->b_cold, b->b_warm, BB_NO_FALLTHROUGH(b), b, b->b_iused, b->b_startdepth, b->b_offset, b_return); if (b->b_instr) { int i; @@ -9424,15 +9436,34 @@ propagate_line_numbers(basicblock *entryblock) { static int calculate_jump_targets(basicblock *entryblock) { + int max_label = -1; + for (basicblock *b = entryblock; b != NULL; b = b->b_next) { + if (b->b_label > max_label) { + max_label = b->b_label; + } + } + size_t mapsize = sizeof(basicblock *) * (max_label + 1); + basicblock **label2block = (basicblock **)PyMem_Malloc(mapsize); + if (!label2block) { + PyErr_NoMemory(); + return -1; + } + memset(label2block, 0, mapsize); + for (basicblock *b = entryblock; b != NULL; b = b->b_next) { + if (b->b_label >= 0) { + label2block[b->b_label] = b; + } + } for (basicblock *b = entryblock; b != NULL; b = b->b_next) { for (int i = 0; i < b->b_iused; i++) { struct instr *instr = &b->b_instr[i]; assert(instr->i_target == NULL); - instr->i_target = instr->i_target_label.block; - instr->i_target_label = NO_LABEL; + instr->i_target = label2block[instr->i_target_label.id]; if (is_jump(instr) || is_block_push(instr)) { assert(instr->i_target != NULL); + assert(instr->i_target->b_label == instr->i_target_label.id); } + instr->i_target_label = NO_LABEL; } } return 0; From 68963b56fb32e44912c65ea73aacfd942e20e663 Mon Sep 17 00:00:00 2001 From: Irit Katriel <iritkatriel@yahoo.com> Date: Wed, 3 Aug 2022 11:15:30 +0100 Subject: [PATCH 09/14] remove the block from jump_target_label, calculate it from the label id --- Python/compile.c | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/Python/compile.c b/Python/compile.c index 46267b53f41e2a..477b41781019fd 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -141,16 +141,15 @@ static struct location NO_LOCATION = {-1, -1, -1, -1}; typedef struct jump_target_label_ { int id; - struct basicblock_ *block; } jump_target_label; -static struct jump_target_label_ NO_LABEL = {-1, NULL}; +static struct jump_target_label_ NO_LABEL = {-1}; #define SAME_LABEL(L1, L2) ((L1).id == (L2).id) #define IS_LABEL(L) (!SAME_LABEL((L), (NO_LABEL))) #define NEW_JUMP_TARGET_LABEL(C, NAME) \ - jump_target_label NAME = {cfg_new_label_id(CFG_BUILDER(C)), cfg_builder_new_block(CFG_BUILDER(C))}; \ + jump_target_label NAME = {cfg_new_label_id(CFG_BUILDER(C))}; \ if (!IS_LABEL(NAME)) { \ return 0; \ } @@ -1322,18 +1321,12 @@ static int cfg_builder_maybe_start_new_block(cfg_builder *g) { if (cfg_builder_current_block_is_terminated(g)) { - basicblock *b; - if (IS_LABEL(g->g_current_label)) { - b = g->g_current_label.block; - b->b_label = g->g_current_label.id; - g->g_current_label = NO_LABEL; - } - else { - b = cfg_builder_new_block(g); - } + basicblock *b = cfg_builder_new_block(g); if (b == NULL) { return -1; } + b->b_label = g->g_current_label.id; + g->g_current_label = NO_LABEL; cfg_builder_use_next_block(g, b); } return 0; @@ -7410,16 +7403,15 @@ push_cold_blocks_to_end(cfg_builder *g, int code_flags) { if (explicit_jump == NULL) { return -1; } - jump_target_label next_label = {b->b_next->b_label, b->b_next}; + jump_target_label next_label = {b->b_next->b_label}; basicblock_addop(explicit_jump, JUMP, 0, next_label, NO_LOCATION); explicit_jump->b_cold = 1; explicit_jump->b_next = b->b_next; b->b_next = explicit_jump; - /* calculate target from target_label */ - /* TODO: formalize an API for adding jumps in the backend */ + /* set target */ struct instr *last = basicblock_last_instr(explicit_jump); - last->i_target = last->i_target_label.block; + last->i_target = b->b_next; last->i_target_label = NO_LABEL; } } From 59d2eabd5612d6e4c89194283daacfff49256510 Mon Sep 17 00:00:00 2001 From: Irit Katriel <iritkatriel@yahoo.com> Date: Wed, 3 Aug 2022 12:54:18 +0100 Subject: [PATCH 10/14] free label2block --- Python/compile.c | 1 + 1 file changed, 1 insertion(+) diff --git a/Python/compile.c b/Python/compile.c index 477b41781019fd..1b1ac7c08d408b 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -9458,6 +9458,7 @@ calculate_jump_targets(basicblock *entryblock) instr->i_target_label = NO_LABEL; } } + PyMem_Free(label2block); return 0; } From a2289d1ac32110116d043205be289c71be556105 Mon Sep 17 00:00:00 2001 From: Irit Katriel <iritkatriel@yahoo.com> Date: Wed, 3 Aug 2022 13:00:54 +0100 Subject: [PATCH 11/14] rename fields of cfg_builder to all have g_ prefixes --- Python/compile.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/Python/compile.c b/Python/compile.c index 1b1ac7c08d408b..9cec0eefc1f3c8 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -350,12 +350,12 @@ enum { typedef struct cfg_builder_ { /* The entryblock, at which control flow begins. All blocks of the CFG are reachable through the b_next links */ - basicblock *cfg_entryblock; + basicblock *g_entryblock; /* Pointer to the most recently allocated block. By following b_list links, you can reach all allocated blocks. */ - basicblock *block_list; + basicblock *g_block_list; /* pointer to the block currently being constructed */ - basicblock *curblock; + basicblock *g_curblock; /* label for the next instruction to be placed */ jump_target_label g_current_label; /* next free label id */ @@ -751,7 +751,7 @@ dictbytype(PyObject *src, int scope_type, int flag, Py_ssize_t offset) static void cfg_builder_check(cfg_builder *g) { - for (basicblock *block = g->block_list; block != NULL; block = block->b_list) { + for (basicblock *block = g->g_block_list; block != NULL; block = block->b_list) { assert(!_PyMem_IsPtrFreed(block)); if (block->b_instr != NULL) { assert(block->b_ialloc > 0); @@ -769,7 +769,7 @@ static void cfg_builder_free(cfg_builder* g) { cfg_builder_check(g); - basicblock *b = g->block_list; + basicblock *b = g->g_block_list; while (b != NULL) { if (b->b_instr) { PyObject_Free((void *)b->b_instr); @@ -884,8 +884,8 @@ cfg_builder_new_block(cfg_builder *g) return NULL; } /* Extend the singly linked list of blocks with new block. */ - b->b_list = g->block_list; - g->block_list = b; + b->b_list = g->g_block_list; + g->g_block_list = b; b->b_label = -1; return b; } @@ -894,8 +894,8 @@ static basicblock * cfg_builder_use_next_block(cfg_builder *g, basicblock *block) { assert(block != NULL); - g->curblock->b_next = block; - g->curblock = block; + g->g_curblock->b_next = block; + g->g_curblock = block; return block; } @@ -1313,7 +1313,7 @@ cfg_builder_current_block_is_terminated(cfg_builder *g) if (IS_LABEL(g->g_current_label)) { return true; } - struct instr *last = basicblock_last_instr(g->curblock); + struct instr *last = basicblock_last_instr(g->g_curblock); return last && IS_TERMINATOR_OPCODE(last->i_opcode); } @@ -1339,7 +1339,7 @@ cfg_builder_addop(cfg_builder *g, int opcode, int oparg, jump_target_label targe if (cfg_builder_maybe_start_new_block(g) != 0) { return -1; } - return basicblock_addop(g->curblock, opcode, oparg, target, loc); + return basicblock_addop(g->g_curblock, opcode, oparg, target, loc); } static int @@ -1788,11 +1788,11 @@ compiler_enter_scope(struct compiler *c, identifier name, c->c_nestlevel++; cfg_builder *g = CFG_BUILDER(c); - g->block_list = NULL; + g->g_block_list = NULL; block = cfg_builder_new_block(g); if (block == NULL) return 0; - g->curblock = g->cfg_entryblock = block; + g->g_curblock = g->g_entryblock = block; g->g_current_label = NO_LABEL; if (u->u_scope_type == COMPILER_SCOPE_MODULE) { @@ -7386,7 +7386,7 @@ mark_cold(basicblock *entryblock) { static int push_cold_blocks_to_end(cfg_builder *g, int code_flags) { - basicblock *entryblock = g->cfg_entryblock; + basicblock *entryblock = g->g_entryblock; if (entryblock->b_next == NULL) { /* single basicblock, no need to reorder */ return 0; @@ -8516,7 +8516,7 @@ assemble(struct compiler *c, int addNone) } /* Make sure every block that falls off the end returns None. */ - if (!basicblock_returns(CFG_BUILDER(c)->curblock)) { + if (!basicblock_returns(CFG_BUILDER(c)->g_curblock)) { UNSET_LOC(c); if (addNone) ADDOP_LOAD_CONST(c, Py_None); @@ -8538,7 +8538,7 @@ assemble(struct compiler *c, int addNone) } int nblocks = 0; - for (basicblock *b = CFG_BUILDER(c)->block_list; b != NULL; b = b->b_list) { + for (basicblock *b = CFG_BUILDER(c)->g_block_list; b != NULL; b = b->b_list) { nblocks++; } if ((size_t)nblocks > SIZE_MAX / sizeof(basicblock *)) { @@ -8547,7 +8547,7 @@ assemble(struct compiler *c, int addNone) } cfg_builder *g = CFG_BUILDER(c); - basicblock *entryblock = g->cfg_entryblock; + basicblock *entryblock = g->g_entryblock; assert(entryblock != NULL); /* Set firstlineno if it wasn't explicitly set. */ @@ -9567,7 +9567,7 @@ duplicate_exits_without_lineno(cfg_builder *g) { /* Copy all exit blocks without line number that are targets of a jump. */ - basicblock *entryblock = g->cfg_entryblock; + basicblock *entryblock = g->g_entryblock; for (basicblock *b = entryblock; b != NULL; b = b->b_next) { if (b->b_iused > 0 && is_jump(&b->b_instr[b->b_iused-1])) { basicblock *target = b->b_instr[b->b_iused-1].i_target; From 893f890ce7fac1d2db48aaf067cd4264799fb168 Mon Sep 17 00:00:00 2001 From: Irit Katriel <iritkatriel@yahoo.com> Date: Wed, 3 Aug 2022 13:26:49 +0100 Subject: [PATCH 12/14] move lookup of label to inside if 'it's a jump' --- Python/compile.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Python/compile.c b/Python/compile.c index 9cec0eefc1f3c8..6bd25266e060aa 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -9450,10 +9450,12 @@ calculate_jump_targets(basicblock *entryblock) for (int i = 0; i < b->b_iused; i++) { struct instr *instr = &b->b_instr[i]; assert(instr->i_target == NULL); - instr->i_target = label2block[instr->i_target_label.id]; if (is_jump(instr) || is_block_push(instr)) { + int lbl = instr->i_target_label.id; + assert(lbl >= 0 && lbl <= max_label); + instr->i_target = label2block[lbl]; assert(instr->i_target != NULL); - assert(instr->i_target->b_label == instr->i_target_label.id); + assert(instr->i_target->b_label == lbl); } instr->i_target_label = NO_LABEL; } From 09c699ba6402e80deb987d1604551909e586bc17 Mon Sep 17 00:00:00 2001 From: Irit Katriel <iritkatriel@yahoo.com> Date: Wed, 3 Aug 2022 16:38:11 +0100 Subject: [PATCH 13/14] Revert "rename fields of cfg_builder to all have g_ prefixes" This reverts commit a2289d1ac32110116d043205be289c71be556105. --- Python/compile.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/Python/compile.c b/Python/compile.c index 6bd25266e060aa..fe16b89290c3a4 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -350,12 +350,12 @@ enum { typedef struct cfg_builder_ { /* The entryblock, at which control flow begins. All blocks of the CFG are reachable through the b_next links */ - basicblock *g_entryblock; + basicblock *cfg_entryblock; /* Pointer to the most recently allocated block. By following b_list links, you can reach all allocated blocks. */ - basicblock *g_block_list; + basicblock *block_list; /* pointer to the block currently being constructed */ - basicblock *g_curblock; + basicblock *curblock; /* label for the next instruction to be placed */ jump_target_label g_current_label; /* next free label id */ @@ -751,7 +751,7 @@ dictbytype(PyObject *src, int scope_type, int flag, Py_ssize_t offset) static void cfg_builder_check(cfg_builder *g) { - for (basicblock *block = g->g_block_list; block != NULL; block = block->b_list) { + for (basicblock *block = g->block_list; block != NULL; block = block->b_list) { assert(!_PyMem_IsPtrFreed(block)); if (block->b_instr != NULL) { assert(block->b_ialloc > 0); @@ -769,7 +769,7 @@ static void cfg_builder_free(cfg_builder* g) { cfg_builder_check(g); - basicblock *b = g->g_block_list; + basicblock *b = g->block_list; while (b != NULL) { if (b->b_instr) { PyObject_Free((void *)b->b_instr); @@ -884,8 +884,8 @@ cfg_builder_new_block(cfg_builder *g) return NULL; } /* Extend the singly linked list of blocks with new block. */ - b->b_list = g->g_block_list; - g->g_block_list = b; + b->b_list = g->block_list; + g->block_list = b; b->b_label = -1; return b; } @@ -894,8 +894,8 @@ static basicblock * cfg_builder_use_next_block(cfg_builder *g, basicblock *block) { assert(block != NULL); - g->g_curblock->b_next = block; - g->g_curblock = block; + g->curblock->b_next = block; + g->curblock = block; return block; } @@ -1313,7 +1313,7 @@ cfg_builder_current_block_is_terminated(cfg_builder *g) if (IS_LABEL(g->g_current_label)) { return true; } - struct instr *last = basicblock_last_instr(g->g_curblock); + struct instr *last = basicblock_last_instr(g->curblock); return last && IS_TERMINATOR_OPCODE(last->i_opcode); } @@ -1339,7 +1339,7 @@ cfg_builder_addop(cfg_builder *g, int opcode, int oparg, jump_target_label targe if (cfg_builder_maybe_start_new_block(g) != 0) { return -1; } - return basicblock_addop(g->g_curblock, opcode, oparg, target, loc); + return basicblock_addop(g->curblock, opcode, oparg, target, loc); } static int @@ -1788,11 +1788,11 @@ compiler_enter_scope(struct compiler *c, identifier name, c->c_nestlevel++; cfg_builder *g = CFG_BUILDER(c); - g->g_block_list = NULL; + g->block_list = NULL; block = cfg_builder_new_block(g); if (block == NULL) return 0; - g->g_curblock = g->g_entryblock = block; + g->curblock = g->cfg_entryblock = block; g->g_current_label = NO_LABEL; if (u->u_scope_type == COMPILER_SCOPE_MODULE) { @@ -7386,7 +7386,7 @@ mark_cold(basicblock *entryblock) { static int push_cold_blocks_to_end(cfg_builder *g, int code_flags) { - basicblock *entryblock = g->g_entryblock; + basicblock *entryblock = g->cfg_entryblock; if (entryblock->b_next == NULL) { /* single basicblock, no need to reorder */ return 0; @@ -8516,7 +8516,7 @@ assemble(struct compiler *c, int addNone) } /* Make sure every block that falls off the end returns None. */ - if (!basicblock_returns(CFG_BUILDER(c)->g_curblock)) { + if (!basicblock_returns(CFG_BUILDER(c)->curblock)) { UNSET_LOC(c); if (addNone) ADDOP_LOAD_CONST(c, Py_None); @@ -8538,7 +8538,7 @@ assemble(struct compiler *c, int addNone) } int nblocks = 0; - for (basicblock *b = CFG_BUILDER(c)->g_block_list; b != NULL; b = b->b_list) { + for (basicblock *b = CFG_BUILDER(c)->block_list; b != NULL; b = b->b_list) { nblocks++; } if ((size_t)nblocks > SIZE_MAX / sizeof(basicblock *)) { @@ -8547,7 +8547,7 @@ assemble(struct compiler *c, int addNone) } cfg_builder *g = CFG_BUILDER(c); - basicblock *entryblock = g->g_entryblock; + basicblock *entryblock = g->cfg_entryblock; assert(entryblock != NULL); /* Set firstlineno if it wasn't explicitly set. */ @@ -9569,7 +9569,7 @@ duplicate_exits_without_lineno(cfg_builder *g) { /* Copy all exit blocks without line number that are targets of a jump. */ - basicblock *entryblock = g->g_entryblock; + basicblock *entryblock = g->cfg_entryblock; for (basicblock *b = entryblock; b != NULL; b = b->b_next) { if (b->b_iused > 0 && is_jump(&b->b_instr[b->b_iused-1])) { basicblock *target = b->b_instr[b->b_iused-1].i_target; From df2766c464bf818553a309449e0dc93e013b2fed Mon Sep 17 00:00:00 2001 From: Irit Katriel <iritkatriel@yahoo.com> Date: Wed, 3 Aug 2022 16:38:28 +0100 Subject: [PATCH 14/14] Revert "remove the block from jump_target_label, calculate it from the label id" This reverts commit 68963b56fb32e44912c65ea73aacfd942e20e663. --- Python/compile.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/Python/compile.c b/Python/compile.c index fe16b89290c3a4..3c4dd56b05926a 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -141,15 +141,16 @@ static struct location NO_LOCATION = {-1, -1, -1, -1}; typedef struct jump_target_label_ { int id; + struct basicblock_ *block; } jump_target_label; -static struct jump_target_label_ NO_LABEL = {-1}; +static struct jump_target_label_ NO_LABEL = {-1, NULL}; #define SAME_LABEL(L1, L2) ((L1).id == (L2).id) #define IS_LABEL(L) (!SAME_LABEL((L), (NO_LABEL))) #define NEW_JUMP_TARGET_LABEL(C, NAME) \ - jump_target_label NAME = {cfg_new_label_id(CFG_BUILDER(C))}; \ + jump_target_label NAME = {cfg_new_label_id(CFG_BUILDER(C)), cfg_builder_new_block(CFG_BUILDER(C))}; \ if (!IS_LABEL(NAME)) { \ return 0; \ } @@ -1321,12 +1322,18 @@ static int cfg_builder_maybe_start_new_block(cfg_builder *g) { if (cfg_builder_current_block_is_terminated(g)) { - basicblock *b = cfg_builder_new_block(g); + basicblock *b; + if (IS_LABEL(g->g_current_label)) { + b = g->g_current_label.block; + b->b_label = g->g_current_label.id; + g->g_current_label = NO_LABEL; + } + else { + b = cfg_builder_new_block(g); + } if (b == NULL) { return -1; } - b->b_label = g->g_current_label.id; - g->g_current_label = NO_LABEL; cfg_builder_use_next_block(g, b); } return 0; @@ -7403,15 +7410,16 @@ push_cold_blocks_to_end(cfg_builder *g, int code_flags) { if (explicit_jump == NULL) { return -1; } - jump_target_label next_label = {b->b_next->b_label}; + jump_target_label next_label = {b->b_next->b_label, b->b_next}; basicblock_addop(explicit_jump, JUMP, 0, next_label, NO_LOCATION); explicit_jump->b_cold = 1; explicit_jump->b_next = b->b_next; b->b_next = explicit_jump; - /* set target */ + /* calculate target from target_label */ + /* TODO: formalize an API for adding jumps in the backend */ struct instr *last = basicblock_last_instr(explicit_jump); - last->i_target = b->b_next; + last->i_target = last->i_target_label.block; last->i_target_label = NO_LABEL; } }