Expand Up @@ -105,6 +105,11 @@ (IS_VIRTUAL_JUMP_OPCODE(opcode) || \ is_bit_set_in_table(_PyOpcode_Jump, opcode)) #define IS_BLOCK_PUSH_OPCODE(opcode) \ ((opcode) == SETUP_FINALLY || \ (opcode) == SETUP_WITH || \ (opcode) == SETUP_CLEANUP) /* opcodes which are not emitted in codegen stage, only by the assembler */ #define IS_ASSEMBLER_OPCODE(opcode) \ ((opcode) == JUMP_FORWARD || \ Expand Down Expand Up @@ -191,7 +196,7 @@ static inline int is_block_push(struct instr *instr) { int opcode = instr->i_opcode; return opcode == SETUP_FINALLY || opcode == SETUP_WITH || opcode == SETUP_CLEANUP ; returnIS_BLOCK_PUSH_OPCODE( opcode) ; } static inline int Expand Down Expand Up @@ -432,10 +437,9 @@ static int basicblock_next_instr(basicblock *); static int compiler_enter_scope(struct compiler *, identifier, int, void *, int); static void compiler_free(struct compiler *); static basicblock *compiler_new_block(struct compiler *); static int compiler_addop(struct compiler *, int); static int compiler_addop_i(struct compiler *, int, Py_ssize_t); static int compiler_addop_j(struct compiler *, int, basicblock *); static int compiler_addop_j_noline(struct compiler *, int, basicblock *); static int compiler_addop(struct compiler *, int, bool); static int compiler_addop_i(struct compiler *, int, Py_ssize_t, bool); static int compiler_addop_j(struct compiler *, int, basicblock *, bool); static int compiler_error(struct compiler *, const char *, ...); static int compiler_warn(struct compiler *, const char *, ...); static int compiler_nameop(struct compiler *, identifier, expr_context_ty); Expand Down Expand Up @@ -967,6 +971,25 @@ basicblock_next_instr(basicblock *b) (new).i_end_lineno = (old).i_end_lineno; \ (new).i_end_col_offset = (old).i_end_col_offset; struct location { int lineno; int end_lineno; int col_offset; int end_col_offset; }; #define NO_LOCATION ((struct location){-1, 0, 0, 0}) /* current compiler unit's location */ #define CU_LOCATION(CU) \ ((struct location){ \ (CU)->u_lineno, \ (CU)->u_end_lineno, \ (CU)->u_col_offset, \ (CU)->u_end_col_offset, \ }) /* Return the stack effect of opcode with argument oparg. Some opcodes have different stack effect when jump to the target and Expand Down Expand Up @@ -1269,48 +1292,46 @@ compiler_use_new_implicit_block_if_needed(struct compiler *c) */ static int basicblock_addop_line (basicblock *b, int opcode, intline , int end_line, int col_offset, int end_col_offset )basicblock_addop (basicblock *b, int opcode, intoparg ,basicblock *target, struct location loc ){ assert(IS_WITHIN_OPCODE_RANGE(opcode)); assert(!IS_ASSEMBLER_OPCODE(opcode)); assert(!HAS_ARG(opcode) || IS_ARTIFICIAL(opcode)); assert(HAS_ARG(opcode) || oparg == 0); assert(0 <= oparg && oparg < (1 << 30)); assert((target == NULL) || IS_JUMP_OPCODE(opcode) || IS_BLOCK_PUSH_OPCODE(opcode)); assert(oparg == 0 || target == NULL); int off = basicblock_next_instr(b); if (off < 0) { return 0; } struct instr *i = &b->b_instr[off]; i->i_opcode = opcode; i->i_oparg = 0; i->i_lineno = line; i->i_end_lineno = end_line; i->i_col_offset = col_offset; i->i_end_col_offset = end_col_offset; i->i_oparg = oparg; i->i_target = target; i->i_lineno = loc.lineno; i->i_end_lineno = loc.end_lineno; i->i_col_offset = loc.col_offset; i->i_end_col_offset = loc.end_col_offset; return 1; } static int compiler_addop(struct compiler *c, int opcode) compiler_addop(struct compiler *c, int opcode, bool line ) { assert(!HAS_ARG(opcode) || IS_ARTIFICIAL(opcode)); if (compiler_use_new_implicit_block_if_needed(c) < 0) { return -1; } return basicblock_addop_line(c->u->u_curblock, opcode, c->u->u_lineno, c->u->u_end_lineno, c->u->u_col_offset, c->u->u_end_col_offset); } static int compiler_addop_noline(struct compiler *c, int opcode) { if (compiler_use_new_implicit_block_if_needed(c) < 0) { return -1; } return basicblock_addop_line(c->u->u_curblock, opcode, -1, 0, 0, 0); struct location loc = line ? CU_LOCATION(c->u) : NO_LOCATION; return basicblock_addop(c->u->u_curblock, opcode, 0, NULL, loc); } static Py_ssize_t compiler_add_o(PyObject *dict, PyObject *o) { Expand Down Expand Up @@ -1467,7 +1488,7 @@ compiler_addop_load_const(struct compiler *c, PyObject *o) Py_ssize_t arg = compiler_add_const(c, o); if (arg < 0) return 0; return compiler_addop_i(c, LOAD_CONST, arg); return compiler_addop_i(c, LOAD_CONST, arg, true ); } static int Expand All @@ -1477,7 +1498,7 @@ compiler_addop_o(struct compiler *c, int opcode, PyObject *dict, Py_ssize_t arg = compiler_add_o(dict, o); if (arg < 0) return 0; return compiler_addop_i(c, opcode, arg); return compiler_addop_i(c, opcode, arg, true ); } static int Expand All @@ -1493,18 +1514,18 @@ compiler_addop_name(struct compiler *c, int opcode, PyObject *dict, Py_DECREF(mangled); if (arg < 0) return 0; return compiler_addop_i(c, opcode, arg); return compiler_addop_i(c, opcode, arg, true ); } /* Add an opcode with an integer argument. Returns 0 on failure, 1 on success. */ static int basicblock_addop_i_line(basicblock *b, int opcode, Py_ssize_t oparg, int lineno, int end_lineno, int col_offset, int end_col_offset) compiler_addop_i(struct compiler *c, int opcode, Py_ssize_t oparg, bool line) { if (compiler_use_new_implicit_block_if_needed(c) < 0) { return -1; } /* oparg value is unsigned, but a signed C int is usually used to store it in the C code (like Python/ceval.c). Expand All @@ -1513,104 +1534,36 @@ basicblock_addop_i_line(basicblock *b, int opcode, Py_ssize_t oparg, The argument of a concrete bytecode instruction is limited to 8-bit. EXTENDED_ARG is used for 16, 24, and 32-bit arguments. */ assert(IS_WITHIN_OPCODE_RANGE(opcode)); assert(!IS_ASSEMBLER_OPCODE(opcode)); assert(HAS_ARG(opcode)); assert(0 <= oparg && oparg <= 2147483647); int oparg_ = Py_SAFE_DOWNCAST(oparg, Py_ssize_t, int); int off = basicblock_next_instr(b); if (off < 0) { return 0; } struct instr *i = &b->b_instr[off]; i->i_opcode = opcode; i->i_oparg = Py_SAFE_DOWNCAST(oparg, Py_ssize_t, int); i->i_lineno = lineno; i->i_end_lineno = end_lineno; i->i_col_offset = col_offset; i->i_end_col_offset = end_col_offset; return 1; struct location loc = line ? CU_LOCATION(c->u) : NO_LOCATION; return basicblock_addop(c->u->u_curblock, opcode, oparg_, NULL, loc); } static int compiler_addop_i (struct compiler *c, int opcode,Py_ssize_t oparg )compiler_addop_j (struct compiler *c, int opcode,basicblock *target, bool line ){ if (compiler_use_new_implicit_block_if_needed(c) < 0) { return -1; } return basicblock_addop_i_line(c->u->u_curblock, opcode, oparg, c->u->u_lineno, c->u->u_end_lineno, c->u->u_col_offset, c->u->u_end_col_offset); } static int compiler_addop_i_noline(struct compiler *c, int opcode, Py_ssize_t oparg) { if (compiler_use_new_implicit_block_if_needed(c) < 0) { return -1; } return basicblock_addop_i_line(c->u->u_curblock, opcode, oparg, -1, 0, 0, 0); } static int basicblock_add_jump(basicblock *b, int opcode, int lineno, int end_lineno, int col_offset, int end_col_offset, basicblock *target) { assert(IS_WITHIN_OPCODE_RANGE(opcode)); assert(!IS_ASSEMBLER_OPCODE(opcode)); assert(HAS_ARG(opcode) || IS_VIRTUAL_OPCODE(opcode)); struct location loc = line ? CU_LOCATION(c->u) : NO_LOCATION; assert(target != NULL); int off = basicblock_next_instr(b); struct instr *i = &b->b_instr[off]; if (off < 0) { return 0; } i->i_opcode = opcode; i->i_target = target; i->i_lineno = lineno; i->i_end_lineno = end_lineno; i->i_col_offset = col_offset; i->i_end_col_offset = end_col_offset; return 1; } static int compiler_addop_j(struct compiler *c, int opcode, basicblock *b) { if (compiler_use_new_implicit_block_if_needed(c) < 0) { return -1; } return basicblock_add_jump(c->u->u_curblock, opcode, c->u->u_lineno, c->u->u_end_lineno, c->u->u_col_offset, c->u->u_end_col_offset, b); } static int compiler_addop_j_noline(struct compiler *c, int opcode, basicblock *b) { if (compiler_use_new_implicit_block_if_needed(c) < 0) { return -1; } return basicblock_add_jump(c->u->u_curblock, opcode, -1, 0, 0, 0, b); assert(IS_JUMP_OPCODE(opcode) || IS_BLOCK_PUSH_OPCODE(opcode)); return basicblock_addop(c->u->u_curblock, opcode, 0, target, loc); } #define ADDOP(C, OP) { \ if (!compiler_addop((C), (OP))) \ if (!compiler_addop((C), (OP), true )) \ return 0; \ } #define ADDOP_NOLINE(C, OP) { \ if (!compiler_addop_noline ((C), (OP))) \ if (!compiler_addop ((C), (OP), false )) \ return 0; \ } #define ADDOP_IN_SCOPE(C, OP) { \ if (!compiler_addop((C), (OP))) { \ if (!compiler_addop((C), (OP), true )) { \ compiler_exit_scope(c); \ return 0; \ } \ Expand Down Expand Up @@ -1649,25 +1602,25 @@ compiler_addop_j_noline(struct compiler *c, int opcode, basicblock *b) } #define ADDOP_I(C, OP, O) { \ if (!compiler_addop_i((C), (OP), (O))) \ if (!compiler_addop_i((C), (OP), (O), true )) \ return 0; \ } #define ADDOP_I_NOLINE(C, OP, O) { \ if (!compiler_addop_i_noline ((C), (OP), (O))) \ if (!compiler_addop_i ((C), (OP), (O), false )) \ return 0; \ } #define ADDOP_JUMP(C, OP, O) { \ if (!compiler_addop_j((C), (OP), (O))) \ if (!compiler_addop_j((C), (OP), (O), true )) \ return 0; \ } /* Add a jump with no line number. * Used for artificial jumps that have no corresponding * token in the source code. */ #define ADDOP_JUMP_NOLINE(C, OP, O) { \ if (!compiler_addop_j_noline ((C), (OP), (O))) \ if (!compiler_addop_j ((C), (OP), (O), false )) \ return 0; \ } Expand Down Expand Up @@ -4320,7 +4273,7 @@ compiler_nameop(struct compiler *c, identifier name, expr_context_ty ctx) if (op == LOAD_GLOBAL) { arg <<= 1; } return compiler_addop_i(c, op, arg); return compiler_addop_i(c, op, arg, true ); } static int Expand Down Expand Up @@ -6305,7 +6258,7 @@ emit_and_reset_fail_pop(struct compiler *c, pattern_context *pc) } while (--pc->fail_pop_size) { compiler_use_next_block(c, pc->fail_pop[pc->fail_pop_size]); if (!compiler_addop(c, POP_TOP)) { if (!compiler_addop(c, POP_TOP, true )) { pc->fail_pop_size = 0; PyObject_Free(pc->fail_pop); pc->fail_pop = NULL; Expand Down Expand Up @@ -6739,7 +6692,7 @@ compiler_pattern_or(struct compiler *c, pattern_ty p, pattern_context *pc) pc->fail_pop = NULL; pc->fail_pop_size = 0; pc->on_top = 0; if (!compiler_addop_i(c, COPY, 1) || !compiler_pattern(c, alt, pc)) { if (!compiler_addop_i(c, COPY, 1, true ) || !compiler_pattern(c, alt, pc)) { goto error; } // Success! Expand Down Expand Up @@ -6802,7 +6755,7 @@ compiler_pattern_or(struct compiler *c, pattern_ty p, pattern_context *pc) } } assert(control); if (!compiler_addop_j(c, JUMP, end) || if (!compiler_addop_j(c, JUMP, end, true ) || !emit_and_reset_fail_pop(c, pc)) { goto error; Expand All @@ -6814,7 +6767,7 @@ compiler_pattern_or(struct compiler *c, pattern_ty p, pattern_context *pc) // Need to NULL this for the PyObject_Free call in the error block. old_pc.fail_pop = NULL; // No match. Pop the remaining copy of the subject and fail: if (!compiler_addop(c, POP_TOP) || !jump_to_fail_pop(c, pc, JUMP)) { if (!compiler_addop(c, POP_TOP, true ) || !jump_to_fail_pop(c, pc, JUMP)) { goto error; } compiler_use_next_block(c, end); Expand Down Expand Up @@ -7477,7 +7430,7 @@ push_cold_blocks_to_end(struct compiler *c, basicblock *entry, int code_flags) { if (explicit_jump == NULL) { return -1; } basicblock_add_jump (explicit_jump, JUMP,-1, 0,0, 0, b->b_next);basicblock_addop (explicit_jump, JUMP, 0, b->b_next, NO_LOCATION ); explicit_jump->b_cold = 1; explicit_jump->b_next = b->b_next; Expand Down