bpo-41463: Generate information about jumps from 'opcode.py' rather than duplicating it in 'compile.c' (GH-21714)
Generate information about jumps from 'opcode.py' rather than duplicate it in 'compile.c'
This commit is contained in:
parent
c7decc27d5
commit
582aaf19e8
|
@ -127,6 +127,28 @@ extern "C" {
|
||||||
#define SET_UPDATE 163
|
#define SET_UPDATE 163
|
||||||
#define DICT_MERGE 164
|
#define DICT_MERGE 164
|
||||||
#define DICT_UPDATE 165
|
#define DICT_UPDATE 165
|
||||||
|
#ifdef NEED_OPCODE_JUMP_TABLES
|
||||||
|
static uint32_t _PyOpcode_RelativeJump[8] = {
|
||||||
|
0U,
|
||||||
|
0U,
|
||||||
|
536870912U,
|
||||||
|
67125248U,
|
||||||
|
67141632U,
|
||||||
|
0U,
|
||||||
|
0U,
|
||||||
|
0U,
|
||||||
|
};
|
||||||
|
static uint32_t _PyOpcode_Jump[8] = {
|
||||||
|
0U,
|
||||||
|
0U,
|
||||||
|
536870912U,
|
||||||
|
101695488U,
|
||||||
|
67141632U,
|
||||||
|
0U,
|
||||||
|
0U,
|
||||||
|
0U,
|
||||||
|
};
|
||||||
|
#endif /* OPCODE_TABLES */
|
||||||
|
|
||||||
/* EXCEPT_HANDLER is a special, implicit block type which is created when
|
/* EXCEPT_HANDLER is a special, implicit block type which is created when
|
||||||
entering an except handler. It is not an opcode but we define it here
|
entering an except handler. It is not an opcode but we define it here
|
||||||
|
|
132
Python/compile.c
132
Python/compile.c
|
@ -27,6 +27,7 @@
|
||||||
#include "ast.h"
|
#include "ast.h"
|
||||||
#include "code.h"
|
#include "code.h"
|
||||||
#include "symtable.h"
|
#include "symtable.h"
|
||||||
|
#define NEED_OPCODE_JUMP_TABLES
|
||||||
#include "opcode.h"
|
#include "opcode.h"
|
||||||
#include "wordcode_helpers.h"
|
#include "wordcode_helpers.h"
|
||||||
|
|
||||||
|
@ -45,14 +46,38 @@
|
||||||
&& (c->u->u_ste->ste_type == ModuleBlock))
|
&& (c->u->u_ste->ste_type == ModuleBlock))
|
||||||
|
|
||||||
struct instr {
|
struct instr {
|
||||||
unsigned i_jabs : 1;
|
|
||||||
unsigned i_jrel : 1;
|
|
||||||
unsigned char i_opcode;
|
unsigned char i_opcode;
|
||||||
int i_oparg;
|
int i_oparg;
|
||||||
struct basicblock_ *i_target; /* target block (if jump instruction) */
|
struct basicblock_ *i_target; /* target block (if jump instruction) */
|
||||||
int i_lineno;
|
int i_lineno;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define LOG_BITS_PER_INT 5
|
||||||
|
#define MASK_LOW_LOG_BITS 31
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
is_bit_set_in_table(uint32_t *table, int bitindex) {
|
||||||
|
/* Is the relevant bit set in the relevant word? */
|
||||||
|
/* 256 bits fit into 8 32-bits words.
|
||||||
|
* Word is indexed by (bitindex>>ln(size of int in bits)).
|
||||||
|
* Bit within word is the low bits of bitindex.
|
||||||
|
*/
|
||||||
|
uint32_t word = table[bitindex >> LOG_BITS_PER_INT];
|
||||||
|
return (word >> (bitindex & MASK_LOW_LOG_BITS)) & 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
is_relative_jump(struct instr *i)
|
||||||
|
{
|
||||||
|
return is_bit_set_in_table(_PyOpcode_RelativeJump, i->i_opcode);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
is_jump(struct instr *i)
|
||||||
|
{
|
||||||
|
return is_bit_set_in_table(_PyOpcode_Jump, i->i_opcode);
|
||||||
|
}
|
||||||
|
|
||||||
typedef struct basicblock_ {
|
typedef struct basicblock_ {
|
||||||
/* Each basicblock in a compilation unit is linked via b_list in the
|
/* Each basicblock in a compilation unit is linked via b_list in the
|
||||||
reverse order that the block are allocated. b_list points to the next
|
reverse order that the block are allocated. b_list points to the next
|
||||||
|
@ -182,7 +207,7 @@ static basicblock *compiler_new_block(struct compiler *);
|
||||||
static int compiler_next_instr(basicblock *);
|
static int compiler_next_instr(basicblock *);
|
||||||
static int compiler_addop(struct compiler *, int);
|
static int compiler_addop(struct compiler *, int);
|
||||||
static int compiler_addop_i(struct compiler *, int, Py_ssize_t);
|
static int compiler_addop_i(struct compiler *, int, Py_ssize_t);
|
||||||
static int compiler_addop_j(struct compiler *, int, basicblock *, int);
|
static int compiler_addop_j(struct compiler *, int, basicblock *);
|
||||||
static int compiler_error(struct compiler *, const char *);
|
static int compiler_error(struct compiler *, const char *);
|
||||||
static int compiler_warn(struct compiler *, const char *, ...);
|
static int compiler_warn(struct compiler *, const char *, ...);
|
||||||
static int compiler_nameop(struct compiler *, identifier, expr_context_ty);
|
static int compiler_nameop(struct compiler *, identifier, expr_context_ty);
|
||||||
|
@ -1381,7 +1406,7 @@ compiler_addop_i(struct compiler *c, int opcode, Py_ssize_t oparg)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
compiler_addop_j(struct compiler *c, int opcode, basicblock *b, int absolute)
|
compiler_addop_j(struct compiler *c, int opcode, basicblock *b)
|
||||||
{
|
{
|
||||||
struct instr *i;
|
struct instr *i;
|
||||||
int off;
|
int off;
|
||||||
|
@ -1398,10 +1423,6 @@ compiler_addop_j(struct compiler *c, int opcode, basicblock *b, int absolute)
|
||||||
i = &c->u->u_curblock->b_instr[off];
|
i = &c->u->u_curblock->b_instr[off];
|
||||||
i->i_opcode = opcode;
|
i->i_opcode = opcode;
|
||||||
i->i_target = b;
|
i->i_target = b;
|
||||||
if (absolute)
|
|
||||||
i->i_jabs = 1;
|
|
||||||
else
|
|
||||||
i->i_jrel = 1;
|
|
||||||
i->i_lineno = c->u->u_lineno;
|
i->i_lineno = c->u->u_lineno;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -1471,17 +1492,11 @@ compiler_addop_j(struct compiler *c, int opcode, basicblock *b, int absolute)
|
||||||
return 0; \
|
return 0; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ADDOP_JABS(C, OP, O) { \
|
#define ADDOP_JUMP(C, OP, O) { \
|
||||||
if (!compiler_addop_j((C), (OP), (O), 1)) \
|
if (!compiler_addop_j((C), (OP), (O))) \
|
||||||
return 0; \
|
return 0; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ADDOP_JREL(C, OP, O) { \
|
|
||||||
if (!compiler_addop_j((C), (OP), (O), 0)) \
|
|
||||||
return 0; \
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#define ADDOP_COMPARE(C, CMP) { \
|
#define ADDOP_COMPARE(C, CMP) { \
|
||||||
if (!compiler_addcompare((C), (cmpop_ty)(CMP))) \
|
if (!compiler_addcompare((C), (cmpop_ty)(CMP))) \
|
||||||
return 0; \
|
return 0; \
|
||||||
|
@ -2545,7 +2560,7 @@ compiler_jump_if(struct compiler *c, expr_ty e, basicblock *next, int cond)
|
||||||
return 0;
|
return 0;
|
||||||
if (!compiler_jump_if(c, e->v.IfExp.body, next, cond))
|
if (!compiler_jump_if(c, e->v.IfExp.body, next, cond))
|
||||||
return 0;
|
return 0;
|
||||||
ADDOP_JREL(c, JUMP_FORWARD, end);
|
ADDOP_JUMP(c, JUMP_FORWARD, end);
|
||||||
compiler_use_next_block(c, next2);
|
compiler_use_next_block(c, next2);
|
||||||
if (!compiler_jump_if(c, e->v.IfExp.orelse, next, cond))
|
if (!compiler_jump_if(c, e->v.IfExp.orelse, next, cond))
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2568,20 +2583,20 @@ compiler_jump_if(struct compiler *c, expr_ty e, basicblock *next, int cond)
|
||||||
ADDOP(c, DUP_TOP);
|
ADDOP(c, DUP_TOP);
|
||||||
ADDOP(c, ROT_THREE);
|
ADDOP(c, ROT_THREE);
|
||||||
ADDOP_COMPARE(c, asdl_seq_GET(e->v.Compare.ops, i));
|
ADDOP_COMPARE(c, asdl_seq_GET(e->v.Compare.ops, i));
|
||||||
ADDOP_JABS(c, POP_JUMP_IF_FALSE, cleanup);
|
ADDOP_JUMP(c, POP_JUMP_IF_FALSE, cleanup);
|
||||||
NEXT_BLOCK(c);
|
NEXT_BLOCK(c);
|
||||||
}
|
}
|
||||||
VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Compare.comparators, n));
|
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_COMPARE(c, asdl_seq_GET(e->v.Compare.ops, n));
|
||||||
ADDOP_JABS(c, cond ? POP_JUMP_IF_TRUE : POP_JUMP_IF_FALSE, next);
|
ADDOP_JUMP(c, cond ? POP_JUMP_IF_TRUE : POP_JUMP_IF_FALSE, next);
|
||||||
basicblock *end = compiler_new_block(c);
|
basicblock *end = compiler_new_block(c);
|
||||||
if (end == NULL)
|
if (end == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
ADDOP_JREL(c, JUMP_FORWARD, end);
|
ADDOP_JUMP(c, JUMP_FORWARD, end);
|
||||||
compiler_use_next_block(c, cleanup);
|
compiler_use_next_block(c, cleanup);
|
||||||
ADDOP(c, POP_TOP);
|
ADDOP(c, POP_TOP);
|
||||||
if (!cond) {
|
if (!cond) {
|
||||||
ADDOP_JREL(c, JUMP_FORWARD, next);
|
ADDOP_JUMP(c, JUMP_FORWARD, next);
|
||||||
}
|
}
|
||||||
compiler_use_next_block(c, end);
|
compiler_use_next_block(c, end);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -2596,7 +2611,7 @@ compiler_jump_if(struct compiler *c, expr_ty e, basicblock *next, int cond)
|
||||||
|
|
||||||
/* general implementation */
|
/* general implementation */
|
||||||
VISIT(c, expr, e);
|
VISIT(c, expr, e);
|
||||||
ADDOP_JABS(c, cond ? POP_JUMP_IF_TRUE : POP_JUMP_IF_FALSE, next);
|
ADDOP_JUMP(c, cond ? POP_JUMP_IF_TRUE : POP_JUMP_IF_FALSE, next);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2615,7 +2630,7 @@ compiler_ifexp(struct compiler *c, expr_ty e)
|
||||||
if (!compiler_jump_if(c, e->v.IfExp.test, next, 0))
|
if (!compiler_jump_if(c, e->v.IfExp.test, next, 0))
|
||||||
return 0;
|
return 0;
|
||||||
VISIT(c, expr, e->v.IfExp.body);
|
VISIT(c, expr, e->v.IfExp.body);
|
||||||
ADDOP_JREL(c, JUMP_FORWARD, end);
|
ADDOP_JUMP(c, JUMP_FORWARD, end);
|
||||||
compiler_use_next_block(c, next);
|
compiler_use_next_block(c, next);
|
||||||
VISIT(c, expr, e->v.IfExp.orelse);
|
VISIT(c, expr, e->v.IfExp.orelse);
|
||||||
compiler_use_next_block(c, end);
|
compiler_use_next_block(c, end);
|
||||||
|
@ -2721,7 +2736,7 @@ compiler_if(struct compiler *c, stmt_ty s)
|
||||||
}
|
}
|
||||||
VISIT_SEQ(c, stmt, s->v.If.body);
|
VISIT_SEQ(c, stmt, s->v.If.body);
|
||||||
if (asdl_seq_LEN(s->v.If.orelse)) {
|
if (asdl_seq_LEN(s->v.If.orelse)) {
|
||||||
ADDOP_JREL(c, JUMP_FORWARD, end);
|
ADDOP_JUMP(c, JUMP_FORWARD, end);
|
||||||
compiler_use_next_block(c, next);
|
compiler_use_next_block(c, next);
|
||||||
VISIT_SEQ(c, stmt, s->v.If.orelse);
|
VISIT_SEQ(c, stmt, s->v.If.orelse);
|
||||||
}
|
}
|
||||||
|
@ -2747,10 +2762,10 @@ compiler_for(struct compiler *c, stmt_ty s)
|
||||||
VISIT(c, expr, s->v.For.iter);
|
VISIT(c, expr, s->v.For.iter);
|
||||||
ADDOP(c, GET_ITER);
|
ADDOP(c, GET_ITER);
|
||||||
compiler_use_next_block(c, start);
|
compiler_use_next_block(c, start);
|
||||||
ADDOP_JREL(c, FOR_ITER, cleanup);
|
ADDOP_JUMP(c, FOR_ITER, cleanup);
|
||||||
VISIT(c, expr, s->v.For.target);
|
VISIT(c, expr, s->v.For.target);
|
||||||
VISIT_SEQ(c, stmt, s->v.For.body);
|
VISIT_SEQ(c, stmt, s->v.For.body);
|
||||||
ADDOP_JABS(c, JUMP_ABSOLUTE, start);
|
ADDOP_JUMP(c, JUMP_ABSOLUTE, start);
|
||||||
compiler_use_next_block(c, cleanup);
|
compiler_use_next_block(c, cleanup);
|
||||||
|
|
||||||
compiler_pop_fblock(c, FOR_LOOP, start);
|
compiler_pop_fblock(c, FOR_LOOP, start);
|
||||||
|
@ -2786,7 +2801,7 @@ compiler_async_for(struct compiler *c, stmt_ty s)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/* SETUP_FINALLY to guard the __anext__ call */
|
/* SETUP_FINALLY to guard the __anext__ call */
|
||||||
ADDOP_JREL(c, SETUP_FINALLY, except);
|
ADDOP_JUMP(c, SETUP_FINALLY, except);
|
||||||
ADDOP(c, GET_ANEXT);
|
ADDOP(c, GET_ANEXT);
|
||||||
ADDOP_LOAD_CONST(c, Py_None);
|
ADDOP_LOAD_CONST(c, Py_None);
|
||||||
ADDOP(c, YIELD_FROM);
|
ADDOP(c, YIELD_FROM);
|
||||||
|
@ -2795,7 +2810,7 @@ compiler_async_for(struct compiler *c, stmt_ty s)
|
||||||
/* Success block for __anext__ */
|
/* Success block for __anext__ */
|
||||||
VISIT(c, expr, s->v.AsyncFor.target);
|
VISIT(c, expr, s->v.AsyncFor.target);
|
||||||
VISIT_SEQ(c, stmt, s->v.AsyncFor.body);
|
VISIT_SEQ(c, stmt, s->v.AsyncFor.body);
|
||||||
ADDOP_JABS(c, JUMP_ABSOLUTE, start);
|
ADDOP_JUMP(c, JUMP_ABSOLUTE, start);
|
||||||
|
|
||||||
compiler_pop_fblock(c, FOR_LOOP, start);
|
compiler_pop_fblock(c, FOR_LOOP, start);
|
||||||
|
|
||||||
|
@ -2859,7 +2874,7 @@ compiler_while(struct compiler *c, stmt_ty s)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
VISIT_SEQ(c, stmt, s->v.While.body);
|
VISIT_SEQ(c, stmt, s->v.While.body);
|
||||||
ADDOP_JABS(c, JUMP_ABSOLUTE, loop);
|
ADDOP_JUMP(c, JUMP_ABSOLUTE, loop);
|
||||||
|
|
||||||
/* XXX should the two POP instructions be in a separate block
|
/* XXX should the two POP instructions be in a separate block
|
||||||
if there is no else clause ?
|
if there is no else clause ?
|
||||||
|
@ -2918,7 +2933,7 @@ compiler_break(struct compiler *c)
|
||||||
if (!compiler_unwind_fblock(c, loop, 0)) {
|
if (!compiler_unwind_fblock(c, loop, 0)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
ADDOP_JABS(c, JUMP_ABSOLUTE, loop->fb_exit);
|
ADDOP_JUMP(c, JUMP_ABSOLUTE, loop->fb_exit);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2932,7 +2947,7 @@ compiler_continue(struct compiler *c)
|
||||||
if (loop == NULL) {
|
if (loop == NULL) {
|
||||||
return compiler_error(c, "'continue' not properly in loop");
|
return compiler_error(c, "'continue' not properly in loop");
|
||||||
}
|
}
|
||||||
ADDOP_JABS(c, JUMP_ABSOLUTE, loop->fb_block);
|
ADDOP_JUMP(c, JUMP_ABSOLUTE, loop->fb_block);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2978,7 +2993,7 @@ compiler_try_finally(struct compiler *c, stmt_ty s)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* `try` block */
|
/* `try` block */
|
||||||
ADDOP_JREL(c, SETUP_FINALLY, end);
|
ADDOP_JUMP(c, SETUP_FINALLY, end);
|
||||||
compiler_use_next_block(c, body);
|
compiler_use_next_block(c, body);
|
||||||
if (!compiler_push_fblock(c, FINALLY_TRY, body, end, s->v.Try.finalbody))
|
if (!compiler_push_fblock(c, FINALLY_TRY, body, end, s->v.Try.finalbody))
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2992,7 +3007,7 @@ compiler_try_finally(struct compiler *c, stmt_ty s)
|
||||||
ADDOP(c, POP_BLOCK);
|
ADDOP(c, POP_BLOCK);
|
||||||
compiler_pop_fblock(c, FINALLY_TRY, body);
|
compiler_pop_fblock(c, FINALLY_TRY, body);
|
||||||
VISIT_SEQ(c, stmt, s->v.Try.finalbody);
|
VISIT_SEQ(c, stmt, s->v.Try.finalbody);
|
||||||
ADDOP_JREL(c, JUMP_FORWARD, exit);
|
ADDOP_JUMP(c, JUMP_FORWARD, exit);
|
||||||
/* `finally` block */
|
/* `finally` block */
|
||||||
compiler_use_next_block(c, end);
|
compiler_use_next_block(c, end);
|
||||||
if (!compiler_push_fblock(c, FINALLY_END, end, NULL, NULL))
|
if (!compiler_push_fblock(c, FINALLY_END, end, NULL, NULL))
|
||||||
|
@ -3046,14 +3061,14 @@ compiler_try_except(struct compiler *c, stmt_ty s)
|
||||||
end = compiler_new_block(c);
|
end = compiler_new_block(c);
|
||||||
if (body == NULL || except == NULL || orelse == NULL || end == NULL)
|
if (body == NULL || except == NULL || orelse == NULL || end == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
ADDOP_JREL(c, SETUP_FINALLY, except);
|
ADDOP_JUMP(c, SETUP_FINALLY, except);
|
||||||
compiler_use_next_block(c, body);
|
compiler_use_next_block(c, body);
|
||||||
if (!compiler_push_fblock(c, EXCEPT, body, NULL, NULL))
|
if (!compiler_push_fblock(c, EXCEPT, body, NULL, NULL))
|
||||||
return 0;
|
return 0;
|
||||||
VISIT_SEQ(c, stmt, s->v.Try.body);
|
VISIT_SEQ(c, stmt, s->v.Try.body);
|
||||||
ADDOP(c, POP_BLOCK);
|
ADDOP(c, POP_BLOCK);
|
||||||
compiler_pop_fblock(c, EXCEPT, body);
|
compiler_pop_fblock(c, EXCEPT, body);
|
||||||
ADDOP_JREL(c, JUMP_FORWARD, orelse);
|
ADDOP_JUMP(c, JUMP_FORWARD, orelse);
|
||||||
n = asdl_seq_LEN(s->v.Try.handlers);
|
n = asdl_seq_LEN(s->v.Try.handlers);
|
||||||
compiler_use_next_block(c, except);
|
compiler_use_next_block(c, except);
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
|
@ -3068,7 +3083,7 @@ compiler_try_except(struct compiler *c, stmt_ty s)
|
||||||
if (handler->v.ExceptHandler.type) {
|
if (handler->v.ExceptHandler.type) {
|
||||||
ADDOP(c, DUP_TOP);
|
ADDOP(c, DUP_TOP);
|
||||||
VISIT(c, expr, handler->v.ExceptHandler.type);
|
VISIT(c, expr, handler->v.ExceptHandler.type);
|
||||||
ADDOP_JABS(c, JUMP_IF_NOT_EXC_MATCH, except);
|
ADDOP_JUMP(c, JUMP_IF_NOT_EXC_MATCH, except);
|
||||||
}
|
}
|
||||||
ADDOP(c, POP_TOP);
|
ADDOP(c, POP_TOP);
|
||||||
if (handler->v.ExceptHandler.name) {
|
if (handler->v.ExceptHandler.name) {
|
||||||
|
@ -3095,7 +3110,7 @@ compiler_try_except(struct compiler *c, stmt_ty s)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* second try: */
|
/* second try: */
|
||||||
ADDOP_JREL(c, SETUP_FINALLY, cleanup_end);
|
ADDOP_JUMP(c, SETUP_FINALLY, cleanup_end);
|
||||||
compiler_use_next_block(c, cleanup_body);
|
compiler_use_next_block(c, cleanup_body);
|
||||||
if (!compiler_push_fblock(c, HANDLER_CLEANUP, cleanup_body, NULL, handler->v.ExceptHandler.name))
|
if (!compiler_push_fblock(c, HANDLER_CLEANUP, cleanup_body, NULL, handler->v.ExceptHandler.name))
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -3109,7 +3124,7 @@ compiler_try_except(struct compiler *c, stmt_ty s)
|
||||||
ADDOP_LOAD_CONST(c, Py_None);
|
ADDOP_LOAD_CONST(c, Py_None);
|
||||||
compiler_nameop(c, handler->v.ExceptHandler.name, Store);
|
compiler_nameop(c, handler->v.ExceptHandler.name, Store);
|
||||||
compiler_nameop(c, handler->v.ExceptHandler.name, Del);
|
compiler_nameop(c, handler->v.ExceptHandler.name, Del);
|
||||||
ADDOP_JREL(c, JUMP_FORWARD, end);
|
ADDOP_JUMP(c, JUMP_FORWARD, end);
|
||||||
|
|
||||||
/* except: */
|
/* except: */
|
||||||
compiler_use_next_block(c, cleanup_end);
|
compiler_use_next_block(c, cleanup_end);
|
||||||
|
@ -3136,7 +3151,7 @@ compiler_try_except(struct compiler *c, stmt_ty s)
|
||||||
VISIT_SEQ(c, stmt, handler->v.ExceptHandler.body);
|
VISIT_SEQ(c, stmt, handler->v.ExceptHandler.body);
|
||||||
compiler_pop_fblock(c, HANDLER_CLEANUP, cleanup_body);
|
compiler_pop_fblock(c, HANDLER_CLEANUP, cleanup_body);
|
||||||
ADDOP(c, POP_EXCEPT);
|
ADDOP(c, POP_EXCEPT);
|
||||||
ADDOP_JREL(c, JUMP_FORWARD, end);
|
ADDOP_JUMP(c, JUMP_FORWARD, end);
|
||||||
}
|
}
|
||||||
compiler_use_next_block(c, except);
|
compiler_use_next_block(c, except);
|
||||||
}
|
}
|
||||||
|
@ -3645,7 +3660,7 @@ compiler_boolop(struct compiler *c, expr_ty e)
|
||||||
assert(n >= 0);
|
assert(n >= 0);
|
||||||
for (i = 0; i < n; ++i) {
|
for (i = 0; i < n; ++i) {
|
||||||
VISIT(c, expr, (expr_ty)asdl_seq_GET(s, i));
|
VISIT(c, expr, (expr_ty)asdl_seq_GET(s, i));
|
||||||
ADDOP_JABS(c, jumpi, end);
|
ADDOP_JUMP(c, jumpi, end);
|
||||||
basicblock *next = compiler_new_block(c);
|
basicblock *next = compiler_new_block(c);
|
||||||
if (next == NULL) {
|
if (next == NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -3933,7 +3948,7 @@ compiler_compare(struct compiler *c, expr_ty e)
|
||||||
ADDOP(c, DUP_TOP);
|
ADDOP(c, DUP_TOP);
|
||||||
ADDOP(c, ROT_THREE);
|
ADDOP(c, ROT_THREE);
|
||||||
ADDOP_COMPARE(c, asdl_seq_GET(e->v.Compare.ops, i));
|
ADDOP_COMPARE(c, asdl_seq_GET(e->v.Compare.ops, i));
|
||||||
ADDOP_JABS(c, JUMP_IF_FALSE_OR_POP, cleanup);
|
ADDOP_JUMP(c, JUMP_IF_FALSE_OR_POP, cleanup);
|
||||||
NEXT_BLOCK(c);
|
NEXT_BLOCK(c);
|
||||||
}
|
}
|
||||||
VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Compare.comparators, n));
|
VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Compare.comparators, n));
|
||||||
|
@ -3941,7 +3956,7 @@ compiler_compare(struct compiler *c, expr_ty e)
|
||||||
basicblock *end = compiler_new_block(c);
|
basicblock *end = compiler_new_block(c);
|
||||||
if (end == NULL)
|
if (end == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
ADDOP_JREL(c, JUMP_FORWARD, end);
|
ADDOP_JUMP(c, JUMP_FORWARD, end);
|
||||||
compiler_use_next_block(c, cleanup);
|
compiler_use_next_block(c, cleanup);
|
||||||
ADDOP(c, ROT_TWO);
|
ADDOP(c, ROT_TWO);
|
||||||
ADDOP(c, POP_TOP);
|
ADDOP(c, POP_TOP);
|
||||||
|
@ -4435,7 +4450,7 @@ compiler_sync_comprehension_generator(struct compiler *c,
|
||||||
if (start) {
|
if (start) {
|
||||||
depth++;
|
depth++;
|
||||||
compiler_use_next_block(c, start);
|
compiler_use_next_block(c, start);
|
||||||
ADDOP_JREL(c, FOR_ITER, anchor);
|
ADDOP_JUMP(c, FOR_ITER, anchor);
|
||||||
NEXT_BLOCK(c);
|
NEXT_BLOCK(c);
|
||||||
}
|
}
|
||||||
VISIT(c, expr, gen->target);
|
VISIT(c, expr, gen->target);
|
||||||
|
@ -4487,7 +4502,7 @@ compiler_sync_comprehension_generator(struct compiler *c,
|
||||||
}
|
}
|
||||||
compiler_use_next_block(c, if_cleanup);
|
compiler_use_next_block(c, if_cleanup);
|
||||||
if (start) {
|
if (start) {
|
||||||
ADDOP_JABS(c, JUMP_ABSOLUTE, start);
|
ADDOP_JUMP(c, JUMP_ABSOLUTE, start);
|
||||||
compiler_use_next_block(c, anchor);
|
compiler_use_next_block(c, anchor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4526,7 +4541,7 @@ compiler_async_comprehension_generator(struct compiler *c,
|
||||||
|
|
||||||
compiler_use_next_block(c, start);
|
compiler_use_next_block(c, start);
|
||||||
|
|
||||||
ADDOP_JREL(c, SETUP_FINALLY, except);
|
ADDOP_JUMP(c, SETUP_FINALLY, except);
|
||||||
ADDOP(c, GET_ANEXT);
|
ADDOP(c, GET_ANEXT);
|
||||||
ADDOP_LOAD_CONST(c, Py_None);
|
ADDOP_LOAD_CONST(c, Py_None);
|
||||||
ADDOP(c, YIELD_FROM);
|
ADDOP(c, YIELD_FROM);
|
||||||
|
@ -4577,7 +4592,7 @@ compiler_async_comprehension_generator(struct compiler *c,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
compiler_use_next_block(c, if_cleanup);
|
compiler_use_next_block(c, if_cleanup);
|
||||||
ADDOP_JABS(c, JUMP_ABSOLUTE, start);
|
ADDOP_JUMP(c, JUMP_ABSOLUTE, start);
|
||||||
|
|
||||||
compiler_use_next_block(c, except);
|
compiler_use_next_block(c, except);
|
||||||
ADDOP(c, END_ASYNC_FOR);
|
ADDOP(c, END_ASYNC_FOR);
|
||||||
|
@ -4773,7 +4788,7 @@ compiler_with_except_finish(struct compiler *c) {
|
||||||
exit = compiler_new_block(c);
|
exit = compiler_new_block(c);
|
||||||
if (exit == NULL)
|
if (exit == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
ADDOP_JABS(c, POP_JUMP_IF_TRUE, exit);
|
ADDOP_JUMP(c, POP_JUMP_IF_TRUE, exit);
|
||||||
ADDOP(c, RERAISE);
|
ADDOP(c, RERAISE);
|
||||||
compiler_use_next_block(c, exit);
|
compiler_use_next_block(c, exit);
|
||||||
ADDOP(c, POP_TOP);
|
ADDOP(c, POP_TOP);
|
||||||
|
@ -4835,7 +4850,7 @@ compiler_async_with(struct compiler *c, stmt_ty s, int pos)
|
||||||
ADDOP_LOAD_CONST(c, Py_None);
|
ADDOP_LOAD_CONST(c, Py_None);
|
||||||
ADDOP(c, YIELD_FROM);
|
ADDOP(c, YIELD_FROM);
|
||||||
|
|
||||||
ADDOP_JREL(c, SETUP_ASYNC_WITH, final);
|
ADDOP_JUMP(c, SETUP_ASYNC_WITH, final);
|
||||||
|
|
||||||
/* SETUP_ASYNC_WITH pushes a finally block. */
|
/* SETUP_ASYNC_WITH pushes a finally block. */
|
||||||
compiler_use_next_block(c, block);
|
compiler_use_next_block(c, block);
|
||||||
|
@ -4873,7 +4888,7 @@ compiler_async_with(struct compiler *c, stmt_ty s, int pos)
|
||||||
|
|
||||||
ADDOP(c, POP_TOP);
|
ADDOP(c, POP_TOP);
|
||||||
|
|
||||||
ADDOP_JABS(c, JUMP_ABSOLUTE, exit);
|
ADDOP_JUMP(c, JUMP_ABSOLUTE, exit);
|
||||||
|
|
||||||
/* For exceptional outcome: */
|
/* For exceptional outcome: */
|
||||||
compiler_use_next_block(c, final);
|
compiler_use_next_block(c, final);
|
||||||
|
@ -4927,7 +4942,7 @@ compiler_with(struct compiler *c, stmt_ty s, int pos)
|
||||||
/* Evaluate EXPR */
|
/* Evaluate EXPR */
|
||||||
VISIT(c, expr, item->context_expr);
|
VISIT(c, expr, item->context_expr);
|
||||||
/* Will push bound __exit__ */
|
/* Will push bound __exit__ */
|
||||||
ADDOP_JREL(c, SETUP_WITH, final);
|
ADDOP_JUMP(c, SETUP_WITH, final);
|
||||||
|
|
||||||
/* SETUP_WITH pushes a finally block. */
|
/* SETUP_WITH pushes a finally block. */
|
||||||
compiler_use_next_block(c, block);
|
compiler_use_next_block(c, block);
|
||||||
|
@ -4961,7 +4976,7 @@ compiler_with(struct compiler *c, stmt_ty s, int pos)
|
||||||
if (!compiler_call_exit_with_nones(c))
|
if (!compiler_call_exit_with_nones(c))
|
||||||
return 0;
|
return 0;
|
||||||
ADDOP(c, POP_TOP);
|
ADDOP(c, POP_TOP);
|
||||||
ADDOP_JREL(c, JUMP_FORWARD, exit);
|
ADDOP_JUMP(c, JUMP_FORWARD, exit);
|
||||||
|
|
||||||
/* For exceptional outcome: */
|
/* For exceptional outcome: */
|
||||||
compiler_use_next_block(c, final);
|
compiler_use_next_block(c, final);
|
||||||
|
@ -5492,7 +5507,7 @@ stackdepth(struct compiler *c)
|
||||||
maxdepth = new_depth;
|
maxdepth = new_depth;
|
||||||
}
|
}
|
||||||
assert(depth >= 0); /* invalid code or bug in stackdepth() */
|
assert(depth >= 0); /* invalid code or bug in stackdepth() */
|
||||||
if (instr->i_jrel || instr->i_jabs) {
|
if (is_jump(instr)) {
|
||||||
effect = stack_effect(instr->i_opcode, instr->i_oparg, 1);
|
effect = stack_effect(instr->i_opcode, instr->i_oparg, 1);
|
||||||
assert(effect != PY_INVALID_STACK_EFFECT);
|
assert(effect != PY_INVALID_STACK_EFFECT);
|
||||||
int target_depth = depth + effect;
|
int target_depth = depth + effect;
|
||||||
|
@ -5730,9 +5745,9 @@ assemble_jump_offsets(struct assembler *a, struct compiler *c)
|
||||||
the jump instruction.
|
the jump instruction.
|
||||||
*/
|
*/
|
||||||
bsize += isize;
|
bsize += isize;
|
||||||
if (instr->i_jabs || instr->i_jrel) {
|
if (is_jump(instr)) {
|
||||||
instr->i_oparg = instr->i_target->b_offset;
|
instr->i_oparg = instr->i_target->b_offset;
|
||||||
if (instr->i_jrel) {
|
if (is_relative_jump(instr)) {
|
||||||
instr->i_oparg -= bsize;
|
instr->i_oparg -= bsize;
|
||||||
}
|
}
|
||||||
instr->i_oparg *= sizeof(_Py_CODEUNIT);
|
instr->i_oparg *= sizeof(_Py_CODEUNIT);
|
||||||
|
@ -5946,8 +5961,8 @@ makecode(struct compiler *c, struct assembler *a, PyObject *consts)
|
||||||
static void
|
static void
|
||||||
dump_instr(const struct instr *i)
|
dump_instr(const struct instr *i)
|
||||||
{
|
{
|
||||||
const char *jrel = i->i_jrel ? "jrel " : "";
|
const char *jrel = (is_relative_jump(instr)) ? "jrel " : "";
|
||||||
const char *jabs = i->i_jabs ? "jabs " : "";
|
const char *jabs = (is_jump(instr) && !is_relative_jump(instr))? "jabs " : "";
|
||||||
char arg[128];
|
char arg[128];
|
||||||
|
|
||||||
*arg = '\0';
|
*arg = '\0';
|
||||||
|
@ -6122,7 +6137,7 @@ optimize_basic_block(basicblock *bb, PyObject *consts)
|
||||||
struct instr *inst = &bb->b_instr[i];
|
struct instr *inst = &bb->b_instr[i];
|
||||||
int oparg = inst->i_oparg;
|
int oparg = inst->i_oparg;
|
||||||
int nextop = i+1 < bb->b_iused ? bb->b_instr[i+1].i_opcode : 0;
|
int nextop = i+1 < bb->b_iused ? bb->b_instr[i+1].i_opcode : 0;
|
||||||
if (inst->i_jabs || inst->i_jrel) {
|
if (is_jump(inst)) {
|
||||||
/* Skip over empty basic blocks. */
|
/* Skip over empty basic blocks. */
|
||||||
while (inst->i_target->b_iused == 0) {
|
while (inst->i_target->b_iused == 0) {
|
||||||
inst->i_target = inst->i_target->b_next;
|
inst->i_target = inst->i_target->b_next;
|
||||||
|
@ -6148,7 +6163,6 @@ optimize_basic_block(basicblock *bb, PyObject *consts)
|
||||||
if (is_true == 1) {
|
if (is_true == 1) {
|
||||||
inst->i_opcode = NOP;
|
inst->i_opcode = NOP;
|
||||||
bb->b_instr[i+1].i_opcode = NOP;
|
bb->b_instr[i+1].i_opcode = NOP;
|
||||||
bb->b_instr[i+1].i_jabs = 0;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -6318,7 +6332,7 @@ mark_reachable(struct assembler *a) {
|
||||||
}
|
}
|
||||||
for (int i = 0; i < b->b_iused; i++) {
|
for (int i = 0; i < b->b_iused; i++) {
|
||||||
basicblock *target;
|
basicblock *target;
|
||||||
if (b->b_instr[i].i_jrel || b->b_instr[i].i_jabs) {
|
if (is_jump(&b->b_instr[i])) {
|
||||||
target = b->b_instr[i].i_target;
|
target = b->b_instr[i].i_target;
|
||||||
if (target->b_reachable == 0) {
|
if (target->b_reachable == 0) {
|
||||||
target->b_reachable = 1;
|
target->b_reachable = 1;
|
||||||
|
|
|
@ -30,6 +30,18 @@ footer = """
|
||||||
#endif /* !Py_OPCODE_H */
|
#endif /* !Py_OPCODE_H */
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
UINT32_MASK = (1<<32)-1
|
||||||
|
|
||||||
|
def write_int_array_from_ops(name, ops, out):
|
||||||
|
bits = 0
|
||||||
|
for op in ops:
|
||||||
|
bits |= 1<<op
|
||||||
|
out.write(f"static uint32_t {name}[8] = {{\n")
|
||||||
|
for i in range(8):
|
||||||
|
out.write(f" {bits & UINT32_MASK}U,\n")
|
||||||
|
bits >>= 32
|
||||||
|
assert bits == 0
|
||||||
|
out.write(f"}};\n")
|
||||||
|
|
||||||
def main(opcode_py, outfile='Include/opcode.h'):
|
def main(opcode_py, outfile='Include/opcode.h'):
|
||||||
opcode = {}
|
opcode = {}
|
||||||
|
@ -41,6 +53,8 @@ def main(opcode_py, outfile='Include/opcode.h'):
|
||||||
code = fp.read()
|
code = fp.read()
|
||||||
exec(code, opcode)
|
exec(code, opcode)
|
||||||
opmap = opcode['opmap']
|
opmap = opcode['opmap']
|
||||||
|
hasjrel = opcode['hasjrel']
|
||||||
|
hasjabs = opcode['hasjabs']
|
||||||
with open(outfile, 'w') as fobj:
|
with open(outfile, 'w') as fobj:
|
||||||
fobj.write(header)
|
fobj.write(header)
|
||||||
for name in opcode['opname']:
|
for name in opcode['opname']:
|
||||||
|
@ -49,8 +63,13 @@ def main(opcode_py, outfile='Include/opcode.h'):
|
||||||
if name == 'POP_EXCEPT': # Special entry for HAVE_ARGUMENT
|
if name == 'POP_EXCEPT': # Special entry for HAVE_ARGUMENT
|
||||||
fobj.write("#define %-23s %3d\n" %
|
fobj.write("#define %-23s %3d\n" %
|
||||||
('HAVE_ARGUMENT', opcode['HAVE_ARGUMENT']))
|
('HAVE_ARGUMENT', opcode['HAVE_ARGUMENT']))
|
||||||
|
fobj.write("#ifdef NEED_OPCODE_JUMP_TABLES\n")
|
||||||
|
write_int_array_from_ops("_PyOpcode_RelativeJump", opcode['hasjrel'], fobj)
|
||||||
|
write_int_array_from_ops("_PyOpcode_Jump", opcode['hasjrel'] + opcode['hasjabs'], fobj)
|
||||||
|
fobj.write("#endif /* OPCODE_TABLES */\n")
|
||||||
fobj.write(footer)
|
fobj.write(footer)
|
||||||
|
|
||||||
|
|
||||||
print("%s regenerated from %s" % (outfile, opcode_py))
|
print("%s regenerated from %s" % (outfile, opcode_py))
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue