Skip to content

Commit 58f5227

Browse files
authored
gh-105481: add pseudo-instructions to the bytecodes DSL (#105506)
1 parent 20a56d8 commit 58f5227

File tree

8 files changed

+507
-267
lines changed

8 files changed

+507
-267
lines changed

Python/assemble.c

+3-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "pycore_code.h" // write_location_entry_start()
55
#include "pycore_compile.h"
66
#include "pycore_opcode.h" // _PyOpcode_Caches[] and opcode category macros
7+
#include "opcode_metadata.h" // IS_PSEUDO_INSTR
78

89

910
#define DEFAULT_CODE_SIZE 128
@@ -338,7 +339,8 @@ static void
338339
write_instr(_Py_CODEUNIT *codestr, instruction *instr, int ilen)
339340
{
340341
int opcode = instr->i_opcode;
341-
assert(!IS_PSEUDO_OPCODE(opcode));
342+
assert(IS_PSEUDO_OPCODE(opcode) == IS_PSEUDO_INSTR(opcode));
343+
assert(!IS_PSEUDO_INSTR(opcode));
342344
int oparg = instr->i_oparg;
343345
assert(HAS_ARG(opcode) || oparg == 0);
344346
int caches = _PyOpcode_Caches[opcode];

Python/bytecodes.c

+47
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
#define macro(name) static int MACRO_##name
5151
#define super(name) static int SUPER_##name
5252
#define family(name, ...) static int family_##name
53+
#define pseudo(name) static int pseudo_##name
5354

5455
// Dummy variables for stack effects.
5556
static PyObject *value, *value1, *value2, *left, *right, *res, *sum, *prod, *sub;
@@ -218,6 +219,10 @@ dummy_func(
218219
SETLOCAL(oparg, value);
219220
}
220221

222+
pseudo(STORE_FAST_MAYBE_NULL) = {
223+
STORE_FAST,
224+
};
225+
221226
inst(STORE_FAST_LOAD_FAST, (value1 -- value2)) {
222227
uint32_t oparg1 = oparg >> 4;
223228
uint32_t oparg2 = oparg & 15;
@@ -1674,6 +1679,18 @@ dummy_func(
16741679
ERROR_IF(res == NULL, error);
16751680
}
16761681

1682+
pseudo(LOAD_SUPER_METHOD) = {
1683+
LOAD_SUPER_ATTR,
1684+
};
1685+
1686+
pseudo(LOAD_ZERO_SUPER_METHOD) = {
1687+
LOAD_SUPER_ATTR,
1688+
};
1689+
1690+
pseudo(LOAD_ZERO_SUPER_ATTR) = {
1691+
LOAD_SUPER_ATTR,
1692+
};
1693+
16771694
inst(LOAD_SUPER_ATTR_ATTR, (unused/1, global_super, class, self -- res2 if (oparg & 1), res)) {
16781695
assert(!(oparg & 1));
16791696
DEOPT_IF(global_super != (PyObject *)&PySuper_Type, LOAD_SUPER_ATTR);
@@ -1772,6 +1789,10 @@ dummy_func(
17721789
}
17731790
}
17741791

1792+
pseudo(LOAD_METHOD) = {
1793+
LOAD_ATTR,
1794+
};
1795+
17751796
inst(LOAD_ATTR_INSTANCE_VALUE, (unused/1, type_version/2, index/1, unused/5, owner -- res2 if (oparg & 1), res)) {
17761797
PyTypeObject *tp = Py_TYPE(owner);
17771798
assert(type_version != 0);
@@ -2142,6 +2163,16 @@ dummy_func(
21422163
CHECK_EVAL_BREAKER();
21432164
}
21442165

2166+
pseudo(JUMP) = {
2167+
JUMP_FORWARD,
2168+
JUMP_BACKWARD,
2169+
};
2170+
2171+
pseudo(JUMP_NO_INTERRUPT) = {
2172+
JUMP_FORWARD,
2173+
JUMP_BACKWARD_NO_INTERRUPT,
2174+
};
2175+
21452176
inst(ENTER_EXECUTOR, (--)) {
21462177
_PyExecutorObject *executor = (_PyExecutorObject *)frame->f_code->co_executors->executors[oparg];
21472178
Py_INCREF(executor);
@@ -2530,6 +2561,22 @@ dummy_func(
25302561
ERROR_IF(res == NULL, error);
25312562
}
25322563

2564+
pseudo(SETUP_FINALLY) = {
2565+
NOP,
2566+
};
2567+
2568+
pseudo(SETUP_CLEANUP) = {
2569+
NOP,
2570+
};
2571+
2572+
pseudo(SETUP_WITH) = {
2573+
NOP,
2574+
};
2575+
2576+
pseudo(POP_BLOCK) = {
2577+
NOP,
2578+
};
2579+
25332580
inst(PUSH_EXC_INFO, (new_exc -- prev_exc, new_exc)) {
25342581
_PyErr_StackItem *exc_info = tstate->exc_info;
25352582
if (exc_info->exc_value != NULL) {

Python/compile.c

+11-1
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,8 @@ enum {
134134
int
135135
_PyCompile_InstrSize(int opcode, int oparg)
136136
{
137-
assert(!IS_PSEUDO_OPCODE(opcode));
137+
assert(IS_PSEUDO_OPCODE(opcode) == IS_PSEUDO_INSTR(opcode));
138+
assert(!IS_PSEUDO_INSTR(opcode));
138139
assert(HAS_ARG(opcode) || oparg == 0);
139140
int extended_args = (0xFFFFFF < oparg) + (0xFFFF < oparg) + (0xFF < oparg);
140141
int caches = _PyOpcode_Caches[opcode];
@@ -241,9 +242,14 @@ instr_sequence_use_label(instr_sequence *seq, int lbl) {
241242
return SUCCESS;
242243
}
243244

245+
246+
#define MAX_OPCODE 511
247+
244248
static int
245249
instr_sequence_addop(instr_sequence *seq, int opcode, int oparg, location loc)
246250
{
251+
assert(0 <= opcode && opcode <= MAX_OPCODE);
252+
assert(IS_PSEUDO_OPCODE(opcode) == IS_PSEUDO_INSTR(opcode));
247253
assert(IS_WITHIN_OPCODE_RANGE(opcode));
248254
assert(HAS_ARG(opcode) || HAS_TARGET(opcode) || oparg == 0);
249255
assert(0 <= oparg && oparg < (1 << 30));
@@ -1055,6 +1061,7 @@ compiler_addop_name(struct compiler_unit *u, location loc,
10551061
arg <<= 1;
10561062
}
10571063
if (opcode == LOAD_METHOD) {
1064+
assert(SAME_OPCODE_METADATA(LOAD_METHOD, LOAD_ATTR));
10581065
opcode = LOAD_ATTR;
10591066
arg <<= 1;
10601067
arg |= 1;
@@ -1064,15 +1071,18 @@ compiler_addop_name(struct compiler_unit *u, location loc,
10641071
arg |= 2;
10651072
}
10661073
if (opcode == LOAD_SUPER_METHOD) {
1074+
assert(SAME_OPCODE_METADATA(LOAD_SUPER_METHOD, LOAD_SUPER_ATTR));
10671075
opcode = LOAD_SUPER_ATTR;
10681076
arg <<= 2;
10691077
arg |= 3;
10701078
}
10711079
if (opcode == LOAD_ZERO_SUPER_ATTR) {
1080+
assert(SAME_OPCODE_METADATA(LOAD_ZERO_SUPER_ATTR, LOAD_SUPER_ATTR));
10721081
opcode = LOAD_SUPER_ATTR;
10731082
arg <<= 2;
10741083
}
10751084
if (opcode == LOAD_ZERO_SUPER_METHOD) {
1085+
assert(SAME_OPCODE_METADATA(LOAD_ZERO_SUPER_METHOD, LOAD_SUPER_ATTR));
10761086
opcode = LOAD_SUPER_ATTR;
10771087
arg <<= 2;
10781088
arg |= 1;

Python/flowgraph.c

+6
Original file line numberDiff line numberDiff line change
@@ -416,9 +416,13 @@ normalize_jumps_in_block(cfg_builder *g, basicblock *b) {
416416
bool is_forward = last->i_target->b_visited == 0;
417417
switch(last->i_opcode) {
418418
case JUMP:
419+
assert(SAME_OPCODE_METADATA(JUMP, JUMP_FORWARD));
420+
assert(SAME_OPCODE_METADATA(JUMP, JUMP_BACKWARD));
419421
last->i_opcode = is_forward ? JUMP_FORWARD : JUMP_BACKWARD;
420422
return SUCCESS;
421423
case JUMP_NO_INTERRUPT:
424+
assert(SAME_OPCODE_METADATA(JUMP_NO_INTERRUPT, JUMP_FORWARD));
425+
assert(SAME_OPCODE_METADATA(JUMP_NO_INTERRUPT, JUMP_BACKWARD_NO_INTERRUPT));
422426
last->i_opcode = is_forward ?
423427
JUMP_FORWARD : JUMP_BACKWARD_NO_INTERRUPT;
424428
return SUCCESS;
@@ -2071,9 +2075,11 @@ _PyCfg_ConvertPseudoOps(basicblock *entryblock)
20712075
for (int i = 0; i < b->b_iused; i++) {
20722076
cfg_instr *instr = &b->b_instr[i];
20732077
if (is_block_push(instr) || instr->i_opcode == POP_BLOCK) {
2078+
assert(SAME_OPCODE_METADATA(instr->i_opcode, NOP));
20742079
INSTR_SET_OP0(instr, NOP);
20752080
}
20762081
else if (instr->i_opcode == STORE_FAST_MAYBE_NULL) {
2082+
assert(SAME_OPCODE_METADATA(STORE_FAST_MAYBE_NULL, STORE_FAST));
20772083
instr->i_opcode = STORE_FAST;
20782084
}
20792085
}

0 commit comments

Comments
 (0)