Skip to content

Commit ac8b7b3

Browse files
committed
instr has both target_label and target. Front end sets target_label and backend calculates target from it
1 parent 1a59e4d commit ac8b7b3

File tree

1 file changed

+55
-19
lines changed

1 file changed

+55
-19
lines changed

Python/compile.c

Lines changed: 55 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -154,8 +154,11 @@ typedef struct basicblock_* jump_target_label;
154154
struct instr {
155155
int i_opcode;
156156
int i_oparg;
157-
/* target block (if jump instruction) */
158-
jump_target_label i_target;
157+
/* target block (if jump instruction) -- we temporarily have both the label
158+
and the block in the instr. The label is set by front end, and the block
159+
is calculated by backend. */
160+
jump_target_label i_target_label;
161+
struct basicblock_ *i_target;
159162
/* target block when exception is raised, should not be set by front-end. */
160163
struct basicblock_ *i_except;
161164
struct location i_loc;
@@ -1266,7 +1269,7 @@ PyCompile_OpcodeStackEffect(int opcode, int oparg)
12661269

12671270
static int
12681271
basicblock_addop(basicblock *b, int opcode, int oparg,
1269-
basicblock *target, struct location loc)
1272+
jump_target_label target, struct location loc)
12701273
{
12711274
assert(IS_WITHIN_OPCODE_RANGE(opcode));
12721275
assert(!IS_ASSEMBLER_OPCODE(opcode));
@@ -1284,14 +1287,15 @@ basicblock_addop(basicblock *b, int opcode, int oparg,
12841287
struct instr *i = &b->b_instr[off];
12851288
i->i_opcode = opcode;
12861289
i->i_oparg = oparg;
1287-
i->i_target = target;
1290+
i->i_target_label = target;
1291+
i->i_target = NULL;
12881292
i->i_loc = loc;
12891293

12901294
return 1;
12911295
}
12921296

12931297
static int
1294-
cfg_builder_addop(cfg_builder *g, int opcode, int oparg, basicblock *target,
1298+
cfg_builder_addop(cfg_builder *g, int opcode, int oparg, jump_target_label target,
12951299
struct location loc)
12961300
{
12971301
struct instr *last = basicblock_last_instr(g->curblock);
@@ -1309,7 +1313,7 @@ static int
13091313
cfg_builder_addop_noarg(cfg_builder *g, int opcode, struct location loc)
13101314
{
13111315
assert(!HAS_ARG(opcode));
1312-
return cfg_builder_addop(g, opcode, 0, NULL, loc);
1316+
return cfg_builder_addop(g, opcode, 0, NO_LABEL, loc);
13131317
}
13141318

13151319
static Py_ssize_t
@@ -1521,7 +1525,7 @@ cfg_builder_addop_i(cfg_builder *g, int opcode, Py_ssize_t oparg, struct locatio
15211525
EXTENDED_ARG is used for 16, 24, and 32-bit arguments. */
15221526

15231527
int oparg_ = Py_SAFE_DOWNCAST(oparg, Py_ssize_t, int);
1524-
return cfg_builder_addop(g, opcode, oparg_, NULL, loc);
1528+
return cfg_builder_addop(g, opcode, oparg_, NO_LABEL, loc);
15251529
}
15261530

15271531
static int
@@ -5116,15 +5120,15 @@ compiler_sync_comprehension_generator(struct compiler *c,
51165120
expr_ty elt = asdl_seq_GET(elts, 0);
51175121
if (elt->kind != Starred_kind) {
51185122
VISIT(c, expr, elt);
5119-
start = NULL;
5123+
start = NO_LABEL;
51205124
}
51215125
}
5122-
if (start) {
5126+
if (start != NO_LABEL) {
51235127
VISIT(c, expr, gen->iter);
51245128
ADDOP(c, GET_ITER);
51255129
}
51265130
}
5127-
if (start) {
5131+
if (start != NO_LABEL) {
51285132
depth++;
51295133
USE_LABEL(c, start);
51305134
ADDOP_JUMP(c, FOR_ITER, anchor);
@@ -5175,7 +5179,7 @@ compiler_sync_comprehension_generator(struct compiler *c,
51755179
}
51765180

51775181
USE_LABEL(c, if_cleanup);
5178-
if (start) {
5182+
if (start != NO_LABEL) {
51795183
ADDOP_JUMP(c, JUMP, start);
51805184

51815185
USE_LABEL(c, anchor);
@@ -5196,10 +5200,6 @@ compiler_async_comprehension_generator(struct compiler *c,
51965200
NEW_JUMP_TARGET_LABEL(c, except);
51975201
NEW_JUMP_TARGET_LABEL(c, if_cleanup);
51985202

5199-
if (start == NULL || if_cleanup == NULL || except == NULL) {
5200-
return 0;
5201-
}
5202-
52035203
gen = (comprehension_ty)asdl_seq_GET(generators, gen_index);
52045204

52055205
if (gen_index == 0) {
@@ -7370,10 +7370,15 @@ push_cold_blocks_to_end(cfg_builder *g, int code_flags) {
73707370
return -1;
73717371
}
73727372
basicblock_addop(explicit_jump, JUMP, 0, b->b_next, NO_LOCATION);
7373-
73747373
explicit_jump->b_cold = 1;
73757374
explicit_jump->b_next = b->b_next;
73767375
b->b_next = explicit_jump;
7376+
7377+
/* calculate target from target_label */
7378+
/* TODO: formalize an API for adding jumps in the backend */
7379+
struct instr *last = basicblock_last_instr(explicit_jump);
7380+
last->i_target = last->i_target_label;
7381+
last->i_target_label = NULL;
73777382
}
73787383
}
73797384

@@ -8210,6 +8215,9 @@ dump_basicblock(const basicblock *b)
82108215
static int
82118216
normalize_basic_block(basicblock *bb);
82128217

8218+
static int
8219+
calculate_jump_targets(basicblock *entryblock);
8220+
82138221
static int
82148222
optimize_cfg(basicblock *entryblock, PyObject *consts, PyObject *const_cache);
82158223

@@ -8428,7 +8436,7 @@ static void
84288436
eliminate_empty_basic_blocks(basicblock *entryblock);
84298437

84308438

8431-
static void
8439+
static int
84328440
remove_redundant_jumps(basicblock *entryblock) {
84338441
/* If a non-empty block ends with a jump instruction, check if the next
84348442
* non-empty block reached through normal flow control is the target
@@ -8442,6 +8450,10 @@ remove_redundant_jumps(basicblock *entryblock) {
84428450
assert(!IS_ASSEMBLER_OPCODE(b_last_instr->i_opcode));
84438451
if (b_last_instr->i_opcode == JUMP ||
84448452
b_last_instr->i_opcode == JUMP_NO_INTERRUPT) {
8453+
if (b_last_instr->i_target == NULL) {
8454+
PyErr_SetString(PyExc_SystemError, "jump with NULL target");
8455+
return -1;
8456+
}
84458457
if (b_last_instr->i_target == b->b_next) {
84468458
assert(b->b_next->b_iused);
84478459
b_last_instr->i_opcode = NOP;
@@ -8453,6 +8465,7 @@ remove_redundant_jumps(basicblock *entryblock) {
84538465
if (removed) {
84548466
eliminate_empty_basic_blocks(entryblock);
84558467
}
8468+
return 0;
84568469
}
84578470

84588471
static PyCodeObject *
@@ -8530,7 +8543,9 @@ assemble(struct compiler *c, int addNone)
85308543
if (consts == NULL) {
85318544
goto error;
85328545
}
8533-
8546+
if (calculate_jump_targets(entryblock)) {
8547+
goto error;
8548+
}
85348549
if (optimize_cfg(entryblock, consts, c->c_const_cache)) {
85358550
goto error;
85368551
}
@@ -8558,7 +8573,9 @@ assemble(struct compiler *c, int addNone)
85588573
goto error;
85598574
}
85608575

8561-
remove_redundant_jumps(entryblock);
8576+
if (remove_redundant_jumps(entryblock) < 0) {
8577+
goto error;
8578+
}
85628579
for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
85638580
clean_basic_block(b);
85648581
}
@@ -9372,6 +9389,25 @@ propagate_line_numbers(basicblock *entryblock) {
93729389
}
93739390
}
93749391

9392+
9393+
/* Calculate the actual jump target from the target_label */
9394+
static int
9395+
calculate_jump_targets(basicblock *entryblock)
9396+
{
9397+
for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
9398+
for (int i = 0; i < b->b_iused; i++) {
9399+
struct instr *instr = &b->b_instr[i];
9400+
assert(instr->i_target == NULL);
9401+
instr->i_target = instr->i_target_label;
9402+
instr->i_target_label = NULL;
9403+
if (is_jump(instr) || is_block_push(instr)) {
9404+
assert(instr->i_target != NULL);
9405+
}
9406+
}
9407+
}
9408+
return 0;
9409+
}
9410+
93759411
/* Perform optimizations on a control flow graph.
93769412
The consts object should still be in list form to allow new constants
93779413
to be appended.

0 commit comments

Comments
 (0)