Branch data Line data Source code
1 : : /*
2 : : * This file compiles an abstract syntax tree (AST) into Python bytecode.
3 : : *
4 : : * The primary entry point is _PyAST_Compile(), which returns a
5 : : * PyCodeObject. The compiler makes several passes to build the code
6 : : * object:
7 : : * 1. Checks for future statements. See future.c
8 : : * 2. Builds a symbol table. See symtable.c.
9 : : * 3. Generate code for basic blocks. See compiler_mod() in this file.
10 : : * 4. Assemble the basic blocks into final code. See assemble() in
11 : : * this file.
12 : : * 5. Optimize the byte code (peephole optimizations).
13 : : *
14 : : * Note that compiler_mod() suggests module, but the module ast type
15 : : * (mod_ty) has cases for expressions and interactive statements.
16 : : *
17 : : * CAUTION: The VISIT_* macros abort the current function when they
18 : : * encounter a problem. So don't invoke them when there is memory
19 : : * which needs to be released. Code blocks are OK, as the compiler
20 : : * structure takes care of releasing those. Use the arena to manage
21 : : * objects.
22 : : */
23 : :
24 : : #include <stdbool.h>
25 : :
26 : : // Need _PyOpcode_RelativeJump of pycore_opcode.h
27 : : #define NEED_OPCODE_TABLES
28 : :
29 : : #include "Python.h"
30 : : #include "pycore_ast.h" // _PyAST_GetDocString()
31 : : #include "pycore_code.h" // _PyCode_New()
32 : : #include "pycore_compile.h"
33 : : #include "pycore_intrinsics.h"
34 : : #include "pycore_long.h" // _PyLong_GetZero()
35 : : #include "pycore_opcode.h" // _PyOpcode_Caches
36 : : #include "pycore_pymem.h" // _PyMem_IsPtrFreed()
37 : : #include "pycore_symtable.h" // PySTEntryObject, _PyFuture_FromAST()
38 : :
39 : : #include "opcode_metadata.h" // _PyOpcode_opcode_metadata, _PyOpcode_num_popped/pushed
40 : :
41 : :
42 : : #define DEFAULT_BLOCK_SIZE 16
43 : : #define DEFAULT_CODE_SIZE 128
44 : : #define DEFAULT_LNOTAB_SIZE 16
45 : : #define DEFAULT_CNOTAB_SIZE 32
46 : :
47 : : #define COMP_GENEXP 0
48 : : #define COMP_LISTCOMP 1
49 : : #define COMP_SETCOMP 2
50 : : #define COMP_DICTCOMP 3
51 : :
52 : : /* A soft limit for stack use, to avoid excessive
53 : : * memory use for large constants, etc.
54 : : *
55 : : * The value 30 is plucked out of thin air.
56 : : * Code that could use more stack than this is
57 : : * rare, so the exact value is unimportant.
58 : : */
59 : : #define STACK_USE_GUIDELINE 30
60 : :
61 : : #undef SUCCESS
62 : : #undef ERROR
63 : : #define SUCCESS 0
64 : : #define ERROR -1
65 : :
66 : : #define RETURN_IF_ERROR(X) \
67 : : if ((X) == -1) { \
68 : : return ERROR; \
69 : : }
70 : :
71 : : /* If we exceed this limit, it should
72 : : * be considered a compiler bug.
73 : : * Currently it should be impossible
74 : : * to exceed STACK_USE_GUIDELINE * 100,
75 : : * as 100 is the maximum parse depth.
76 : : * For performance reasons we will
77 : : * want to reduce this to a
78 : : * few hundred in the future.
79 : : *
80 : : * NOTE: Whatever MAX_ALLOWED_STACK_USE is
81 : : * set to, it should never restrict what Python
82 : : * we can write, just how we compile it.
83 : : */
84 : : #define MAX_ALLOWED_STACK_USE (STACK_USE_GUIDELINE * 100)
85 : :
86 : :
87 : : #define MAX_REAL_OPCODE 254
88 : :
89 : : #define IS_WITHIN_OPCODE_RANGE(opcode) \
90 : : (((opcode) >= 0 && (opcode) <= MAX_REAL_OPCODE) || \
91 : : IS_PSEUDO_OPCODE(opcode))
92 : :
93 : : #define IS_JUMP_OPCODE(opcode) \
94 : : is_bit_set_in_table(_PyOpcode_Jump, opcode)
95 : :
96 : : #define IS_BLOCK_PUSH_OPCODE(opcode) \
97 : : ((opcode) == SETUP_FINALLY || \
98 : : (opcode) == SETUP_WITH || \
99 : : (opcode) == SETUP_CLEANUP)
100 : :
101 : : #define HAS_TARGET(opcode) \
102 : : (IS_JUMP_OPCODE(opcode) || IS_BLOCK_PUSH_OPCODE(opcode))
103 : :
104 : : /* opcodes that must be last in the basicblock */
105 : : #define IS_TERMINATOR_OPCODE(opcode) \
106 : : (IS_JUMP_OPCODE(opcode) || IS_SCOPE_EXIT_OPCODE(opcode))
107 : :
108 : : /* opcodes which are not emitted in codegen stage, only by the assembler */
109 : : #define IS_ASSEMBLER_OPCODE(opcode) \
110 : : ((opcode) == JUMP_FORWARD || \
111 : : (opcode) == JUMP_BACKWARD || \
112 : : (opcode) == JUMP_BACKWARD_NO_INTERRUPT)
113 : :
114 : : #define IS_BACKWARDS_JUMP_OPCODE(opcode) \
115 : : ((opcode) == JUMP_BACKWARD || \
116 : : (opcode) == JUMP_BACKWARD_NO_INTERRUPT)
117 : :
118 : : #define IS_UNCONDITIONAL_JUMP_OPCODE(opcode) \
119 : : ((opcode) == JUMP || \
120 : : (opcode) == JUMP_NO_INTERRUPT || \
121 : : (opcode) == JUMP_FORWARD || \
122 : : (opcode) == JUMP_BACKWARD || \
123 : : (opcode) == JUMP_BACKWARD_NO_INTERRUPT)
124 : :
125 : : #define IS_SCOPE_EXIT_OPCODE(opcode) \
126 : : ((opcode) == RETURN_VALUE || \
127 : : (opcode) == RETURN_CONST || \
128 : : (opcode) == RAISE_VARARGS || \
129 : : (opcode) == RERAISE)
130 : :
131 : : #define IS_SUPERINSTRUCTION_OPCODE(opcode) \
132 : : ((opcode) == LOAD_FAST__LOAD_FAST || \
133 : : (opcode) == LOAD_FAST__LOAD_CONST || \
134 : : (opcode) == LOAD_CONST__LOAD_FAST || \
135 : : (opcode) == STORE_FAST__LOAD_FAST || \
136 : : (opcode) == STORE_FAST__STORE_FAST)
137 : :
138 : : #define IS_TOP_LEVEL_AWAIT(C) ( \
139 : : ((C)->c_flags.cf_flags & PyCF_ALLOW_TOP_LEVEL_AWAIT) \
140 : : && ((C)->u->u_ste->ste_type == ModuleBlock))
141 : :
142 : : typedef _PyCompilerSrcLocation location;
143 : :
144 : : #define LOCATION(LNO, END_LNO, COL, END_COL) \
145 : : ((const location){(LNO), (END_LNO), (COL), (END_COL)})
146 : :
147 : : static location NO_LOCATION = {-1, -1, -1, -1};
148 : :
149 : : /* Return true if loc1 starts after loc2 ends. */
150 : : static inline bool
151 : 524 : location_is_after(location loc1, location loc2) {
152 [ - + ]: 524 : return (loc1.lineno > loc2.end_lineno) ||
153 [ # # ]: 0 : ((loc1.lineno == loc2.end_lineno) &&
154 [ # # ]: 0 : (loc1.col_offset > loc2.end_col_offset));
155 : : }
156 : :
157 : : static inline bool
158 : 342036 : same_location(location a, location b)
159 : : {
160 : 595006 : return a.lineno == b.lineno &&
161 [ + + ]: 252970 : a.end_lineno == b.end_lineno &&
162 [ + + + + ]: 719666 : a.col_offset == b.col_offset &&
163 [ + + ]: 124660 : a.end_col_offset == b.end_col_offset;
164 : : }
165 : :
166 : : #define LOC(x) SRC_LOCATION_FROM_AST(x)
167 : :
168 : : typedef struct jump_target_label_ {
169 : : int id;
170 : : } jump_target_label;
171 : :
172 : : static struct jump_target_label_ NO_LABEL = {-1};
173 : :
174 : : #define SAME_LABEL(L1, L2) ((L1).id == (L2).id)
175 : : #define IS_LABEL(L) (!SAME_LABEL((L), (NO_LABEL)))
176 : :
177 : : #define NEW_JUMP_TARGET_LABEL(C, NAME) \
178 : : jump_target_label NAME = instr_sequence_new_label(INSTR_SEQUENCE(C)); \
179 : : if (!IS_LABEL(NAME)) { \
180 : : return ERROR; \
181 : : }
182 : :
183 : : #define USE_LABEL(C, LBL) \
184 : : RETURN_IF_ERROR(instr_sequence_use_label(INSTR_SEQUENCE(C), (LBL).id))
185 : :
186 : : struct cfg_instr {
187 : : int i_opcode;
188 : : int i_oparg;
189 : : location i_loc;
190 : : struct basicblock_ *i_target; /* target block (if jump instruction) */
191 : : struct basicblock_ *i_except; /* target block when exception is raised */
192 : : };
193 : :
194 : : /* One arg*/
195 : : #define INSTR_SET_OP1(I, OP, ARG) \
196 : : do { \
197 : : assert(HAS_ARG(OP)); \
198 : : struct cfg_instr *_instr__ptr_ = (I); \
199 : : _instr__ptr_->i_opcode = (OP); \
200 : : _instr__ptr_->i_oparg = (ARG); \
201 : : } while (0);
202 : :
203 : : /* No args*/
204 : : #define INSTR_SET_OP0(I, OP) \
205 : : do { \
206 : : assert(!HAS_ARG(OP)); \
207 : : struct cfg_instr *_instr__ptr_ = (I); \
208 : : _instr__ptr_->i_opcode = (OP); \
209 : : _instr__ptr_->i_oparg = 0; \
210 : : } while (0);
211 : :
212 : : typedef struct exceptstack {
213 : : struct basicblock_ *handlers[CO_MAXBLOCKS+1];
214 : : int depth;
215 : : } ExceptStack;
216 : :
217 : : #define LOG_BITS_PER_INT 5
218 : : #define MASK_LOW_LOG_BITS 31
219 : :
220 : : static inline int
221 : 4262278 : is_bit_set_in_table(const uint32_t *table, int bitindex) {
222 : : /* Is the relevant bit set in the relevant word? */
223 : : /* 512 bits fit into 9 32-bits words.
224 : : * Word is indexed by (bitindex>>ln(size of int in bits)).
225 : : * Bit within word is the low bits of bitindex.
226 : : */
227 [ + - + - ]: 4262278 : if (bitindex >= 0 && bitindex < 512) {
228 : 4262278 : uint32_t word = table[bitindex >> LOG_BITS_PER_INT];
229 : 4262278 : return (word >> (bitindex & MASK_LOW_LOG_BITS)) & 1;
230 : : }
231 : : else {
232 : 0 : return 0;
233 : : }
234 : : }
235 : :
236 : : static inline int
237 : 26506 : is_relative_jump(struct cfg_instr *i)
238 : : {
239 : 26506 : return is_bit_set_in_table(_PyOpcode_RelativeJump, i->i_opcode);
240 : : }
241 : :
242 : : static inline int
243 : 1431493 : is_block_push(struct cfg_instr *i)
244 : : {
245 [ + + + + : 1431493 : return IS_BLOCK_PUSH_OPCODE(i->i_opcode);
+ + ]
246 : : }
247 : :
248 : : static inline int
249 : 1621642 : is_jump(struct cfg_instr *i)
250 : : {
251 : 1621642 : return IS_JUMP_OPCODE(i->i_opcode);
252 : : }
253 : :
254 : : static int
255 : 1860948 : instr_size(struct cfg_instr *instruction)
256 : : {
257 : 1860948 : int opcode = instruction->i_opcode;
258 : : assert(!IS_PSEUDO_OPCODE(opcode));
259 : 1860948 : int oparg = instruction->i_oparg;
260 : : assert(HAS_ARG(opcode) || oparg == 0);
261 : 1860948 : int extended_args = (0xFFFFFF < oparg) + (0xFFFF < oparg) + (0xFF < oparg);
262 : 1860948 : int caches = _PyOpcode_Caches[opcode];
263 : 1860948 : return extended_args + 1 + caches;
264 : : }
265 : :
266 : : static void
267 : 342036 : write_instr(_Py_CODEUNIT *codestr, struct cfg_instr *instruction, int ilen)
268 : : {
269 : 342036 : int opcode = instruction->i_opcode;
270 : : assert(!IS_PSEUDO_OPCODE(opcode));
271 : 342036 : int oparg = instruction->i_oparg;
272 : : assert(HAS_ARG(opcode) || oparg == 0);
273 : 342036 : int caches = _PyOpcode_Caches[opcode];
274 [ - - + + : 342036 : switch (ilen - caches) {
- ]
275 : 0 : case 4:
276 : 0 : codestr->op.code = EXTENDED_ARG;
277 : 0 : codestr->op.arg = (oparg >> 24) & 0xFF;
278 : 0 : codestr++;
279 : : /* fall through */
280 : 0 : case 3:
281 : 0 : codestr->op.code = EXTENDED_ARG;
282 : 0 : codestr->op.arg = (oparg >> 16) & 0xFF;
283 : 0 : codestr++;
284 : : /* fall through */
285 : 3324 : case 2:
286 : 3324 : codestr->op.code = EXTENDED_ARG;
287 : 3324 : codestr->op.arg = (oparg >> 8) & 0xFF;
288 : 3324 : codestr++;
289 : : /* fall through */
290 : 342036 : case 1:
291 : 342036 : codestr->op.code = opcode;
292 : 342036 : codestr->op.arg = oparg & 0xFF;
293 : 342036 : codestr++;
294 : 342036 : break;
295 : 0 : default:
296 : 0 : Py_UNREACHABLE();
297 : : }
298 [ + + ]: 815594 : while (caches--) {
299 : 473558 : codestr->op.code = CACHE;
300 : 473558 : codestr->op.arg = 0;
301 : 473558 : codestr++;
302 : : }
303 : 342036 : }
304 : :
305 : : typedef struct basicblock_ {
306 : : /* Each basicblock in a compilation unit is linked via b_list in the
307 : : reverse order that the block are allocated. b_list points to the next
308 : : block, not to be confused with b_next, which is next by control flow. */
309 : : struct basicblock_ *b_list;
310 : : /* The label of this block if it is a jump target, -1 otherwise */
311 : : jump_target_label b_label;
312 : : /* Exception stack at start of block, used by assembler to create the exception handling table */
313 : : ExceptStack *b_exceptstack;
314 : : /* pointer to an array of instructions, initially NULL */
315 : : struct cfg_instr *b_instr;
316 : : /* If b_next is non-NULL, it is a pointer to the next
317 : : block reached by normal control flow. */
318 : : struct basicblock_ *b_next;
319 : : /* number of instructions used */
320 : : int b_iused;
321 : : /* length of instruction array (b_instr) */
322 : : int b_ialloc;
323 : : /* Used by add_checks_for_loads_of_unknown_variables */
324 : : uint64_t b_unsafe_locals_mask;
325 : : /* Number of predecessors that a block has. */
326 : : int b_predecessors;
327 : : /* depth of stack upon entry of block, computed by stackdepth() */
328 : : int b_startdepth;
329 : : /* instruction offset for block, computed by assemble_jump_offsets() */
330 : : int b_offset;
331 : : /* Basic block is an exception handler that preserves lasti */
332 : : unsigned b_preserve_lasti : 1;
333 : : /* Used by compiler passes to mark whether they have visited a basic block. */
334 : : unsigned b_visited : 1;
335 : : /* b_except_handler is used by the cold-detection algorithm to mark exception targets */
336 : : unsigned b_except_handler : 1;
337 : : /* b_cold is true if this block is not perf critical (like an exception handler) */
338 : : unsigned b_cold : 1;
339 : : /* b_warm is used by the cold-detection algorithm to mark blocks which are definitely not cold */
340 : : unsigned b_warm : 1;
341 : : } basicblock;
342 : :
343 : :
344 : : static struct cfg_instr *
345 : 1316809 : basicblock_last_instr(const basicblock *b) {
346 : : assert(b->b_iused >= 0);
347 [ + + ]: 1316809 : if (b->b_iused > 0) {
348 : : assert(b->b_instr != NULL);
349 : 1272680 : return &b->b_instr[b->b_iused - 1];
350 : : }
351 : 44129 : return NULL;
352 : : }
353 : :
354 : : static inline int
355 : 65096 : basicblock_exits_scope(const basicblock *b) {
356 : 65096 : struct cfg_instr *last = basicblock_last_instr(b);
357 [ + - + + : 65096 : return last && IS_SCOPE_EXIT_OPCODE(last->i_opcode);
+ + + + +
+ ]
358 : : }
359 : :
360 : : static inline int
361 : 347556 : basicblock_nofallthrough(const basicblock *b) {
362 : 347556 : struct cfg_instr *last = basicblock_last_instr(b);
363 [ + + ]: 692674 : return (last &&
364 [ + + + + : 345118 : (IS_SCOPE_EXIT_OPCODE(last->i_opcode) ||
+ + + + ]
365 [ + + + + : 247926 : IS_UNCONDITIONAL_JUMP_OPCODE(last->i_opcode)));
+ - + - -
+ ]
366 : : }
367 : :
368 : : #define BB_NO_FALLTHROUGH(B) (basicblock_nofallthrough(B))
369 : : #define BB_HAS_FALLTHROUGH(B) (!basicblock_nofallthrough(B))
370 : :
371 : : /* fblockinfo tracks the current frame block.
372 : :
373 : : A frame block is used to handle loops, try/except, and try/finally.
374 : : It's called a frame block to distinguish it from a basic block in the
375 : : compiler IR.
376 : : */
377 : :
378 : : enum fblocktype { WHILE_LOOP, FOR_LOOP, TRY_EXCEPT, FINALLY_TRY, FINALLY_END,
379 : : WITH, ASYNC_WITH, HANDLER_CLEANUP, POP_VALUE, EXCEPTION_HANDLER,
380 : : EXCEPTION_GROUP_HANDLER, ASYNC_COMPREHENSION_GENERATOR };
381 : :
382 : : struct fblockinfo {
383 : : enum fblocktype fb_type;
384 : : jump_target_label fb_block;
385 : : /* (optional) type-specific exit or cleanup block */
386 : : jump_target_label fb_exit;
387 : : /* (optional) additional information required for unwinding */
388 : : void *fb_datum;
389 : : };
390 : :
391 : : enum {
392 : : COMPILER_SCOPE_MODULE,
393 : : COMPILER_SCOPE_CLASS,
394 : : COMPILER_SCOPE_FUNCTION,
395 : : COMPILER_SCOPE_ASYNC_FUNCTION,
396 : : COMPILER_SCOPE_LAMBDA,
397 : : COMPILER_SCOPE_COMPREHENSION,
398 : : };
399 : :
400 : : typedef struct cfg_builder_ {
401 : : /* The entryblock, at which control flow begins. All blocks of the
402 : : CFG are reachable through the b_next links */
403 : : basicblock *g_entryblock;
404 : : /* Pointer to the most recently allocated block. By following
405 : : b_list links, you can reach all allocated blocks. */
406 : : basicblock *g_block_list;
407 : : /* pointer to the block currently being constructed */
408 : : basicblock *g_curblock;
409 : : /* label for the next instruction to be placed */
410 : : jump_target_label g_current_label;
411 : : } cfg_builder;
412 : :
413 : : typedef struct {
414 : : int i_opcode;
415 : : int i_oparg;
416 : : location i_loc;
417 : : } instruction;
418 : :
419 : :
420 : : typedef struct instr_sequence_ {
421 : : instruction *s_instrs;
422 : : int s_allocated;
423 : : int s_used;
424 : :
425 : : int *s_labelmap; /* label id --> instr offset */
426 : : int s_labelmap_size;
427 : : int s_next_free_label; /* next free label id */
428 : : } instr_sequence;
429 : :
430 : : #define INITIAL_INSTR_SEQUENCE_SIZE 100
431 : : #define INITIAL_INSTR_SEQUENCE_LABELS_MAP_SIZE 10
432 : :
433 : : /*
434 : : * Resize the array if index is out of range.
435 : : *
436 : : * idx: the index we want to access
437 : : * arr: pointer to the array
438 : : * alloc: pointer to the capacity of the array
439 : : * default_alloc: initial number of items
440 : : * item_size: size of each item
441 : : *
442 : : */
443 : : static int
444 : 815334 : ensure_array_large_enough(int idx, void **arr_, int *alloc, int default_alloc, size_t item_size)
445 : : {
446 : 815334 : void *arr = *arr_;
447 [ + + ]: 815334 : if (arr == NULL) {
448 : 72673 : int new_alloc = default_alloc;
449 [ - + ]: 72673 : if (idx >= new_alloc) {
450 : 0 : new_alloc = idx + default_alloc;
451 : : }
452 : 72673 : arr = PyObject_Calloc(new_alloc, item_size);
453 [ - + ]: 72673 : if (arr == NULL) {
454 : 0 : PyErr_NoMemory();
455 : 0 : return ERROR;
456 : : }
457 : 72673 : *alloc = new_alloc;
458 : : }
459 [ + + ]: 742661 : else if (idx >= *alloc) {
460 : 8183 : size_t oldsize = *alloc * item_size;
461 : 8183 : int new_alloc = *alloc << 1;
462 [ - + ]: 8183 : if (idx >= new_alloc) {
463 : 0 : new_alloc = idx + default_alloc;
464 : : }
465 : 8183 : size_t newsize = new_alloc * item_size;
466 : :
467 [ - + ]: 8183 : if (oldsize > (SIZE_MAX >> 1)) {
468 : 0 : PyErr_NoMemory();
469 : 0 : return ERROR;
470 : : }
471 : :
472 : : assert(newsize > 0);
473 : 8183 : void *tmp = PyObject_Realloc(arr, newsize);
474 [ - + ]: 8183 : if (tmp == NULL) {
475 : 0 : PyErr_NoMemory();
476 : 0 : return ERROR;
477 : : }
478 : 8183 : *alloc = new_alloc;
479 : 8183 : arr = tmp;
480 : 8183 : memset((char *)arr + oldsize, 0, newsize - oldsize);
481 : : }
482 : :
483 : 815334 : *arr_ = arr;
484 : 815334 : return SUCCESS;
485 : : }
486 : :
487 : : static int
488 : 386612 : instr_sequence_next_inst(instr_sequence *seq) {
489 : : assert(seq->s_instrs != NULL || seq->s_used == 0);
490 : :
491 [ - + ]: 386612 : RETURN_IF_ERROR(
492 : : ensure_array_large_enough(seq->s_used + 1,
493 : : (void**)&seq->s_instrs,
494 : : &seq->s_allocated,
495 : : INITIAL_INSTR_SEQUENCE_SIZE,
496 : : sizeof(instruction)));
497 : : assert(seq->s_used < seq->s_allocated);
498 : 386612 : return seq->s_used++;
499 : : }
500 : :
501 : : static jump_target_label
502 : 33597 : instr_sequence_new_label(instr_sequence *seq)
503 : : {
504 : 33597 : jump_target_label lbl = {++seq->s_next_free_label};
505 : 33597 : return lbl;
506 : : }
507 : :
508 : : static int
509 : 33597 : instr_sequence_use_label(instr_sequence *seq, int lbl) {
510 : 33597 : int old_size = seq->s_labelmap_size;
511 [ - + ]: 33597 : RETURN_IF_ERROR(
512 : : ensure_array_large_enough(lbl,
513 : : (void**)&seq->s_labelmap,
514 : : &seq->s_labelmap_size,
515 : : INITIAL_INSTR_SEQUENCE_LABELS_MAP_SIZE,
516 : : sizeof(int)));
517 : :
518 [ + + ]: 97907 : for(int i = old_size; i < seq->s_labelmap_size; i++) {
519 : 64310 : seq->s_labelmap[i] = -111; /* something weird, for debugging */
520 : : }
521 : 33597 : seq->s_labelmap[lbl] = seq->s_used; /* label refers to the next instruction */
522 : 33597 : return SUCCESS;
523 : : }
524 : :
525 : : static int
526 : 386082 : instr_sequence_addop(instr_sequence *seq, int opcode, int oparg, location loc)
527 : : {
528 : : assert(IS_WITHIN_OPCODE_RANGE(opcode));
529 : : assert(!IS_ASSEMBLER_OPCODE(opcode));
530 : : assert(HAS_ARG(opcode) || HAS_TARGET(opcode) || oparg == 0);
531 : : assert(0 <= oparg && oparg < (1 << 30));
532 : :
533 : 386082 : int idx = instr_sequence_next_inst(seq);
534 [ - + ]: 386082 : RETURN_IF_ERROR(idx);
535 : 386082 : instruction *ci = &seq->s_instrs[idx];
536 : 386082 : ci->i_opcode = opcode;
537 : 386082 : ci->i_oparg = oparg;
538 : 386082 : ci->i_loc = loc;
539 : 386082 : return SUCCESS;
540 : : }
541 : :
542 : : static int
543 : 530 : instr_sequence_insert_instruction(instr_sequence *seq, int pos,
544 : : int opcode, int oparg, location loc)
545 : : {
546 : : assert(pos >= 0 && pos <= seq->s_used);
547 : 530 : int last_idx = instr_sequence_next_inst(seq);
548 [ - + ]: 530 : RETURN_IF_ERROR(last_idx);
549 [ + + ]: 27294 : for (int i=last_idx-1; i >= pos; i--) {
550 : 26764 : seq->s_instrs[i+1] = seq->s_instrs[i];
551 : : }
552 : 530 : instruction *ci = &seq->s_instrs[pos];
553 : 530 : ci->i_opcode = opcode;
554 : 530 : ci->i_oparg = oparg;
555 : 530 : ci->i_loc = loc;
556 : :
557 : : /* fix the labels map */
558 [ + + ]: 8160 : for(int lbl=0; lbl < seq->s_labelmap_size; lbl++) {
559 [ + + ]: 7630 : if (seq->s_labelmap[lbl] >= pos) {
560 : 4243 : seq->s_labelmap[lbl]++;
561 : : }
562 : : }
563 : 530 : return SUCCESS;
564 : : }
565 : :
566 : : static void
567 : 8041 : instr_sequence_fini(instr_sequence *seq) {
568 : 8041 : PyObject_Free(seq->s_labelmap);
569 : 8041 : seq->s_labelmap = NULL;
570 : :
571 : 8041 : PyObject_Free(seq->s_instrs);
572 : 8041 : seq->s_instrs = NULL;
573 : 8041 : }
574 : :
575 : : static int basicblock_addop(basicblock *b, int opcode, int oparg, location loc);
576 : : static int cfg_builder_maybe_start_new_block(cfg_builder *g);
577 : :
578 : : static int
579 : 33597 : cfg_builder_use_label(cfg_builder *g, jump_target_label lbl)
580 : : {
581 : 33597 : g->g_current_label = lbl;
582 : 33597 : return cfg_builder_maybe_start_new_block(g);
583 : : }
584 : :
585 : : static int
586 : 386612 : cfg_builder_addop(cfg_builder *g, int opcode, int oparg, location loc)
587 : : {
588 [ - + ]: 386612 : RETURN_IF_ERROR(cfg_builder_maybe_start_new_block(g));
589 : 386612 : return basicblock_addop(g->g_curblock, opcode, oparg, loc);
590 : : }
591 : :
592 : : static int cfg_builder_init(cfg_builder *g);
593 : :
594 : : static int
595 : 8041 : instr_sequence_to_cfg(instr_sequence *seq, cfg_builder *g) {
596 : 8041 : memset(g, 0, sizeof(cfg_builder));
597 [ - + ]: 8041 : RETURN_IF_ERROR(cfg_builder_init(g));
598 : : /* Note: there can be more than one label for the same offset */
599 [ + + ]: 394653 : for (int i = 0; i < seq->s_used; i++) {
600 [ + + ]: 10102672 : for (int j=0; j < seq->s_labelmap_size; j++) {
601 [ + + ]: 9716060 : if (seq->s_labelmap[j] == i) {
602 : 33597 : jump_target_label lbl = {j};
603 [ - + ]: 33597 : RETURN_IF_ERROR(cfg_builder_use_label(g, lbl));
604 : : }
605 : : }
606 : 386612 : instruction *instr = &seq->s_instrs[i];
607 [ - + ]: 386612 : RETURN_IF_ERROR(cfg_builder_addop(g, instr->i_opcode, instr->i_oparg, instr->i_loc));
608 : : }
609 : 8041 : int nblocks = 0;
610 [ + + ]: 69608 : for (basicblock *b = g->g_block_list; b != NULL; b = b->b_list) {
611 : 61567 : nblocks++;
612 : : }
613 [ - + ]: 8041 : if ((size_t)nblocks > SIZE_MAX / sizeof(basicblock *)) {
614 : 0 : PyErr_NoMemory();
615 : 0 : return ERROR;
616 : : }
617 : 8041 : return SUCCESS;
618 : : }
619 : :
620 : :
621 : : /* The following items change on entry and exit of code blocks.
622 : : They must be saved and restored when returning to a block.
623 : : */
624 : : struct compiler_unit {
625 : : PySTEntryObject *u_ste;
626 : :
627 : : PyObject *u_name;
628 : : PyObject *u_qualname; /* dot-separated qualified name (lazy) */
629 : : int u_scope_type;
630 : :
631 : : /* The following fields are dicts that map objects to
632 : : the index of them in co_XXX. The index is used as
633 : : the argument for opcodes that refer to those collections.
634 : : */
635 : : PyObject *u_consts; /* all constants */
636 : : PyObject *u_names; /* all names */
637 : : PyObject *u_varnames; /* local variables */
638 : : PyObject *u_cellvars; /* cell variables */
639 : : PyObject *u_freevars; /* free variables */
640 : :
641 : : PyObject *u_private; /* for private name mangling */
642 : :
643 : : Py_ssize_t u_argcount; /* number of arguments for block */
644 : : Py_ssize_t u_posonlyargcount; /* number of positional only arguments for block */
645 : : Py_ssize_t u_kwonlyargcount; /* number of keyword only arguments for block */
646 : :
647 : : instr_sequence u_instr_sequence; /* codegen output */
648 : :
649 : : int u_nfblocks;
650 : : struct fblockinfo u_fblock[CO_MAXBLOCKS];
651 : :
652 : : int u_firstlineno; /* the first lineno of the block */
653 : : };
654 : :
655 : : /* This struct captures the global state of a compilation.
656 : :
657 : : The u pointer points to the current compilation unit, while units
658 : : for enclosing blocks are stored in c_stack. The u and c_stack are
659 : : managed by compiler_enter_scope() and compiler_exit_scope().
660 : :
661 : : Note that we don't track recursion levels during compilation - the
662 : : task of detecting and rejecting excessive levels of nesting is
663 : : handled by the symbol analysis pass.
664 : :
665 : : */
666 : :
667 : : struct compiler {
668 : : PyObject *c_filename;
669 : : struct symtable *c_st;
670 : : PyFutureFeatures c_future; /* module's __future__ */
671 : : PyCompilerFlags c_flags;
672 : :
673 : : int c_optimize; /* optimization level */
674 : : int c_interactive; /* true if in interactive mode */
675 : : int c_nestlevel;
676 : : PyObject *c_const_cache; /* Python dict holding all constants,
677 : : including names tuple */
678 : : struct compiler_unit *u; /* compiler state for current block */
679 : : PyObject *c_stack; /* Python list holding compiler_unit ptrs */
680 : : PyArena *c_arena; /* pointer to memory allocation arena */
681 : : };
682 : :
683 : : #define INSTR_SEQUENCE(C) (&((C)->u->u_instr_sequence))
684 : :
685 : :
686 : : typedef struct {
687 : : // A list of strings corresponding to name captures. It is used to track:
688 : : // - Repeated name assignments in the same pattern.
689 : : // - Different name assignments in alternatives.
690 : : // - The order of name assignments in alternatives.
691 : : PyObject *stores;
692 : : // If 0, any name captures against our subject will raise.
693 : : int allow_irrefutable;
694 : : // An array of blocks to jump to on failure. Jumping to fail_pop[i] will pop
695 : : // i items off of the stack. The end result looks like this (with each block
696 : : // falling through to the next):
697 : : // fail_pop[4]: POP_TOP
698 : : // fail_pop[3]: POP_TOP
699 : : // fail_pop[2]: POP_TOP
700 : : // fail_pop[1]: POP_TOP
701 : : // fail_pop[0]: NOP
702 : : jump_target_label *fail_pop;
703 : : // The current length of fail_pop.
704 : : Py_ssize_t fail_pop_size;
705 : : // The number of items on top of the stack that need to *stay* on top of the
706 : : // stack. Variable captures go beneath these. All of them will be popped on
707 : : // failure.
708 : : Py_ssize_t on_top;
709 : : } pattern_context;
710 : :
711 : : static int basicblock_next_instr(basicblock *);
712 : :
713 : : static int codegen_addop_i(instr_sequence *seq, int opcode, Py_ssize_t oparg, location loc);
714 : :
715 : : static void compiler_free(struct compiler *);
716 : : static int compiler_error(struct compiler *, location loc, const char *, ...);
717 : : static int compiler_warn(struct compiler *, location loc, const char *, ...);
718 : : static int compiler_nameop(struct compiler *, location, identifier, expr_context_ty);
719 : :
720 : : static PyCodeObject *compiler_mod(struct compiler *, mod_ty);
721 : : static int compiler_visit_stmt(struct compiler *, stmt_ty);
722 : : static int compiler_visit_keyword(struct compiler *, keyword_ty);
723 : : static int compiler_visit_expr(struct compiler *, expr_ty);
724 : : static int compiler_augassign(struct compiler *, stmt_ty);
725 : : static int compiler_annassign(struct compiler *, stmt_ty);
726 : : static int compiler_subscript(struct compiler *, expr_ty);
727 : : static int compiler_slice(struct compiler *, expr_ty);
728 : :
729 : : static bool are_all_items_const(asdl_expr_seq *, Py_ssize_t, Py_ssize_t);
730 : :
731 : :
732 : : static int compiler_with(struct compiler *, stmt_ty, int);
733 : : static int compiler_async_with(struct compiler *, stmt_ty, int);
734 : : static int compiler_async_for(struct compiler *, stmt_ty);
735 : : static int compiler_call_simple_kw_helper(struct compiler *c,
736 : : location loc,
737 : : asdl_keyword_seq *keywords,
738 : : Py_ssize_t nkwelts);
739 : : static int compiler_call_helper(struct compiler *c, location loc,
740 : : int n, asdl_expr_seq *args,
741 : : asdl_keyword_seq *keywords);
742 : : static int compiler_try_except(struct compiler *, stmt_ty);
743 : : static int compiler_try_star_except(struct compiler *, stmt_ty);
744 : : static int compiler_set_qualname(struct compiler *);
745 : :
746 : : static int compiler_sync_comprehension_generator(
747 : : struct compiler *c, location loc,
748 : : asdl_comprehension_seq *generators, int gen_index,
749 : : int depth,
750 : : expr_ty elt, expr_ty val, int type);
751 : :
752 : : static int compiler_async_comprehension_generator(
753 : : struct compiler *c, location loc,
754 : : asdl_comprehension_seq *generators, int gen_index,
755 : : int depth,
756 : : expr_ty elt, expr_ty val, int type);
757 : :
758 : : static int compiler_pattern(struct compiler *, pattern_ty, pattern_context *);
759 : : static int compiler_match(struct compiler *, stmt_ty);
760 : : static int compiler_pattern_subpattern(struct compiler *,
761 : : pattern_ty, pattern_context *);
762 : :
763 : : static int remove_redundant_nops(basicblock *bb);
764 : :
765 : : static PyCodeObject *assemble(struct compiler *, int addNone);
766 : :
767 : : #define CAPSULE_NAME "compile.c compiler unit"
768 : :
769 : :
770 : : static int
771 : 319 : compiler_setup(struct compiler *c, mod_ty mod, PyObject *filename,
772 : : PyCompilerFlags flags, int optimize, PyArena *arena)
773 : : {
774 : 319 : c->c_const_cache = PyDict_New();
775 [ - + ]: 319 : if (!c->c_const_cache) {
776 : 0 : return ERROR;
777 : : }
778 : :
779 : 319 : c->c_stack = PyList_New(0);
780 [ - + ]: 319 : if (!c->c_stack) {
781 : 0 : return ERROR;
782 : : }
783 : :
784 : 319 : c->c_filename = Py_NewRef(filename);
785 : 319 : c->c_arena = arena;
786 [ - + ]: 319 : if (!_PyFuture_FromAST(mod, filename, &c->c_future)) {
787 : 0 : return ERROR;
788 : : }
789 : 319 : int merged = c->c_future.ff_features | flags.cf_flags;
790 : 319 : c->c_future.ff_features = merged;
791 : 319 : flags.cf_flags = merged;
792 : 319 : c->c_flags = flags;
793 [ + + ]: 319 : c->c_optimize = (optimize == -1) ? _Py_GetConfig()->optimization_level : optimize;
794 : 319 : c->c_nestlevel = 0;
795 : :
796 : : _PyASTOptimizeState state;
797 : 319 : state.optimize = c->c_optimize;
798 : 319 : state.ff_features = merged;
799 : :
800 [ - + ]: 319 : if (!_PyAST_Optimize(mod, arena, &state)) {
801 : 0 : return ERROR;
802 : : }
803 : 319 : c->c_st = _PySymtable_Build(mod, filename, &c->c_future);
804 [ - + ]: 319 : if (c->c_st == NULL) {
805 [ # # ]: 0 : if (!PyErr_Occurred()) {
806 : 0 : PyErr_SetString(PyExc_SystemError, "no symtable");
807 : : }
808 : 0 : return ERROR;
809 : : }
810 : 319 : return SUCCESS;
811 : : }
812 : :
813 : : static struct compiler*
814 : 319 : new_compiler(mod_ty mod, PyObject *filename, PyCompilerFlags *pflags,
815 : : int optimize, PyArena *arena)
816 : : {
817 [ + + ]: 319 : PyCompilerFlags flags = pflags ? *pflags : _PyCompilerFlags_INIT;
818 : 319 : struct compiler *c = PyMem_Calloc(1, sizeof(struct compiler));
819 [ - + ]: 319 : if (c == NULL) {
820 : 0 : return NULL;
821 : : }
822 [ - + ]: 319 : if (compiler_setup(c, mod, filename, flags, optimize, arena) < 0) {
823 : 0 : compiler_free(c);
824 : 0 : return NULL;
825 : : }
826 : 319 : return c;
827 : : }
828 : :
829 : : PyCodeObject *
830 : 319 : _PyAST_Compile(mod_ty mod, PyObject *filename, PyCompilerFlags *pflags,
831 : : int optimize, PyArena *arena)
832 : : {
833 : 319 : struct compiler *c = new_compiler(mod, filename, pflags, optimize, arena);
834 [ - + ]: 319 : if (c == NULL) {
835 : 0 : return NULL;
836 : : }
837 : :
838 : 319 : PyCodeObject *co = compiler_mod(c, mod);
839 : 319 : compiler_free(c);
840 : : assert(co || PyErr_Occurred());
841 : 319 : return co;
842 : : }
843 : :
844 : : static void
845 : 319 : compiler_free(struct compiler *c)
846 : : {
847 [ + - ]: 319 : if (c->c_st)
848 : 319 : _PySymtable_Free(c->c_st);
849 : 319 : Py_XDECREF(c->c_filename);
850 : 319 : Py_XDECREF(c->c_const_cache);
851 : 319 : Py_XDECREF(c->c_stack);
852 : 319 : PyMem_Free(c);
853 : 319 : }
854 : :
855 : : static PyObject *
856 : 8041 : list2dict(PyObject *list)
857 : : {
858 : : Py_ssize_t i, n;
859 : : PyObject *v, *k;
860 : 8041 : PyObject *dict = PyDict_New();
861 [ - + ]: 8041 : if (!dict) return NULL;
862 : :
863 : 8041 : n = PyList_Size(list);
864 [ + + ]: 22014 : for (i = 0; i < n; i++) {
865 : 13973 : v = PyLong_FromSsize_t(i);
866 [ - + ]: 13973 : if (!v) {
867 : 0 : Py_DECREF(dict);
868 : 0 : return NULL;
869 : : }
870 : 13973 : k = PyList_GET_ITEM(list, i);
871 [ - + ]: 13973 : if (PyDict_SetItem(dict, k, v) < 0) {
872 : 0 : Py_DECREF(v);
873 : 0 : Py_DECREF(dict);
874 : 0 : return NULL;
875 : : }
876 : 13973 : Py_DECREF(v);
877 : : }
878 : 8041 : return dict;
879 : : }
880 : :
881 : : /* Return new dict containing names from src that match scope(s).
882 : :
883 : : src is a symbol table dictionary. If the scope of a name matches
884 : : either scope_type or flag is set, insert it into the new dict. The
885 : : values are integers, starting at offset and increasing by one for
886 : : each key.
887 : : */
888 : :
889 : : static PyObject *
890 : 16082 : dictbytype(PyObject *src, int scope_type, int flag, Py_ssize_t offset)
891 : : {
892 : 16082 : Py_ssize_t i = offset, scope, num_keys, key_i;
893 : 16082 : PyObject *k, *v, *dest = PyDict_New();
894 : : PyObject *sorted_keys;
895 : :
896 : : assert(offset >= 0);
897 [ - + ]: 16082 : if (dest == NULL)
898 : 0 : return NULL;
899 : :
900 : : /* Sort the keys so that we have a deterministic order on the indexes
901 : : saved in the returned dictionary. These indexes are used as indexes
902 : : into the free and cell var storage. Therefore if they aren't
903 : : deterministic, then the generated bytecode is not deterministic.
904 : : */
905 : 16082 : sorted_keys = PyDict_Keys(src);
906 [ - + ]: 16082 : if (sorted_keys == NULL)
907 : 0 : return NULL;
908 [ - + ]: 16082 : if (PyList_Sort(sorted_keys) != 0) {
909 : 0 : Py_DECREF(sorted_keys);
910 : 0 : return NULL;
911 : : }
912 : 16082 : num_keys = PyList_GET_SIZE(sorted_keys);
913 : :
914 [ + + ]: 118292 : for (key_i = 0; key_i < num_keys; key_i++) {
915 : : /* XXX this should probably be a macro in symtable.h */
916 : : long vi;
917 : 102210 : k = PyList_GET_ITEM(sorted_keys, key_i);
918 : 102210 : v = PyDict_GetItemWithError(src, k);
919 : : assert(v && PyLong_Check(v));
920 : 102210 : vi = PyLong_AS_LONG(v);
921 : 102210 : scope = (vi >> SCOPE_OFFSET) & SCOPE_MASK;
922 : :
923 [ + + - + ]: 102210 : if (scope == scope_type || vi & flag) {
924 : 1525 : PyObject *item = PyLong_FromSsize_t(i);
925 [ - + ]: 1525 : if (item == NULL) {
926 : 0 : Py_DECREF(sorted_keys);
927 : 0 : Py_DECREF(dest);
928 : 0 : return NULL;
929 : : }
930 : 1525 : i++;
931 [ - + ]: 1525 : if (PyDict_SetItem(dest, k, item) < 0) {
932 : 0 : Py_DECREF(sorted_keys);
933 : 0 : Py_DECREF(item);
934 : 0 : Py_DECREF(dest);
935 : 0 : return NULL;
936 : : }
937 : 1525 : Py_DECREF(item);
938 : : }
939 : : }
940 : 16082 : Py_DECREF(sorted_keys);
941 : 16082 : return dest;
942 : : }
943 : :
944 : : #ifndef NDEBUG
945 : : static bool
946 : : cfg_builder_check(cfg_builder *g)
947 : : {
948 : : assert(g->g_entryblock->b_iused > 0);
949 : : for (basicblock *block = g->g_block_list; block != NULL; block = block->b_list) {
950 : : assert(!_PyMem_IsPtrFreed(block));
951 : : if (block->b_instr != NULL) {
952 : : assert(block->b_ialloc > 0);
953 : : assert(block->b_iused >= 0);
954 : : assert(block->b_ialloc >= block->b_iused);
955 : : }
956 : : else {
957 : : assert (block->b_iused == 0);
958 : : assert (block->b_ialloc == 0);
959 : : }
960 : : }
961 : : return true;
962 : : }
963 : : #endif
964 : :
965 : : static basicblock *cfg_builder_new_block(cfg_builder *g);
966 : :
967 : : static int
968 : 8041 : cfg_builder_init(cfg_builder *g)
969 : : {
970 : 8041 : g->g_block_list = NULL;
971 : 8041 : basicblock *block = cfg_builder_new_block(g);
972 [ - + ]: 8041 : if (block == NULL) {
973 : 0 : return ERROR;
974 : : }
975 : 8041 : g->g_curblock = g->g_entryblock = block;
976 : 8041 : g->g_current_label = NO_LABEL;
977 : 8041 : return SUCCESS;
978 : : }
979 : :
980 : : static void
981 : 8041 : cfg_builder_fini(cfg_builder* g)
982 : : {
983 : : assert(cfg_builder_check(g));
984 : 8041 : basicblock *b = g->g_block_list;
985 [ + + ]: 71160 : while (b != NULL) {
986 [ + + ]: 63119 : if (b->b_instr) {
987 : 60469 : PyObject_Free((void *)b->b_instr);
988 : : }
989 : 63119 : basicblock *next = b->b_list;
990 : 63119 : PyObject_Free((void *)b);
991 : 63119 : b = next;
992 : : }
993 : 8041 : }
994 : :
995 : : static void
996 : 8041 : compiler_unit_free(struct compiler_unit *u)
997 : : {
998 : 8041 : instr_sequence_fini(&u->u_instr_sequence);
999 [ + - ]: 8041 : Py_CLEAR(u->u_ste);
1000 [ + - ]: 8041 : Py_CLEAR(u->u_name);
1001 [ + + ]: 8041 : Py_CLEAR(u->u_qualname);
1002 [ + - ]: 8041 : Py_CLEAR(u->u_consts);
1003 [ + - ]: 8041 : Py_CLEAR(u->u_names);
1004 [ + - ]: 8041 : Py_CLEAR(u->u_varnames);
1005 [ + - ]: 8041 : Py_CLEAR(u->u_freevars);
1006 [ + - ]: 8041 : Py_CLEAR(u->u_cellvars);
1007 [ + + ]: 8041 : Py_CLEAR(u->u_private);
1008 : 8041 : PyObject_Free(u);
1009 : 8041 : }
1010 : :
1011 : : static int
1012 : 7722 : compiler_set_qualname(struct compiler *c)
1013 : : {
1014 : : Py_ssize_t stack_size;
1015 : 7722 : struct compiler_unit *u = c->u;
1016 : : PyObject *name, *base;
1017 : :
1018 : 7722 : base = NULL;
1019 : 7722 : stack_size = PyList_GET_SIZE(c->c_stack);
1020 : : assert(stack_size >= 1);
1021 [ + + ]: 7722 : if (stack_size > 1) {
1022 : 4981 : int scope, force_global = 0;
1023 : : struct compiler_unit *parent;
1024 : : PyObject *mangled, *capsule;
1025 : :
1026 : 4981 : capsule = PyList_GET_ITEM(c->c_stack, stack_size - 1);
1027 : 4981 : parent = (struct compiler_unit *)PyCapsule_GetPointer(capsule, CAPSULE_NAME);
1028 : : assert(parent);
1029 : :
1030 [ + + ]: 4981 : if (u->u_scope_type == COMPILER_SCOPE_FUNCTION
1031 [ + + ]: 655 : || u->u_scope_type == COMPILER_SCOPE_ASYNC_FUNCTION
1032 [ + + ]: 516 : || u->u_scope_type == COMPILER_SCOPE_CLASS) {
1033 : : assert(u->u_name);
1034 : 4494 : mangled = _Py_Mangle(parent->u_private, u->u_name);
1035 [ - + ]: 4494 : if (!mangled) {
1036 : 0 : return ERROR;
1037 : : }
1038 : :
1039 : 4494 : scope = _PyST_GetScope(parent->u_ste, mangled);
1040 : 4494 : Py_DECREF(mangled);
1041 : : assert(scope != GLOBAL_IMPLICIT);
1042 [ - + ]: 4494 : if (scope == GLOBAL_EXPLICIT)
1043 : 0 : force_global = 1;
1044 : : }
1045 : :
1046 [ + - ]: 4981 : if (!force_global) {
1047 [ + + ]: 4981 : if (parent->u_scope_type == COMPILER_SCOPE_FUNCTION
1048 [ + + ]: 4253 : || parent->u_scope_type == COMPILER_SCOPE_ASYNC_FUNCTION
1049 [ - + ]: 4229 : || parent->u_scope_type == COMPILER_SCOPE_LAMBDA)
1050 : : {
1051 : : _Py_DECLARE_STR(dot_locals, ".<locals>");
1052 : 752 : base = PyUnicode_Concat(parent->u_qualname,
1053 : : &_Py_STR(dot_locals));
1054 [ - + ]: 752 : if (base == NULL) {
1055 : 0 : return ERROR;
1056 : : }
1057 : : }
1058 : : else {
1059 : 4229 : base = Py_NewRef(parent->u_qualname);
1060 : : }
1061 : : }
1062 : : }
1063 : :
1064 [ + + ]: 7722 : if (base != NULL) {
1065 : : _Py_DECLARE_STR(dot, ".");
1066 : 4981 : name = PyUnicode_Concat(base, &_Py_STR(dot));
1067 : 4981 : Py_DECREF(base);
1068 [ - + ]: 4981 : if (name == NULL) {
1069 : 0 : return ERROR;
1070 : : }
1071 : 4981 : PyUnicode_Append(&name, u->u_name);
1072 [ - + ]: 4981 : if (name == NULL) {
1073 : 0 : return ERROR;
1074 : : }
1075 : : }
1076 : : else {
1077 : 2741 : name = Py_NewRef(u->u_name);
1078 : : }
1079 : 7722 : u->u_qualname = name;
1080 : :
1081 : 7722 : return SUCCESS;
1082 : : }
1083 : :
1084 : : /* Allocate a new block and return a pointer to it.
1085 : : Returns NULL on error.
1086 : : */
1087 : : static basicblock *
1088 : 63119 : cfg_builder_new_block(cfg_builder *g)
1089 : : {
1090 : 63119 : basicblock *b = (basicblock *)PyObject_Calloc(1, sizeof(basicblock));
1091 [ - + ]: 63119 : if (b == NULL) {
1092 : 0 : PyErr_NoMemory();
1093 : 0 : return NULL;
1094 : : }
1095 : : /* Extend the singly linked list of blocks with new block. */
1096 : 63119 : b->b_list = g->g_block_list;
1097 : 63119 : g->g_block_list = b;
1098 : 63119 : b->b_label = NO_LABEL;
1099 : 63119 : return b;
1100 : : }
1101 : :
1102 : : static basicblock *
1103 : 53526 : cfg_builder_use_next_block(cfg_builder *g, basicblock *block)
1104 : : {
1105 : : assert(block != NULL);
1106 : 53526 : g->g_curblock->b_next = block;
1107 : 53526 : g->g_curblock = block;
1108 : 53526 : return block;
1109 : : }
1110 : :
1111 : : static inline int
1112 : 2669 : basicblock_append_instructions(basicblock *target, basicblock *source)
1113 : : {
1114 [ + + ]: 7754 : for (int i = 0; i < source->b_iused; i++) {
1115 : 5085 : int n = basicblock_next_instr(target);
1116 [ - + ]: 5085 : if (n < 0) {
1117 : 0 : return ERROR;
1118 : : }
1119 : 5085 : target->b_instr[n] = source->b_instr[i];
1120 : : }
1121 : 2669 : return SUCCESS;
1122 : : }
1123 : :
1124 : : static basicblock *
1125 : 514 : copy_basicblock(cfg_builder *g, basicblock *block)
1126 : : {
1127 : : /* Cannot copy a block if it has a fallthrough, since
1128 : : * a block can only have one fallthrough predecessor.
1129 : : */
1130 : : assert(BB_NO_FALLTHROUGH(block));
1131 : 514 : basicblock *result = cfg_builder_new_block(g);
1132 [ - + ]: 514 : if (result == NULL) {
1133 : 0 : return NULL;
1134 : : }
1135 [ - + ]: 514 : if (basicblock_append_instructions(result, block) < 0) {
1136 : 0 : return NULL;
1137 : : }
1138 : 514 : return result;
1139 : : }
1140 : :
1141 : : /* Returns the offset of the next instruction in the current block's
1142 : : b_instr array. Resizes the b_instr as necessary.
1143 : : Returns -1 on failure.
1144 : : */
1145 : :
1146 : : static int
1147 : 395125 : basicblock_next_instr(basicblock *b)
1148 : : {
1149 : : assert(b != NULL);
1150 : :
1151 [ - + ]: 395125 : RETURN_IF_ERROR(
1152 : : ensure_array_large_enough(
1153 : : b->b_iused + 1,
1154 : : (void**)&b->b_instr,
1155 : : &b->b_ialloc,
1156 : : DEFAULT_BLOCK_SIZE,
1157 : : sizeof(struct cfg_instr)));
1158 : :
1159 : 395125 : return b->b_iused++;
1160 : : }
1161 : :
1162 : :
1163 : : /* Return the stack effect of opcode with argument oparg.
1164 : :
1165 : : Some opcodes have different stack effect when jump to the target and
1166 : : when not jump. The 'jump' parameter specifies the case:
1167 : :
1168 : : * 0 -- when not jump
1169 : : * 1 -- when jump
1170 : : * -1 -- maximal
1171 : : */
1172 : : static int
1173 : 374600 : stack_effect(int opcode, int oparg, int jump)
1174 : : {
1175 [ + - + + ]: 374600 : if (0 <= opcode && opcode <= MAX_REAL_OPCODE) {
1176 [ - + ]: 351088 : if (_PyOpcode_Deopt[opcode] != opcode) {
1177 : : // Specialized instructions are not supported.
1178 : 0 : return PY_INVALID_STACK_EFFECT;
1179 : : }
1180 : : int popped, pushed;
1181 [ + + ]: 351088 : if (jump > 0) {
1182 : 15669 : popped = _PyOpcode_num_popped(opcode, oparg, true);
1183 : 15669 : pushed = _PyOpcode_num_pushed(opcode, oparg, true);
1184 : : }
1185 : : else {
1186 : 335419 : popped = _PyOpcode_num_popped(opcode, oparg, false);
1187 : 335419 : pushed = _PyOpcode_num_pushed(opcode, oparg, false);
1188 : : }
1189 [ + - - + ]: 351088 : if (popped < 0 || pushed < 0) {
1190 : 0 : return PY_INVALID_STACK_EFFECT;
1191 : : }
1192 [ + - ]: 351088 : if (jump >= 0) {
1193 : 351088 : return pushed - popped;
1194 : : }
1195 [ # # ]: 0 : if (jump < 0) {
1196 : : // Compute max(pushed - popped, alt_pushed - alt_popped)
1197 : 0 : int alt_popped = _PyOpcode_num_popped(opcode, oparg, true);
1198 : 0 : int alt_pushed = _PyOpcode_num_pushed(opcode, oparg, true);
1199 [ # # # # ]: 0 : if (alt_popped < 0 || alt_pushed < 0) {
1200 : 0 : return PY_INVALID_STACK_EFFECT;
1201 : : }
1202 : 0 : int diff = pushed - popped;
1203 : 0 : int alt_diff = alt_pushed - alt_popped;
1204 [ # # ]: 0 : if (alt_diff > diff) {
1205 : 0 : return alt_diff;
1206 : : }
1207 : 0 : return diff;
1208 : : }
1209 : : }
1210 : :
1211 : : // Pseudo ops
1212 [ + + + + : 23512 : switch (opcode) {
- - ]
1213 : 14050 : case POP_BLOCK:
1214 : : case JUMP:
1215 : : case JUMP_NO_INTERRUPT:
1216 : 14050 : return 0;
1217 : :
1218 : : /* Exception handling pseudo-instructions */
1219 : 3352 : case SETUP_FINALLY:
1220 : : /* 0 in the normal flow.
1221 : : * Restore the stack position and push 1 value before jumping to
1222 : : * the handler if an exception be raised. */
1223 : 3352 : return jump ? 1 : 0;
1224 : 5332 : case SETUP_CLEANUP:
1225 : : /* As SETUP_FINALLY, but pushes lasti as well */
1226 [ + + ]: 5332 : return jump ? 2 : 0;
1227 : 778 : case SETUP_WITH:
1228 : : /* 0 in the normal flow.
1229 : : * Restore the stack position to the position before the result
1230 : : * of __(a)enter__ and push 2 values before jumping to the handler
1231 : : * if an exception be raised. */
1232 : 778 : return jump ? 1 : 0;
1233 : :
1234 : 0 : case LOAD_METHOD:
1235 : 0 : return 1;
1236 : 0 : default:
1237 : 0 : return PY_INVALID_STACK_EFFECT;
1238 : : }
1239 : :
1240 : : return PY_INVALID_STACK_EFFECT; /* not reachable */
1241 : : }
1242 : :
1243 : : int
1244 : 0 : PyCompile_OpcodeStackEffectWithJump(int opcode, int oparg, int jump)
1245 : : {
1246 : 0 : return stack_effect(opcode, oparg, jump);
1247 : : }
1248 : :
1249 : : int
1250 : 0 : PyCompile_OpcodeStackEffect(int opcode, int oparg)
1251 : : {
1252 : 0 : return stack_effect(opcode, oparg, -1);
1253 : : }
1254 : :
1255 : : static int
1256 : 387650 : basicblock_addop(basicblock *b, int opcode, int oparg, location loc)
1257 : : {
1258 : : assert(IS_WITHIN_OPCODE_RANGE(opcode));
1259 : : assert(!IS_ASSEMBLER_OPCODE(opcode));
1260 : : assert(HAS_ARG(opcode) || HAS_TARGET(opcode) || oparg == 0);
1261 : : assert(0 <= oparg && oparg < (1 << 30));
1262 : :
1263 : 387650 : int off = basicblock_next_instr(b);
1264 [ - + ]: 387650 : if (off < 0) {
1265 : 0 : return ERROR;
1266 : : }
1267 : 387650 : struct cfg_instr *i = &b->b_instr[off];
1268 : 387650 : i->i_opcode = opcode;
1269 : 387650 : i->i_oparg = oparg;
1270 : 387650 : i->i_target = NULL;
1271 : 387650 : i->i_loc = loc;
1272 : :
1273 : 387650 : return SUCCESS;
1274 : : }
1275 : :
1276 : : static bool
1277 : 420209 : cfg_builder_current_block_is_terminated(cfg_builder *g)
1278 : : {
1279 : 420209 : struct cfg_instr *last = basicblock_last_instr(g->g_curblock);
1280 [ + + + + : 420209 : if (last && IS_TERMINATOR_OPCODE(last->i_opcode)) {
+ + + - +
+ + + ]
1281 : 39002 : return true;
1282 : : }
1283 [ + + ]: 381207 : if (IS_LABEL(g->g_current_label)) {
1284 [ + + + - ]: 14524 : if (last || IS_LABEL(g->g_curblock->b_label)) {
1285 : 14524 : return true;
1286 : : }
1287 : : else {
1288 : : /* current block is empty, label it */
1289 : 0 : g->g_curblock->b_label = g->g_current_label;
1290 : 0 : g->g_current_label = NO_LABEL;
1291 : : }
1292 : : }
1293 : 366683 : return false;
1294 : : }
1295 : :
1296 : : static int
1297 : 420209 : cfg_builder_maybe_start_new_block(cfg_builder *g)
1298 : : {
1299 [ + + ]: 420209 : if (cfg_builder_current_block_is_terminated(g)) {
1300 : 53526 : basicblock *b = cfg_builder_new_block(g);
1301 [ - + ]: 53526 : if (b == NULL) {
1302 : 0 : return ERROR;
1303 : : }
1304 : 53526 : b->b_label = g->g_current_label;
1305 : 53526 : g->g_current_label = NO_LABEL;
1306 : 53526 : cfg_builder_use_next_block(g, b);
1307 : : }
1308 : 420209 : return SUCCESS;
1309 : : }
1310 : :
1311 : : static int
1312 : 67751 : codegen_addop_noarg(instr_sequence *seq, int opcode, location loc)
1313 : : {
1314 : : assert(!HAS_ARG(opcode));
1315 : 67751 : return instr_sequence_addop(seq, opcode, 0, loc);
1316 : : }
1317 : :
1318 : : static Py_ssize_t
1319 : 213543 : dict_add_o(PyObject *dict, PyObject *o)
1320 : : {
1321 : : PyObject *v;
1322 : : Py_ssize_t arg;
1323 : :
1324 : 213543 : v = PyDict_GetItemWithError(dict, o);
1325 [ + + ]: 213543 : if (!v) {
1326 [ - + ]: 102168 : if (PyErr_Occurred()) {
1327 : 0 : return ERROR;
1328 : : }
1329 : 102168 : arg = PyDict_GET_SIZE(dict);
1330 : 102168 : v = PyLong_FromSsize_t(arg);
1331 [ - + ]: 102168 : if (!v) {
1332 : 0 : return ERROR;
1333 : : }
1334 [ - + ]: 102168 : if (PyDict_SetItem(dict, o, v) < 0) {
1335 : 0 : Py_DECREF(v);
1336 : 0 : return ERROR;
1337 : : }
1338 : 102168 : Py_DECREF(v);
1339 : : }
1340 : : else
1341 : 111375 : arg = PyLong_AsLong(v);
1342 : 213543 : return arg;
1343 : : }
1344 : :
1345 : : // Merge const *o* recursively and return constant key object.
1346 : : static PyObject*
1347 : 72196 : merge_consts_recursive(PyObject *const_cache, PyObject *o)
1348 : : {
1349 : : assert(PyDict_CheckExact(const_cache));
1350 : : // None and Ellipsis are singleton, and key is the singleton.
1351 : : // No need to merge object and key.
1352 [ + + + + ]: 72196 : if (o == Py_None || o == Py_Ellipsis) {
1353 : 22062 : return Py_NewRef(o);
1354 : : }
1355 : :
1356 : 50134 : PyObject *key = _PyCode_ConstantKey(o);
1357 [ - + ]: 50134 : if (key == NULL) {
1358 : 0 : return NULL;
1359 : : }
1360 : :
1361 : : // t is borrowed reference
1362 : 50134 : PyObject *t = PyDict_SetDefault(const_cache, key, key);
1363 [ + + ]: 50134 : if (t != key) {
1364 : : // o is registered in const_cache. Just use it.
1365 : 8159 : Py_XINCREF(t);
1366 : 8159 : Py_DECREF(key);
1367 : 8159 : return t;
1368 : : }
1369 : :
1370 : : // We registered o in const_cache.
1371 : : // When o is a tuple or frozenset, we want to merge its
1372 : : // items too.
1373 [ + + ]: 41975 : if (PyTuple_CheckExact(o)) {
1374 : 2102 : Py_ssize_t len = PyTuple_GET_SIZE(o);
1375 [ + + ]: 8890 : for (Py_ssize_t i = 0; i < len; i++) {
1376 : 6788 : PyObject *item = PyTuple_GET_ITEM(o, i);
1377 : 6788 : PyObject *u = merge_consts_recursive(const_cache, item);
1378 [ - + ]: 6788 : if (u == NULL) {
1379 : 0 : Py_DECREF(key);
1380 : 0 : return NULL;
1381 : : }
1382 : :
1383 : : // See _PyCode_ConstantKey()
1384 : : PyObject *v; // borrowed
1385 [ + + ]: 6788 : if (PyTuple_CheckExact(u)) {
1386 : 416 : v = PyTuple_GET_ITEM(u, 1);
1387 : : }
1388 : : else {
1389 : 6372 : v = u;
1390 : : }
1391 [ + + ]: 6788 : if (v != item) {
1392 : 830 : PyTuple_SET_ITEM(o, i, Py_NewRef(v));
1393 : 830 : Py_DECREF(item);
1394 : : }
1395 : :
1396 : 6788 : Py_DECREF(u);
1397 : : }
1398 : : }
1399 [ + + ]: 39873 : else if (PyFrozenSet_CheckExact(o)) {
1400 : : // *key* is tuple. And its first item is frozenset of
1401 : : // constant keys.
1402 : : // See _PyCode_ConstantKey() for detail.
1403 : : assert(PyTuple_CheckExact(key));
1404 : : assert(PyTuple_GET_SIZE(key) == 2);
1405 : :
1406 : 36 : Py_ssize_t len = PySet_GET_SIZE(o);
1407 [ - + ]: 36 : if (len == 0) { // empty frozenset should not be re-created.
1408 : 0 : return key;
1409 : : }
1410 : 36 : PyObject *tuple = PyTuple_New(len);
1411 [ - + ]: 36 : if (tuple == NULL) {
1412 : 0 : Py_DECREF(key);
1413 : 0 : return NULL;
1414 : : }
1415 : 36 : Py_ssize_t i = 0, pos = 0;
1416 : : PyObject *item;
1417 : : Py_hash_t hash;
1418 [ + + ]: 160 : while (_PySet_NextEntry(o, &pos, &item, &hash)) {
1419 : 124 : PyObject *k = merge_consts_recursive(const_cache, item);
1420 [ - + ]: 124 : if (k == NULL) {
1421 : 0 : Py_DECREF(tuple);
1422 : 0 : Py_DECREF(key);
1423 : 0 : return NULL;
1424 : : }
1425 : : PyObject *u;
1426 [ - + ]: 124 : if (PyTuple_CheckExact(k)) {
1427 : 0 : u = Py_NewRef(PyTuple_GET_ITEM(k, 1));
1428 : 0 : Py_DECREF(k);
1429 : : }
1430 : : else {
1431 : 124 : u = k;
1432 : : }
1433 : 124 : PyTuple_SET_ITEM(tuple, i, u); // Steals reference of u.
1434 : 124 : i++;
1435 : : }
1436 : :
1437 : : // Instead of rewriting o, we create new frozenset and embed in the
1438 : : // key tuple. Caller should get merged frozenset from the key tuple.
1439 : 36 : PyObject *new = PyFrozenSet_New(tuple);
1440 : 36 : Py_DECREF(tuple);
1441 [ - + ]: 36 : if (new == NULL) {
1442 : 0 : Py_DECREF(key);
1443 : 0 : return NULL;
1444 : : }
1445 : : assert(PyTuple_GET_ITEM(key, 1) == o);
1446 : 36 : Py_DECREF(o);
1447 : 36 : PyTuple_SET_ITEM(key, 1, new);
1448 : : }
1449 : :
1450 : 41975 : return key;
1451 : : }
1452 : :
1453 : : static Py_ssize_t
1454 : 65284 : compiler_add_const(PyObject *const_cache, struct compiler_unit *u, PyObject *o)
1455 : : {
1456 : : assert(PyDict_CheckExact(const_cache));
1457 : 65284 : PyObject *key = merge_consts_recursive(const_cache, o);
1458 [ - + ]: 65284 : if (key == NULL) {
1459 : 0 : return ERROR;
1460 : : }
1461 : :
1462 : 65284 : Py_ssize_t arg = dict_add_o(u->u_consts, key);
1463 : 65284 : Py_DECREF(key);
1464 : 65284 : return arg;
1465 : : }
1466 : :
1467 : : static int
1468 : 57553 : compiler_addop_load_const(PyObject *const_cache, struct compiler_unit *u, location loc, PyObject *o)
1469 : : {
1470 : 57553 : Py_ssize_t arg = compiler_add_const(const_cache, u, o);
1471 [ - + ]: 57553 : if (arg < 0) {
1472 : 0 : return ERROR;
1473 : : }
1474 : 57553 : return codegen_addop_i(&u->u_instr_sequence, LOAD_CONST, arg, loc);
1475 : : }
1476 : :
1477 : : static int
1478 : 71669 : compiler_addop_o(struct compiler_unit *u, location loc,
1479 : : int opcode, PyObject *dict, PyObject *o)
1480 : : {
1481 : 71669 : Py_ssize_t arg = dict_add_o(dict, o);
1482 [ - + ]: 71669 : if (arg < 0) {
1483 : 0 : return ERROR;
1484 : : }
1485 : 71669 : return codegen_addop_i(&u->u_instr_sequence, opcode, arg, loc);
1486 : : }
1487 : :
1488 : : static int
1489 : 32372 : compiler_addop_name(struct compiler_unit *u, location loc,
1490 : : int opcode, PyObject *dict, PyObject *o)
1491 : : {
1492 : 32372 : PyObject *mangled = _Py_Mangle(u->u_private, o);
1493 [ - + ]: 32372 : if (!mangled) {
1494 : 0 : return ERROR;
1495 : : }
1496 : 32372 : Py_ssize_t arg = dict_add_o(dict, mangled);
1497 : 32372 : Py_DECREF(mangled);
1498 [ - + ]: 32372 : if (arg < 0) {
1499 : 0 : return ERROR;
1500 : : }
1501 [ + + ]: 32372 : if (opcode == LOAD_ATTR) {
1502 : 16077 : arg <<= 1;
1503 : : }
1504 [ + + ]: 32372 : if (opcode == LOAD_METHOD) {
1505 : 11010 : opcode = LOAD_ATTR;
1506 : 11010 : arg <<= 1;
1507 : 11010 : arg |= 1;
1508 : : }
1509 : 32372 : return codegen_addop_i(&u->u_instr_sequence, opcode, arg, loc);
1510 : : }
1511 : :
1512 : : /* Add an opcode with an integer argument */
1513 : : static int
1514 : 289336 : codegen_addop_i(instr_sequence *seq, int opcode, Py_ssize_t oparg, location loc)
1515 : : {
1516 : : /* oparg value is unsigned, but a signed C int is usually used to store
1517 : : it in the C code (like Python/ceval.c).
1518 : :
1519 : : Limit to 32-bit signed C int (rather than INT_MAX) for portability.
1520 : :
1521 : : The argument of a concrete bytecode instruction is limited to 8-bit.
1522 : : EXTENDED_ARG is used for 16, 24, and 32-bit arguments. */
1523 : :
1524 : 289336 : int oparg_ = Py_SAFE_DOWNCAST(oparg, Py_ssize_t, int);
1525 : 289336 : return instr_sequence_addop(seq, opcode, oparg_, loc);
1526 : : }
1527 : :
1528 : : static int
1529 : 28995 : codegen_addop_j(instr_sequence *seq, location loc,
1530 : : int opcode, jump_target_label target)
1531 : : {
1532 : : assert(IS_LABEL(target));
1533 : : assert(IS_JUMP_OPCODE(opcode) || IS_BLOCK_PUSH_OPCODE(opcode));
1534 : 28995 : return instr_sequence_addop(seq, opcode, target.id, loc);
1535 : : }
1536 : :
1537 : : #define ADDOP(C, LOC, OP) \
1538 : : RETURN_IF_ERROR(codegen_addop_noarg(INSTR_SEQUENCE(C), (OP), (LOC)))
1539 : :
1540 : : #define ADDOP_IN_SCOPE(C, LOC, OP) { \
1541 : : if (codegen_addop_noarg(INSTR_SEQUENCE(C), (OP), (LOC)) < 0) { \
1542 : : compiler_exit_scope(C); \
1543 : : return ERROR; \
1544 : : } \
1545 : : }
1546 : :
1547 : : #define ADDOP_LOAD_CONST(C, LOC, O) \
1548 : : RETURN_IF_ERROR(compiler_addop_load_const((C)->c_const_cache, (C)->u, (LOC), (O)))
1549 : :
1550 : : /* Same as ADDOP_LOAD_CONST, but steals a reference. */
1551 : : #define ADDOP_LOAD_CONST_NEW(C, LOC, O) { \
1552 : : PyObject *__new_const = (O); \
1553 : : if (__new_const == NULL) { \
1554 : : return ERROR; \
1555 : : } \
1556 : : if (compiler_addop_load_const((C)->c_const_cache, (C)->u, (LOC), __new_const) < 0) { \
1557 : : Py_DECREF(__new_const); \
1558 : : return ERROR; \
1559 : : } \
1560 : : Py_DECREF(__new_const); \
1561 : : }
1562 : :
1563 : : #define ADDOP_N(C, LOC, OP, O, TYPE) { \
1564 : : assert(!HAS_CONST(OP)); /* use ADDOP_LOAD_CONST_NEW */ \
1565 : : if (compiler_addop_o((C)->u, (LOC), (OP), (C)->u->u_ ## TYPE, (O)) < 0) { \
1566 : : Py_DECREF((O)); \
1567 : : return ERROR; \
1568 : : } \
1569 : : Py_DECREF((O)); \
1570 : : }
1571 : :
1572 : : #define ADDOP_NAME(C, LOC, OP, O, TYPE) \
1573 : : RETURN_IF_ERROR(compiler_addop_name((C)->u, (LOC), (OP), (C)->u->u_ ## TYPE, (O)))
1574 : :
1575 : : #define ADDOP_I(C, LOC, OP, O) \
1576 : : RETURN_IF_ERROR(codegen_addop_i(INSTR_SEQUENCE(C), (OP), (O), (LOC)))
1577 : :
1578 : : #define ADDOP_JUMP(C, LOC, OP, O) \
1579 : : RETURN_IF_ERROR(codegen_addop_j(INSTR_SEQUENCE(C), (LOC), (OP), (O)))
1580 : :
1581 : : #define ADDOP_COMPARE(C, LOC, CMP) \
1582 : : RETURN_IF_ERROR(compiler_addcompare((C), (LOC), (cmpop_ty)(CMP)))
1583 : :
1584 : : #define ADDOP_BINARY(C, LOC, BINOP) \
1585 : : RETURN_IF_ERROR(addop_binary((C), (LOC), (BINOP), false))
1586 : :
1587 : : #define ADDOP_INPLACE(C, LOC, BINOP) \
1588 : : RETURN_IF_ERROR(addop_binary((C), (LOC), (BINOP), true))
1589 : :
1590 : : #define ADD_YIELD_FROM(C, LOC, await) \
1591 : : RETURN_IF_ERROR(compiler_add_yield_from((C), (LOC), (await)))
1592 : :
1593 : : #define POP_EXCEPT_AND_RERAISE(C, LOC) \
1594 : : RETURN_IF_ERROR(compiler_pop_except_and_reraise((C), (LOC)))
1595 : :
1596 : : #define ADDOP_YIELD(C, LOC) \
1597 : : RETURN_IF_ERROR(addop_yield((C), (LOC)))
1598 : :
1599 : : /* VISIT and VISIT_SEQ takes an ASDL type as their second argument. They use
1600 : : the ASDL name to synthesize the name of the C type and the visit function.
1601 : : */
1602 : :
1603 : : #define VISIT(C, TYPE, V) \
1604 : : RETURN_IF_ERROR(compiler_visit_ ## TYPE((C), (V)));
1605 : :
1606 : : #define VISIT_IN_SCOPE(C, TYPE, V) {\
1607 : : if (compiler_visit_ ## TYPE((C), (V)) < 0) { \
1608 : : compiler_exit_scope(C); \
1609 : : return ERROR; \
1610 : : } \
1611 : : }
1612 : :
1613 : : #define VISIT_SEQ(C, TYPE, SEQ) { \
1614 : : int _i; \
1615 : : asdl_ ## TYPE ## _seq *seq = (SEQ); /* avoid variable capture */ \
1616 : : for (_i = 0; _i < asdl_seq_LEN(seq); _i++) { \
1617 : : TYPE ## _ty elt = (TYPE ## _ty)asdl_seq_GET(seq, _i); \
1618 : : RETURN_IF_ERROR(compiler_visit_ ## TYPE((C), elt)); \
1619 : : } \
1620 : : }
1621 : :
1622 : : #define VISIT_SEQ_IN_SCOPE(C, TYPE, SEQ) { \
1623 : : int _i; \
1624 : : asdl_ ## TYPE ## _seq *seq = (SEQ); /* avoid variable capture */ \
1625 : : for (_i = 0; _i < asdl_seq_LEN(seq); _i++) { \
1626 : : TYPE ## _ty elt = (TYPE ## _ty)asdl_seq_GET(seq, _i); \
1627 : : if (compiler_visit_ ## TYPE((C), elt) < 0) { \
1628 : : compiler_exit_scope(C); \
1629 : : return ERROR; \
1630 : : } \
1631 : : } \
1632 : : }
1633 : :
1634 : :
1635 : : static int
1636 : 8041 : compiler_enter_scope(struct compiler *c, identifier name,
1637 : : int scope_type, void *key, int lineno)
1638 : : {
1639 : 8041 : location loc = LOCATION(lineno, lineno, 0, 0);
1640 : :
1641 : : struct compiler_unit *u;
1642 : :
1643 : 8041 : u = (struct compiler_unit *)PyObject_Calloc(1, sizeof(
1644 : : struct compiler_unit));
1645 [ - + ]: 8041 : if (!u) {
1646 : 0 : PyErr_NoMemory();
1647 : 0 : return ERROR;
1648 : : }
1649 : 8041 : u->u_scope_type = scope_type;
1650 : 8041 : u->u_argcount = 0;
1651 : 8041 : u->u_posonlyargcount = 0;
1652 : 8041 : u->u_kwonlyargcount = 0;
1653 : 8041 : u->u_ste = PySymtable_Lookup(c->c_st, key);
1654 [ - + ]: 8041 : if (!u->u_ste) {
1655 : 0 : compiler_unit_free(u);
1656 : 0 : return ERROR;
1657 : : }
1658 : 8041 : u->u_name = Py_NewRef(name);
1659 : 8041 : u->u_varnames = list2dict(u->u_ste->ste_varnames);
1660 : 8041 : u->u_cellvars = dictbytype(u->u_ste->ste_symbols, CELL, 0, 0);
1661 [ + - - + ]: 8041 : if (!u->u_varnames || !u->u_cellvars) {
1662 : 0 : compiler_unit_free(u);
1663 : 0 : return ERROR;
1664 : : }
1665 [ + + ]: 8041 : if (u->u_ste->ste_needs_class_closure) {
1666 : : /* Cook up an implicit __class__ cell. */
1667 : : int res;
1668 : : assert(u->u_scope_type == COMPILER_SCOPE_CLASS);
1669 : : assert(PyDict_GET_SIZE(u->u_cellvars) == 0);
1670 : 112 : res = PyDict_SetItem(u->u_cellvars, &_Py_ID(__class__),
1671 : : _PyLong_GetZero());
1672 [ - + ]: 112 : if (res < 0) {
1673 : 0 : compiler_unit_free(u);
1674 : 0 : return ERROR;
1675 : : }
1676 : : }
1677 : :
1678 : 8041 : u->u_freevars = dictbytype(u->u_ste->ste_symbols, FREE, DEF_FREE_CLASS,
1679 : : PyDict_GET_SIZE(u->u_cellvars));
1680 [ - + ]: 8041 : if (!u->u_freevars) {
1681 : 0 : compiler_unit_free(u);
1682 : 0 : return ERROR;
1683 : : }
1684 : :
1685 : 8041 : u->u_nfblocks = 0;
1686 : 8041 : u->u_firstlineno = lineno;
1687 : 8041 : u->u_consts = PyDict_New();
1688 [ - + ]: 8041 : if (!u->u_consts) {
1689 : 0 : compiler_unit_free(u);
1690 : 0 : return ERROR;
1691 : : }
1692 : 8041 : u->u_names = PyDict_New();
1693 [ - + ]: 8041 : if (!u->u_names) {
1694 : 0 : compiler_unit_free(u);
1695 : 0 : return ERROR;
1696 : : }
1697 : :
1698 : 8041 : u->u_private = NULL;
1699 : :
1700 : : /* Push the old compiler_unit on the stack. */
1701 [ + + ]: 8041 : if (c->u) {
1702 : 7722 : PyObject *capsule = PyCapsule_New(c->u, CAPSULE_NAME, NULL);
1703 [ + - - + ]: 7722 : if (!capsule || PyList_Append(c->c_stack, capsule) < 0) {
1704 : 0 : Py_XDECREF(capsule);
1705 : 0 : compiler_unit_free(u);
1706 : 0 : return ERROR;
1707 : : }
1708 : 7722 : Py_DECREF(capsule);
1709 : 7722 : u->u_private = Py_XNewRef(c->u->u_private);
1710 : : }
1711 : 8041 : c->u = u;
1712 : :
1713 : 8041 : c->c_nestlevel++;
1714 : :
1715 [ + + ]: 8041 : if (u->u_scope_type == COMPILER_SCOPE_MODULE) {
1716 : 319 : loc.lineno = 0;
1717 : : }
1718 : : else {
1719 [ - + ]: 7722 : RETURN_IF_ERROR(compiler_set_qualname(c));
1720 : : }
1721 [ - + ]: 8041 : ADDOP_I(c, loc, RESUME, 0);
1722 : :
1723 [ + + ]: 8041 : if (u->u_scope_type == COMPILER_SCOPE_MODULE) {
1724 : 319 : loc.lineno = -1;
1725 : : }
1726 : 8041 : return SUCCESS;
1727 : : }
1728 : :
1729 : : static void
1730 : 8041 : compiler_exit_scope(struct compiler *c)
1731 : : {
1732 : : // Don't call PySequence_DelItem() with an exception raised
1733 : 8041 : PyObject *exc = PyErr_GetRaisedException();
1734 : :
1735 : 8041 : c->c_nestlevel--;
1736 : 8041 : compiler_unit_free(c->u);
1737 : : /* Restore c->u to the parent unit. */
1738 : 8041 : Py_ssize_t n = PyList_GET_SIZE(c->c_stack) - 1;
1739 [ + + ]: 8041 : if (n >= 0) {
1740 : 7722 : PyObject *capsule = PyList_GET_ITEM(c->c_stack, n);
1741 : 7722 : c->u = (struct compiler_unit *)PyCapsule_GetPointer(capsule, CAPSULE_NAME);
1742 : : assert(c->u);
1743 : : /* we are deleting from a list so this really shouldn't fail */
1744 [ - + ]: 7722 : if (PySequence_DelItem(c->c_stack, n) < 0) {
1745 : 0 : _PyErr_WriteUnraisableMsg("on removing the last compiler "
1746 : : "stack item", NULL);
1747 : : }
1748 : : }
1749 : : else {
1750 : 319 : c->u = NULL;
1751 : : }
1752 : :
1753 : 8041 : PyErr_SetRaisedException(exc);
1754 : 8041 : }
1755 : :
1756 : : /* Search if variable annotations are present statically in a block. */
1757 : :
1758 : : static bool
1759 : 2106 : find_ann(asdl_stmt_seq *stmts)
1760 : : {
1761 : 2106 : int i, j, res = 0;
1762 : : stmt_ty st;
1763 : :
1764 [ + + + + ]: 14783 : for (i = 0; i < asdl_seq_LEN(stmts); i++) {
1765 : 12678 : st = (stmt_ty)asdl_seq_GET(stmts, i);
1766 [ + + - + : 12678 : switch (st->kind) {
+ + - + -
+ ]
1767 : 1 : case AnnAssign_kind:
1768 : 1 : return true;
1769 : 34 : case For_kind:
1770 [ + - - + ]: 68 : res = find_ann(st->v.For.body) ||
1771 : 34 : find_ann(st->v.For.orelse);
1772 : 34 : break;
1773 : 0 : case AsyncFor_kind:
1774 [ # # # # ]: 0 : res = find_ann(st->v.AsyncFor.body) ||
1775 : 0 : find_ann(st->v.AsyncFor.orelse);
1776 : 0 : break;
1777 : 1 : case While_kind:
1778 [ + - - + ]: 2 : res = find_ann(st->v.While.body) ||
1779 : 1 : find_ann(st->v.While.orelse);
1780 : 1 : break;
1781 : 310 : case If_kind:
1782 [ + - - + ]: 620 : res = find_ann(st->v.If.body) ||
1783 : 310 : find_ann(st->v.If.orelse);
1784 : 310 : break;
1785 : 1 : case With_kind:
1786 : 1 : res = find_ann(st->v.With.body);
1787 : 1 : break;
1788 : 0 : case AsyncWith_kind:
1789 : 0 : res = find_ann(st->v.AsyncWith.body);
1790 : 0 : break;
1791 : 105 : case Try_kind:
1792 [ + + + + ]: 210 : for (j = 0; j < asdl_seq_LEN(st->v.Try.handlers); j++) {
1793 : 105 : excepthandler_ty handler = (excepthandler_ty)asdl_seq_GET(
1794 : : st->v.Try.handlers, j);
1795 [ - + ]: 105 : if (find_ann(handler->v.ExceptHandler.body)) {
1796 : 0 : return true;
1797 : : }
1798 : : }
1799 [ + - ]: 210 : res = find_ann(st->v.Try.body) ||
1800 [ + - - + ]: 210 : find_ann(st->v.Try.finalbody) ||
1801 : 105 : find_ann(st->v.Try.orelse);
1802 : 105 : break;
1803 : 0 : case TryStar_kind:
1804 [ # # # # ]: 0 : for (j = 0; j < asdl_seq_LEN(st->v.TryStar.handlers); j++) {
1805 : 0 : excepthandler_ty handler = (excepthandler_ty)asdl_seq_GET(
1806 : : st->v.TryStar.handlers, j);
1807 [ # # ]: 0 : if (find_ann(handler->v.ExceptHandler.body)) {
1808 : 0 : return true;
1809 : : }
1810 : : }
1811 [ # # ]: 0 : res = find_ann(st->v.TryStar.body) ||
1812 [ # # # # ]: 0 : find_ann(st->v.TryStar.finalbody) ||
1813 : 0 : find_ann(st->v.TryStar.orelse);
1814 : 0 : break;
1815 : 12226 : default:
1816 : 12226 : res = false;
1817 : : }
1818 [ - + ]: 12677 : if (res) {
1819 : 0 : break;
1820 : : }
1821 : : }
1822 : 2105 : return res;
1823 : : }
1824 : :
1825 : : /*
1826 : : * Frame block handling functions
1827 : : */
1828 : :
1829 : : static int
1830 : 6394 : compiler_push_fblock(struct compiler *c, location loc,
1831 : : enum fblocktype t, jump_target_label block_label,
1832 : : jump_target_label exit, void *datum)
1833 : : {
1834 : : struct fblockinfo *f;
1835 [ - + ]: 6394 : if (c->u->u_nfblocks >= CO_MAXBLOCKS) {
1836 : 0 : return compiler_error(c, loc, "too many statically nested blocks");
1837 : : }
1838 : 6394 : f = &c->u->u_fblock[c->u->u_nfblocks++];
1839 : 6394 : f->fb_type = t;
1840 : 6394 : f->fb_block = block_label;
1841 : 6394 : f->fb_exit = exit;
1842 : 6394 : f->fb_datum = datum;
1843 : 6394 : return SUCCESS;
1844 : : }
1845 : :
1846 : : static void
1847 : 6394 : compiler_pop_fblock(struct compiler *c, enum fblocktype t, jump_target_label block_label)
1848 : : {
1849 : 6394 : struct compiler_unit *u = c->u;
1850 : : assert(u->u_nfblocks > 0);
1851 : 6394 : u->u_nfblocks--;
1852 : : assert(u->u_fblock[u->u_nfblocks].fb_type == t);
1853 : : assert(SAME_LABEL(u->u_fblock[u->u_nfblocks].fb_block, block_label));
1854 : 6394 : }
1855 : :
1856 : : static int
1857 : 481 : compiler_call_exit_with_nones(struct compiler *c, location loc)
1858 : : {
1859 [ - + ]: 481 : ADDOP_LOAD_CONST(c, loc, Py_None);
1860 [ - + ]: 481 : ADDOP_LOAD_CONST(c, loc, Py_None);
1861 [ - + ]: 481 : ADDOP_LOAD_CONST(c, loc, Py_None);
1862 [ - + ]: 481 : ADDOP_I(c, loc, CALL, 2);
1863 : 481 : return SUCCESS;
1864 : : }
1865 : :
1866 : : static int
1867 : 195 : compiler_add_yield_from(struct compiler *c, location loc, int await)
1868 : : {
1869 [ - + ]: 195 : NEW_JUMP_TARGET_LABEL(c, send);
1870 [ - + ]: 195 : NEW_JUMP_TARGET_LABEL(c, fail);
1871 [ - + ]: 195 : NEW_JUMP_TARGET_LABEL(c, exit);
1872 : :
1873 [ - + ]: 195 : USE_LABEL(c, send);
1874 [ - + ]: 195 : ADDOP_JUMP(c, loc, SEND, exit);
1875 : : // Set up a virtual try/except to handle when StopIteration is raised during
1876 : : // a close or throw call. The only way YIELD_VALUE raises if they do!
1877 [ - + ]: 195 : ADDOP_JUMP(c, loc, SETUP_FINALLY, fail);
1878 [ - + ]: 195 : ADDOP_I(c, loc, YIELD_VALUE, 0);
1879 [ - + ]: 195 : ADDOP(c, NO_LOCATION, POP_BLOCK);
1880 [ + + - + ]: 195 : ADDOP_I(c, loc, RESUME, await ? 3 : 2);
1881 [ - + ]: 195 : ADDOP_JUMP(c, loc, JUMP_NO_INTERRUPT, send);
1882 : :
1883 [ - + ]: 195 : USE_LABEL(c, fail);
1884 [ - + ]: 195 : ADDOP(c, loc, CLEANUP_THROW);
1885 : :
1886 [ - + ]: 195 : USE_LABEL(c, exit);
1887 [ - + ]: 195 : ADDOP_I(c, loc, SWAP, 2);
1888 [ - + ]: 195 : ADDOP(c, loc, POP_TOP);
1889 : 195 : return SUCCESS;
1890 : : }
1891 : :
1892 : : static int
1893 : 1878 : compiler_pop_except_and_reraise(struct compiler *c, location loc)
1894 : : {
1895 : : /* Stack contents
1896 : : * [exc_info, lasti, exc] COPY 3
1897 : : * [exc_info, lasti, exc, exc_info] POP_EXCEPT
1898 : : * [exc_info, lasti, exc] RERAISE 1
1899 : : * (exception_unwind clears the stack)
1900 : : */
1901 : :
1902 [ - + ]: 1878 : ADDOP_I(c, loc, COPY, 3);
1903 [ - + ]: 1878 : ADDOP(c, loc, POP_EXCEPT);
1904 [ - + ]: 1878 : ADDOP_I(c, loc, RERAISE, 1);
1905 : 1878 : return SUCCESS;
1906 : : }
1907 : :
1908 : : /* Unwind a frame block. If preserve_tos is true, the TOS before
1909 : : * popping the blocks will be restored afterwards, unless another
1910 : : * return, break or continue is found. In which case, the TOS will
1911 : : * be popped.
1912 : : */
1913 : : static int
1914 : 1586 : compiler_unwind_fblock(struct compiler *c, location *ploc,
1915 : : struct fblockinfo *info, int preserve_tos)
1916 : : {
1917 [ + + + + : 1586 : switch (info->fb_type) {
+ + + -
- ]
1918 : 606 : case WHILE_LOOP:
1919 : : case EXCEPTION_HANDLER:
1920 : : case EXCEPTION_GROUP_HANDLER:
1921 : : case ASYNC_COMPREHENSION_GENERATOR:
1922 : 606 : return SUCCESS;
1923 : :
1924 : 224 : case FOR_LOOP:
1925 : : /* Pop the iterator */
1926 [ + + ]: 224 : if (preserve_tos) {
1927 [ - + ]: 71 : ADDOP_I(c, *ploc, SWAP, 2);
1928 : : }
1929 [ - + ]: 224 : ADDOP(c, *ploc, POP_TOP);
1930 : 224 : return SUCCESS;
1931 : :
1932 : 223 : case TRY_EXCEPT:
1933 [ - + ]: 223 : ADDOP(c, *ploc, POP_BLOCK);
1934 : 223 : return SUCCESS;
1935 : :
1936 : 49 : case FINALLY_TRY:
1937 : : /* This POP_BLOCK gets the line number of the unwinding statement */
1938 [ - + ]: 49 : ADDOP(c, *ploc, POP_BLOCK);
1939 [ + + ]: 49 : if (preserve_tos) {
1940 [ - + ]: 44 : RETURN_IF_ERROR(
1941 : : compiler_push_fblock(c, *ploc, POP_VALUE, NO_LABEL, NO_LABEL, NULL));
1942 : : }
1943 : : /* Emit the finally block */
1944 [ - + + - : 122 : VISIT_SEQ(c, stmt, info->fb_datum);
+ + ]
1945 [ + + ]: 49 : if (preserve_tos) {
1946 : 44 : compiler_pop_fblock(c, POP_VALUE, NO_LABEL);
1947 : : }
1948 : : /* The finally block should appear to execute after the
1949 : : * statement causing the unwinding, so make the unwinding
1950 : : * instruction artificial */
1951 : 49 : *ploc = NO_LOCATION;
1952 : 49 : return SUCCESS;
1953 : :
1954 : 1 : case FINALLY_END:
1955 [ - + ]: 1 : if (preserve_tos) {
1956 [ # # ]: 0 : ADDOP_I(c, *ploc, SWAP, 2);
1957 : : }
1958 [ - + ]: 1 : ADDOP(c, *ploc, POP_TOP); /* exc_value */
1959 [ - + ]: 1 : if (preserve_tos) {
1960 [ # # ]: 0 : ADDOP_I(c, *ploc, SWAP, 2);
1961 : : }
1962 [ - + ]: 1 : ADDOP(c, *ploc, POP_BLOCK);
1963 [ - + ]: 1 : ADDOP(c, *ploc, POP_EXCEPT);
1964 : 1 : return SUCCESS;
1965 : :
1966 : 92 : case WITH:
1967 : : case ASYNC_WITH:
1968 : 92 : *ploc = LOC((stmt_ty)info->fb_datum);
1969 [ - + ]: 92 : ADDOP(c, *ploc, POP_BLOCK);
1970 [ + + ]: 92 : if (preserve_tos) {
1971 [ - + ]: 76 : ADDOP_I(c, *ploc, SWAP, 2);
1972 : : }
1973 [ - + ]: 92 : RETURN_IF_ERROR(compiler_call_exit_with_nones(c, *ploc));
1974 [ + + ]: 92 : if (info->fb_type == ASYNC_WITH) {
1975 [ - + ]: 3 : ADDOP_I(c, *ploc, GET_AWAITABLE, 2);
1976 [ - + ]: 3 : ADDOP_LOAD_CONST(c, *ploc, Py_None);
1977 [ - + ]: 3 : ADD_YIELD_FROM(c, *ploc, 1);
1978 : : }
1979 [ - + ]: 92 : ADDOP(c, *ploc, POP_TOP);
1980 : : /* The exit block should appear to execute after the
1981 : : * statement causing the unwinding, so make the unwinding
1982 : : * instruction artificial */
1983 : 92 : *ploc = NO_LOCATION;
1984 : 92 : return SUCCESS;
1985 : :
1986 : 391 : case HANDLER_CLEANUP: {
1987 [ + + ]: 391 : if (info->fb_datum) {
1988 [ - + ]: 74 : ADDOP(c, *ploc, POP_BLOCK);
1989 : : }
1990 [ + + ]: 391 : if (preserve_tos) {
1991 [ - + ]: 121 : ADDOP_I(c, *ploc, SWAP, 2);
1992 : : }
1993 [ - + ]: 391 : ADDOP(c, *ploc, POP_BLOCK);
1994 [ - + ]: 391 : ADDOP(c, *ploc, POP_EXCEPT);
1995 [ + + ]: 391 : if (info->fb_datum) {
1996 [ - + ]: 74 : ADDOP_LOAD_CONST(c, *ploc, Py_None);
1997 [ - + ]: 74 : RETURN_IF_ERROR(compiler_nameop(c, *ploc, info->fb_datum, Store));
1998 [ - + ]: 74 : RETURN_IF_ERROR(compiler_nameop(c, *ploc, info->fb_datum, Del));
1999 : : }
2000 : 391 : return SUCCESS;
2001 : : }
2002 : 0 : case POP_VALUE: {
2003 [ # # ]: 0 : if (preserve_tos) {
2004 [ # # ]: 0 : ADDOP_I(c, *ploc, SWAP, 2);
2005 : : }
2006 [ # # ]: 0 : ADDOP(c, *ploc, POP_TOP);
2007 : 0 : return SUCCESS;
2008 : : }
2009 : : }
2010 : 0 : Py_UNREACHABLE();
2011 : : }
2012 : :
2013 : : /** Unwind block stack. If loop is not NULL, then stop when the first loop is encountered. */
2014 : : static int
2015 : 7659 : compiler_unwind_fblock_stack(struct compiler *c, location *ploc,
2016 : : int preserve_tos, struct fblockinfo **loop)
2017 : : {
2018 [ + + ]: 7659 : if (c->u->u_nfblocks == 0) {
2019 : 5842 : return SUCCESS;
2020 : : }
2021 : 1817 : struct fblockinfo *top = &c->u->u_fblock[c->u->u_nfblocks-1];
2022 [ - + ]: 1817 : if (top->fb_type == EXCEPTION_GROUP_HANDLER) {
2023 : 0 : return compiler_error(
2024 : : c, *ploc, "'break', 'continue' and 'return' cannot appear in an except* block");
2025 : : }
2026 [ + + + + : 1817 : if (loop != NULL && (top->fb_type == WHILE_LOOP || top->fb_type == FOR_LOOP)) {
+ + ]
2027 : 506 : *loop = top;
2028 : 506 : return SUCCESS;
2029 : : }
2030 : 1311 : struct fblockinfo copy = *top;
2031 : 1311 : c->u->u_nfblocks--;
2032 [ - + ]: 1311 : RETURN_IF_ERROR(compiler_unwind_fblock(c, ploc, ©, preserve_tos));
2033 [ - + ]: 1311 : RETURN_IF_ERROR(compiler_unwind_fblock_stack(c, ploc, preserve_tos, loop));
2034 : 1311 : c->u->u_fblock[c->u->u_nfblocks] = copy;
2035 : 1311 : c->u->u_nfblocks++;
2036 : 1311 : return SUCCESS;
2037 : : }
2038 : :
2039 : : /* Compile a sequence of statements, checking for a docstring
2040 : : and for annotations. */
2041 : :
2042 : : static int
2043 : 939 : compiler_body(struct compiler *c, location loc, asdl_stmt_seq *stmts)
2044 : : {
2045 : 939 : int i = 0;
2046 : : stmt_ty st;
2047 : : PyObject *docstring;
2048 : :
2049 : : /* Set current line number to the line number of first statement.
2050 : : This way line number for SETUP_ANNOTATIONS will always
2051 : : coincide with the line number of first "real" statement in module.
2052 : : If body is empty, then lineno will be set later in assemble. */
2053 [ + + + + : 939 : if (c->u->u_scope_type == COMPILER_SCOPE_MODULE && asdl_seq_LEN(stmts)) {
+ - ]
2054 : 200 : st = (stmt_ty)asdl_seq_GET(stmts, 0);
2055 : 200 : loc = LOC(st);
2056 : : }
2057 : : /* Every annotated class and module should have __annotations__. */
2058 [ + + ]: 939 : if (find_ann(stmts)) {
2059 [ - + ]: 1 : ADDOP(c, loc, SETUP_ANNOTATIONS);
2060 : : }
2061 [ + + - + ]: 939 : if (!asdl_seq_LEN(stmts)) {
2062 : 6 : return SUCCESS;
2063 : : }
2064 : : /* if not -OO mode, set docstring */
2065 [ + - ]: 933 : if (c->c_optimize < 2) {
2066 : 933 : docstring = _PyAST_GetDocString(stmts);
2067 [ + + ]: 933 : if (docstring) {
2068 : 564 : i = 1;
2069 : 564 : st = (stmt_ty)asdl_seq_GET(stmts, 0);
2070 : : assert(st->kind == Expr_kind);
2071 [ - + ]: 564 : VISIT(c, expr, st->v.Expr.value);
2072 [ - + ]: 564 : RETURN_IF_ERROR(compiler_nameop(c, NO_LOCATION, &_Py_ID(__doc__), Store));
2073 : : }
2074 : : }
2075 [ + - + + ]: 11662 : for (; i < asdl_seq_LEN(stmts); i++) {
2076 [ - + ]: 10729 : VISIT(c, stmt, (stmt_ty)asdl_seq_GET(stmts, i));
2077 : : }
2078 : 933 : return SUCCESS;
2079 : : }
2080 : :
2081 : : static int
2082 : 319 : compiler_codegen(struct compiler *c, mod_ty mod)
2083 : : {
2084 : : _Py_DECLARE_STR(anon_module, "<module>");
2085 [ - + ]: 319 : RETURN_IF_ERROR(
2086 : : compiler_enter_scope(c, &_Py_STR(anon_module), COMPILER_SCOPE_MODULE,
2087 : : mod, 1));
2088 : :
2089 : 319 : location loc = LOCATION(1, 1, 0, 0);
2090 [ + + + - ]: 319 : switch (mod->kind) {
2091 : 206 : case Module_kind:
2092 [ - + ]: 206 : if (compiler_body(c, loc, mod->v.Module.body) < 0) {
2093 : 0 : compiler_exit_scope(c);
2094 : 0 : return ERROR;
2095 : : }
2096 : 206 : break;
2097 : 56 : case Interactive_kind:
2098 [ - + ]: 56 : if (find_ann(mod->v.Interactive.body)) {
2099 [ # # ]: 0 : ADDOP(c, loc, SETUP_ANNOTATIONS);
2100 : : }
2101 : 56 : c->c_interactive = 1;
2102 [ - + + - : 112 : VISIT_SEQ_IN_SCOPE(c, stmt, mod->v.Interactive.body);
+ + ]
2103 : 56 : break;
2104 : 57 : case Expression_kind:
2105 [ - + ]: 57 : VISIT_IN_SCOPE(c, expr, mod->v.Expression.body);
2106 : 57 : break;
2107 : 0 : default:
2108 : 0 : PyErr_Format(PyExc_SystemError,
2109 : : "module kind %d should not be possible",
2110 : 0 : mod->kind);
2111 : 0 : return ERROR;
2112 : : }
2113 : 319 : return SUCCESS;
2114 : : }
2115 : :
2116 : : static PyCodeObject *
2117 : 319 : compiler_mod(struct compiler *c, mod_ty mod)
2118 : : {
2119 : 319 : int addNone = mod->kind != Expression_kind;
2120 [ - + ]: 319 : if (compiler_codegen(c, mod) < 0) {
2121 : 0 : return NULL;
2122 : : }
2123 : 319 : PyCodeObject *co = assemble(c, addNone);
2124 : 319 : compiler_exit_scope(c);
2125 : 319 : return co;
2126 : : }
2127 : :
2128 : : /* The test for LOCAL must come before the test for FREE in order to
2129 : : handle classes where name is both local and free. The local var is
2130 : : a method and the free var is a free var referenced within a method.
2131 : : */
2132 : :
2133 : : static int
2134 : 938 : get_ref_type(struct compiler *c, PyObject *name)
2135 : : {
2136 : : int scope;
2137 [ + + + + ]: 1160 : if (c->u->u_scope_type == COMPILER_SCOPE_CLASS &&
2138 : 222 : _PyUnicode_EqualToASCIIString(name, "__class__"))
2139 : 208 : return CELL;
2140 : 730 : scope = _PyST_GetScope(c->u->u_ste, name);
2141 [ - + ]: 730 : if (scope == 0) {
2142 : 0 : PyErr_Format(PyExc_SystemError,
2143 : : "_PyST_GetScope(name=%R) failed: "
2144 : : "unknown scope in unit %S (%R); "
2145 : : "symbols: %R; locals: %R; globals: %R",
2146 : : name,
2147 : 0 : c->u->u_name, c->u->u_ste->ste_id,
2148 : 0 : c->u->u_ste->ste_symbols, c->u->u_varnames, c->u->u_names);
2149 : 0 : return ERROR;
2150 : : }
2151 : 730 : return scope;
2152 : : }
2153 : :
2154 : : static int
2155 : 1050 : compiler_lookup_arg(PyObject *dict, PyObject *name)
2156 : : {
2157 : 1050 : PyObject *v = PyDict_GetItemWithError(dict, name);
2158 [ - + ]: 1050 : if (v == NULL) {
2159 : 0 : return ERROR;
2160 : : }
2161 : 1050 : return PyLong_AS_LONG(v);
2162 : : }
2163 : :
2164 : : static int
2165 : 7722 : compiler_make_closure(struct compiler *c, location loc,
2166 : : PyCodeObject *co, Py_ssize_t flags)
2167 : : {
2168 [ + + ]: 7722 : if (co->co_nfreevars) {
2169 : 627 : int i = PyCode_GetFirstFree(co);
2170 [ + + ]: 1565 : for (; i < co->co_nlocalsplus; ++i) {
2171 : : /* Bypass com_addop_varname because it will generate
2172 : : LOAD_DEREF but LOAD_CLOSURE is needed.
2173 : : */
2174 : 938 : PyObject *name = PyTuple_GET_ITEM(co->co_localsplusnames, i);
2175 : :
2176 : : /* Special case: If a class contains a method with a
2177 : : free variable that has the same name as a method,
2178 : : the name will be considered free *and* local in the
2179 : : class. It should be handled by the closure, as
2180 : : well as by the normal name lookup logic.
2181 : : */
2182 : 938 : int reftype = get_ref_type(c, name);
2183 [ - + ]: 938 : if (reftype == -1) {
2184 : 0 : return ERROR;
2185 : : }
2186 : : int arg;
2187 [ + + ]: 938 : if (reftype == CELL) {
2188 : 902 : arg = compiler_lookup_arg(c->u->u_cellvars, name);
2189 : : }
2190 : : else {
2191 : 36 : arg = compiler_lookup_arg(c->u->u_freevars, name);
2192 : : }
2193 [ - + ]: 938 : if (arg == -1) {
2194 : 0 : PyObject *freevars = _PyCode_GetFreevars(co);
2195 [ # # ]: 0 : if (freevars == NULL) {
2196 : 0 : PyErr_Clear();
2197 : : }
2198 : 0 : PyErr_Format(PyExc_SystemError,
2199 : : "compiler_lookup_arg(name=%R) with reftype=%d failed in %S; "
2200 : : "freevars of code %S: %R",
2201 : : name,
2202 : : reftype,
2203 : 0 : c->u->u_name,
2204 : : co->co_name,
2205 : : freevars);
2206 : 0 : Py_DECREF(freevars);
2207 : 0 : return ERROR;
2208 : : }
2209 [ - + ]: 938 : ADDOP_I(c, loc, LOAD_CLOSURE, arg);
2210 : : }
2211 : 627 : flags |= 0x08;
2212 [ - + ]: 627 : ADDOP_I(c, loc, BUILD_TUPLE, co->co_nfreevars);
2213 : : }
2214 [ - + ]: 7722 : ADDOP_LOAD_CONST(c, loc, (PyObject*)co);
2215 [ - + ]: 7722 : ADDOP_I(c, loc, MAKE_FUNCTION, flags);
2216 : 7722 : return SUCCESS;
2217 : : }
2218 : :
2219 : : static int
2220 : 7134 : compiler_decorators(struct compiler *c, asdl_expr_seq* decos)
2221 : : {
2222 [ + + ]: 7134 : if (!decos) {
2223 : 6544 : return SUCCESS;
2224 : : }
2225 : :
2226 [ + - + + ]: 1211 : for (Py_ssize_t i = 0; i < asdl_seq_LEN(decos); i++) {
2227 [ - + ]: 621 : VISIT(c, expr, (expr_ty)asdl_seq_GET(decos, i));
2228 : : }
2229 : 590 : return SUCCESS;
2230 : : }
2231 : :
2232 : : static int
2233 : 7134 : compiler_apply_decorators(struct compiler *c, asdl_expr_seq* decos)
2234 : : {
2235 [ + + ]: 7134 : if (!decos) {
2236 : 6544 : return SUCCESS;
2237 : : }
2238 : :
2239 [ + - + + ]: 1211 : for (Py_ssize_t i = asdl_seq_LEN(decos) - 1; i > -1; i--) {
2240 : 621 : location loc = LOC((expr_ty)asdl_seq_GET(decos, i));
2241 [ - + ]: 621 : ADDOP_I(c, loc, CALL, 0);
2242 : : }
2243 : 590 : return SUCCESS;
2244 : : }
2245 : :
2246 : : static int
2247 : 6536 : compiler_visit_kwonlydefaults(struct compiler *c, location loc,
2248 : : asdl_arg_seq *kwonlyargs, asdl_expr_seq *kw_defaults)
2249 : : {
2250 : : /* Push a dict of keyword-only default values.
2251 : :
2252 : : Return -1 on error, 0 if no dict pushed, 1 if a dict is pushed.
2253 : : */
2254 : : int i;
2255 : 6536 : PyObject *keys = NULL;
2256 : :
2257 [ + - + + ]: 7109 : for (i = 0; i < asdl_seq_LEN(kwonlyargs); i++) {
2258 : 573 : arg_ty arg = asdl_seq_GET(kwonlyargs, i);
2259 : 573 : expr_ty default_ = asdl_seq_GET(kw_defaults, i);
2260 [ + + ]: 573 : if (default_) {
2261 : 563 : PyObject *mangled = _Py_Mangle(c->u->u_private, arg->arg);
2262 [ - + ]: 563 : if (!mangled) {
2263 : 0 : goto error;
2264 : : }
2265 [ + + ]: 563 : if (keys == NULL) {
2266 : 221 : keys = PyList_New(1);
2267 [ - + ]: 221 : if (keys == NULL) {
2268 : 0 : Py_DECREF(mangled);
2269 : 0 : return ERROR;
2270 : : }
2271 : 221 : PyList_SET_ITEM(keys, 0, mangled);
2272 : : }
2273 : : else {
2274 : 342 : int res = PyList_Append(keys, mangled);
2275 : 342 : Py_DECREF(mangled);
2276 [ - + ]: 342 : if (res == -1) {
2277 : 0 : goto error;
2278 : : }
2279 : : }
2280 [ - + ]: 563 : if (compiler_visit_expr(c, default_) < 0) {
2281 : 0 : goto error;
2282 : : }
2283 : : }
2284 : : }
2285 [ + + ]: 6536 : if (keys != NULL) {
2286 : 221 : Py_ssize_t default_count = PyList_GET_SIZE(keys);
2287 : 221 : PyObject *keys_tuple = PyList_AsTuple(keys);
2288 : 221 : Py_DECREF(keys);
2289 [ - + - + ]: 221 : ADDOP_LOAD_CONST_NEW(c, loc, keys_tuple);
2290 [ - + ]: 221 : ADDOP_I(c, loc, BUILD_CONST_KEY_MAP, default_count);
2291 : : assert(default_count > 0);
2292 : 221 : return 1;
2293 : : }
2294 : : else {
2295 : 6315 : return 0;
2296 : : }
2297 : :
2298 : 0 : error:
2299 : 0 : Py_XDECREF(keys);
2300 : 0 : return ERROR;
2301 : : }
2302 : :
2303 : : static int
2304 : 0 : compiler_visit_annexpr(struct compiler *c, expr_ty annotation)
2305 : : {
2306 : 0 : location loc = LOC(annotation);
2307 [ # # # # ]: 0 : ADDOP_LOAD_CONST_NEW(c, loc, _PyAST_ExprAsUnicode(annotation));
2308 : 0 : return SUCCESS;
2309 : : }
2310 : :
2311 : : static int
2312 : 19050 : compiler_visit_argannotation(struct compiler *c, identifier id,
2313 : : expr_ty annotation, Py_ssize_t *annotations_len, location loc)
2314 : : {
2315 [ + + ]: 19050 : if (!annotation) {
2316 : 18453 : return SUCCESS;
2317 : : }
2318 : 597 : PyObject *mangled = _Py_Mangle(c->u->u_private, id);
2319 [ - + ]: 597 : if (!mangled) {
2320 : 0 : return ERROR;
2321 : : }
2322 [ - + ]: 597 : ADDOP_LOAD_CONST(c, loc, mangled);
2323 : 597 : Py_DECREF(mangled);
2324 : :
2325 [ - + ]: 597 : if (c->c_future.ff_features & CO_FUTURE_ANNOTATIONS) {
2326 [ # # ]: 0 : VISIT(c, annexpr, annotation);
2327 : : }
2328 : : else {
2329 [ - + ]: 597 : if (annotation->kind == Starred_kind) {
2330 : : // *args: *Ts (where Ts is a TypeVarTuple).
2331 : : // Do [annotation_value] = [*Ts].
2332 : : // (Note that in theory we could end up here even for an argument
2333 : : // other than *args, but in practice the grammar doesn't allow it.)
2334 [ # # ]: 0 : VISIT(c, expr, annotation->v.Starred.value);
2335 [ # # ]: 0 : ADDOP_I(c, loc, UNPACK_SEQUENCE, (Py_ssize_t) 1);
2336 : : }
2337 : : else {
2338 [ - + ]: 597 : VISIT(c, expr, annotation);
2339 : : }
2340 : : }
2341 : 597 : *annotations_len += 2;
2342 : 597 : return SUCCESS;
2343 : : }
2344 : :
2345 : : static int
2346 : 19203 : compiler_visit_argannotations(struct compiler *c, asdl_arg_seq* args,
2347 : : Py_ssize_t *annotations_len, location loc)
2348 : : {
2349 : : int i;
2350 [ + - + + ]: 31849 : for (i = 0; i < asdl_seq_LEN(args); i++) {
2351 : 12646 : arg_ty arg = (arg_ty)asdl_seq_GET(args, i);
2352 [ - + ]: 12646 : RETURN_IF_ERROR(
2353 : : compiler_visit_argannotation(
2354 : : c,
2355 : : arg->arg,
2356 : : arg->annotation,
2357 : : annotations_len,
2358 : : loc));
2359 : : }
2360 : 19203 : return SUCCESS;
2361 : : }
2362 : :
2363 : : static int
2364 : 6401 : compiler_visit_annotations(struct compiler *c, location loc,
2365 : : arguments_ty args, expr_ty returns)
2366 : : {
2367 : : /* Push arg annotation names and values.
2368 : : The expressions are evaluated out-of-order wrt the source code.
2369 : :
2370 : : Return -1 on error, 0 if no annotations pushed, 1 if a annotations is pushed.
2371 : : */
2372 : 6401 : Py_ssize_t annotations_len = 0;
2373 : :
2374 [ - + ]: 6401 : RETURN_IF_ERROR(
2375 : : compiler_visit_argannotations(c, args->args, &annotations_len, loc));
2376 : :
2377 [ - + ]: 6401 : RETURN_IF_ERROR(
2378 : : compiler_visit_argannotations(c, args->posonlyargs, &annotations_len, loc));
2379 : :
2380 [ + + + + ]: 6401 : if (args->vararg && args->vararg->annotation) {
2381 [ - + ]: 1 : RETURN_IF_ERROR(
2382 : : compiler_visit_argannotation(c, args->vararg->arg,
2383 : : args->vararg->annotation, &annotations_len, loc));
2384 : : }
2385 : :
2386 [ - + ]: 6401 : RETURN_IF_ERROR(
2387 : : compiler_visit_argannotations(c, args->kwonlyargs, &annotations_len, loc));
2388 : :
2389 [ + + + + ]: 6401 : if (args->kwarg && args->kwarg->annotation) {
2390 [ - + ]: 2 : RETURN_IF_ERROR(
2391 : : compiler_visit_argannotation(c, args->kwarg->arg,
2392 : : args->kwarg->annotation, &annotations_len, loc));
2393 : : }
2394 : :
2395 [ - + ]: 6401 : RETURN_IF_ERROR(
2396 : : compiler_visit_argannotation(c, &_Py_ID(return), returns, &annotations_len, loc));
2397 : :
2398 [ + + ]: 6401 : if (annotations_len) {
2399 [ - + ]: 254 : ADDOP_I(c, loc, BUILD_TUPLE, annotations_len);
2400 : 254 : return 1;
2401 : : }
2402 : :
2403 : 6147 : return 0;
2404 : : }
2405 : :
2406 : : static int
2407 : 998 : compiler_visit_defaults(struct compiler *c, arguments_ty args,
2408 : : location loc)
2409 : : {
2410 [ - + + - : 2774 : VISIT_SEQ(c, expr, args->defaults);
+ + ]
2411 [ + - - + ]: 998 : ADDOP_I(c, loc, BUILD_TUPLE, asdl_seq_LEN(args->defaults));
2412 : 998 : return SUCCESS;
2413 : : }
2414 : :
2415 : : static Py_ssize_t
2416 : 6536 : compiler_default_arguments(struct compiler *c, location loc,
2417 : : arguments_ty args)
2418 : : {
2419 : 6536 : Py_ssize_t funcflags = 0;
2420 [ + - + - : 6536 : if (args->defaults && asdl_seq_LEN(args->defaults) > 0) {
+ + ]
2421 [ - + ]: 998 : RETURN_IF_ERROR(compiler_visit_defaults(c, args, loc));
2422 : 998 : funcflags |= 0x01;
2423 : : }
2424 [ + - ]: 6536 : if (args->kwonlyargs) {
2425 : 6536 : int res = compiler_visit_kwonlydefaults(c, loc,
2426 : : args->kwonlyargs,
2427 : : args->kw_defaults);
2428 [ - + ]: 6536 : RETURN_IF_ERROR(res);
2429 [ + + ]: 6536 : if (res > 0) {
2430 : 221 : funcflags |= 0x02;
2431 : : }
2432 : : }
2433 : 6536 : return funcflags;
2434 : : }
2435 : :
2436 : : static bool
2437 : 135505 : forbidden_name(struct compiler *c, location loc, identifier name,
2438 : : expr_context_ty ctx)
2439 : : {
2440 [ + + - + ]: 135505 : if (ctx == Store && _PyUnicode_EqualToASCIIString(name, "__debug__")) {
2441 : 0 : compiler_error(c, loc, "cannot assign to __debug__");
2442 : 0 : return true;
2443 : : }
2444 [ + + - + ]: 135505 : if (ctx == Del && _PyUnicode_EqualToASCIIString(name, "__debug__")) {
2445 : 0 : compiler_error(c, loc, "cannot delete __debug__");
2446 : 0 : return true;
2447 : : }
2448 : 135505 : return false;
2449 : : }
2450 : :
2451 : : static int
2452 : 26067 : compiler_check_debug_one_arg(struct compiler *c, arg_ty arg)
2453 : : {
2454 [ + + ]: 26067 : if (arg != NULL) {
2455 [ - + ]: 13520 : if (forbidden_name(c, LOC(arg), arg->arg, Store)) {
2456 : 0 : return ERROR;
2457 : : }
2458 : : }
2459 : 26067 : return SUCCESS;
2460 : : }
2461 : :
2462 : : static int
2463 : 19608 : compiler_check_debug_args_seq(struct compiler *c, asdl_arg_seq *args)
2464 : : {
2465 [ + - ]: 19608 : if (args != NULL) {
2466 [ + - + + ]: 32603 : for (Py_ssize_t i = 0, n = asdl_seq_LEN(args); i < n; i++) {
2467 [ - + ]: 12995 : RETURN_IF_ERROR(
2468 : : compiler_check_debug_one_arg(c, asdl_seq_GET(args, i)));
2469 : : }
2470 : : }
2471 : 19608 : return SUCCESS;
2472 : : }
2473 : :
2474 : : static int
2475 : 6536 : compiler_check_debug_args(struct compiler *c, arguments_ty args)
2476 : : {
2477 [ - + ]: 6536 : RETURN_IF_ERROR(compiler_check_debug_args_seq(c, args->posonlyargs));
2478 [ - + ]: 6536 : RETURN_IF_ERROR(compiler_check_debug_args_seq(c, args->args));
2479 [ - + ]: 6536 : RETURN_IF_ERROR(compiler_check_debug_one_arg(c, args->vararg));
2480 [ - + ]: 6536 : RETURN_IF_ERROR(compiler_check_debug_args_seq(c, args->kwonlyargs));
2481 [ - + ]: 6536 : RETURN_IF_ERROR(compiler_check_debug_one_arg(c, args->kwarg));
2482 : 6536 : return SUCCESS;
2483 : : }
2484 : :
2485 : : static inline int
2486 : 2390 : insert_instruction(basicblock *block, int pos, struct cfg_instr *instr) {
2487 [ - + ]: 2390 : RETURN_IF_ERROR(basicblock_next_instr(block));
2488 [ + + ]: 31932 : for (int i = block->b_iused - 1; i > pos; i--) {
2489 : 29542 : block->b_instr[i] = block->b_instr[i-1];
2490 : : }
2491 : 2390 : block->b_instr[pos] = *instr;
2492 : 2390 : return SUCCESS;
2493 : : }
2494 : :
2495 : : static int
2496 : 530 : wrap_in_stopiteration_handler(struct compiler *c)
2497 : : {
2498 [ - + ]: 530 : NEW_JUMP_TARGET_LABEL(c, handler);
2499 : :
2500 : : /* Insert SETUP_CLEANUP at start */
2501 [ - + ]: 530 : RETURN_IF_ERROR(
2502 : : instr_sequence_insert_instruction(
2503 : : INSTR_SEQUENCE(c), 0,
2504 : : SETUP_CLEANUP, handler.id, NO_LOCATION));
2505 : :
2506 [ - + ]: 530 : ADDOP_LOAD_CONST(c, NO_LOCATION, Py_None);
2507 [ - + ]: 530 : ADDOP(c, NO_LOCATION, RETURN_VALUE);
2508 [ - + ]: 530 : USE_LABEL(c, handler);
2509 [ - + ]: 530 : ADDOP_I(c, NO_LOCATION, CALL_INTRINSIC_1, INTRINSIC_STOPITERATION_ERROR);
2510 [ - + ]: 530 : ADDOP_I(c, NO_LOCATION, RERAISE, 1);
2511 : 530 : return SUCCESS;
2512 : : }
2513 : :
2514 : : static int
2515 : 6401 : compiler_function(struct compiler *c, stmt_ty s, int is_async)
2516 : : {
2517 : : PyCodeObject *co;
2518 : 6401 : PyObject *docstring = NULL;
2519 : : arguments_ty args;
2520 : : expr_ty returns;
2521 : : identifier name;
2522 : : asdl_expr_seq* decos;
2523 : : asdl_stmt_seq *body;
2524 : : Py_ssize_t i, funcflags;
2525 : : int annotations;
2526 : : int scope_type;
2527 : : int firstlineno;
2528 : :
2529 [ + + ]: 6401 : if (is_async) {
2530 : : assert(s->kind == AsyncFunctionDef_kind);
2531 : :
2532 : 158 : args = s->v.AsyncFunctionDef.args;
2533 : 158 : returns = s->v.AsyncFunctionDef.returns;
2534 : 158 : decos = s->v.AsyncFunctionDef.decorator_list;
2535 : 158 : name = s->v.AsyncFunctionDef.name;
2536 : 158 : body = s->v.AsyncFunctionDef.body;
2537 : :
2538 : 158 : scope_type = COMPILER_SCOPE_ASYNC_FUNCTION;
2539 : : } else {
2540 : : assert(s->kind == FunctionDef_kind);
2541 : :
2542 : 6243 : args = s->v.FunctionDef.args;
2543 : 6243 : returns = s->v.FunctionDef.returns;
2544 : 6243 : decos = s->v.FunctionDef.decorator_list;
2545 : 6243 : name = s->v.FunctionDef.name;
2546 : 6243 : body = s->v.FunctionDef.body;
2547 : :
2548 : 6243 : scope_type = COMPILER_SCOPE_FUNCTION;
2549 : : }
2550 : :
2551 [ - + ]: 6401 : RETURN_IF_ERROR(compiler_check_debug_args(c, args));
2552 [ - + ]: 6401 : RETURN_IF_ERROR(compiler_decorators(c, decos));
2553 : :
2554 : 6401 : firstlineno = s->lineno;
2555 [ + + + - ]: 6401 : if (asdl_seq_LEN(decos)) {
2556 : 573 : firstlineno = ((expr_ty)asdl_seq_GET(decos, 0))->lineno;
2557 : : }
2558 : :
2559 : 6401 : location loc = LOC(s);
2560 : 6401 : funcflags = compiler_default_arguments(c, loc, args);
2561 [ - + ]: 6401 : if (funcflags == -1) {
2562 : 0 : return ERROR;
2563 : : }
2564 : 6401 : annotations = compiler_visit_annotations(c, loc, args, returns);
2565 [ - + ]: 6401 : RETURN_IF_ERROR(annotations);
2566 [ + + ]: 6401 : if (annotations > 0) {
2567 : 254 : funcflags |= 0x04;
2568 : : }
2569 : :
2570 [ - + ]: 6401 : RETURN_IF_ERROR(
2571 : : compiler_enter_scope(c, name, scope_type, (void *)s, firstlineno));
2572 : :
2573 : : /* if not -OO mode, add docstring */
2574 [ + - ]: 6401 : if (c->c_optimize < 2) {
2575 : 6401 : docstring = _PyAST_GetDocString(body);
2576 : : }
2577 [ + + - + ]: 6401 : if (compiler_add_const(c->c_const_cache, c->u, docstring ? docstring : Py_None) < 0) {
2578 : 0 : compiler_exit_scope(c);
2579 : 0 : return ERROR;
2580 : : }
2581 : :
2582 [ + - ]: 6401 : c->u->u_argcount = asdl_seq_LEN(args->args);
2583 [ + - ]: 6401 : c->u->u_posonlyargcount = asdl_seq_LEN(args->posonlyargs);
2584 [ + - ]: 6401 : c->u->u_kwonlyargcount = asdl_seq_LEN(args->kwonlyargs);
2585 [ + - + + ]: 25786 : for (i = docstring ? 1 : 0; i < asdl_seq_LEN(body); i++) {
2586 [ - + ]: 19385 : VISIT_IN_SCOPE(c, stmt, (stmt_ty)asdl_seq_GET(body, i));
2587 : : }
2588 [ + + + + ]: 6401 : if (c->u->u_ste->ste_coroutine || c->u->u_ste->ste_generator) {
2589 [ - + ]: 333 : if (wrap_in_stopiteration_handler(c) < 0) {
2590 : 0 : compiler_exit_scope(c);
2591 : 0 : return ERROR;
2592 : : }
2593 : : }
2594 : 6401 : co = assemble(c, 1);
2595 : 6401 : compiler_exit_scope(c);
2596 [ - + ]: 6401 : if (co == NULL) {
2597 : 0 : Py_XDECREF(co);
2598 : 0 : return ERROR;
2599 : : }
2600 [ - + ]: 6401 : if (compiler_make_closure(c, loc, co, funcflags) < 0) {
2601 : 0 : Py_DECREF(co);
2602 : 0 : return ERROR;
2603 : : }
2604 : 6401 : Py_DECREF(co);
2605 : :
2606 [ - + ]: 6401 : RETURN_IF_ERROR(compiler_apply_decorators(c, decos));
2607 : 6401 : return compiler_nameop(c, loc, name, Store);
2608 : : }
2609 : :
2610 : : static int
2611 : 733 : compiler_class(struct compiler *c, stmt_ty s)
2612 : : {
2613 : : PyCodeObject *co;
2614 : : int i, firstlineno;
2615 : 733 : asdl_expr_seq *decos = s->v.ClassDef.decorator_list;
2616 : :
2617 [ - + ]: 733 : RETURN_IF_ERROR(compiler_decorators(c, decos));
2618 : :
2619 : 733 : firstlineno = s->lineno;
2620 [ + + + - ]: 733 : if (asdl_seq_LEN(decos)) {
2621 : 17 : firstlineno = ((expr_ty)asdl_seq_GET(decos, 0))->lineno;
2622 : : }
2623 : :
2624 : : /* ultimately generate code for:
2625 : : <name> = __build_class__(<func>, <name>, *<bases>, **<keywords>)
2626 : : where:
2627 : : <func> is a zero arg function/closure created from the class body.
2628 : : It mutates its locals to build the class namespace.
2629 : : <name> is the class name
2630 : : <bases> is the positional arguments and *varargs argument
2631 : : <keywords> is the keyword arguments and **kwds argument
2632 : : This borrows from compiler_call.
2633 : : */
2634 : : /* 1. compile the class body into a code object */
2635 [ - + ]: 733 : RETURN_IF_ERROR(
2636 : : compiler_enter_scope(c, s->v.ClassDef.name,
2637 : : COMPILER_SCOPE_CLASS, (void *)s, firstlineno));
2638 : :
2639 : : /* this block represents what we do in the new scope */
2640 : : {
2641 : 733 : location loc = LOCATION(firstlineno, firstlineno, 0, 0);
2642 : : /* use the class name for name mangling */
2643 : 733 : Py_XSETREF(c->u->u_private, Py_NewRef(s->v.ClassDef.name));
2644 : : /* load (global) __name__ ... */
2645 [ - + ]: 733 : if (compiler_nameop(c, loc, &_Py_ID(__name__), Load) < 0) {
2646 : 0 : compiler_exit_scope(c);
2647 : 0 : return ERROR;
2648 : : }
2649 : : /* ... and store it as __module__ */
2650 [ - + ]: 733 : if (compiler_nameop(c, loc, &_Py_ID(__module__), Store) < 0) {
2651 : 0 : compiler_exit_scope(c);
2652 : 0 : return ERROR;
2653 : : }
2654 : : assert(c->u->u_qualname);
2655 [ - + ]: 733 : ADDOP_LOAD_CONST(c, loc, c->u->u_qualname);
2656 [ - + ]: 733 : if (compiler_nameop(c, loc, &_Py_ID(__qualname__), Store) < 0) {
2657 : 0 : compiler_exit_scope(c);
2658 : 0 : return ERROR;
2659 : : }
2660 : : /* compile the body proper */
2661 [ - + ]: 733 : if (compiler_body(c, loc, s->v.ClassDef.body) < 0) {
2662 : 0 : compiler_exit_scope(c);
2663 : 0 : return ERROR;
2664 : : }
2665 : : /* The following code is artificial */
2666 : : /* Return __classcell__ if it is referenced, otherwise return None */
2667 [ + + ]: 733 : if (c->u->u_ste->ste_needs_class_closure) {
2668 : : /* Store __classcell__ into class namespace & return it */
2669 : 112 : i = compiler_lookup_arg(c->u->u_cellvars, &_Py_ID(__class__));
2670 [ - + ]: 112 : if (i < 0) {
2671 : 0 : compiler_exit_scope(c);
2672 : 0 : return ERROR;
2673 : : }
2674 : : assert(i == 0);
2675 [ - + ]: 112 : ADDOP_I(c, NO_LOCATION, LOAD_CLOSURE, i);
2676 [ - + ]: 112 : ADDOP_I(c, NO_LOCATION, COPY, 1);
2677 [ - + ]: 112 : if (compiler_nameop(c, NO_LOCATION, &_Py_ID(__classcell__), Store) < 0) {
2678 : 0 : compiler_exit_scope(c);
2679 : 0 : return ERROR;
2680 : : }
2681 : : }
2682 : : else {
2683 : : /* No methods referenced __class__, so just return None */
2684 : : assert(PyDict_GET_SIZE(c->u->u_cellvars) == 0);
2685 [ - + ]: 621 : ADDOP_LOAD_CONST(c, NO_LOCATION, Py_None);
2686 : : }
2687 [ - + ]: 733 : ADDOP_IN_SCOPE(c, NO_LOCATION, RETURN_VALUE);
2688 : : /* create the code object */
2689 : 733 : co = assemble(c, 1);
2690 : : }
2691 : : /* leave the new scope */
2692 : 733 : compiler_exit_scope(c);
2693 [ - + ]: 733 : if (co == NULL) {
2694 : 0 : return ERROR;
2695 : : }
2696 : :
2697 : 733 : location loc = LOC(s);
2698 : : /* 2. load the 'build_class' function */
2699 [ - + ]: 733 : ADDOP(c, loc, PUSH_NULL);
2700 [ - + ]: 733 : ADDOP(c, loc, LOAD_BUILD_CLASS);
2701 : :
2702 : : /* 3. load a function (or closure) made from the code object */
2703 [ - + ]: 733 : if (compiler_make_closure(c, loc, co, 0) < 0) {
2704 : 0 : Py_DECREF(co);
2705 : 0 : return ERROR;
2706 : : }
2707 : 733 : Py_DECREF(co);
2708 : :
2709 : : /* 4. load class name */
2710 [ - + ]: 733 : ADDOP_LOAD_CONST(c, loc, s->v.ClassDef.name);
2711 : :
2712 : : /* 5. generate the rest of the code for the call */
2713 [ - + ]: 733 : RETURN_IF_ERROR(compiler_call_helper(c, loc, 2,
2714 : : s->v.ClassDef.bases,
2715 : : s->v.ClassDef.keywords));
2716 : :
2717 : : /* 6. apply decorators */
2718 [ - + ]: 733 : RETURN_IF_ERROR(compiler_apply_decorators(c, decos));
2719 : :
2720 : : /* 7. store into <name> */
2721 [ - + ]: 733 : RETURN_IF_ERROR(compiler_nameop(c, loc, s->v.ClassDef.name, Store));
2722 : 733 : return SUCCESS;
2723 : : }
2724 : :
2725 : : /* Return false if the expression is a constant value except named singletons.
2726 : : Return true otherwise. */
2727 : : static bool
2728 : 12784 : check_is_arg(expr_ty e)
2729 : : {
2730 [ + + ]: 12784 : if (e->kind != Constant_kind) {
2731 : 8880 : return true;
2732 : : }
2733 : 3904 : PyObject *value = e->v.Constant.value;
2734 : : return (value == Py_None
2735 [ + + ]: 2093 : || value == Py_False
2736 [ + + ]: 2085 : || value == Py_True
2737 [ + + + + ]: 5997 : || value == Py_Ellipsis);
2738 : : }
2739 : :
2740 : : /* Check operands of identity checks ("is" and "is not").
2741 : : Emit a warning if any operand is a constant except named singletons.
2742 : : */
2743 : : static int
2744 : 6367 : check_compare(struct compiler *c, expr_ty e)
2745 : : {
2746 : : Py_ssize_t i, n;
2747 : 6367 : bool left = check_is_arg(e->v.Compare.left);
2748 [ + - ]: 6367 : n = asdl_seq_LEN(e->v.Compare.ops);
2749 [ + + ]: 12784 : for (i = 0; i < n; i++) {
2750 : 6417 : cmpop_ty op = (cmpop_ty)asdl_seq_GET(e->v.Compare.ops, i);
2751 : 6417 : bool right = check_is_arg((expr_ty)asdl_seq_GET(e->v.Compare.comparators, i));
2752 [ + + + + ]: 6417 : if (op == Is || op == IsNot) {
2753 [ + - - + ]: 2359 : if (!right || !left) {
2754 : 0 : const char *msg = (op == Is)
2755 : : ? "\"is\" with a literal. Did you mean \"==\"?"
2756 [ # # ]: 0 : : "\"is not\" with a literal. Did you mean \"!=\"?";
2757 : 0 : return compiler_warn(c, LOC(e), msg);
2758 : : }
2759 : : }
2760 : 6417 : left = right;
2761 : : }
2762 : 6367 : return SUCCESS;
2763 : : }
2764 : :
2765 : 6426 : static int compiler_addcompare(struct compiler *c, location loc,
2766 : : cmpop_ty op)
2767 : : {
2768 : : int cmp;
2769 [ + + + + : 6426 : switch (op) {
+ + + + +
+ - ]
2770 : 1615 : case Eq:
2771 : 1615 : cmp = Py_EQ;
2772 : 1615 : break;
2773 : 441 : case NotEq:
2774 : 441 : cmp = Py_NE;
2775 : 441 : break;
2776 : 368 : case Lt:
2777 : 368 : cmp = Py_LT;
2778 : 368 : break;
2779 : 187 : case LtE:
2780 : 187 : cmp = Py_LE;
2781 : 187 : break;
2782 : 308 : case Gt:
2783 : 308 : cmp = Py_GT;
2784 : 308 : break;
2785 : 156 : case GtE:
2786 : 156 : cmp = Py_GE;
2787 : 156 : break;
2788 : 1337 : case Is:
2789 [ - + ]: 1337 : ADDOP_I(c, loc, IS_OP, 0);
2790 : 1337 : return SUCCESS;
2791 : 1023 : case IsNot:
2792 [ - + ]: 1023 : ADDOP_I(c, loc, IS_OP, 1);
2793 : 1023 : return SUCCESS;
2794 : 703 : case In:
2795 [ - + ]: 703 : ADDOP_I(c, loc, CONTAINS_OP, 0);
2796 : 703 : return SUCCESS;
2797 : 288 : case NotIn:
2798 [ - + ]: 288 : ADDOP_I(c, loc, CONTAINS_OP, 1);
2799 : 288 : return SUCCESS;
2800 : 0 : default:
2801 : 0 : Py_UNREACHABLE();
2802 : : }
2803 : : /* cmp goes in top bits of the oparg, while the low bits are used by quickened
2804 : : * versions of this opcode to store the comparison mask. */
2805 [ - + ]: 3075 : ADDOP_I(c, loc, COMPARE_OP, cmp << 4);
2806 : 3075 : return SUCCESS;
2807 : : }
2808 : :
2809 : :
2810 : :
2811 : : static int
2812 : 14708 : compiler_jump_if(struct compiler *c, location loc,
2813 : : expr_ty e, jump_target_label next, int cond)
2814 : : {
2815 [ + + + + : 14708 : switch (e->kind) {
+ ]
2816 : 1538 : case UnaryOp_kind:
2817 [ + - ]: 1538 : if (e->v.UnaryOp.op == Not) {
2818 : 1538 : return compiler_jump_if(c, loc, e->v.UnaryOp.operand, next, !cond);
2819 : : }
2820 : : /* fallback to general implementation */
2821 : 0 : break;
2822 : 1429 : case BoolOp_kind: {
2823 : 1429 : asdl_expr_seq *s = e->v.BoolOp.values;
2824 [ + - ]: 1429 : Py_ssize_t i, n = asdl_seq_LEN(s) - 1;
2825 : : assert(n >= 0);
2826 : 1429 : int cond2 = e->v.BoolOp.op == Or;
2827 : 1429 : jump_target_label next2 = next;
2828 [ + + ]: 1429 : if (!cond2 != !cond) {
2829 [ - + ]: 469 : NEW_JUMP_TARGET_LABEL(c, new_next2);
2830 : 469 : next2 = new_next2;
2831 : : }
2832 [ + + ]: 3067 : for (i = 0; i < n; ++i) {
2833 [ - + ]: 1638 : RETURN_IF_ERROR(
2834 : : compiler_jump_if(c, loc, (expr_ty)asdl_seq_GET(s, i), next2, cond2));
2835 : : }
2836 [ - + ]: 1429 : RETURN_IF_ERROR(
2837 : : compiler_jump_if(c, loc, (expr_ty)asdl_seq_GET(s, n), next, cond));
2838 [ + + ]: 1429 : if (!SAME_LABEL(next2, next)) {
2839 [ - + ]: 469 : USE_LABEL(c, next2);
2840 : : }
2841 : 1429 : return SUCCESS;
2842 : : }
2843 : 2 : case IfExp_kind: {
2844 [ - + ]: 2 : NEW_JUMP_TARGET_LABEL(c, end);
2845 [ - + ]: 2 : NEW_JUMP_TARGET_LABEL(c, next2);
2846 [ - + ]: 2 : RETURN_IF_ERROR(
2847 : : compiler_jump_if(c, loc, e->v.IfExp.test, next2, 0));
2848 [ - + ]: 2 : RETURN_IF_ERROR(
2849 : : compiler_jump_if(c, loc, e->v.IfExp.body, next, cond));
2850 [ - + ]: 2 : ADDOP_JUMP(c, NO_LOCATION, JUMP, end);
2851 : :
2852 [ - + ]: 2 : USE_LABEL(c, next2);
2853 [ - + ]: 2 : RETURN_IF_ERROR(
2854 : : compiler_jump_if(c, loc, e->v.IfExp.orelse, next, cond));
2855 : :
2856 [ - + ]: 2 : USE_LABEL(c, end);
2857 : 2 : return SUCCESS;
2858 : : }
2859 : 5835 : case Compare_kind: {
2860 [ + - ]: 5835 : Py_ssize_t n = asdl_seq_LEN(e->v.Compare.ops) - 1;
2861 [ + + ]: 5835 : if (n > 0) {
2862 [ - + ]: 46 : RETURN_IF_ERROR(check_compare(c, e));
2863 [ - + ]: 46 : NEW_JUMP_TARGET_LABEL(c, cleanup);
2864 [ - + ]: 46 : VISIT(c, expr, e->v.Compare.left);
2865 [ + + ]: 92 : for (Py_ssize_t i = 0; i < n; i++) {
2866 [ - + ]: 46 : VISIT(c, expr,
2867 : : (expr_ty)asdl_seq_GET(e->v.Compare.comparators, i));
2868 [ - + ]: 46 : ADDOP_I(c, LOC(e), SWAP, 2);
2869 [ - + ]: 46 : ADDOP_I(c, LOC(e), COPY, 2);
2870 [ - + ]: 46 : ADDOP_COMPARE(c, LOC(e), asdl_seq_GET(e->v.Compare.ops, i));
2871 [ - + ]: 46 : ADDOP_JUMP(c, LOC(e), POP_JUMP_IF_FALSE, cleanup);
2872 : : }
2873 [ - + ]: 46 : VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Compare.comparators, n));
2874 [ - + ]: 46 : ADDOP_COMPARE(c, LOC(e), asdl_seq_GET(e->v.Compare.ops, n));
2875 [ + + - + ]: 46 : ADDOP_JUMP(c, LOC(e), cond ? POP_JUMP_IF_TRUE : POP_JUMP_IF_FALSE, next);
2876 [ - + ]: 46 : NEW_JUMP_TARGET_LABEL(c, end);
2877 [ - + ]: 46 : ADDOP_JUMP(c, NO_LOCATION, JUMP, end);
2878 : :
2879 [ - + ]: 46 : USE_LABEL(c, cleanup);
2880 [ - + ]: 46 : ADDOP(c, LOC(e), POP_TOP);
2881 [ + + ]: 46 : if (!cond) {
2882 [ - + ]: 15 : ADDOP_JUMP(c, NO_LOCATION, JUMP, next);
2883 : : }
2884 : :
2885 [ - + ]: 46 : USE_LABEL(c, end);
2886 : 46 : return SUCCESS;
2887 : : }
2888 : : /* fallback to general implementation */
2889 : 5789 : break;
2890 : : }
2891 : 5904 : default:
2892 : : /* fallback to general implementation */
2893 : 5904 : break;
2894 : : }
2895 : :
2896 : : /* general implementation */
2897 [ - + ]: 11693 : VISIT(c, expr, e);
2898 [ + + - + ]: 11693 : ADDOP_JUMP(c, LOC(e), cond ? POP_JUMP_IF_TRUE : POP_JUMP_IF_FALSE, next);
2899 : 11693 : return SUCCESS;
2900 : : }
2901 : :
2902 : : static int
2903 : 231 : compiler_ifexp(struct compiler *c, expr_ty e)
2904 : : {
2905 : : assert(e->kind == IfExp_kind);
2906 [ - + ]: 231 : NEW_JUMP_TARGET_LABEL(c, end);
2907 [ - + ]: 231 : NEW_JUMP_TARGET_LABEL(c, next);
2908 : :
2909 [ - + ]: 231 : RETURN_IF_ERROR(
2910 : : compiler_jump_if(c, LOC(e), e->v.IfExp.test, next, 0));
2911 : :
2912 [ - + ]: 231 : VISIT(c, expr, e->v.IfExp.body);
2913 [ - + ]: 231 : ADDOP_JUMP(c, NO_LOCATION, JUMP, end);
2914 : :
2915 [ - + ]: 231 : USE_LABEL(c, next);
2916 [ - + ]: 231 : VISIT(c, expr, e->v.IfExp.orelse);
2917 : :
2918 [ - + ]: 231 : USE_LABEL(c, end);
2919 : 231 : return SUCCESS;
2920 : : }
2921 : :
2922 : : static int
2923 : 135 : compiler_lambda(struct compiler *c, expr_ty e)
2924 : : {
2925 : : PyCodeObject *co;
2926 : : Py_ssize_t funcflags;
2927 : 135 : arguments_ty args = e->v.Lambda.args;
2928 : : assert(e->kind == Lambda_kind);
2929 : :
2930 [ - + ]: 135 : RETURN_IF_ERROR(compiler_check_debug_args(c, args));
2931 : :
2932 : 135 : location loc = LOC(e);
2933 : 135 : funcflags = compiler_default_arguments(c, loc, args);
2934 [ - + ]: 135 : if (funcflags == -1) {
2935 : 0 : return ERROR;
2936 : : }
2937 : :
2938 : : _Py_DECLARE_STR(anon_lambda, "<lambda>");
2939 [ - + ]: 135 : RETURN_IF_ERROR(
2940 : : compiler_enter_scope(c, &_Py_STR(anon_lambda), COMPILER_SCOPE_LAMBDA,
2941 : : (void *)e, e->lineno));
2942 : :
2943 : : /* Make None the first constant, so the lambda can't have a
2944 : : docstring. */
2945 [ - + ]: 135 : RETURN_IF_ERROR(compiler_add_const(c->c_const_cache, c->u, Py_None));
2946 : :
2947 [ + - ]: 135 : c->u->u_argcount = asdl_seq_LEN(args->args);
2948 [ + - ]: 135 : c->u->u_posonlyargcount = asdl_seq_LEN(args->posonlyargs);
2949 [ + - ]: 135 : c->u->u_kwonlyargcount = asdl_seq_LEN(args->kwonlyargs);
2950 [ - + ]: 135 : VISIT_IN_SCOPE(c, expr, e->v.Lambda.body);
2951 [ + + ]: 135 : if (c->u->u_ste->ste_generator) {
2952 : 2 : co = assemble(c, 0);
2953 : : }
2954 : : else {
2955 : 133 : location loc = LOCATION(e->lineno, e->lineno, 0, 0);
2956 [ - + ]: 133 : ADDOP_IN_SCOPE(c, loc, RETURN_VALUE);
2957 : 133 : co = assemble(c, 1);
2958 : : }
2959 : 135 : compiler_exit_scope(c);
2960 [ - + ]: 135 : if (co == NULL) {
2961 : 0 : return ERROR;
2962 : : }
2963 : :
2964 [ - + ]: 135 : if (compiler_make_closure(c, loc, co, funcflags) < 0) {
2965 : 0 : Py_DECREF(co);
2966 : 0 : return ERROR;
2967 : : }
2968 : 135 : Py_DECREF(co);
2969 : :
2970 : 135 : return SUCCESS;
2971 : : }
2972 : :
2973 : : static int
2974 : 8896 : compiler_if(struct compiler *c, stmt_ty s)
2975 : : {
2976 : : jump_target_label next;
2977 : : assert(s->kind == If_kind);
2978 [ - + ]: 8896 : NEW_JUMP_TARGET_LABEL(c, end);
2979 [ + + + - ]: 8896 : if (asdl_seq_LEN(s->v.If.orelse)) {
2980 [ - + ]: 2430 : NEW_JUMP_TARGET_LABEL(c, orelse);
2981 : 2430 : next = orelse;
2982 : : }
2983 : : else {
2984 : 6466 : next = end;
2985 : : }
2986 [ - + ]: 8896 : RETURN_IF_ERROR(
2987 : : compiler_jump_if(c, LOC(s), s->v.If.test, next, 0));
2988 : :
2989 [ - + + - : 22071 : VISIT_SEQ(c, stmt, s->v.If.body);
+ + ]
2990 [ + + + - ]: 8896 : if (asdl_seq_LEN(s->v.If.orelse)) {
2991 [ - + ]: 2430 : ADDOP_JUMP(c, NO_LOCATION, JUMP, end);
2992 : :
2993 [ - + ]: 2430 : USE_LABEL(c, next);
2994 [ - + + - : 5605 : VISIT_SEQ(c, stmt, s->v.If.orelse);
+ + ]
2995 : : }
2996 : :
2997 [ - + ]: 8896 : USE_LABEL(c, end);
2998 : 8896 : return SUCCESS;
2999 : : }
3000 : :
3001 : : static int
3002 : 1236 : compiler_for(struct compiler *c, stmt_ty s)
3003 : : {
3004 : 1236 : location loc = LOC(s);
3005 [ - + ]: 1236 : NEW_JUMP_TARGET_LABEL(c, start);
3006 [ - + ]: 1236 : NEW_JUMP_TARGET_LABEL(c, body);
3007 [ - + ]: 1236 : NEW_JUMP_TARGET_LABEL(c, cleanup);
3008 [ - + ]: 1236 : NEW_JUMP_TARGET_LABEL(c, end);
3009 : :
3010 [ - + ]: 1236 : RETURN_IF_ERROR(compiler_push_fblock(c, loc, FOR_LOOP, start, end, NULL));
3011 : :
3012 [ - + ]: 1236 : VISIT(c, expr, s->v.For.iter);
3013 [ - + ]: 1236 : ADDOP(c, loc, GET_ITER);
3014 : :
3015 [ - + ]: 1236 : USE_LABEL(c, start);
3016 [ - + ]: 1236 : ADDOP_JUMP(c, loc, FOR_ITER, cleanup);
3017 : :
3018 [ - + ]: 1236 : USE_LABEL(c, body);
3019 [ - + ]: 1236 : VISIT(c, expr, s->v.For.target);
3020 [ - + + - : 3601 : VISIT_SEQ(c, stmt, s->v.For.body);
+ + ]
3021 : : /* Mark jump as artificial */
3022 [ - + ]: 1236 : ADDOP_JUMP(c, NO_LOCATION, JUMP, start);
3023 : :
3024 [ - + ]: 1236 : USE_LABEL(c, cleanup);
3025 [ - + ]: 1236 : ADDOP(c, NO_LOCATION, END_FOR);
3026 : :
3027 : 1236 : compiler_pop_fblock(c, FOR_LOOP, start);
3028 : :
3029 [ - + + + : 1299 : VISIT_SEQ(c, stmt, s->v.For.orelse);
+ + ]
3030 : :
3031 [ - + ]: 1236 : USE_LABEL(c, end);
3032 : 1236 : return SUCCESS;
3033 : : }
3034 : :
3035 : :
3036 : : static int
3037 : 0 : compiler_async_for(struct compiler *c, stmt_ty s)
3038 : : {
3039 : 0 : location loc = LOC(s);
3040 [ # # # # ]: 0 : if (IS_TOP_LEVEL_AWAIT(c)){
3041 : 0 : c->u->u_ste->ste_coroutine = 1;
3042 [ # # ]: 0 : } else if (c->u->u_scope_type != COMPILER_SCOPE_ASYNC_FUNCTION) {
3043 : 0 : return compiler_error(c, loc, "'async for' outside async function");
3044 : : }
3045 : :
3046 [ # # ]: 0 : NEW_JUMP_TARGET_LABEL(c, start);
3047 [ # # ]: 0 : NEW_JUMP_TARGET_LABEL(c, except);
3048 [ # # ]: 0 : NEW_JUMP_TARGET_LABEL(c, end);
3049 : :
3050 [ # # ]: 0 : VISIT(c, expr, s->v.AsyncFor.iter);
3051 [ # # ]: 0 : ADDOP(c, loc, GET_AITER);
3052 : :
3053 [ # # ]: 0 : USE_LABEL(c, start);
3054 [ # # ]: 0 : RETURN_IF_ERROR(compiler_push_fblock(c, loc, FOR_LOOP, start, end, NULL));
3055 : :
3056 : : /* SETUP_FINALLY to guard the __anext__ call */
3057 [ # # ]: 0 : ADDOP_JUMP(c, loc, SETUP_FINALLY, except);
3058 [ # # ]: 0 : ADDOP(c, loc, GET_ANEXT);
3059 [ # # ]: 0 : ADDOP_LOAD_CONST(c, loc, Py_None);
3060 [ # # ]: 0 : ADD_YIELD_FROM(c, loc, 1);
3061 [ # # ]: 0 : ADDOP(c, loc, POP_BLOCK); /* for SETUP_FINALLY */
3062 : :
3063 : : /* Success block for __anext__ */
3064 [ # # ]: 0 : VISIT(c, expr, s->v.AsyncFor.target);
3065 [ # # # # : 0 : VISIT_SEQ(c, stmt, s->v.AsyncFor.body);
# # ]
3066 : : /* Mark jump as artificial */
3067 [ # # ]: 0 : ADDOP_JUMP(c, NO_LOCATION, JUMP, start);
3068 : :
3069 : 0 : compiler_pop_fblock(c, FOR_LOOP, start);
3070 : :
3071 : : /* Except block for __anext__ */
3072 [ # # ]: 0 : USE_LABEL(c, except);
3073 : :
3074 : : /* Use same line number as the iterator,
3075 : : * as the END_ASYNC_FOR succeeds the `for`, not the body. */
3076 : 0 : loc = LOC(s->v.AsyncFor.iter);
3077 [ # # ]: 0 : ADDOP(c, loc, END_ASYNC_FOR);
3078 : :
3079 : : /* `else` block */
3080 [ # # # # : 0 : VISIT_SEQ(c, stmt, s->v.For.orelse);
# # ]
3081 : :
3082 [ # # ]: 0 : USE_LABEL(c, end);
3083 : 0 : return SUCCESS;
3084 : : }
3085 : :
3086 : : static int
3087 : 305 : compiler_while(struct compiler *c, stmt_ty s)
3088 : : {
3089 [ - + ]: 305 : NEW_JUMP_TARGET_LABEL(c, loop);
3090 [ - + ]: 305 : NEW_JUMP_TARGET_LABEL(c, body);
3091 [ - + ]: 305 : NEW_JUMP_TARGET_LABEL(c, end);
3092 [ - + ]: 305 : NEW_JUMP_TARGET_LABEL(c, anchor);
3093 : :
3094 [ - + ]: 305 : USE_LABEL(c, loop);
3095 : :
3096 [ - + ]: 305 : RETURN_IF_ERROR(compiler_push_fblock(c, LOC(s), WHILE_LOOP, loop, end, NULL));
3097 [ - + ]: 305 : RETURN_IF_ERROR(compiler_jump_if(c, LOC(s), s->v.While.test, anchor, 0));
3098 : :
3099 [ - + ]: 305 : USE_LABEL(c, body);
3100 [ - + + - : 1214 : VISIT_SEQ(c, stmt, s->v.While.body);
+ + ]
3101 [ - + ]: 305 : RETURN_IF_ERROR(compiler_jump_if(c, LOC(s), s->v.While.test, body, 1));
3102 : :
3103 : 305 : compiler_pop_fblock(c, WHILE_LOOP, loop);
3104 : :
3105 [ - + ]: 305 : USE_LABEL(c, anchor);
3106 [ + + ]: 305 : if (s->v.While.orelse) {
3107 [ - + + - : 10 : VISIT_SEQ(c, stmt, s->v.While.orelse);
+ + ]
3108 : : }
3109 : :
3110 [ - + ]: 305 : USE_LABEL(c, end);
3111 : 305 : return SUCCESS;
3112 : : }
3113 : :
3114 : : static int
3115 : 5842 : compiler_return(struct compiler *c, stmt_ty s)
3116 : : {
3117 : 5842 : location loc = LOC(s);
3118 [ + + ]: 11356 : int preserve_tos = ((s->v.Return.value != NULL) &&
3119 [ + + ]: 5514 : (s->v.Return.value->kind != Constant_kind));
3120 [ - + ]: 5842 : if (c->u->u_ste->ste_type != FunctionBlock) {
3121 : 0 : return compiler_error(c, loc, "'return' outside function");
3122 : : }
3123 [ + + ]: 5842 : if (s->v.Return.value != NULL &&
3124 [ + + - + ]: 5514 : c->u->u_ste->ste_coroutine && c->u->u_ste->ste_generator)
3125 : : {
3126 : 0 : return compiler_error(c, loc, "'return' with value in async generator");
3127 : : }
3128 : :
3129 [ + + ]: 5842 : if (preserve_tos) {
3130 [ - + ]: 4825 : VISIT(c, expr, s->v.Return.value);
3131 : : } else {
3132 : : /* Emit instruction with line number for return value */
3133 [ + + ]: 1017 : if (s->v.Return.value != NULL) {
3134 : 689 : loc = LOC(s->v.Return.value);
3135 [ - + ]: 689 : ADDOP(c, loc, NOP);
3136 : : }
3137 : : }
3138 [ + + + + ]: 5842 : if (s->v.Return.value == NULL || s->v.Return.value->lineno != s->lineno) {
3139 : 338 : loc = LOC(s);
3140 [ - + ]: 338 : ADDOP(c, loc, NOP);
3141 : : }
3142 : :
3143 [ - + ]: 5842 : RETURN_IF_ERROR(compiler_unwind_fblock_stack(c, &loc, preserve_tos, NULL));
3144 [ + + ]: 5842 : if (s->v.Return.value == NULL) {
3145 [ - + ]: 328 : ADDOP_LOAD_CONST(c, loc, Py_None);
3146 : : }
3147 [ + + ]: 5514 : else if (!preserve_tos) {
3148 [ - + ]: 689 : ADDOP_LOAD_CONST(c, loc, s->v.Return.value->v.Constant.value);
3149 : : }
3150 [ - + ]: 5842 : ADDOP(c, loc, RETURN_VALUE);
3151 : :
3152 : 5842 : return SUCCESS;
3153 : : }
3154 : :
3155 : : static int
3156 : 275 : compiler_break(struct compiler *c, location loc)
3157 : : {
3158 : 275 : struct fblockinfo *loop = NULL;
3159 : 275 : location origin_loc = loc;
3160 : : /* Emit instruction with line number */
3161 [ - + ]: 275 : ADDOP(c, loc, NOP);
3162 [ - + ]: 275 : RETURN_IF_ERROR(compiler_unwind_fblock_stack(c, &loc, 0, &loop));
3163 [ - + ]: 275 : if (loop == NULL) {
3164 : 0 : return compiler_error(c, origin_loc, "'break' outside loop");
3165 : : }
3166 [ - + ]: 275 : RETURN_IF_ERROR(compiler_unwind_fblock(c, &loc, loop, 0));
3167 [ - + ]: 275 : ADDOP_JUMP(c, loc, JUMP, loop->fb_exit);
3168 : 275 : return SUCCESS;
3169 : : }
3170 : :
3171 : : static int
3172 : 231 : compiler_continue(struct compiler *c, location loc)
3173 : : {
3174 : 231 : struct fblockinfo *loop = NULL;
3175 : 231 : location origin_loc = loc;
3176 : : /* Emit instruction with line number */
3177 [ - + ]: 231 : ADDOP(c, loc, NOP);
3178 [ - + ]: 231 : RETURN_IF_ERROR(compiler_unwind_fblock_stack(c, &loc, 0, &loop));
3179 [ - + ]: 231 : if (loop == NULL) {
3180 : 0 : return compiler_error(c, origin_loc, "'continue' not properly in loop");
3181 : : }
3182 [ - + ]: 231 : ADDOP_JUMP(c, loc, JUMP, loop->fb_block);
3183 : 231 : return SUCCESS;
3184 : : }
3185 : :
3186 : :
3187 : : static location
3188 : 192 : location_of_last_executing_statement(asdl_stmt_seq *stmts)
3189 : : {
3190 [ + - + - ]: 192 : for (Py_ssize_t i = asdl_seq_LEN(stmts) - 1; i >= 0; i++) {
3191 : 192 : location loc = LOC((stmt_ty)asdl_seq_GET(stmts, i));
3192 [ + - ]: 192 : if (loc.lineno > 0) {
3193 : 192 : return loc;
3194 : : }
3195 : : }
3196 : 0 : return NO_LOCATION;
3197 : : }
3198 : :
3199 : : /* Code generated for "try: <body> finally: <finalbody>" is as follows:
3200 : :
3201 : : SETUP_FINALLY L
3202 : : <code for body>
3203 : : POP_BLOCK
3204 : : <code for finalbody>
3205 : : JUMP E
3206 : : L:
3207 : : <code for finalbody>
3208 : : E:
3209 : :
3210 : : The special instructions use the block stack. Each block
3211 : : stack entry contains the instruction that created it (here
3212 : : SETUP_FINALLY), the level of the value stack at the time the
3213 : : block stack entry was created, and a label (here L).
3214 : :
3215 : : SETUP_FINALLY:
3216 : : Pushes the current value stack level and the label
3217 : : onto the block stack.
3218 : : POP_BLOCK:
3219 : : Pops en entry from the block stack.
3220 : :
3221 : : The block stack is unwound when an exception is raised:
3222 : : when a SETUP_FINALLY entry is found, the raised and the caught
3223 : : exceptions are pushed onto the value stack (and the exception
3224 : : condition is cleared), and the interpreter jumps to the label
3225 : : gotten from the block stack.
3226 : : */
3227 : :
3228 : : static int
3229 : 192 : compiler_try_finally(struct compiler *c, stmt_ty s)
3230 : : {
3231 : 192 : location loc = LOC(s);
3232 : :
3233 [ - + ]: 192 : NEW_JUMP_TARGET_LABEL(c, body);
3234 [ - + ]: 192 : NEW_JUMP_TARGET_LABEL(c, end);
3235 [ - + ]: 192 : NEW_JUMP_TARGET_LABEL(c, exit);
3236 [ - + ]: 192 : NEW_JUMP_TARGET_LABEL(c, cleanup);
3237 : :
3238 : : /* `try` block */
3239 [ - + ]: 192 : ADDOP_JUMP(c, loc, SETUP_FINALLY, end);
3240 : :
3241 [ - + ]: 192 : USE_LABEL(c, body);
3242 [ - + ]: 192 : RETURN_IF_ERROR(
3243 : : compiler_push_fblock(c, loc, FINALLY_TRY, body, end,
3244 : : s->v.Try.finalbody));
3245 : :
3246 [ + + + - : 192 : if (s->v.Try.handlers && asdl_seq_LEN(s->v.Try.handlers)) {
+ - ]
3247 [ - + ]: 20 : RETURN_IF_ERROR(compiler_try_except(c, s));
3248 : : }
3249 : : else {
3250 [ - + + - : 511 : VISIT_SEQ(c, stmt, s->v.Try.body);
+ + ]
3251 : : }
3252 [ - + ]: 192 : ADDOP(c, NO_LOCATION, POP_BLOCK);
3253 : 192 : compiler_pop_fblock(c, FINALLY_TRY, body);
3254 [ - + + - : 461 : VISIT_SEQ(c, stmt, s->v.Try.finalbody);
+ + ]
3255 : :
3256 [ - + ]: 192 : ADDOP_JUMP(c, NO_LOCATION, JUMP, exit);
3257 : : /* `finally` block */
3258 : :
3259 [ - + ]: 192 : USE_LABEL(c, end);
3260 : :
3261 : 192 : loc = NO_LOCATION;
3262 [ - + ]: 192 : ADDOP_JUMP(c, loc, SETUP_CLEANUP, cleanup);
3263 [ - + ]: 192 : ADDOP(c, loc, PUSH_EXC_INFO);
3264 [ - + ]: 192 : RETURN_IF_ERROR(
3265 : : compiler_push_fblock(c, loc, FINALLY_END, end, NO_LABEL, NULL));
3266 [ - + + - : 461 : VISIT_SEQ(c, stmt, s->v.Try.finalbody);
+ + ]
3267 : 192 : loc = location_of_last_executing_statement(s->v.Try.finalbody);
3268 : 192 : compiler_pop_fblock(c, FINALLY_END, end);
3269 : :
3270 [ - + ]: 192 : ADDOP_I(c, loc, RERAISE, 0);
3271 : :
3272 [ - + ]: 192 : USE_LABEL(c, cleanup);
3273 [ - + ]: 192 : POP_EXCEPT_AND_RERAISE(c, loc);
3274 : :
3275 [ - + ]: 192 : USE_LABEL(c, exit);
3276 : 192 : return SUCCESS;
3277 : : }
3278 : :
3279 : : static int
3280 : 0 : compiler_try_star_finally(struct compiler *c, stmt_ty s)
3281 : : {
3282 : 0 : location loc = LOC(s);
3283 : :
3284 [ # # ]: 0 : NEW_JUMP_TARGET_LABEL(c, body);
3285 [ # # ]: 0 : NEW_JUMP_TARGET_LABEL(c, end);
3286 [ # # ]: 0 : NEW_JUMP_TARGET_LABEL(c, exit);
3287 [ # # ]: 0 : NEW_JUMP_TARGET_LABEL(c, cleanup);
3288 : : /* `try` block */
3289 [ # # ]: 0 : ADDOP_JUMP(c, loc, SETUP_FINALLY, end);
3290 : :
3291 [ # # ]: 0 : USE_LABEL(c, body);
3292 [ # # ]: 0 : RETURN_IF_ERROR(
3293 : : compiler_push_fblock(c, loc, FINALLY_TRY, body, end,
3294 : : s->v.TryStar.finalbody));
3295 : :
3296 [ # # # # : 0 : if (s->v.TryStar.handlers && asdl_seq_LEN(s->v.TryStar.handlers)) {
# # ]
3297 [ # # ]: 0 : RETURN_IF_ERROR(compiler_try_star_except(c, s));
3298 : : }
3299 : : else {
3300 [ # # # # : 0 : VISIT_SEQ(c, stmt, s->v.TryStar.body);
# # ]
3301 : : }
3302 [ # # ]: 0 : ADDOP(c, NO_LOCATION, POP_BLOCK);
3303 : 0 : compiler_pop_fblock(c, FINALLY_TRY, body);
3304 [ # # # # : 0 : VISIT_SEQ(c, stmt, s->v.TryStar.finalbody);
# # ]
3305 : :
3306 [ # # ]: 0 : ADDOP_JUMP(c, NO_LOCATION, JUMP, exit);
3307 : :
3308 : : /* `finally` block */
3309 [ # # ]: 0 : USE_LABEL(c, end);
3310 : :
3311 : 0 : loc = NO_LOCATION;
3312 [ # # ]: 0 : ADDOP_JUMP(c, loc, SETUP_CLEANUP, cleanup);
3313 [ # # ]: 0 : ADDOP(c, loc, PUSH_EXC_INFO);
3314 [ # # ]: 0 : RETURN_IF_ERROR(
3315 : : compiler_push_fblock(c, loc, FINALLY_END, end, NO_LABEL, NULL));
3316 : :
3317 [ # # # # : 0 : VISIT_SEQ(c, stmt, s->v.TryStar.finalbody);
# # ]
3318 : 0 : loc = location_of_last_executing_statement(s->v.Try.finalbody);
3319 : :
3320 : 0 : compiler_pop_fblock(c, FINALLY_END, end);
3321 [ # # ]: 0 : ADDOP_I(c, loc, RERAISE, 0);
3322 : :
3323 [ # # ]: 0 : USE_LABEL(c, cleanup);
3324 [ # # ]: 0 : POP_EXCEPT_AND_RERAISE(c, loc);
3325 : :
3326 [ # # ]: 0 : USE_LABEL(c, exit);
3327 : 0 : return SUCCESS;
3328 : : }
3329 : :
3330 : :
3331 : : /*
3332 : : Code generated for "try: S except E1 as V1: S1 except E2 as V2: S2 ...":
3333 : : (The contents of the value stack is shown in [], with the top
3334 : : at the right; 'tb' is trace-back info, 'val' the exception's
3335 : : associated value, and 'exc' the exception.)
3336 : :
3337 : : Value stack Label Instruction Argument
3338 : : [] SETUP_FINALLY L1
3339 : : [] <code for S>
3340 : : [] POP_BLOCK
3341 : : [] JUMP L0
3342 : :
3343 : : [exc] L1: <evaluate E1> )
3344 : : [exc, E1] CHECK_EXC_MATCH )
3345 : : [exc, bool] POP_JUMP_IF_FALSE L2 ) only if E1
3346 : : [exc] <assign to V1> (or POP if no V1)
3347 : : [] <code for S1>
3348 : : JUMP L0
3349 : :
3350 : : [exc] L2: <evaluate E2>
3351 : : .............................etc.......................
3352 : :
3353 : : [exc] Ln+1: RERAISE # re-raise exception
3354 : :
3355 : : [] L0: <next statement>
3356 : :
3357 : : Of course, parts are not generated if Vi or Ei is not present.
3358 : : */
3359 : : static int
3360 : 1297 : compiler_try_except(struct compiler *c, stmt_ty s)
3361 : : {
3362 : 1297 : location loc = LOC(s);
3363 : : Py_ssize_t i, n;
3364 : :
3365 [ - + ]: 1297 : NEW_JUMP_TARGET_LABEL(c, body);
3366 [ - + ]: 1297 : NEW_JUMP_TARGET_LABEL(c, except);
3367 [ - + ]: 1297 : NEW_JUMP_TARGET_LABEL(c, end);
3368 [ - + ]: 1297 : NEW_JUMP_TARGET_LABEL(c, cleanup);
3369 : :
3370 [ - + ]: 1297 : ADDOP_JUMP(c, loc, SETUP_FINALLY, except);
3371 : :
3372 [ - + ]: 1297 : USE_LABEL(c, body);
3373 [ - + ]: 1297 : RETURN_IF_ERROR(
3374 : : compiler_push_fblock(c, loc, TRY_EXCEPT, body, NO_LABEL, NULL));
3375 [ - + + - : 3050 : VISIT_SEQ(c, stmt, s->v.Try.body);
+ + ]
3376 : 1297 : compiler_pop_fblock(c, TRY_EXCEPT, body);
3377 [ - + ]: 1297 : ADDOP(c, NO_LOCATION, POP_BLOCK);
3378 [ + + + - : 1297 : if (s->v.Try.orelse && asdl_seq_LEN(s->v.Try.orelse)) {
+ - ]
3379 [ - + + - : 622 : VISIT_SEQ(c, stmt, s->v.Try.orelse);
+ + ]
3380 : : }
3381 [ - + ]: 1297 : ADDOP_JUMP(c, NO_LOCATION, JUMP, end);
3382 [ + - ]: 1297 : n = asdl_seq_LEN(s->v.Try.handlers);
3383 : :
3384 [ - + ]: 1297 : USE_LABEL(c, except);
3385 : :
3386 [ - + ]: 1297 : ADDOP_JUMP(c, NO_LOCATION, SETUP_CLEANUP, cleanup);
3387 [ - + ]: 1297 : ADDOP(c, NO_LOCATION, PUSH_EXC_INFO);
3388 : :
3389 : : /* Runtime will push a block here, so we need to account for that */
3390 [ - + ]: 1297 : RETURN_IF_ERROR(
3391 : : compiler_push_fblock(c, loc, EXCEPTION_HANDLER, NO_LABEL, NO_LABEL, NULL));
3392 : :
3393 [ + + ]: 2739 : for (i = 0; i < n; i++) {
3394 : 1442 : excepthandler_ty handler = (excepthandler_ty)asdl_seq_GET(
3395 : : s->v.Try.handlers, i);
3396 : 1442 : location loc = LOC(handler);
3397 [ + + - + ]: 1442 : if (!handler->v.ExceptHandler.type && i < n-1) {
3398 : 0 : return compiler_error(c, loc, "default 'except:' must be last");
3399 : : }
3400 [ - + ]: 1442 : NEW_JUMP_TARGET_LABEL(c, next_except);
3401 : 1442 : except = next_except;
3402 [ + + ]: 1442 : if (handler->v.ExceptHandler.type) {
3403 [ - + ]: 1375 : VISIT(c, expr, handler->v.ExceptHandler.type);
3404 [ - + ]: 1375 : ADDOP(c, loc, CHECK_EXC_MATCH);
3405 [ - + ]: 1375 : ADDOP_JUMP(c, loc, POP_JUMP_IF_FALSE, except);
3406 : : }
3407 [ + + ]: 1442 : if (handler->v.ExceptHandler.name) {
3408 [ - + ]: 261 : NEW_JUMP_TARGET_LABEL(c, cleanup_end);
3409 [ - + ]: 261 : NEW_JUMP_TARGET_LABEL(c, cleanup_body);
3410 : :
3411 [ - + ]: 261 : RETURN_IF_ERROR(
3412 : : compiler_nameop(c, loc, handler->v.ExceptHandler.name, Store));
3413 : :
3414 : : /*
3415 : : try:
3416 : : # body
3417 : : except type as name:
3418 : : try:
3419 : : # body
3420 : : finally:
3421 : : name = None # in case body contains "del name"
3422 : : del name
3423 : : */
3424 : :
3425 : : /* second try: */
3426 [ - + ]: 261 : ADDOP_JUMP(c, loc, SETUP_CLEANUP, cleanup_end);
3427 : :
3428 [ - + ]: 261 : USE_LABEL(c, cleanup_body);
3429 [ - + ]: 261 : RETURN_IF_ERROR(
3430 : : compiler_push_fblock(c, loc, HANDLER_CLEANUP, cleanup_body,
3431 : : NO_LABEL, handler->v.ExceptHandler.name));
3432 : :
3433 : : /* second # body */
3434 [ - + + - : 704 : VISIT_SEQ(c, stmt, handler->v.ExceptHandler.body);
+ + ]
3435 : 261 : compiler_pop_fblock(c, HANDLER_CLEANUP, cleanup_body);
3436 : : /* name = None; del name; # Mark as artificial */
3437 [ - + ]: 261 : ADDOP(c, NO_LOCATION, POP_BLOCK);
3438 [ - + ]: 261 : ADDOP(c, NO_LOCATION, POP_BLOCK);
3439 [ - + ]: 261 : ADDOP(c, NO_LOCATION, POP_EXCEPT);
3440 [ - + ]: 261 : ADDOP_LOAD_CONST(c, NO_LOCATION, Py_None);
3441 [ - + ]: 261 : RETURN_IF_ERROR(
3442 : : compiler_nameop(c, NO_LOCATION, handler->v.ExceptHandler.name, Store));
3443 [ - + ]: 261 : RETURN_IF_ERROR(
3444 : : compiler_nameop(c, NO_LOCATION, handler->v.ExceptHandler.name, Del));
3445 [ - + ]: 261 : ADDOP_JUMP(c, NO_LOCATION, JUMP, end);
3446 : :
3447 : : /* except: */
3448 [ - + ]: 261 : USE_LABEL(c, cleanup_end);
3449 : :
3450 : : /* name = None; del name; # artificial */
3451 [ - + ]: 261 : ADDOP_LOAD_CONST(c, NO_LOCATION, Py_None);
3452 [ - + ]: 261 : RETURN_IF_ERROR(
3453 : : compiler_nameop(c, NO_LOCATION, handler->v.ExceptHandler.name, Store));
3454 [ - + ]: 261 : RETURN_IF_ERROR(
3455 : : compiler_nameop(c, NO_LOCATION, handler->v.ExceptHandler.name, Del));
3456 : :
3457 [ - + ]: 261 : ADDOP_I(c, NO_LOCATION, RERAISE, 1);
3458 : : }
3459 : : else {
3460 [ - + ]: 1181 : NEW_JUMP_TARGET_LABEL(c, cleanup_body);
3461 : :
3462 [ - + ]: 1181 : ADDOP(c, loc, POP_TOP); /* exc_value */
3463 : :
3464 [ - + ]: 1181 : USE_LABEL(c, cleanup_body);
3465 [ - + ]: 1181 : RETURN_IF_ERROR(
3466 : : compiler_push_fblock(c, loc, HANDLER_CLEANUP, cleanup_body,
3467 : : NO_LABEL, NULL));
3468 : :
3469 [ - + + - : 2665 : VISIT_SEQ(c, stmt, handler->v.ExceptHandler.body);
+ + ]
3470 : 1181 : compiler_pop_fblock(c, HANDLER_CLEANUP, cleanup_body);
3471 [ - + ]: 1181 : ADDOP(c, NO_LOCATION, POP_BLOCK);
3472 [ - + ]: 1181 : ADDOP(c, NO_LOCATION, POP_EXCEPT);
3473 [ - + ]: 1181 : ADDOP_JUMP(c, NO_LOCATION, JUMP, end);
3474 : : }
3475 : :
3476 [ - + ]: 1442 : USE_LABEL(c, except);
3477 : : }
3478 : : /* artificial */
3479 : 1297 : compiler_pop_fblock(c, EXCEPTION_HANDLER, NO_LABEL);
3480 [ - + ]: 1297 : ADDOP_I(c, NO_LOCATION, RERAISE, 0);
3481 : :
3482 [ - + ]: 1297 : USE_LABEL(c, cleanup);
3483 [ - + ]: 1297 : POP_EXCEPT_AND_RERAISE(c, NO_LOCATION);
3484 : :
3485 [ - + ]: 1297 : USE_LABEL(c, end);
3486 : 1297 : return SUCCESS;
3487 : : }
3488 : :
3489 : : /*
3490 : : Code generated for "try: S except* E1 as V1: S1 except* E2 as V2: S2 ...":
3491 : : (The contents of the value stack is shown in [], with the top
3492 : : at the right; 'tb' is trace-back info, 'val' the exception instance,
3493 : : and 'typ' the exception's type.)
3494 : :
3495 : : Value stack Label Instruction Argument
3496 : : [] SETUP_FINALLY L1
3497 : : [] <code for S>
3498 : : [] POP_BLOCK
3499 : : [] JUMP L0
3500 : :
3501 : : [exc] L1: BUILD_LIST ) list for raised/reraised excs ("result")
3502 : : [orig, res] COPY 2 ) make a copy of the original EG
3503 : :
3504 : : [orig, res, exc] <evaluate E1>
3505 : : [orig, res, exc, E1] CHECK_EG_MATCH
3506 : : [orig, res, rest/exc, match?] COPY 1
3507 : : [orig, res, rest/exc, match?, match?] POP_JUMP_IF_NOT_NONE H1
3508 : : [orig, res, exc, None] POP_TOP
3509 : : [orig, res, exc] JUMP L2
3510 : :
3511 : : [orig, res, rest, match] H1: <assign to V1> (or POP if no V1)
3512 : :
3513 : : [orig, res, rest] SETUP_FINALLY R1
3514 : : [orig, res, rest] <code for S1>
3515 : : [orig, res, rest] JUMP L2
3516 : :
3517 : : [orig, res, rest, i, v] R1: LIST_APPEND 3 ) exc raised in except* body - add to res
3518 : : [orig, res, rest, i] POP
3519 : :
3520 : : [orig, res, rest] L2: <evaluate E2>
3521 : : .............................etc.......................
3522 : :
3523 : : [orig, res, rest] Ln+1: LIST_APPEND 1 ) add unhandled exc to res (could be None)
3524 : :
3525 : : [orig, res] CALL_INTRINSIC_2 PREP_RERAISE_STAR
3526 : : [exc] COPY 1
3527 : : [exc, exc] POP_JUMP_IF_NOT_NONE RER
3528 : : [exc] POP_TOP
3529 : : [] JUMP L0
3530 : :
3531 : : [exc] RER: SWAP 2
3532 : : [exc, prev_exc_info] POP_EXCEPT
3533 : : [exc] RERAISE 0
3534 : :
3535 : : [] L0: <next statement>
3536 : : */
3537 : : static int
3538 : 0 : compiler_try_star_except(struct compiler *c, stmt_ty s)
3539 : : {
3540 : 0 : location loc = LOC(s);
3541 : :
3542 [ # # ]: 0 : NEW_JUMP_TARGET_LABEL(c, body);
3543 [ # # ]: 0 : NEW_JUMP_TARGET_LABEL(c, except);
3544 [ # # ]: 0 : NEW_JUMP_TARGET_LABEL(c, orelse);
3545 [ # # ]: 0 : NEW_JUMP_TARGET_LABEL(c, end);
3546 [ # # ]: 0 : NEW_JUMP_TARGET_LABEL(c, cleanup);
3547 [ # # ]: 0 : NEW_JUMP_TARGET_LABEL(c, reraise_star);
3548 : :
3549 [ # # ]: 0 : ADDOP_JUMP(c, loc, SETUP_FINALLY, except);
3550 : :
3551 [ # # ]: 0 : USE_LABEL(c, body);
3552 [ # # ]: 0 : RETURN_IF_ERROR(
3553 : : compiler_push_fblock(c, loc, TRY_EXCEPT, body, NO_LABEL, NULL));
3554 [ # # # # : 0 : VISIT_SEQ(c, stmt, s->v.TryStar.body);
# # ]
3555 : 0 : compiler_pop_fblock(c, TRY_EXCEPT, body);
3556 [ # # ]: 0 : ADDOP(c, NO_LOCATION, POP_BLOCK);
3557 [ # # ]: 0 : ADDOP_JUMP(c, NO_LOCATION, JUMP, orelse);
3558 [ # # ]: 0 : Py_ssize_t n = asdl_seq_LEN(s->v.TryStar.handlers);
3559 : :
3560 [ # # ]: 0 : USE_LABEL(c, except);
3561 : :
3562 [ # # ]: 0 : ADDOP_JUMP(c, NO_LOCATION, SETUP_CLEANUP, cleanup);
3563 [ # # ]: 0 : ADDOP(c, NO_LOCATION, PUSH_EXC_INFO);
3564 : :
3565 : : /* Runtime will push a block here, so we need to account for that */
3566 [ # # ]: 0 : RETURN_IF_ERROR(
3567 : : compiler_push_fblock(c, loc, EXCEPTION_GROUP_HANDLER,
3568 : : NO_LABEL, NO_LABEL, "except handler"));
3569 : :
3570 [ # # ]: 0 : for (Py_ssize_t i = 0; i < n; i++) {
3571 : 0 : excepthandler_ty handler = (excepthandler_ty)asdl_seq_GET(
3572 : : s->v.TryStar.handlers, i);
3573 : 0 : location loc = LOC(handler);
3574 [ # # ]: 0 : NEW_JUMP_TARGET_LABEL(c, next_except);
3575 : 0 : except = next_except;
3576 [ # # ]: 0 : NEW_JUMP_TARGET_LABEL(c, handle_match);
3577 [ # # ]: 0 : if (i == 0) {
3578 : : /* create empty list for exceptions raised/reraise in the except* blocks */
3579 : : /*
3580 : : [orig] BUILD_LIST
3581 : : */
3582 : : /* Create a copy of the original EG */
3583 : : /*
3584 : : [orig, []] COPY 2
3585 : : [orig, [], exc]
3586 : : */
3587 [ # # ]: 0 : ADDOP_I(c, loc, BUILD_LIST, 0);
3588 [ # # ]: 0 : ADDOP_I(c, loc, COPY, 2);
3589 : : }
3590 [ # # ]: 0 : if (handler->v.ExceptHandler.type) {
3591 [ # # ]: 0 : VISIT(c, expr, handler->v.ExceptHandler.type);
3592 [ # # ]: 0 : ADDOP(c, loc, CHECK_EG_MATCH);
3593 [ # # ]: 0 : ADDOP_I(c, loc, COPY, 1);
3594 [ # # ]: 0 : ADDOP_JUMP(c, loc, POP_JUMP_IF_NOT_NONE, handle_match);
3595 [ # # ]: 0 : ADDOP(c, loc, POP_TOP); // match
3596 [ # # ]: 0 : ADDOP_JUMP(c, loc, JUMP, except);
3597 : : }
3598 : :
3599 [ # # ]: 0 : USE_LABEL(c, handle_match);
3600 : :
3601 [ # # ]: 0 : NEW_JUMP_TARGET_LABEL(c, cleanup_end);
3602 [ # # ]: 0 : NEW_JUMP_TARGET_LABEL(c, cleanup_body);
3603 : :
3604 [ # # ]: 0 : if (handler->v.ExceptHandler.name) {
3605 [ # # ]: 0 : RETURN_IF_ERROR(
3606 : : compiler_nameop(c, loc, handler->v.ExceptHandler.name, Store));
3607 : : }
3608 : : else {
3609 [ # # ]: 0 : ADDOP(c, loc, POP_TOP); // match
3610 : : }
3611 : :
3612 : : /*
3613 : : try:
3614 : : # body
3615 : : except type as name:
3616 : : try:
3617 : : # body
3618 : : finally:
3619 : : name = None # in case body contains "del name"
3620 : : del name
3621 : : */
3622 : : /* second try: */
3623 [ # # ]: 0 : ADDOP_JUMP(c, loc, SETUP_CLEANUP, cleanup_end);
3624 : :
3625 [ # # ]: 0 : USE_LABEL(c, cleanup_body);
3626 [ # # ]: 0 : RETURN_IF_ERROR(
3627 : : compiler_push_fblock(c, loc, HANDLER_CLEANUP, cleanup_body,
3628 : : NO_LABEL, handler->v.ExceptHandler.name));
3629 : :
3630 : : /* second # body */
3631 [ # # # # : 0 : VISIT_SEQ(c, stmt, handler->v.ExceptHandler.body);
# # ]
3632 : 0 : compiler_pop_fblock(c, HANDLER_CLEANUP, cleanup_body);
3633 : : /* name = None; del name; # artificial */
3634 [ # # ]: 0 : ADDOP(c, NO_LOCATION, POP_BLOCK);
3635 [ # # ]: 0 : if (handler->v.ExceptHandler.name) {
3636 [ # # ]: 0 : ADDOP_LOAD_CONST(c, NO_LOCATION, Py_None);
3637 [ # # ]: 0 : RETURN_IF_ERROR(
3638 : : compiler_nameop(c, NO_LOCATION, handler->v.ExceptHandler.name, Store));
3639 [ # # ]: 0 : RETURN_IF_ERROR(
3640 : : compiler_nameop(c, NO_LOCATION, handler->v.ExceptHandler.name, Del));
3641 : : }
3642 [ # # ]: 0 : ADDOP_JUMP(c, NO_LOCATION, JUMP, except);
3643 : :
3644 : : /* except: */
3645 [ # # ]: 0 : USE_LABEL(c, cleanup_end);
3646 : :
3647 : : /* name = None; del name; # artificial */
3648 [ # # ]: 0 : if (handler->v.ExceptHandler.name) {
3649 [ # # ]: 0 : ADDOP_LOAD_CONST(c, NO_LOCATION, Py_None);
3650 [ # # ]: 0 : RETURN_IF_ERROR(
3651 : : compiler_nameop(c, NO_LOCATION, handler->v.ExceptHandler.name, Store));
3652 [ # # ]: 0 : RETURN_IF_ERROR(
3653 : : compiler_nameop(c, NO_LOCATION, handler->v.ExceptHandler.name, Del));
3654 : : }
3655 : :
3656 : : /* add exception raised to the res list */
3657 [ # # ]: 0 : ADDOP_I(c, NO_LOCATION, LIST_APPEND, 3); // exc
3658 [ # # ]: 0 : ADDOP(c, NO_LOCATION, POP_TOP); // lasti
3659 [ # # ]: 0 : ADDOP_JUMP(c, NO_LOCATION, JUMP, except);
3660 : :
3661 [ # # ]: 0 : USE_LABEL(c, except);
3662 : :
3663 [ # # ]: 0 : if (i == n - 1) {
3664 : : /* Add exc to the list (if not None it's the unhandled part of the EG) */
3665 [ # # ]: 0 : ADDOP_I(c, NO_LOCATION, LIST_APPEND, 1);
3666 [ # # ]: 0 : ADDOP_JUMP(c, NO_LOCATION, JUMP, reraise_star);
3667 : : }
3668 : : }
3669 : : /* artificial */
3670 : 0 : compiler_pop_fblock(c, EXCEPTION_GROUP_HANDLER, NO_LABEL);
3671 [ # # ]: 0 : NEW_JUMP_TARGET_LABEL(c, reraise);
3672 : :
3673 [ # # ]: 0 : USE_LABEL(c, reraise_star);
3674 [ # # ]: 0 : ADDOP_I(c, NO_LOCATION, CALL_INTRINSIC_2, INTRINSIC_PREP_RERAISE_STAR);
3675 [ # # ]: 0 : ADDOP_I(c, NO_LOCATION, COPY, 1);
3676 [ # # ]: 0 : ADDOP_JUMP(c, NO_LOCATION, POP_JUMP_IF_NOT_NONE, reraise);
3677 : :
3678 : : /* Nothing to reraise */
3679 [ # # ]: 0 : ADDOP(c, NO_LOCATION, POP_TOP);
3680 [ # # ]: 0 : ADDOP(c, NO_LOCATION, POP_BLOCK);
3681 [ # # ]: 0 : ADDOP(c, NO_LOCATION, POP_EXCEPT);
3682 [ # # ]: 0 : ADDOP_JUMP(c, NO_LOCATION, JUMP, end);
3683 : :
3684 [ # # ]: 0 : USE_LABEL(c, reraise);
3685 [ # # ]: 0 : ADDOP(c, NO_LOCATION, POP_BLOCK);
3686 [ # # ]: 0 : ADDOP_I(c, NO_LOCATION, SWAP, 2);
3687 [ # # ]: 0 : ADDOP(c, NO_LOCATION, POP_EXCEPT);
3688 [ # # ]: 0 : ADDOP_I(c, NO_LOCATION, RERAISE, 0);
3689 : :
3690 [ # # ]: 0 : USE_LABEL(c, cleanup);
3691 [ # # ]: 0 : POP_EXCEPT_AND_RERAISE(c, NO_LOCATION);
3692 : :
3693 [ # # ]: 0 : USE_LABEL(c, orelse);
3694 [ # # # # : 0 : VISIT_SEQ(c, stmt, s->v.TryStar.orelse);
# # ]
3695 : :
3696 [ # # ]: 0 : USE_LABEL(c, end);
3697 : 0 : return SUCCESS;
3698 : : }
3699 : :
3700 : : static int
3701 : 1469 : compiler_try(struct compiler *c, stmt_ty s) {
3702 [ + + + - : 1469 : if (s->v.Try.finalbody && asdl_seq_LEN(s->v.Try.finalbody))
+ - ]
3703 : 192 : return compiler_try_finally(c, s);
3704 : : else
3705 : 1277 : return compiler_try_except(c, s);
3706 : : }
3707 : :
3708 : : static int
3709 : 0 : compiler_try_star(struct compiler *c, stmt_ty s)
3710 : : {
3711 [ # # # # : 0 : if (s->v.TryStar.finalbody && asdl_seq_LEN(s->v.TryStar.finalbody)) {
# # ]
3712 : 0 : return compiler_try_star_finally(c, s);
3713 : : }
3714 : : else {
3715 : 0 : return compiler_try_star_except(c, s);
3716 : : }
3717 : : }
3718 : :
3719 : : static int
3720 : 50 : compiler_import_as(struct compiler *c, location loc,
3721 : : identifier name, identifier asname)
3722 : : {
3723 : : /* The IMPORT_NAME opcode was already generated. This function
3724 : : merely needs to bind the result to a name.
3725 : :
3726 : : If there is a dot in name, we need to split it and emit a
3727 : : IMPORT_FROM for each name.
3728 : : */
3729 : 50 : Py_ssize_t len = PyUnicode_GET_LENGTH(name);
3730 : 50 : Py_ssize_t dot = PyUnicode_FindChar(name, '.', 0, len, 1);
3731 [ - + ]: 50 : if (dot == -2) {
3732 : 0 : return ERROR;
3733 : : }
3734 [ + + ]: 50 : if (dot != -1) {
3735 : : /* Consume the base module name to get the first attribute */
3736 : 4 : while (1) {
3737 : 8 : Py_ssize_t pos = dot + 1;
3738 : : PyObject *attr;
3739 : 8 : dot = PyUnicode_FindChar(name, '.', pos, len, 1);
3740 [ - + ]: 8 : if (dot == -2) {
3741 : 0 : return ERROR;
3742 : : }
3743 [ + + ]: 8 : attr = PyUnicode_Substring(name, pos, (dot != -1) ? dot : len);
3744 [ - + ]: 8 : if (!attr) {
3745 : 0 : return ERROR;
3746 : : }
3747 [ - + ]: 8 : ADDOP_N(c, loc, IMPORT_FROM, attr, names);
3748 [ + + ]: 8 : if (dot == -1) {
3749 : 4 : break;
3750 : : }
3751 [ - + ]: 4 : ADDOP_I(c, loc, SWAP, 2);
3752 [ - + ]: 4 : ADDOP(c, loc, POP_TOP);
3753 : : }
3754 [ - + ]: 4 : RETURN_IF_ERROR(compiler_nameop(c, loc, asname, Store));
3755 [ - + ]: 4 : ADDOP(c, loc, POP_TOP);
3756 : 4 : return SUCCESS;
3757 : : }
3758 : 46 : return compiler_nameop(c, loc, asname, Store);
3759 : : }
3760 : :
3761 : : static int
3762 : 899 : compiler_import(struct compiler *c, stmt_ty s)
3763 : : {
3764 : 899 : location loc = LOC(s);
3765 : : /* The Import node stores a module name like a.b.c as a single
3766 : : string. This is convenient for all cases except
3767 : : import a.b.c as d
3768 : : where we need to parse that string to extract the individual
3769 : : module names.
3770 : : XXX Perhaps change the representation to make this case simpler?
3771 : : */
3772 [ + - ]: 899 : Py_ssize_t i, n = asdl_seq_LEN(s->v.Import.names);
3773 : :
3774 : 899 : PyObject *zero = _PyLong_GetZero(); // borrowed reference
3775 [ + + ]: 1819 : for (i = 0; i < n; i++) {
3776 : 920 : alias_ty alias = (alias_ty)asdl_seq_GET(s->v.Import.names, i);
3777 : : int r;
3778 : :
3779 [ - + ]: 920 : ADDOP_LOAD_CONST(c, loc, zero);
3780 [ - + ]: 920 : ADDOP_LOAD_CONST(c, loc, Py_None);
3781 [ - + ]: 920 : ADDOP_NAME(c, loc, IMPORT_NAME, alias->name, names);
3782 : :
3783 [ + + ]: 920 : if (alias->asname) {
3784 : 50 : r = compiler_import_as(c, loc, alias->name, alias->asname);
3785 [ - + ]: 50 : RETURN_IF_ERROR(r);
3786 : : }
3787 : : else {
3788 : 870 : identifier tmp = alias->name;
3789 : 870 : Py_ssize_t dot = PyUnicode_FindChar(
3790 : 870 : alias->name, '.', 0, PyUnicode_GET_LENGTH(alias->name), 1);
3791 [ + + ]: 870 : if (dot != -1) {
3792 : 22 : tmp = PyUnicode_Substring(alias->name, 0, dot);
3793 [ - + ]: 22 : if (tmp == NULL) {
3794 : 0 : return ERROR;
3795 : : }
3796 : : }
3797 : 870 : r = compiler_nameop(c, loc, tmp, Store);
3798 [ + + ]: 870 : if (dot != -1) {
3799 : 22 : Py_DECREF(tmp);
3800 : : }
3801 [ - + ]: 870 : RETURN_IF_ERROR(r);
3802 : : }
3803 : : }
3804 : 899 : return SUCCESS;
3805 : : }
3806 : :
3807 : : static int
3808 : 524 : compiler_from_import(struct compiler *c, stmt_ty s)
3809 : : {
3810 [ + - ]: 524 : Py_ssize_t n = asdl_seq_LEN(s->v.ImportFrom.names);
3811 : :
3812 [ - + - + ]: 524 : ADDOP_LOAD_CONST_NEW(c, LOC(s), PyLong_FromLong(s->v.ImportFrom.level));
3813 : :
3814 : 524 : PyObject *names = PyTuple_New(n);
3815 [ - + ]: 524 : if (!names) {
3816 : 0 : return ERROR;
3817 : : }
3818 : :
3819 : : /* build up the names */
3820 [ + + ]: 1347 : for (Py_ssize_t i = 0; i < n; i++) {
3821 : 823 : alias_ty alias = (alias_ty)asdl_seq_GET(s->v.ImportFrom.names, i);
3822 : 823 : PyTuple_SET_ITEM(names, i, Py_NewRef(alias->name));
3823 : : }
3824 : :
3825 [ + - ]: 524 : if (location_is_after(LOC(s), c->c_future.ff_location) &&
3826 [ + + - + ]: 953 : s->v.ImportFrom.module &&
3827 : 429 : _PyUnicode_EqualToASCIIString(s->v.ImportFrom.module, "__future__"))
3828 : : {
3829 : 0 : Py_DECREF(names);
3830 : 0 : return compiler_error(c, LOC(s), "from __future__ imports must occur "
3831 : : "at the beginning of the file");
3832 : : }
3833 [ - + - + ]: 524 : ADDOP_LOAD_CONST_NEW(c, LOC(s), names);
3834 : :
3835 [ + + ]: 524 : if (s->v.ImportFrom.module) {
3836 [ - + ]: 429 : ADDOP_NAME(c, LOC(s), IMPORT_NAME, s->v.ImportFrom.module, names);
3837 : : }
3838 : : else {
3839 : : _Py_DECLARE_STR(empty, "");
3840 [ - + ]: 95 : ADDOP_NAME(c, LOC(s), IMPORT_NAME, &_Py_STR(empty), names);
3841 : : }
3842 [ + + ]: 1299 : for (Py_ssize_t i = 0; i < n; i++) {
3843 : 823 : alias_ty alias = (alias_ty)asdl_seq_GET(s->v.ImportFrom.names, i);
3844 : : identifier store_name;
3845 : :
3846 [ + + + + ]: 823 : if (i == 0 && PyUnicode_READ_CHAR(alias->name, 0) == '*') {
3847 : : assert(n == 1);
3848 [ - + ]: 48 : ADDOP_I(c, LOC(s), CALL_INTRINSIC_1, INTRINSIC_IMPORT_STAR);
3849 [ - + ]: 48 : ADDOP(c, NO_LOCATION, POP_TOP);
3850 : 48 : return SUCCESS;
3851 : : }
3852 : :
3853 [ - + ]: 775 : ADDOP_NAME(c, LOC(s), IMPORT_FROM, alias->name, names);
3854 : 775 : store_name = alias->name;
3855 [ + + ]: 775 : if (alias->asname) {
3856 : 90 : store_name = alias->asname;
3857 : : }
3858 : :
3859 [ - + ]: 775 : RETURN_IF_ERROR(compiler_nameop(c, LOC(s), store_name, Store));
3860 : : }
3861 : : /* remove imported module */
3862 [ - + ]: 476 : ADDOP(c, LOC(s), POP_TOP);
3863 : 476 : return SUCCESS;
3864 : : }
3865 : :
3866 : : static int
3867 : 239 : compiler_assert(struct compiler *c, stmt_ty s)
3868 : : {
3869 : : /* Always emit a warning if the test is a non-zero length tuple */
3870 [ - + ]: 239 : if ((s->v.Assert.test->kind == Tuple_kind &&
3871 [ # # # # ]: 0 : asdl_seq_LEN(s->v.Assert.test->v.Tuple.elts) > 0) ||
3872 [ + + - + ]: 242 : (s->v.Assert.test->kind == Constant_kind &&
3873 [ - - ]: 3 : PyTuple_Check(s->v.Assert.test->v.Constant.value) &&
3874 : 0 : PyTuple_Size(s->v.Assert.test->v.Constant.value) > 0))
3875 : : {
3876 [ # # ]: 0 : RETURN_IF_ERROR(
3877 : : compiler_warn(c, LOC(s), "assertion is always true, "
3878 : : "perhaps remove parentheses?"));
3879 : : }
3880 [ - + ]: 239 : if (c->c_optimize) {
3881 : 0 : return SUCCESS;
3882 : : }
3883 [ - + ]: 239 : NEW_JUMP_TARGET_LABEL(c, end);
3884 [ - + ]: 239 : RETURN_IF_ERROR(compiler_jump_if(c, LOC(s), s->v.Assert.test, end, 1));
3885 [ - + ]: 239 : ADDOP(c, LOC(s), LOAD_ASSERTION_ERROR);
3886 [ + + ]: 239 : if (s->v.Assert.msg) {
3887 [ - + ]: 71 : VISIT(c, expr, s->v.Assert.msg);
3888 [ - + ]: 71 : ADDOP_I(c, LOC(s), CALL, 0);
3889 : : }
3890 [ - + ]: 239 : ADDOP_I(c, LOC(s), RAISE_VARARGS, 1);
3891 : :
3892 [ - + ]: 239 : USE_LABEL(c, end);
3893 : 239 : return SUCCESS;
3894 : : }
3895 : :
3896 : : static int
3897 : 8026 : compiler_stmt_expr(struct compiler *c, location loc, expr_ty value)
3898 : : {
3899 [ + + + - ]: 8026 : if (c->c_interactive && c->c_nestlevel <= 1) {
3900 [ - + ]: 47 : VISIT(c, expr, value);
3901 [ - + ]: 47 : ADDOP_I(c, loc, CALL_INTRINSIC_1, INTRINSIC_PRINT);
3902 [ - + ]: 47 : ADDOP(c, NO_LOCATION, POP_TOP);
3903 : 47 : return SUCCESS;
3904 : : }
3905 : :
3906 [ + + ]: 7979 : if (value->kind == Constant_kind) {
3907 : : /* ignore constant statement */
3908 [ - + ]: 1 : ADDOP(c, loc, NOP);
3909 : 1 : return SUCCESS;
3910 : : }
3911 : :
3912 [ - + ]: 7978 : VISIT(c, expr, value);
3913 [ - + ]: 7978 : ADDOP(c, NO_LOCATION, POP_TOP); /* artificial */
3914 : 7978 : return SUCCESS;
3915 : : }
3916 : :
3917 : : static int
3918 : 55660 : compiler_visit_stmt(struct compiler *c, stmt_ty s)
3919 : : {
3920 : :
3921 [ + + + + : 55660 : switch (s->kind) {
+ + + + +
+ + + + -
+ + + + +
+ + + + +
+ - - ]
3922 : 6243 : case FunctionDef_kind:
3923 : 6243 : return compiler_function(c, s, 0);
3924 : 733 : case ClassDef_kind:
3925 : 733 : return compiler_class(c, s);
3926 : 5842 : case Return_kind:
3927 : 5842 : return compiler_return(c, s);
3928 : 201 : case Delete_kind:
3929 [ - + + - : 439 : VISIT_SEQ(c, expr, s->v.Delete.targets)
+ + ]
3930 : 201 : break;
3931 : 16725 : case Assign_kind:
3932 : : {
3933 [ + - ]: 16725 : Py_ssize_t n = asdl_seq_LEN(s->v.Assign.targets);
3934 [ - + ]: 16725 : VISIT(c, expr, s->v.Assign.value);
3935 [ + + ]: 33608 : for (Py_ssize_t i = 0; i < n; i++) {
3936 [ + + ]: 16883 : if (i < n - 1) {
3937 [ - + ]: 158 : ADDOP_I(c, LOC(s), COPY, 1);
3938 : : }
3939 [ - + ]: 16883 : VISIT(c, expr,
3940 : : (expr_ty)asdl_seq_GET(s->v.Assign.targets, i));
3941 : : }
3942 : 16725 : break;
3943 : : }
3944 : 722 : case AugAssign_kind:
3945 : 722 : return compiler_augassign(c, s);
3946 : 17 : case AnnAssign_kind:
3947 : 17 : return compiler_annassign(c, s);
3948 : 1236 : case For_kind:
3949 : 1236 : return compiler_for(c, s);
3950 : 305 : case While_kind:
3951 : 305 : return compiler_while(c, s);
3952 : 8896 : case If_kind:
3953 : 8896 : return compiler_if(c, s);
3954 : 4 : case Match_kind:
3955 : 4 : return compiler_match(c, s);
3956 : 1939 : case Raise_kind:
3957 : : {
3958 : 1939 : Py_ssize_t n = 0;
3959 [ + + ]: 1939 : if (s->v.Raise.exc) {
3960 [ - + ]: 1739 : VISIT(c, expr, s->v.Raise.exc);
3961 : 1739 : n++;
3962 [ + + ]: 1739 : if (s->v.Raise.cause) {
3963 [ - + ]: 102 : VISIT(c, expr, s->v.Raise.cause);
3964 : 102 : n++;
3965 : : }
3966 : : }
3967 [ - + ]: 1939 : ADDOP_I(c, LOC(s), RAISE_VARARGS, (int)n);
3968 : 1939 : break;
3969 : : }
3970 : 1469 : case Try_kind:
3971 : 1469 : return compiler_try(c, s);
3972 : 0 : case TryStar_kind:
3973 : 0 : return compiler_try_star(c, s);
3974 : 239 : case Assert_kind:
3975 : 239 : return compiler_assert(c, s);
3976 : 899 : case Import_kind:
3977 : 899 : return compiler_import(c, s);
3978 : 524 : case ImportFrom_kind:
3979 : 524 : return compiler_from_import(c, s);
3980 : 87 : case Global_kind:
3981 : : case Nonlocal_kind:
3982 : 87 : break;
3983 : 8026 : case Expr_kind:
3984 : : {
3985 : 8026 : return compiler_stmt_expr(c, LOC(s), s->v.Expr.value);
3986 : : }
3987 : 505 : case Pass_kind:
3988 : : {
3989 [ - + ]: 505 : ADDOP(c, LOC(s), NOP);
3990 : 505 : break;
3991 : : }
3992 : 275 : case Break_kind:
3993 : : {
3994 : 275 : return compiler_break(c, LOC(s));
3995 : : }
3996 : 231 : case Continue_kind:
3997 : : {
3998 : 231 : return compiler_continue(c, LOC(s));
3999 : : }
4000 : 379 : case With_kind:
4001 : 379 : return compiler_with(c, s, 0);
4002 : 158 : case AsyncFunctionDef_kind:
4003 : 158 : return compiler_function(c, s, 1);
4004 : 5 : case AsyncWith_kind:
4005 : 5 : return compiler_async_with(c, s, 0);
4006 : 0 : case AsyncFor_kind:
4007 : 0 : return compiler_async_for(c, s);
4008 : : }
4009 : :
4010 : 19457 : return SUCCESS;
4011 : : }
4012 : :
4013 : : static int
4014 : 266 : unaryop(unaryop_ty op)
4015 : : {
4016 [ + + + - ]: 266 : switch (op) {
4017 : 25 : case Invert:
4018 : 25 : return UNARY_INVERT;
4019 : 73 : case Not:
4020 : 73 : return UNARY_NOT;
4021 : 168 : case USub:
4022 : 168 : return UNARY_NEGATIVE;
4023 : 0 : default:
4024 : 0 : PyErr_Format(PyExc_SystemError,
4025 : : "unary op %d should not be possible", op);
4026 : 0 : return 0;
4027 : : }
4028 : : }
4029 : :
4030 : : static int
4031 : 4263 : addop_binary(struct compiler *c, location loc, operator_ty binop,
4032 : : bool inplace)
4033 : : {
4034 : : int oparg;
4035 [ + + + + : 4263 : switch (binop) {
+ + + + +
+ + + +
- ]
4036 : 1898 : case Add:
4037 [ + + ]: 1898 : oparg = inplace ? NB_INPLACE_ADD : NB_ADD;
4038 : 1898 : break;
4039 : 627 : case Sub:
4040 [ + + ]: 627 : oparg = inplace ? NB_INPLACE_SUBTRACT : NB_SUBTRACT;
4041 : 627 : break;
4042 : 415 : case Mult:
4043 [ + + ]: 415 : oparg = inplace ? NB_INPLACE_MULTIPLY : NB_MULTIPLY;
4044 : 415 : break;
4045 : 2 : case MatMult:
4046 [ + + ]: 2 : oparg = inplace ? NB_INPLACE_MATRIX_MULTIPLY : NB_MATRIX_MULTIPLY;
4047 : 2 : break;
4048 : 111 : case Div:
4049 [ + + ]: 111 : oparg = inplace ? NB_INPLACE_TRUE_DIVIDE : NB_TRUE_DIVIDE;
4050 : 111 : break;
4051 : 542 : case Mod:
4052 [ + + ]: 542 : oparg = inplace ? NB_INPLACE_REMAINDER : NB_REMAINDER;
4053 : 542 : break;
4054 : 91 : case Pow:
4055 [ + + ]: 91 : oparg = inplace ? NB_INPLACE_POWER : NB_POWER;
4056 : 91 : break;
4057 : 39 : case LShift:
4058 [ + + ]: 39 : oparg = inplace ? NB_INPLACE_LSHIFT : NB_LSHIFT;
4059 : 39 : break;
4060 : 25 : case RShift:
4061 [ + + ]: 25 : oparg = inplace ? NB_INPLACE_RSHIFT : NB_RSHIFT;
4062 : 25 : break;
4063 : 186 : case BitOr:
4064 [ + + ]: 186 : oparg = inplace ? NB_INPLACE_OR : NB_OR;
4065 : 186 : break;
4066 : 22 : case BitXor:
4067 [ + + ]: 22 : oparg = inplace ? NB_INPLACE_XOR : NB_XOR;
4068 : 22 : break;
4069 : 210 : case BitAnd:
4070 [ + + ]: 210 : oparg = inplace ? NB_INPLACE_AND : NB_AND;
4071 : 210 : break;
4072 : 95 : case FloorDiv:
4073 [ + + ]: 95 : oparg = inplace ? NB_INPLACE_FLOOR_DIVIDE : NB_FLOOR_DIVIDE;
4074 : 95 : break;
4075 : 0 : default:
4076 [ # # ]: 0 : PyErr_Format(PyExc_SystemError, "%s op %d should not be possible",
4077 : : inplace ? "inplace" : "binary", binop);
4078 : 0 : return ERROR;
4079 : : }
4080 [ - + ]: 4263 : ADDOP_I(c, loc, BINARY_OP, oparg);
4081 : 4263 : return SUCCESS;
4082 : : }
4083 : :
4084 : :
4085 : : static int
4086 : 449 : addop_yield(struct compiler *c, location loc) {
4087 [ + - + + ]: 449 : if (c->u->u_ste->ste_generator && c->u->u_ste->ste_coroutine) {
4088 [ - + ]: 3 : ADDOP_I(c, loc, CALL_INTRINSIC_1, INTRINSIC_ASYNC_GEN_WRAP);
4089 : : }
4090 [ - + ]: 449 : ADDOP_I(c, loc, YIELD_VALUE, 0);
4091 [ - + ]: 449 : ADDOP_I(c, loc, RESUME, 1);
4092 : 449 : return SUCCESS;
4093 : : }
4094 : :
4095 : : static int
4096 : 115879 : compiler_nameop(struct compiler *c, location loc,
4097 : : identifier name, expr_context_ty ctx)
4098 : : {
4099 : : int op, scope;
4100 : : Py_ssize_t arg;
4101 : : enum { OP_FAST, OP_GLOBAL, OP_DEREF, OP_NAME } optype;
4102 : :
4103 : 115879 : PyObject *dict = c->u->u_names;
4104 : : PyObject *mangled;
4105 : :
4106 : : assert(!_PyUnicode_EqualToASCIIString(name, "None") &&
4107 : : !_PyUnicode_EqualToASCIIString(name, "True") &&
4108 : : !_PyUnicode_EqualToASCIIString(name, "False"));
4109 : :
4110 [ - + ]: 115879 : if (forbidden_name(c, loc, name, ctx)) {
4111 : 0 : return ERROR;
4112 : : }
4113 : :
4114 : 115879 : mangled = _Py_Mangle(c->u->u_private, name);
4115 [ - + ]: 115879 : if (!mangled) {
4116 : 0 : return ERROR;
4117 : : }
4118 : :
4119 : 115879 : op = 0;
4120 : 115879 : optype = OP_NAME;
4121 : 115879 : scope = _PyST_GetScope(c->u->u_ste, mangled);
4122 [ + + + + : 115879 : switch (scope) {
+ + ]
4123 : 996 : case FREE:
4124 : 996 : dict = c->u->u_freevars;
4125 : 996 : optype = OP_DEREF;
4126 : 996 : break;
4127 : 1452 : case CELL:
4128 : 1452 : dict = c->u->u_cellvars;
4129 : 1452 : optype = OP_DEREF;
4130 : 1452 : break;
4131 : 86222 : case LOCAL:
4132 [ + + ]: 86222 : if (c->u->u_ste->ste_type == FunctionBlock)
4133 : 71661 : optype = OP_FAST;
4134 : 86222 : break;
4135 : 24052 : case GLOBAL_IMPLICIT:
4136 [ + + ]: 24052 : if (c->u->u_ste->ste_type == FunctionBlock)
4137 : 21268 : optype = OP_GLOBAL;
4138 : 24052 : break;
4139 : 287 : case GLOBAL_EXPLICIT:
4140 : 287 : optype = OP_GLOBAL;
4141 : 287 : break;
4142 : 2870 : default:
4143 : : /* scope can be 0 */
4144 : 2870 : break;
4145 : : }
4146 : :
4147 : : /* XXX Leave assert here, but handle __doc__ and the like better */
4148 : : assert(scope || PyUnicode_READ_CHAR(name, 0) == '_');
4149 : :
4150 [ + + + + : 115879 : switch (optype) {
- ]
4151 [ + + - - ]: 2448 : case OP_DEREF:
4152 : : switch (ctx) {
4153 : 2022 : case Load:
4154 [ + + ]: 2022 : op = (c->u->u_ste->ste_type == ClassBlock) ? LOAD_CLASSDEREF : LOAD_DEREF;
4155 : 2022 : break;
4156 : 426 : case Store: op = STORE_DEREF; break;
4157 : 0 : case Del: op = DELETE_DEREF; break;
4158 : : }
4159 : 2448 : break;
4160 [ + + + - ]: 71661 : case OP_FAST:
4161 : : switch (ctx) {
4162 : 55671 : case Load: op = LOAD_FAST; break;
4163 : 15390 : case Store: op = STORE_FAST; break;
4164 : 600 : case Del: op = DELETE_FAST; break;
4165 : : }
4166 [ - + ]: 71661 : ADDOP_N(c, loc, op, mangled, varnames);
4167 : 71661 : return SUCCESS;
4168 [ + + - - ]: 21555 : case OP_GLOBAL:
4169 : : switch (ctx) {
4170 : 21400 : case Load: op = LOAD_GLOBAL; break;
4171 : 155 : case Store: op = STORE_GLOBAL; break;
4172 : 0 : case Del: op = DELETE_GLOBAL; break;
4173 : : }
4174 : 21555 : break;
4175 [ + + + - ]: 20215 : case OP_NAME:
4176 : : switch (ctx) {
4177 : 6996 : case Load: op = LOAD_NAME; break;
4178 : 13085 : case Store: op = STORE_NAME; break;
4179 : 134 : case Del: op = DELETE_NAME; break;
4180 : : }
4181 : 20215 : break;
4182 : : }
4183 : :
4184 : 44218 : assert(op);
4185 : 44218 : arg = dict_add_o(dict, mangled);
4186 : 44218 : Py_DECREF(mangled);
4187 [ - + ]: 44218 : if (arg < 0) {
4188 : 0 : return ERROR;
4189 : : }
4190 [ + + ]: 44218 : if (op == LOAD_GLOBAL) {
4191 : 21400 : arg <<= 1;
4192 : : }
4193 : 44218 : return codegen_addop_i(INSTR_SEQUENCE(c), op, arg, loc);
4194 : : }
4195 : :
4196 : : static int
4197 : 392 : compiler_boolop(struct compiler *c, expr_ty e)
4198 : : {
4199 : : int jumpi;
4200 : : Py_ssize_t i, n;
4201 : : asdl_expr_seq *s;
4202 : :
4203 : 392 : location loc = LOC(e);
4204 : : assert(e->kind == BoolOp_kind);
4205 [ + + ]: 392 : if (e->v.BoolOp.op == And)
4206 : 152 : jumpi = JUMP_IF_FALSE_OR_POP;
4207 : : else
4208 : 240 : jumpi = JUMP_IF_TRUE_OR_POP;
4209 [ - + ]: 392 : NEW_JUMP_TARGET_LABEL(c, end);
4210 : 392 : s = e->v.BoolOp.values;
4211 [ + - ]: 392 : n = asdl_seq_LEN(s) - 1;
4212 : : assert(n >= 0);
4213 [ + + ]: 846 : for (i = 0; i < n; ++i) {
4214 [ - + ]: 454 : VISIT(c, expr, (expr_ty)asdl_seq_GET(s, i));
4215 [ - + ]: 454 : ADDOP_JUMP(c, loc, jumpi, end);
4216 [ - + ]: 454 : NEW_JUMP_TARGET_LABEL(c, next);
4217 : :
4218 [ - + ]: 454 : USE_LABEL(c, next);
4219 : : }
4220 [ - + ]: 392 : VISIT(c, expr, (expr_ty)asdl_seq_GET(s, n));
4221 : :
4222 [ - + ]: 392 : USE_LABEL(c, end);
4223 : 392 : return SUCCESS;
4224 : : }
4225 : :
4226 : : static int
4227 : 3075 : starunpack_helper(struct compiler *c, location loc,
4228 : : asdl_expr_seq *elts, int pushed,
4229 : : int build, int add, int extend, int tuple)
4230 : : {
4231 [ + + ]: 3075 : Py_ssize_t n = asdl_seq_LEN(elts);
4232 [ + + + + ]: 3075 : if (n > 2 && are_all_items_const(elts, 0, n)) {
4233 : 180 : PyObject *folded = PyTuple_New(n);
4234 [ - + ]: 180 : if (folded == NULL) {
4235 : 0 : return ERROR;
4236 : : }
4237 : : PyObject *val;
4238 [ + + ]: 2505 : for (Py_ssize_t i = 0; i < n; i++) {
4239 : 2325 : val = ((expr_ty)asdl_seq_GET(elts, i))->v.Constant.value;
4240 : 2325 : PyTuple_SET_ITEM(folded, i, Py_NewRef(val));
4241 : : }
4242 [ + + + - ]: 180 : if (tuple && !pushed) {
4243 [ - + - + ]: 1 : ADDOP_LOAD_CONST_NEW(c, loc, folded);
4244 : : } else {
4245 [ + + ]: 179 : if (add == SET_ADD) {
4246 : 8 : Py_SETREF(folded, PyFrozenSet_New(folded));
4247 [ - + ]: 8 : if (folded == NULL) {
4248 : 0 : return ERROR;
4249 : : }
4250 : : }
4251 [ - + ]: 179 : ADDOP_I(c, loc, build, pushed);
4252 [ - + - + ]: 179 : ADDOP_LOAD_CONST_NEW(c, loc, folded);
4253 [ - + ]: 179 : ADDOP_I(c, loc, extend, 1);
4254 [ - + ]: 179 : if (tuple) {
4255 [ # # ]: 0 : ADDOP_I(c, loc, CALL_INTRINSIC_1, INTRINSIC_LIST_TO_TUPLE);
4256 : : }
4257 : : }
4258 : 180 : return SUCCESS;
4259 : : }
4260 : :
4261 : 2895 : int big = n+pushed > STACK_USE_GUIDELINE;
4262 : 2895 : int seen_star = 0;
4263 [ + + ]: 8326 : for (Py_ssize_t i = 0; i < n; i++) {
4264 : 5562 : expr_ty elt = asdl_seq_GET(elts, i);
4265 [ + + ]: 5562 : if (elt->kind == Starred_kind) {
4266 : 131 : seen_star = 1;
4267 : 131 : break;
4268 : : }
4269 : : }
4270 [ + + + - ]: 2895 : if (!seen_star && !big) {
4271 [ + + ]: 8019 : for (Py_ssize_t i = 0; i < n; i++) {
4272 : 5255 : expr_ty elt = asdl_seq_GET(elts, i);
4273 [ - + ]: 5255 : VISIT(c, expr, elt);
4274 : : }
4275 [ + + ]: 2764 : if (tuple) {
4276 [ - + ]: 1877 : ADDOP_I(c, loc, BUILD_TUPLE, n+pushed);
4277 : : } else {
4278 [ - + ]: 887 : ADDOP_I(c, loc, build, n+pushed);
4279 : : }
4280 : 2764 : return SUCCESS;
4281 : : }
4282 : 131 : int sequence_built = 0;
4283 [ - + ]: 131 : if (big) {
4284 [ # # ]: 0 : ADDOP_I(c, loc, build, pushed);
4285 : 0 : sequence_built = 1;
4286 : : }
4287 [ + + ]: 456 : for (Py_ssize_t i = 0; i < n; i++) {
4288 : 325 : expr_ty elt = asdl_seq_GET(elts, i);
4289 [ + + ]: 325 : if (elt->kind == Starred_kind) {
4290 [ + + ]: 140 : if (sequence_built == 0) {
4291 [ - + ]: 131 : ADDOP_I(c, loc, build, i+pushed);
4292 : 131 : sequence_built = 1;
4293 : : }
4294 [ - + ]: 140 : VISIT(c, expr, elt->v.Starred.value);
4295 [ - + ]: 140 : ADDOP_I(c, loc, extend, 1);
4296 : : }
4297 : : else {
4298 [ - + ]: 185 : VISIT(c, expr, elt);
4299 [ + + ]: 185 : if (sequence_built) {
4300 [ - + ]: 9 : ADDOP_I(c, loc, add, 1);
4301 : : }
4302 : : }
4303 : : }
4304 : : assert(sequence_built);
4305 [ + + ]: 131 : if (tuple) {
4306 [ - + ]: 129 : ADDOP_I(c, loc, CALL_INTRINSIC_1, INTRINSIC_LIST_TO_TUPLE);
4307 : : }
4308 : 131 : return SUCCESS;
4309 : : }
4310 : :
4311 : : static int
4312 : 1134 : unpack_helper(struct compiler *c, location loc, asdl_expr_seq *elts)
4313 : : {
4314 [ + - ]: 1134 : Py_ssize_t n = asdl_seq_LEN(elts);
4315 : 1134 : int seen_star = 0;
4316 [ + + ]: 3864 : for (Py_ssize_t i = 0; i < n; i++) {
4317 : 2730 : expr_ty elt = asdl_seq_GET(elts, i);
4318 [ + + + - ]: 2730 : if (elt->kind == Starred_kind && !seen_star) {
4319 [ + - ]: 7 : if ((i >= (1 << 8)) ||
4320 [ - + ]: 7 : (n-i-1 >= (INT_MAX >> 8))) {
4321 : 0 : return compiler_error(c, loc,
4322 : : "too many expressions in "
4323 : : "star-unpacking assignment");
4324 : : }
4325 [ - + ]: 7 : ADDOP_I(c, loc, UNPACK_EX, (i + ((n-i-1) << 8)));
4326 : 7 : seen_star = 1;
4327 : : }
4328 [ - + ]: 2723 : else if (elt->kind == Starred_kind) {
4329 : 0 : return compiler_error(c, loc,
4330 : : "multiple starred expressions in assignment");
4331 : : }
4332 : : }
4333 [ + + ]: 1134 : if (!seen_star) {
4334 [ - + ]: 1127 : ADDOP_I(c, loc, UNPACK_SEQUENCE, n);
4335 : : }
4336 : 1134 : return SUCCESS;
4337 : : }
4338 : :
4339 : : static int
4340 : 1134 : assignment_helper(struct compiler *c, location loc, asdl_expr_seq *elts)
4341 : : {
4342 [ + - ]: 1134 : Py_ssize_t n = asdl_seq_LEN(elts);
4343 [ - + ]: 1134 : RETURN_IF_ERROR(unpack_helper(c, loc, elts));
4344 [ + + ]: 3864 : for (Py_ssize_t i = 0; i < n; i++) {
4345 : 2730 : expr_ty elt = asdl_seq_GET(elts, i);
4346 [ + + - + ]: 2730 : VISIT(c, expr, elt->kind != Starred_kind ? elt : elt->v.Starred.value);
4347 : : }
4348 : 1134 : return SUCCESS;
4349 : : }
4350 : :
4351 : : static int
4352 : 1029 : compiler_list(struct compiler *c, expr_ty e)
4353 : : {
4354 : 1029 : location loc = LOC(e);
4355 : 1029 : asdl_expr_seq *elts = e->v.List.elts;
4356 [ + + ]: 1029 : if (e->v.List.ctx == Store) {
4357 : 1 : return assignment_helper(c, loc, elts);
4358 : : }
4359 [ + - ]: 1028 : else if (e->v.List.ctx == Load) {
4360 : 1028 : return starunpack_helper(c, loc, elts, 0,
4361 : : BUILD_LIST, LIST_APPEND, LIST_EXTEND, 0);
4362 : : }
4363 : : else {
4364 [ # # # # : 0 : VISIT_SEQ(c, expr, elts);
# # ]
4365 : : }
4366 : 0 : return SUCCESS;
4367 : : }
4368 : :
4369 : : static int
4370 : 2952 : compiler_tuple(struct compiler *c, expr_ty e)
4371 : : {
4372 : 2952 : location loc = LOC(e);
4373 : 2952 : asdl_expr_seq *elts = e->v.Tuple.elts;
4374 [ + + ]: 2952 : if (e->v.Tuple.ctx == Store) {
4375 : 1133 : return assignment_helper(c, loc, elts);
4376 : : }
4377 [ + + ]: 1819 : else if (e->v.Tuple.ctx == Load) {
4378 : 1818 : return starunpack_helper(c, loc, elts, 0,
4379 : : BUILD_LIST, LIST_APPEND, LIST_EXTEND, 1);
4380 : : }
4381 : : else {
4382 [ - + + - : 43 : VISIT_SEQ(c, expr, elts);
+ + ]
4383 : : }
4384 : 1 : return SUCCESS;
4385 : : }
4386 : :
4387 : : static int
4388 : 40 : compiler_set(struct compiler *c, expr_ty e)
4389 : : {
4390 : 40 : location loc = LOC(e);
4391 : 40 : return starunpack_helper(c, loc, e->v.Set.elts, 0,
4392 : : BUILD_SET, SET_ADD, SET_UPDATE, 0);
4393 : : }
4394 : :
4395 : : static bool
4396 : 924 : are_all_items_const(asdl_expr_seq *seq, Py_ssize_t begin, Py_ssize_t end)
4397 : : {
4398 [ + + ]: 3859 : for (Py_ssize_t i = begin; i < end; i++) {
4399 : 3576 : expr_ty key = (expr_ty)asdl_seq_GET(seq, i);
4400 [ + - + + ]: 3576 : if (key == NULL || key->kind != Constant_kind) {
4401 : 641 : return false;
4402 : : }
4403 : : }
4404 : 283 : return true;
4405 : : }
4406 : :
4407 : : static int
4408 : 282 : compiler_subdict(struct compiler *c, expr_ty e, Py_ssize_t begin, Py_ssize_t end)
4409 : : {
4410 : 282 : Py_ssize_t i, n = end - begin;
4411 : : PyObject *keys, *key;
4412 : 282 : int big = n*2 > STACK_USE_GUIDELINE;
4413 : 282 : location loc = LOC(e);
4414 [ + + + + : 282 : if (n > 1 && !big && are_all_items_const(e->v.Dict.keys, begin, end)) {
+ + ]
4415 [ + + ]: 611 : for (i = begin; i < end; i++) {
4416 [ - + ]: 508 : VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Dict.values, i));
4417 : : }
4418 : 103 : keys = PyTuple_New(n);
4419 [ - + ]: 103 : if (keys == NULL) {
4420 : 0 : return SUCCESS;
4421 : : }
4422 [ + + ]: 611 : for (i = begin; i < end; i++) {
4423 : 508 : key = ((expr_ty)asdl_seq_GET(e->v.Dict.keys, i))->v.Constant.value;
4424 : 508 : PyTuple_SET_ITEM(keys, i - begin, Py_NewRef(key));
4425 : : }
4426 [ - + - + ]: 103 : ADDOP_LOAD_CONST_NEW(c, loc, keys);
4427 [ - + ]: 103 : ADDOP_I(c, loc, BUILD_CONST_KEY_MAP, n);
4428 : 103 : return SUCCESS;
4429 : : }
4430 [ + + ]: 179 : if (big) {
4431 [ - + ]: 135 : ADDOP_I(c, loc, BUILD_MAP, 0);
4432 : : }
4433 [ + + ]: 2559 : for (i = begin; i < end; i++) {
4434 [ - + ]: 2380 : VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Dict.keys, i));
4435 [ - + ]: 2380 : VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Dict.values, i));
4436 [ + + ]: 2380 : if (big) {
4437 [ - + ]: 2292 : ADDOP_I(c, loc, MAP_ADD, 1);
4438 : : }
4439 : : }
4440 [ + + ]: 179 : if (!big) {
4441 [ - + ]: 44 : ADDOP_I(c, loc, BUILD_MAP, n);
4442 : : }
4443 : 179 : return SUCCESS;
4444 : : }
4445 : :
4446 : : static int
4447 : 397 : compiler_dict(struct compiler *c, expr_ty e)
4448 : : {
4449 : 397 : location loc = LOC(e);
4450 : : Py_ssize_t i, n, elements;
4451 : : int have_dict;
4452 : 397 : int is_unpacking = 0;
4453 [ + - ]: 397 : n = asdl_seq_LEN(e->v.Dict.values);
4454 : 397 : have_dict = 0;
4455 : 397 : elements = 0;
4456 [ + + ]: 3297 : for (i = 0; i < n; i++) {
4457 : 2900 : is_unpacking = (expr_ty)asdl_seq_GET(e->v.Dict.keys, i) == NULL;
4458 [ + + ]: 2900 : if (is_unpacking) {
4459 [ - + ]: 12 : if (elements) {
4460 [ # # ]: 0 : RETURN_IF_ERROR(compiler_subdict(c, e, i - elements, i));
4461 [ # # ]: 0 : if (have_dict) {
4462 [ # # ]: 0 : ADDOP_I(c, loc, DICT_UPDATE, 1);
4463 : : }
4464 : 0 : have_dict = 1;
4465 : 0 : elements = 0;
4466 : : }
4467 [ + + ]: 12 : if (have_dict == 0) {
4468 [ - + ]: 6 : ADDOP_I(c, loc, BUILD_MAP, 0);
4469 : 6 : have_dict = 1;
4470 : : }
4471 [ - + ]: 12 : VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Dict.values, i));
4472 [ - + ]: 12 : ADDOP_I(c, loc, DICT_UPDATE, 1);
4473 : : }
4474 : : else {
4475 [ + + ]: 2888 : if (elements*2 > STACK_USE_GUIDELINE) {
4476 [ - + ]: 132 : RETURN_IF_ERROR(compiler_subdict(c, e, i - elements, i + 1));
4477 [ + + ]: 132 : if (have_dict) {
4478 [ - + ]: 122 : ADDOP_I(c, loc, DICT_UPDATE, 1);
4479 : : }
4480 : 132 : have_dict = 1;
4481 : 132 : elements = 0;
4482 : : }
4483 : : else {
4484 : 2756 : elements++;
4485 : : }
4486 : : }
4487 : : }
4488 [ + + ]: 397 : if (elements) {
4489 [ - + ]: 150 : RETURN_IF_ERROR(compiler_subdict(c, e, n - elements, n));
4490 [ + + ]: 150 : if (have_dict) {
4491 [ - + ]: 10 : ADDOP_I(c, loc, DICT_UPDATE, 1);
4492 : : }
4493 : 150 : have_dict = 1;
4494 : : }
4495 [ + + ]: 397 : if (!have_dict) {
4496 [ - + ]: 241 : ADDOP_I(c, loc, BUILD_MAP, 0);
4497 : : }
4498 : 397 : return SUCCESS;
4499 : : }
4500 : :
4501 : : static int
4502 : 6321 : compiler_compare(struct compiler *c, expr_ty e)
4503 : : {
4504 : 6321 : location loc = LOC(e);
4505 : : Py_ssize_t i, n;
4506 : :
4507 [ - + ]: 6321 : RETURN_IF_ERROR(check_compare(c, e));
4508 [ - + ]: 6321 : VISIT(c, expr, e->v.Compare.left);
4509 : : assert(asdl_seq_LEN(e->v.Compare.ops) > 0);
4510 [ + - ]: 6321 : n = asdl_seq_LEN(e->v.Compare.ops) - 1;
4511 [ + + ]: 6321 : if (n == 0) {
4512 [ - + ]: 6317 : VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Compare.comparators, 0));
4513 [ - + ]: 6317 : ADDOP_COMPARE(c, loc, asdl_seq_GET(e->v.Compare.ops, 0));
4514 : : }
4515 : : else {
4516 [ - + ]: 4 : NEW_JUMP_TARGET_LABEL(c, cleanup);
4517 [ + + ]: 8 : for (i = 0; i < n; i++) {
4518 [ - + ]: 4 : VISIT(c, expr,
4519 : : (expr_ty)asdl_seq_GET(e->v.Compare.comparators, i));
4520 [ - + ]: 4 : ADDOP_I(c, loc, SWAP, 2);
4521 [ - + ]: 4 : ADDOP_I(c, loc, COPY, 2);
4522 [ - + ]: 4 : ADDOP_COMPARE(c, loc, asdl_seq_GET(e->v.Compare.ops, i));
4523 [ - + ]: 4 : ADDOP_JUMP(c, loc, JUMP_IF_FALSE_OR_POP, cleanup);
4524 : : }
4525 [ - + ]: 4 : VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Compare.comparators, n));
4526 [ - + ]: 4 : ADDOP_COMPARE(c, loc, asdl_seq_GET(e->v.Compare.ops, n));
4527 [ - + ]: 4 : NEW_JUMP_TARGET_LABEL(c, end);
4528 [ - + ]: 4 : ADDOP_JUMP(c, NO_LOCATION, JUMP, end);
4529 : :
4530 [ - + ]: 4 : USE_LABEL(c, cleanup);
4531 [ - + ]: 4 : ADDOP_I(c, loc, SWAP, 2);
4532 [ - + ]: 4 : ADDOP(c, loc, POP_TOP);
4533 : :
4534 [ - + ]: 4 : USE_LABEL(c, end);
4535 : : }
4536 : 6321 : return SUCCESS;
4537 : : }
4538 : :
4539 : : static PyTypeObject *
4540 : 2593 : infer_type(expr_ty e)
4541 : : {
4542 [ + - - - : 2593 : switch (e->kind) {
- - - +
+ ]
4543 : 43 : case Tuple_kind:
4544 : 43 : return &PyTuple_Type;
4545 : 0 : case List_kind:
4546 : : case ListComp_kind:
4547 : 0 : return &PyList_Type;
4548 : 0 : case Dict_kind:
4549 : : case DictComp_kind:
4550 : 0 : return &PyDict_Type;
4551 : 0 : case Set_kind:
4552 : : case SetComp_kind:
4553 : 0 : return &PySet_Type;
4554 : 0 : case GeneratorExp_kind:
4555 : 0 : return &PyGen_Type;
4556 : 0 : case Lambda_kind:
4557 : 0 : return &PyFunction_Type;
4558 : 0 : case JoinedStr_kind:
4559 : : case FormattedValue_kind:
4560 : 0 : return &PyUnicode_Type;
4561 : 1070 : case Constant_kind:
4562 : 1070 : return Py_TYPE(e->v.Constant.value);
4563 : 1480 : default:
4564 : 1480 : return NULL;
4565 : : }
4566 : : }
4567 : :
4568 : : static int
4569 : 15536 : check_caller(struct compiler *c, expr_ty e)
4570 : : {
4571 [ - + ]: 15536 : switch (e->kind) {
4572 : 0 : case Constant_kind:
4573 : : case Tuple_kind:
4574 : : case List_kind:
4575 : : case ListComp_kind:
4576 : : case Dict_kind:
4577 : : case DictComp_kind:
4578 : : case Set_kind:
4579 : : case SetComp_kind:
4580 : : case GeneratorExp_kind:
4581 : : case JoinedStr_kind:
4582 : : case FormattedValue_kind: {
4583 : 0 : location loc = LOC(e);
4584 : 0 : return compiler_warn(c, loc, "'%.200s' object is not callable; "
4585 : : "perhaps you missed a comma?",
4586 : 0 : infer_type(e)->tp_name);
4587 : : }
4588 : 15536 : default:
4589 : 15536 : return SUCCESS;
4590 : : }
4591 : : }
4592 : :
4593 : : static int
4594 : 2593 : check_subscripter(struct compiler *c, expr_ty e)
4595 : : {
4596 : : PyObject *v;
4597 : :
4598 [ - - + ]: 2593 : switch (e->kind) {
4599 : 0 : case Constant_kind:
4600 : 0 : v = e->v.Constant.value;
4601 [ # # # # : 0 : if (!(v == Py_None || v == Py_Ellipsis ||
# # # # ]
4602 [ # # # # ]: 0 : PyLong_Check(v) || PyFloat_Check(v) || PyComplex_Check(v) ||
4603 [ # # # # : 0 : PyAnySet_Check(v)))
# # ]
4604 : : {
4605 : 0 : return SUCCESS;
4606 : : }
4607 : : /* fall through */
4608 : : case Set_kind:
4609 : : case SetComp_kind:
4610 : : case GeneratorExp_kind:
4611 : : case Lambda_kind: {
4612 : 0 : location loc = LOC(e);
4613 : 0 : return compiler_warn(c, loc, "'%.200s' object is not subscriptable; "
4614 : : "perhaps you missed a comma?",
4615 : 0 : infer_type(e)->tp_name);
4616 : : }
4617 : 2593 : default:
4618 : 2593 : return SUCCESS;
4619 : : }
4620 : : }
4621 : :
4622 : : static int
4623 : 2593 : check_index(struct compiler *c, expr_ty e, expr_ty s)
4624 : : {
4625 : : PyObject *v;
4626 : :
4627 : 2593 : PyTypeObject *index_type = infer_type(s);
4628 [ + + ]: 2593 : if (index_type == NULL
4629 [ + + ]: 1113 : || PyType_FastSubclass(index_type, Py_TPFLAGS_LONG_SUBCLASS)
4630 [ - + ]: 153 : || index_type == &PySlice_Type) {
4631 : 2440 : return SUCCESS;
4632 : : }
4633 : :
4634 [ - - + ]: 153 : switch (e->kind) {
4635 : 0 : case Constant_kind:
4636 : 0 : v = e->v.Constant.value;
4637 [ # # # # : 0 : if (!(PyUnicode_Check(v) || PyBytes_Check(v) || PyTuple_Check(v))) {
# # ]
4638 : 0 : return SUCCESS;
4639 : : }
4640 : : /* fall through */
4641 : : case Tuple_kind:
4642 : : case List_kind:
4643 : : case ListComp_kind:
4644 : : case JoinedStr_kind:
4645 : : case FormattedValue_kind: {
4646 : 0 : location loc = LOC(e);
4647 : 0 : return compiler_warn(c, loc, "%.200s indices must be integers "
4648 : : "or slices, not %.200s; "
4649 : : "perhaps you missed a comma?",
4650 : 0 : infer_type(e)->tp_name,
4651 : : index_type->tp_name);
4652 : : }
4653 : 153 : default:
4654 : 153 : return SUCCESS;
4655 : : }
4656 : : }
4657 : :
4658 : : static int
4659 : 13833 : is_import_originated(struct compiler *c, expr_ty e)
4660 : : {
4661 : : /* Check whether the global scope has an import named
4662 : : e, if it is a Name object. For not traversing all the
4663 : : scope stack every time this function is called, it will
4664 : : only check the global scope to determine whether something
4665 : : is imported or not. */
4666 : :
4667 [ + + ]: 13833 : if (e->kind != Name_kind) {
4668 : 2962 : return 0;
4669 : : }
4670 : :
4671 : 10871 : long flags = _PyST_GetSymbol(c->c_st->st_top, e->v.Name.id);
4672 : 10871 : return flags & DEF_IMPORT;
4673 : : }
4674 : :
4675 : : // If an attribute access spans multiple lines, update the current start
4676 : : // location to point to the attribute name.
4677 : : static location
4678 : 41161 : update_start_location_to_match_attr(struct compiler *c, location loc,
4679 : : expr_ty attr)
4680 : : {
4681 : : assert(attr->kind == Attribute_kind);
4682 [ + + ]: 41161 : if (loc.lineno != attr->end_lineno) {
4683 : 80 : loc.lineno = attr->end_lineno;
4684 : 80 : int len = (int)PyUnicode_GET_LENGTH(attr->v.Attribute.attr);
4685 [ + - ]: 80 : if (len <= attr->end_col_offset) {
4686 : 80 : loc.col_offset = attr->end_col_offset - len;
4687 : : }
4688 : : else {
4689 : : // GH-94694: Somebody's compiling weird ASTs. Just drop the columns:
4690 : 0 : loc.col_offset = -1;
4691 : 0 : loc.end_col_offset = -1;
4692 : : }
4693 : : // Make sure the end position still follows the start position, even for
4694 : : // weird ASTs:
4695 : 80 : loc.end_lineno = Py_MAX(loc.lineno, loc.end_lineno);
4696 [ + + ]: 80 : if (loc.lineno == loc.end_lineno) {
4697 : 75 : loc.end_col_offset = Py_MAX(loc.col_offset, loc.end_col_offset);
4698 : : }
4699 : : }
4700 : 41161 : return loc;
4701 : : }
4702 : :
4703 : : // Return 1 if the method call was optimized, 0 if not, and -1 on error.
4704 : : static int
4705 : 26546 : maybe_optimize_method_call(struct compiler *c, expr_ty e)
4706 : : {
4707 : : Py_ssize_t argsl, i, kwdsl;
4708 : 26546 : expr_ty meth = e->v.Call.func;
4709 : 26546 : asdl_expr_seq *args = e->v.Call.args;
4710 : 26546 : asdl_keyword_seq *kwds = e->v.Call.keywords;
4711 : :
4712 : : /* Check that the call node is an attribute access */
4713 [ + + - + ]: 26546 : if (meth->kind != Attribute_kind || meth->v.Attribute.ctx != Load) {
4714 : 12713 : return 0;
4715 : : }
4716 : :
4717 : : /* Check that the base object is not something that is imported */
4718 [ + + ]: 13833 : if (is_import_originated(c, meth->v.Attribute.value)) {
4719 : 2657 : return 0;
4720 : : }
4721 : :
4722 : : /* Check that there aren't too many arguments */
4723 [ + + ]: 11176 : argsl = asdl_seq_LEN(args);
4724 [ + + ]: 11176 : kwdsl = asdl_seq_LEN(kwds);
4725 [ - + ]: 11176 : if (argsl + kwdsl + (kwdsl != 0) >= STACK_USE_GUIDELINE) {
4726 : 0 : return 0;
4727 : : }
4728 : : /* Check that there are no *varargs types of arguments. */
4729 [ + + ]: 23164 : for (i = 0; i < argsl; i++) {
4730 : 12118 : expr_ty elt = asdl_seq_GET(args, i);
4731 [ + + ]: 12118 : if (elt->kind == Starred_kind) {
4732 : 130 : return 0;
4733 : : }
4734 : : }
4735 : :
4736 [ + + ]: 11859 : for (i = 0; i < kwdsl; i++) {
4737 : 849 : keyword_ty kw = asdl_seq_GET(kwds, i);
4738 [ + + ]: 849 : if (kw->arg == NULL) {
4739 : 36 : return 0;
4740 : : }
4741 : : }
4742 : : /* Alright, we can optimize the code. */
4743 [ - + ]: 11010 : VISIT(c, expr, meth->v.Attribute.value);
4744 : 11010 : location loc = LOC(meth);
4745 : 11010 : loc = update_start_location_to_match_attr(c, loc, meth);
4746 [ - + ]: 11010 : ADDOP_NAME(c, loc, LOAD_METHOD, meth->v.Attribute.attr, names);
4747 [ - + + + : 22825 : VISIT_SEQ(c, expr, e->v.Call.args);
+ + ]
4748 : :
4749 [ + + ]: 11010 : if (kwdsl) {
4750 [ - + + - : 1236 : VISIT_SEQ(c, keyword, kwds);
+ + ]
4751 [ - + ]: 433 : RETURN_IF_ERROR(
4752 : : compiler_call_simple_kw_helper(c, loc, kwds, kwdsl));
4753 : : }
4754 : 11010 : loc = update_start_location_to_match_attr(c, LOC(e), meth);
4755 [ - + ]: 11010 : ADDOP_I(c, loc, CALL, argsl + kwdsl);
4756 : 11010 : return 1;
4757 : : }
4758 : :
4759 : : static int
4760 : 42815 : validate_keywords(struct compiler *c, asdl_keyword_seq *keywords)
4761 : : {
4762 [ + + ]: 42815 : Py_ssize_t nkeywords = asdl_seq_LEN(keywords);
4763 [ + + ]: 46334 : for (Py_ssize_t i = 0; i < nkeywords; i++) {
4764 : 3519 : keyword_ty key = ((keyword_ty)asdl_seq_GET(keywords, i));
4765 [ + + ]: 3519 : if (key->arg == NULL) {
4766 : 362 : continue;
4767 : : }
4768 : 3157 : location loc = LOC(key);
4769 [ - + ]: 3157 : if (forbidden_name(c, loc, key->arg, Store)) {
4770 : 0 : return ERROR;
4771 : : }
4772 [ + + ]: 5646 : for (Py_ssize_t j = i + 1; j < nkeywords; j++) {
4773 : 2489 : keyword_ty other = ((keyword_ty)asdl_seq_GET(keywords, j));
4774 [ + + - + ]: 2489 : if (other->arg && !PyUnicode_Compare(key->arg, other->arg)) {
4775 : 0 : compiler_error(c, LOC(other), "keyword argument repeated: %U", key->arg);
4776 : 0 : return ERROR;
4777 : : }
4778 : : }
4779 : : }
4780 : 42815 : return SUCCESS;
4781 : : }
4782 : :
4783 : : static int
4784 : 26546 : compiler_call(struct compiler *c, expr_ty e)
4785 : : {
4786 [ - + ]: 26546 : RETURN_IF_ERROR(validate_keywords(c, e->v.Call.keywords));
4787 : 26546 : int ret = maybe_optimize_method_call(c, e);
4788 [ - + ]: 26546 : if (ret < 0) {
4789 : 0 : return ERROR;
4790 : : }
4791 [ + + ]: 26546 : if (ret == 1) {
4792 : 11010 : return SUCCESS;
4793 : : }
4794 [ - + ]: 15536 : RETURN_IF_ERROR(check_caller(c, e->v.Call.func));
4795 : 15536 : location loc = LOC(e->v.Call.func);
4796 [ - + ]: 15536 : ADDOP(c, loc, PUSH_NULL);
4797 [ - + ]: 15536 : VISIT(c, expr, e->v.Call.func);
4798 : 15536 : loc = LOC(e);
4799 : 15536 : return compiler_call_helper(c, loc, 0,
4800 : : e->v.Call.args,
4801 : : e->v.Call.keywords);
4802 : : }
4803 : :
4804 : : static int
4805 : 1188 : compiler_joined_str(struct compiler *c, expr_ty e)
4806 : : {
4807 : 1188 : location loc = LOC(e);
4808 [ + - ]: 1188 : Py_ssize_t value_count = asdl_seq_LEN(e->v.JoinedStr.values);
4809 [ - + ]: 1188 : if (value_count > STACK_USE_GUIDELINE) {
4810 : : _Py_DECLARE_STR(empty, "");
4811 [ # # # # ]: 0 : ADDOP_LOAD_CONST_NEW(c, loc, Py_NewRef(&_Py_STR(empty)));
4812 [ # # ]: 0 : ADDOP_NAME(c, loc, LOAD_METHOD, &_Py_ID(join), names);
4813 [ # # ]: 0 : ADDOP_I(c, loc, BUILD_LIST, 0);
4814 [ # # # # ]: 0 : for (Py_ssize_t i = 0; i < asdl_seq_LEN(e->v.JoinedStr.values); i++) {
4815 [ # # ]: 0 : VISIT(c, expr, asdl_seq_GET(e->v.JoinedStr.values, i));
4816 [ # # ]: 0 : ADDOP_I(c, loc, LIST_APPEND, 1);
4817 : : }
4818 [ # # ]: 0 : ADDOP_I(c, loc, CALL, 1);
4819 : : }
4820 : : else {
4821 [ - + + - : 5021 : VISIT_SEQ(c, expr, e->v.JoinedStr.values);
+ + ]
4822 [ + - + + ]: 1188 : if (asdl_seq_LEN(e->v.JoinedStr.values) != 1) {
4823 [ + - - + ]: 1130 : ADDOP_I(c, loc, BUILD_STRING, asdl_seq_LEN(e->v.JoinedStr.values));
4824 : : }
4825 : : }
4826 : 1188 : return SUCCESS;
4827 : : }
4828 : :
4829 : : /* Used to implement f-strings. Format a single value. */
4830 : : static int
4831 : 1826 : compiler_formatted_value(struct compiler *c, expr_ty e)
4832 : : {
4833 : : /* Our oparg encodes 2 pieces of information: the conversion
4834 : : character, and whether or not a format_spec was provided.
4835 : :
4836 : : Convert the conversion char to 3 bits:
4837 : : : 000 0x0 FVC_NONE The default if nothing specified.
4838 : : !s : 001 0x1 FVC_STR
4839 : : !r : 010 0x2 FVC_REPR
4840 : : !a : 011 0x3 FVC_ASCII
4841 : :
4842 : : next bit is whether or not we have a format spec:
4843 : : yes : 100 0x4
4844 : : no : 000 0x0
4845 : : */
4846 : :
4847 : 1826 : int conversion = e->v.FormattedValue.conversion;
4848 : : int oparg;
4849 : :
4850 : : /* The expression to be formatted. */
4851 [ - + ]: 1826 : VISIT(c, expr, e->v.FormattedValue.value);
4852 : :
4853 [ + + - + : 1826 : switch (conversion) {
- ]
4854 : 417 : case 's': oparg = FVC_STR; break;
4855 : 482 : case 'r': oparg = FVC_REPR; break;
4856 : 0 : case 'a': oparg = FVC_ASCII; break;
4857 : 927 : case -1: oparg = FVC_NONE; break;
4858 : 0 : default:
4859 : 0 : PyErr_Format(PyExc_SystemError,
4860 : : "Unrecognized conversion character %d", conversion);
4861 : 0 : return ERROR;
4862 : : }
4863 [ + + ]: 1826 : if (e->v.FormattedValue.format_spec) {
4864 : : /* Evaluate the format spec, and update our opcode arg. */
4865 [ - + ]: 39 : VISIT(c, expr, e->v.FormattedValue.format_spec);
4866 : 39 : oparg |= FVS_HAVE_SPEC;
4867 : : }
4868 : :
4869 : : /* And push our opcode and oparg */
4870 : 1826 : location loc = LOC(e);
4871 [ - + ]: 1826 : ADDOP_I(c, loc, FORMAT_VALUE, oparg);
4872 : :
4873 : 1826 : return SUCCESS;
4874 : : }
4875 : :
4876 : : static int
4877 : 24 : compiler_subkwargs(struct compiler *c, location loc,
4878 : : asdl_keyword_seq *keywords,
4879 : : Py_ssize_t begin, Py_ssize_t end)
4880 : : {
4881 : 24 : Py_ssize_t i, n = end - begin;
4882 : : keyword_ty kw;
4883 : : PyObject *keys, *key;
4884 : : assert(n > 0);
4885 : 24 : int big = n*2 > STACK_USE_GUIDELINE;
4886 [ + + + - ]: 24 : if (n > 1 && !big) {
4887 [ + + ]: 39 : for (i = begin; i < end; i++) {
4888 : 30 : kw = asdl_seq_GET(keywords, i);
4889 [ - + ]: 30 : VISIT(c, expr, kw->value);
4890 : : }
4891 : 9 : keys = PyTuple_New(n);
4892 [ - + ]: 9 : if (keys == NULL) {
4893 : 0 : return ERROR;
4894 : : }
4895 [ + + ]: 39 : for (i = begin; i < end; i++) {
4896 : 30 : key = ((keyword_ty) asdl_seq_GET(keywords, i))->arg;
4897 : 30 : PyTuple_SET_ITEM(keys, i - begin, Py_NewRef(key));
4898 : : }
4899 [ - + - + ]: 9 : ADDOP_LOAD_CONST_NEW(c, loc, keys);
4900 [ - + ]: 9 : ADDOP_I(c, loc, BUILD_CONST_KEY_MAP, n);
4901 : 9 : return SUCCESS;
4902 : : }
4903 [ - + ]: 15 : if (big) {
4904 [ # # ]: 0 : ADDOP_I(c, NO_LOCATION, BUILD_MAP, 0);
4905 : : }
4906 [ + + ]: 30 : for (i = begin; i < end; i++) {
4907 : 15 : kw = asdl_seq_GET(keywords, i);
4908 [ - + ]: 15 : ADDOP_LOAD_CONST(c, loc, kw->arg);
4909 [ - + ]: 15 : VISIT(c, expr, kw->value);
4910 [ - + ]: 15 : if (big) {
4911 [ # # ]: 0 : ADDOP_I(c, NO_LOCATION, MAP_ADD, 1);
4912 : : }
4913 : : }
4914 [ + - ]: 15 : if (!big) {
4915 [ - + ]: 15 : ADDOP_I(c, loc, BUILD_MAP, n);
4916 : : }
4917 : 15 : return SUCCESS;
4918 : : }
4919 : :
4920 : : /* Used by compiler_call_helper and maybe_optimize_method_call to emit
4921 : : * KW_NAMES before CALL.
4922 : : */
4923 : : static int
4924 : 1195 : compiler_call_simple_kw_helper(struct compiler *c, location loc,
4925 : : asdl_keyword_seq *keywords, Py_ssize_t nkwelts)
4926 : : {
4927 : : PyObject *names;
4928 : 1195 : names = PyTuple_New(nkwelts);
4929 [ - + ]: 1195 : if (names == NULL) {
4930 : 0 : return ERROR;
4931 : : }
4932 [ + + ]: 3158 : for (int i = 0; i < nkwelts; i++) {
4933 : 1963 : keyword_ty kw = asdl_seq_GET(keywords, i);
4934 : 1963 : PyTuple_SET_ITEM(names, i, Py_NewRef(kw->arg));
4935 : : }
4936 : 1195 : Py_ssize_t arg = compiler_add_const(c->c_const_cache, c->u, names);
4937 [ - + ]: 1195 : if (arg < 0) {
4938 : 0 : return ERROR;
4939 : : }
4940 : 1195 : Py_DECREF(names);
4941 [ - + ]: 1195 : ADDOP_I(c, loc, KW_NAMES, arg);
4942 : 1195 : return SUCCESS;
4943 : : }
4944 : :
4945 : :
4946 : : /* shared code between compiler_call and compiler_class */
4947 : : static int
4948 : 16269 : compiler_call_helper(struct compiler *c, location loc,
4949 : : int n, /* Args already pushed */
4950 : : asdl_expr_seq *args,
4951 : : asdl_keyword_seq *keywords)
4952 : : {
4953 : : Py_ssize_t i, nseen, nelts, nkwelts;
4954 : :
4955 [ - + ]: 16269 : RETURN_IF_ERROR(validate_keywords(c, keywords));
4956 : :
4957 [ + + ]: 16269 : nelts = asdl_seq_LEN(args);
4958 [ + + ]: 16269 : nkwelts = asdl_seq_LEN(keywords);
4959 : :
4960 [ + + ]: 16269 : if (nelts + nkwelts*2 > STACK_USE_GUIDELINE) {
4961 : 1 : goto ex_call;
4962 : : }
4963 [ + + ]: 38166 : for (i = 0; i < nelts; i++) {
4964 : 22179 : expr_ty elt = asdl_seq_GET(args, i);
4965 [ + + ]: 22179 : if (elt->kind == Starred_kind) {
4966 : 281 : goto ex_call;
4967 : : }
4968 : : }
4969 [ + + ]: 17171 : for (i = 0; i < nkwelts; i++) {
4970 : 1257 : keyword_ty kw = asdl_seq_GET(keywords, i);
4971 [ + + ]: 1257 : if (kw->arg == NULL) {
4972 : 73 : goto ex_call;
4973 : : }
4974 : : }
4975 : :
4976 : : /* No * or ** args, so can use faster calling sequence */
4977 [ + + ]: 37530 : for (i = 0; i < nelts; i++) {
4978 : 21616 : expr_ty elt = asdl_seq_GET(args, i);
4979 : : assert(elt->kind != Starred_kind);
4980 [ - + ]: 21616 : VISIT(c, expr, elt);
4981 : : }
4982 [ + + ]: 15914 : if (nkwelts) {
4983 [ - + + - : 1922 : VISIT_SEQ(c, keyword, keywords);
+ + ]
4984 [ - + ]: 762 : RETURN_IF_ERROR(
4985 : : compiler_call_simple_kw_helper(c, loc, keywords, nkwelts));
4986 : : }
4987 [ - + ]: 15914 : ADDOP_I(c, loc, CALL, n + nelts + nkwelts);
4988 : 15914 : return SUCCESS;
4989 : :
4990 : 355 : ex_call:
4991 : :
4992 : : /* Do positional arguments. */
4993 [ + - + + : 355 : if (n ==0 && nelts == 1 && ((expr_ty)asdl_seq_GET(args, 0))->kind == Starred_kind) {
+ + ]
4994 [ - + ]: 166 : VISIT(c, expr, ((expr_ty)asdl_seq_GET(args, 0))->v.Starred.value);
4995 : : }
4996 : : else {
4997 [ - + ]: 189 : RETURN_IF_ERROR(starunpack_helper(c, loc, args, n, BUILD_LIST,
4998 : : LIST_APPEND, LIST_EXTEND, 1));
4999 : : }
5000 : : /* Then keyword arguments */
5001 [ + + ]: 355 : if (nkwelts) {
5002 : : /* Has a new dict been pushed */
5003 : 189 : int have_dict = 0;
5004 : :
5005 : 189 : nseen = 0; /* the number of keyword arguments on the stack following */
5006 [ + + ]: 415 : for (i = 0; i < nkwelts; i++) {
5007 : 226 : keyword_ty kw = asdl_seq_GET(keywords, i);
5008 [ + + ]: 226 : if (kw->arg == NULL) {
5009 : : /* A keyword argument unpacking. */
5010 [ + + ]: 181 : if (nseen) {
5011 [ - + ]: 16 : RETURN_IF_ERROR(compiler_subkwargs(c, loc, keywords, i - nseen, i));
5012 [ - + ]: 16 : if (have_dict) {
5013 [ # # ]: 0 : ADDOP_I(c, loc, DICT_MERGE, 1);
5014 : : }
5015 : 16 : have_dict = 1;
5016 : 16 : nseen = 0;
5017 : : }
5018 [ + + ]: 181 : if (!have_dict) {
5019 [ - + ]: 165 : ADDOP_I(c, loc, BUILD_MAP, 0);
5020 : 165 : have_dict = 1;
5021 : : }
5022 [ - + ]: 181 : VISIT(c, expr, kw->value);
5023 [ - + ]: 181 : ADDOP_I(c, loc, DICT_MERGE, 1);
5024 : : }
5025 : : else {
5026 : 45 : nseen++;
5027 : : }
5028 : : }
5029 [ + + ]: 189 : if (nseen) {
5030 : : /* Pack up any trailing keyword arguments. */
5031 [ - + ]: 8 : RETURN_IF_ERROR(compiler_subkwargs(c, loc, keywords, nkwelts - nseen, nkwelts));
5032 [ - + ]: 8 : if (have_dict) {
5033 [ # # ]: 0 : ADDOP_I(c, loc, DICT_MERGE, 1);
5034 : : }
5035 : 8 : have_dict = 1;
5036 : : }
5037 : : assert(have_dict);
5038 : : }
5039 [ - + ]: 355 : ADDOP_I(c, loc, CALL_FUNCTION_EX, nkwelts > 0);
5040 : 355 : return SUCCESS;
5041 : : }
5042 : :
5043 : :
5044 : : /* List and set comprehensions and generator expressions work by creating a
5045 : : nested function to perform the actual iteration. This means that the
5046 : : iteration variables don't leak into the current scope.
5047 : : The defined function is called immediately following its definition, with the
5048 : : result of that call being the result of the expression.
5049 : : The LC/SC version returns the populated container, while the GE version is
5050 : : flagged in symtable.c as a generator, so it returns the generator object
5051 : : when the function is called.
5052 : :
5053 : : Possible cleanups:
5054 : : - iterate over the generator sequence instead of using recursion
5055 : : */
5056 : :
5057 : :
5058 : : static int
5059 : 471 : compiler_comprehension_generator(struct compiler *c, location loc,
5060 : : asdl_comprehension_seq *generators, int gen_index,
5061 : : int depth,
5062 : : expr_ty elt, expr_ty val, int type)
5063 : : {
5064 : : comprehension_ty gen;
5065 : 471 : gen = (comprehension_ty)asdl_seq_GET(generators, gen_index);
5066 [ - + ]: 471 : if (gen->is_async) {
5067 : 0 : return compiler_async_comprehension_generator(
5068 : : c, loc, generators, gen_index, depth, elt, val, type);
5069 : : } else {
5070 : 471 : return compiler_sync_comprehension_generator(
5071 : : c, loc, generators, gen_index, depth, elt, val, type);
5072 : : }
5073 : : }
5074 : :
5075 : : static int
5076 : 471 : compiler_sync_comprehension_generator(struct compiler *c, location loc,
5077 : : asdl_comprehension_seq *generators,
5078 : : int gen_index, int depth,
5079 : : expr_ty elt, expr_ty val, int type)
5080 : : {
5081 : : /* generate code for the iterator, then each of the ifs,
5082 : : and then write to the element */
5083 : :
5084 [ - + ]: 471 : NEW_JUMP_TARGET_LABEL(c, start);
5085 [ - + ]: 471 : NEW_JUMP_TARGET_LABEL(c, if_cleanup);
5086 [ - + ]: 471 : NEW_JUMP_TARGET_LABEL(c, anchor);
5087 : :
5088 : 471 : comprehension_ty gen = (comprehension_ty)asdl_seq_GET(generators,
5089 : : gen_index);
5090 : :
5091 [ + + ]: 471 : if (gen_index == 0) {
5092 : : /* Receive outermost iter as an implicit argument */
5093 : 453 : c->u->u_argcount = 1;
5094 [ - + ]: 453 : ADDOP_I(c, loc, LOAD_FAST, 0);
5095 : : }
5096 : : else {
5097 : : /* Sub-iter - calculate on the fly */
5098 : : /* Fast path for the temporary variable assignment idiom:
5099 : : for y in [f(x)]
5100 : : */
5101 : : asdl_expr_seq *elts;
5102 [ - - + ]: 18 : switch (gen->iter->kind) {
5103 : 0 : case List_kind:
5104 : 0 : elts = gen->iter->v.List.elts;
5105 : 0 : break;
5106 : 0 : case Tuple_kind:
5107 : 0 : elts = gen->iter->v.Tuple.elts;
5108 : 0 : break;
5109 : 18 : default:
5110 : 18 : elts = NULL;
5111 : : }
5112 [ - + - - ]: 18 : if (asdl_seq_LEN(elts) == 1) {
5113 : 0 : expr_ty elt = asdl_seq_GET(elts, 0);
5114 [ # # ]: 0 : if (elt->kind != Starred_kind) {
5115 [ # # ]: 0 : VISIT(c, expr, elt);
5116 : 0 : start = NO_LABEL;
5117 : : }
5118 : : }
5119 [ + - ]: 18 : if (IS_LABEL(start)) {
5120 [ - + ]: 18 : VISIT(c, expr, gen->iter);
5121 [ - + ]: 18 : ADDOP(c, loc, GET_ITER);
5122 : : }
5123 : : }
5124 [ + - ]: 471 : if (IS_LABEL(start)) {
5125 : 471 : depth++;
5126 [ - + ]: 471 : USE_LABEL(c, start);
5127 [ - + ]: 471 : ADDOP_JUMP(c, loc, FOR_ITER, anchor);
5128 : : }
5129 [ - + ]: 471 : VISIT(c, expr, gen->target);
5130 : :
5131 : : /* XXX this needs to be cleaned up...a lot! */
5132 [ + - ]: 471 : Py_ssize_t n = asdl_seq_LEN(gen->ifs);
5133 [ + + ]: 591 : for (Py_ssize_t i = 0; i < n; i++) {
5134 : 120 : expr_ty e = (expr_ty)asdl_seq_GET(gen->ifs, i);
5135 [ - + ]: 120 : RETURN_IF_ERROR(compiler_jump_if(c, loc, e, if_cleanup, 0));
5136 : : }
5137 : :
5138 [ + - + + ]: 471 : if (++gen_index < asdl_seq_LEN(generators)) {
5139 [ - + ]: 18 : RETURN_IF_ERROR(
5140 : : compiler_comprehension_generator(c, loc,
5141 : : generators, gen_index, depth,
5142 : : elt, val, type));
5143 : : }
5144 : :
5145 : 471 : location elt_loc = LOC(elt);
5146 : :
5147 : : /* only append after the last for generator */
5148 [ + - + + ]: 471 : if (gen_index >= asdl_seq_LEN(generators)) {
5149 : : /* comprehension specific code */
5150 [ + + + + : 453 : switch (type) {
- ]
5151 : 197 : case COMP_GENEXP:
5152 [ - + ]: 197 : VISIT(c, expr, elt);
5153 [ - + ]: 197 : ADDOP_YIELD(c, elt_loc);
5154 [ - + ]: 197 : ADDOP(c, elt_loc, POP_TOP);
5155 : 453 : break;
5156 : 219 : case COMP_LISTCOMP:
5157 [ - + ]: 219 : VISIT(c, expr, elt);
5158 [ - + ]: 219 : ADDOP_I(c, elt_loc, LIST_APPEND, depth + 1);
5159 : 219 : break;
5160 : 14 : case COMP_SETCOMP:
5161 [ - + ]: 14 : VISIT(c, expr, elt);
5162 [ - + ]: 14 : ADDOP_I(c, elt_loc, SET_ADD, depth + 1);
5163 : 14 : break;
5164 : 23 : case COMP_DICTCOMP:
5165 : : /* With '{k: v}', k is evaluated before v, so we do
5166 : : the same. */
5167 [ - + ]: 23 : VISIT(c, expr, elt);
5168 [ - + ]: 23 : VISIT(c, expr, val);
5169 : 23 : elt_loc = LOCATION(elt->lineno,
5170 : : val->end_lineno,
5171 : : elt->col_offset,
5172 : : val->end_col_offset);
5173 [ - + ]: 23 : ADDOP_I(c, elt_loc, MAP_ADD, depth + 1);
5174 : 23 : break;
5175 : 0 : default:
5176 : 0 : return ERROR;
5177 : : }
5178 : 18 : }
5179 : :
5180 [ - + ]: 471 : USE_LABEL(c, if_cleanup);
5181 [ + - ]: 471 : if (IS_LABEL(start)) {
5182 [ - + ]: 471 : ADDOP_JUMP(c, elt_loc, JUMP, start);
5183 : :
5184 [ - + ]: 471 : USE_LABEL(c, anchor);
5185 [ - + ]: 471 : ADDOP(c, NO_LOCATION, END_FOR);
5186 : : }
5187 : :
5188 : 471 : return SUCCESS;
5189 : : }
5190 : :
5191 : : static int
5192 : 0 : compiler_async_comprehension_generator(struct compiler *c, location loc,
5193 : : asdl_comprehension_seq *generators,
5194 : : int gen_index, int depth,
5195 : : expr_ty elt, expr_ty val, int type)
5196 : : {
5197 [ # # ]: 0 : NEW_JUMP_TARGET_LABEL(c, start);
5198 [ # # ]: 0 : NEW_JUMP_TARGET_LABEL(c, except);
5199 [ # # ]: 0 : NEW_JUMP_TARGET_LABEL(c, if_cleanup);
5200 : :
5201 : 0 : comprehension_ty gen = (comprehension_ty)asdl_seq_GET(generators,
5202 : : gen_index);
5203 : :
5204 [ # # ]: 0 : if (gen_index == 0) {
5205 : : /* Receive outermost iter as an implicit argument */
5206 : 0 : c->u->u_argcount = 1;
5207 [ # # ]: 0 : ADDOP_I(c, loc, LOAD_FAST, 0);
5208 : : }
5209 : : else {
5210 : : /* Sub-iter - calculate on the fly */
5211 [ # # ]: 0 : VISIT(c, expr, gen->iter);
5212 [ # # ]: 0 : ADDOP(c, loc, GET_AITER);
5213 : : }
5214 : :
5215 [ # # ]: 0 : USE_LABEL(c, start);
5216 : : /* Runtime will push a block here, so we need to account for that */
5217 [ # # ]: 0 : RETURN_IF_ERROR(
5218 : : compiler_push_fblock(c, loc, ASYNC_COMPREHENSION_GENERATOR,
5219 : : start, NO_LABEL, NULL));
5220 : :
5221 [ # # ]: 0 : ADDOP_JUMP(c, loc, SETUP_FINALLY, except);
5222 [ # # ]: 0 : ADDOP(c, loc, GET_ANEXT);
5223 [ # # ]: 0 : ADDOP_LOAD_CONST(c, loc, Py_None);
5224 [ # # ]: 0 : ADD_YIELD_FROM(c, loc, 1);
5225 [ # # ]: 0 : ADDOP(c, loc, POP_BLOCK);
5226 [ # # ]: 0 : VISIT(c, expr, gen->target);
5227 : :
5228 [ # # ]: 0 : Py_ssize_t n = asdl_seq_LEN(gen->ifs);
5229 [ # # ]: 0 : for (Py_ssize_t i = 0; i < n; i++) {
5230 : 0 : expr_ty e = (expr_ty)asdl_seq_GET(gen->ifs, i);
5231 [ # # ]: 0 : RETURN_IF_ERROR(compiler_jump_if(c, loc, e, if_cleanup, 0));
5232 : : }
5233 : :
5234 : 0 : depth++;
5235 [ # # # # ]: 0 : if (++gen_index < asdl_seq_LEN(generators)) {
5236 [ # # ]: 0 : RETURN_IF_ERROR(
5237 : : compiler_comprehension_generator(c, loc,
5238 : : generators, gen_index, depth,
5239 : : elt, val, type));
5240 : : }
5241 : :
5242 : 0 : location elt_loc = LOC(elt);
5243 : : /* only append after the last for generator */
5244 [ # # # # ]: 0 : if (gen_index >= asdl_seq_LEN(generators)) {
5245 : : /* comprehension specific code */
5246 [ # # # # : 0 : switch (type) {
# ]
5247 : 0 : case COMP_GENEXP:
5248 [ # # ]: 0 : VISIT(c, expr, elt);
5249 [ # # ]: 0 : ADDOP_YIELD(c, elt_loc);
5250 [ # # ]: 0 : ADDOP(c, elt_loc, POP_TOP);
5251 : 0 : break;
5252 : 0 : case COMP_LISTCOMP:
5253 [ # # ]: 0 : VISIT(c, expr, elt);
5254 [ # # ]: 0 : ADDOP_I(c, elt_loc, LIST_APPEND, depth + 1);
5255 : 0 : break;
5256 : 0 : case COMP_SETCOMP:
5257 [ # # ]: 0 : VISIT(c, expr, elt);
5258 [ # # ]: 0 : ADDOP_I(c, elt_loc, SET_ADD, depth + 1);
5259 : 0 : break;
5260 : 0 : case COMP_DICTCOMP:
5261 : : /* With '{k: v}', k is evaluated before v, so we do
5262 : : the same. */
5263 [ # # ]: 0 : VISIT(c, expr, elt);
5264 [ # # ]: 0 : VISIT(c, expr, val);
5265 : 0 : elt_loc = LOCATION(elt->lineno,
5266 : : val->end_lineno,
5267 : : elt->col_offset,
5268 : : val->end_col_offset);
5269 [ # # ]: 0 : ADDOP_I(c, elt_loc, MAP_ADD, depth + 1);
5270 : 0 : break;
5271 : 0 : default:
5272 : 0 : return ERROR;
5273 : : }
5274 : 0 : }
5275 : :
5276 [ # # ]: 0 : USE_LABEL(c, if_cleanup);
5277 [ # # ]: 0 : ADDOP_JUMP(c, elt_loc, JUMP, start);
5278 : :
5279 : 0 : compiler_pop_fblock(c, ASYNC_COMPREHENSION_GENERATOR, start);
5280 : :
5281 [ # # ]: 0 : USE_LABEL(c, except);
5282 : :
5283 [ # # ]: 0 : ADDOP(c, loc, END_ASYNC_FOR);
5284 : :
5285 : 0 : return SUCCESS;
5286 : : }
5287 : :
5288 : : static int
5289 : 453 : compiler_comprehension(struct compiler *c, expr_ty e, int type,
5290 : : identifier name, asdl_comprehension_seq *generators, expr_ty elt,
5291 : : expr_ty val)
5292 : : {
5293 : 453 : PyCodeObject *co = NULL;
5294 : : comprehension_ty outermost;
5295 : 453 : int scope_type = c->u->u_scope_type;
5296 : 453 : int is_async_generator = 0;
5297 [ - + - - ]: 453 : int is_top_level_await = IS_TOP_LEVEL_AWAIT(c);
5298 : :
5299 : 453 : outermost = (comprehension_ty) asdl_seq_GET(generators, 0);
5300 [ - + ]: 453 : if (compiler_enter_scope(c, name, COMPILER_SCOPE_COMPREHENSION,
5301 : : (void *)e, e->lineno) < 0)
5302 : : {
5303 : 0 : goto error;
5304 : : }
5305 : 453 : location loc = LOC(e);
5306 : :
5307 : 453 : is_async_generator = c->u->u_ste->ste_coroutine;
5308 : :
5309 [ - + - - : 453 : if (is_async_generator && type != COMP_GENEXP &&
- - ]
5310 [ # # ]: 0 : scope_type != COMPILER_SCOPE_ASYNC_FUNCTION &&
5311 [ # # ]: 0 : scope_type != COMPILER_SCOPE_COMPREHENSION &&
5312 : : !is_top_level_await)
5313 : : {
5314 : 0 : compiler_error(c, loc, "asynchronous comprehension outside of "
5315 : : "an asynchronous function");
5316 : 0 : goto error_in_scope;
5317 : : }
5318 : :
5319 [ + + ]: 453 : if (type != COMP_GENEXP) {
5320 : : int op;
5321 [ + + + - ]: 256 : switch (type) {
5322 : 219 : case COMP_LISTCOMP:
5323 : 219 : op = BUILD_LIST;
5324 : 219 : break;
5325 : 14 : case COMP_SETCOMP:
5326 : 14 : op = BUILD_SET;
5327 : 14 : break;
5328 : 23 : case COMP_DICTCOMP:
5329 : 23 : op = BUILD_MAP;
5330 : 23 : break;
5331 : 0 : default:
5332 : 0 : PyErr_Format(PyExc_SystemError,
5333 : : "unknown comprehension type %d", type);
5334 : 0 : goto error_in_scope;
5335 : : }
5336 : :
5337 [ - + ]: 256 : ADDOP_I(c, loc, op, 0);
5338 : : }
5339 : :
5340 [ - + ]: 453 : if (compiler_comprehension_generator(c, loc, generators, 0, 0,
5341 : : elt, val, type) < 0) {
5342 : 0 : goto error_in_scope;
5343 : : }
5344 : :
5345 [ + + ]: 453 : if (type != COMP_GENEXP) {
5346 [ - + ]: 256 : ADDOP(c, LOC(e), RETURN_VALUE);
5347 : : }
5348 [ + + ]: 453 : if (type == COMP_GENEXP) {
5349 [ - + ]: 197 : if (wrap_in_stopiteration_handler(c) < 0) {
5350 : 0 : goto error_in_scope;
5351 : : }
5352 : : }
5353 : :
5354 : 453 : co = assemble(c, 1);
5355 : 453 : compiler_exit_scope(c);
5356 [ - + - - ]: 453 : if (is_top_level_await && is_async_generator){
5357 : 0 : c->u->u_ste->ste_coroutine = 1;
5358 : : }
5359 [ - + ]: 453 : if (co == NULL) {
5360 : 0 : goto error;
5361 : : }
5362 : :
5363 : 453 : loc = LOC(e);
5364 [ - + ]: 453 : if (compiler_make_closure(c, loc, co, 0) < 0) {
5365 : 0 : goto error;
5366 : : }
5367 : 453 : Py_DECREF(co);
5368 : :
5369 [ - + ]: 453 : VISIT(c, expr, outermost->iter);
5370 : :
5371 : 453 : loc = LOC(e);
5372 [ - + ]: 453 : if (outermost->is_async) {
5373 [ # # ]: 0 : ADDOP(c, loc, GET_AITER);
5374 : : } else {
5375 [ - + ]: 453 : ADDOP(c, loc, GET_ITER);
5376 : : }
5377 : :
5378 [ - + ]: 453 : ADDOP_I(c, loc, CALL, 0);
5379 : :
5380 [ - + - - ]: 453 : if (is_async_generator && type != COMP_GENEXP) {
5381 [ # # ]: 0 : ADDOP_I(c, loc, GET_AWAITABLE, 0);
5382 [ # # ]: 0 : ADDOP_LOAD_CONST(c, loc, Py_None);
5383 [ # # ]: 0 : ADD_YIELD_FROM(c, loc, 1);
5384 : : }
5385 : :
5386 : 453 : return SUCCESS;
5387 : 0 : error_in_scope:
5388 : 0 : compiler_exit_scope(c);
5389 : 0 : error:
5390 : 0 : Py_XDECREF(co);
5391 : 0 : return ERROR;
5392 : : }
5393 : :
5394 : : static int
5395 : 197 : compiler_genexp(struct compiler *c, expr_ty e)
5396 : : {
5397 : : assert(e->kind == GeneratorExp_kind);
5398 : : _Py_DECLARE_STR(anon_genexpr, "<genexpr>");
5399 : 197 : return compiler_comprehension(c, e, COMP_GENEXP, &_Py_STR(anon_genexpr),
5400 : : e->v.GeneratorExp.generators,
5401 : : e->v.GeneratorExp.elt, NULL);
5402 : : }
5403 : :
5404 : : static int
5405 : 219 : compiler_listcomp(struct compiler *c, expr_ty e)
5406 : : {
5407 : : assert(e->kind == ListComp_kind);
5408 : : _Py_DECLARE_STR(anon_listcomp, "<listcomp>");
5409 : 219 : return compiler_comprehension(c, e, COMP_LISTCOMP, &_Py_STR(anon_listcomp),
5410 : : e->v.ListComp.generators,
5411 : : e->v.ListComp.elt, NULL);
5412 : : }
5413 : :
5414 : : static int
5415 : 14 : compiler_setcomp(struct compiler *c, expr_ty e)
5416 : : {
5417 : : assert(e->kind == SetComp_kind);
5418 : : _Py_DECLARE_STR(anon_setcomp, "<setcomp>");
5419 : 14 : return compiler_comprehension(c, e, COMP_SETCOMP, &_Py_STR(anon_setcomp),
5420 : : e->v.SetComp.generators,
5421 : : e->v.SetComp.elt, NULL);
5422 : : }
5423 : :
5424 : :
5425 : : static int
5426 : 23 : compiler_dictcomp(struct compiler *c, expr_ty e)
5427 : : {
5428 : : assert(e->kind == DictComp_kind);
5429 : : _Py_DECLARE_STR(anon_dictcomp, "<dictcomp>");
5430 : 23 : return compiler_comprehension(c, e, COMP_DICTCOMP, &_Py_STR(anon_dictcomp),
5431 : : e->v.DictComp.generators,
5432 : : e->v.DictComp.key, e->v.DictComp.value);
5433 : : }
5434 : :
5435 : :
5436 : : static int
5437 : 1963 : compiler_visit_keyword(struct compiler *c, keyword_ty k)
5438 : : {
5439 [ - + ]: 1963 : VISIT(c, expr, k->value);
5440 : 1963 : return SUCCESS;
5441 : : }
5442 : :
5443 : :
5444 : : static int
5445 : 389 : compiler_with_except_finish(struct compiler *c, jump_target_label cleanup) {
5446 [ - + ]: 389 : NEW_JUMP_TARGET_LABEL(c, suppress);
5447 [ - + ]: 389 : ADDOP_JUMP(c, NO_LOCATION, POP_JUMP_IF_TRUE, suppress);
5448 [ - + ]: 389 : ADDOP_I(c, NO_LOCATION, RERAISE, 2);
5449 : :
5450 [ - + ]: 389 : USE_LABEL(c, suppress);
5451 [ - + ]: 389 : ADDOP(c, NO_LOCATION, POP_TOP); /* exc_value */
5452 [ - + ]: 389 : ADDOP(c, NO_LOCATION, POP_BLOCK);
5453 [ - + ]: 389 : ADDOP(c, NO_LOCATION, POP_EXCEPT);
5454 [ - + ]: 389 : ADDOP(c, NO_LOCATION, POP_TOP);
5455 [ - + ]: 389 : ADDOP(c, NO_LOCATION, POP_TOP);
5456 [ - + ]: 389 : NEW_JUMP_TARGET_LABEL(c, exit);
5457 [ - + ]: 389 : ADDOP_JUMP(c, NO_LOCATION, JUMP, exit);
5458 : :
5459 [ - + ]: 389 : USE_LABEL(c, cleanup);
5460 [ - + ]: 389 : POP_EXCEPT_AND_RERAISE(c, NO_LOCATION);
5461 : :
5462 [ - + ]: 389 : USE_LABEL(c, exit);
5463 : 389 : return SUCCESS;
5464 : : }
5465 : :
5466 : : /*
5467 : : Implements the async with statement.
5468 : :
5469 : : The semantics outlined in that PEP are as follows:
5470 : :
5471 : : async with EXPR as VAR:
5472 : : BLOCK
5473 : :
5474 : : It is implemented roughly as:
5475 : :
5476 : : context = EXPR
5477 : : exit = context.__aexit__ # not calling it
5478 : : value = await context.__aenter__()
5479 : : try:
5480 : : VAR = value # if VAR present in the syntax
5481 : : BLOCK
5482 : : finally:
5483 : : if an exception was raised:
5484 : : exc = copy of (exception, instance, traceback)
5485 : : else:
5486 : : exc = (None, None, None)
5487 : : if not (await exit(*exc)):
5488 : : raise
5489 : : */
5490 : : static int
5491 : 5 : compiler_async_with(struct compiler *c, stmt_ty s, int pos)
5492 : : {
5493 : 5 : location loc = LOC(s);
5494 : 5 : withitem_ty item = asdl_seq_GET(s->v.AsyncWith.items, pos);
5495 : :
5496 : : assert(s->kind == AsyncWith_kind);
5497 [ - + - - ]: 5 : if (IS_TOP_LEVEL_AWAIT(c)){
5498 : 0 : c->u->u_ste->ste_coroutine = 1;
5499 [ - + ]: 5 : } else if (c->u->u_scope_type != COMPILER_SCOPE_ASYNC_FUNCTION){
5500 : 0 : return compiler_error(c, loc, "'async with' outside async function");
5501 : : }
5502 : :
5503 [ - + ]: 5 : NEW_JUMP_TARGET_LABEL(c, block);
5504 [ - + ]: 5 : NEW_JUMP_TARGET_LABEL(c, final);
5505 [ - + ]: 5 : NEW_JUMP_TARGET_LABEL(c, exit);
5506 [ - + ]: 5 : NEW_JUMP_TARGET_LABEL(c, cleanup);
5507 : :
5508 : : /* Evaluate EXPR */
5509 [ - + ]: 5 : VISIT(c, expr, item->context_expr);
5510 : :
5511 [ - + ]: 5 : ADDOP(c, loc, BEFORE_ASYNC_WITH);
5512 [ - + ]: 5 : ADDOP_I(c, loc, GET_AWAITABLE, 1);
5513 [ - + ]: 5 : ADDOP_LOAD_CONST(c, loc, Py_None);
5514 [ - + ]: 5 : ADD_YIELD_FROM(c, loc, 1);
5515 : :
5516 [ - + ]: 5 : ADDOP_JUMP(c, loc, SETUP_WITH, final);
5517 : :
5518 : : /* SETUP_WITH pushes a finally block. */
5519 [ - + ]: 5 : USE_LABEL(c, block);
5520 [ - + ]: 5 : RETURN_IF_ERROR(compiler_push_fblock(c, loc, ASYNC_WITH, block, final, s));
5521 : :
5522 [ - + ]: 5 : if (item->optional_vars) {
5523 [ # # ]: 0 : VISIT(c, expr, item->optional_vars);
5524 : : }
5525 : : else {
5526 : : /* Discard result from context.__aenter__() */
5527 [ - + ]: 5 : ADDOP(c, loc, POP_TOP);
5528 : : }
5529 : :
5530 : 5 : pos++;
5531 [ + - + - ]: 5 : if (pos == asdl_seq_LEN(s->v.AsyncWith.items)) {
5532 : : /* BLOCK code */
5533 [ - + + - : 13 : VISIT_SEQ(c, stmt, s->v.AsyncWith.body)
+ + ]
5534 : : }
5535 : : else {
5536 [ # # ]: 0 : RETURN_IF_ERROR(compiler_async_with(c, s, pos));
5537 : : }
5538 : :
5539 : 5 : compiler_pop_fblock(c, ASYNC_WITH, block);
5540 : :
5541 [ - + ]: 5 : ADDOP(c, loc, POP_BLOCK);
5542 : : /* End of body; start the cleanup */
5543 : :
5544 : : /* For successful outcome:
5545 : : * call __exit__(None, None, None)
5546 : : */
5547 [ - + ]: 5 : RETURN_IF_ERROR(compiler_call_exit_with_nones(c, loc));
5548 [ - + ]: 5 : ADDOP_I(c, loc, GET_AWAITABLE, 2);
5549 [ - + ]: 5 : ADDOP_LOAD_CONST(c, loc, Py_None);
5550 [ - + ]: 5 : ADD_YIELD_FROM(c, loc, 1);
5551 : :
5552 [ - + ]: 5 : ADDOP(c, loc, POP_TOP);
5553 : :
5554 [ - + ]: 5 : ADDOP_JUMP(c, loc, JUMP, exit);
5555 : :
5556 : : /* For exceptional outcome: */
5557 [ - + ]: 5 : USE_LABEL(c, final);
5558 : :
5559 [ - + ]: 5 : ADDOP_JUMP(c, loc, SETUP_CLEANUP, cleanup);
5560 [ - + ]: 5 : ADDOP(c, loc, PUSH_EXC_INFO);
5561 [ - + ]: 5 : ADDOP(c, loc, WITH_EXCEPT_START);
5562 [ - + ]: 5 : ADDOP_I(c, loc, GET_AWAITABLE, 2);
5563 [ - + ]: 5 : ADDOP_LOAD_CONST(c, loc, Py_None);
5564 [ - + ]: 5 : ADD_YIELD_FROM(c, loc, 1);
5565 [ - + ]: 5 : RETURN_IF_ERROR(compiler_with_except_finish(c, cleanup));
5566 : :
5567 [ - + ]: 5 : USE_LABEL(c, exit);
5568 : 5 : return SUCCESS;
5569 : : }
5570 : :
5571 : :
5572 : : /*
5573 : : Implements the with statement from PEP 343.
5574 : : with EXPR as VAR:
5575 : : BLOCK
5576 : : is implemented as:
5577 : : <code for EXPR>
5578 : : SETUP_WITH E
5579 : : <code to store to VAR> or POP_TOP
5580 : : <code for BLOCK>
5581 : : LOAD_CONST (None, None, None)
5582 : : CALL_FUNCTION_EX 0
5583 : : JUMP EXIT
5584 : : E: WITH_EXCEPT_START (calls EXPR.__exit__)
5585 : : POP_JUMP_IF_TRUE T:
5586 : : RERAISE
5587 : : T: POP_TOP (remove exception from stack)
5588 : : POP_EXCEPT
5589 : : POP_TOP
5590 : : EXIT:
5591 : : */
5592 : :
5593 : : static int
5594 : 384 : compiler_with(struct compiler *c, stmt_ty s, int pos)
5595 : : {
5596 : 384 : withitem_ty item = asdl_seq_GET(s->v.With.items, pos);
5597 : :
5598 : : assert(s->kind == With_kind);
5599 : :
5600 [ - + ]: 384 : NEW_JUMP_TARGET_LABEL(c, block);
5601 [ - + ]: 384 : NEW_JUMP_TARGET_LABEL(c, final);
5602 [ - + ]: 384 : NEW_JUMP_TARGET_LABEL(c, exit);
5603 [ - + ]: 384 : NEW_JUMP_TARGET_LABEL(c, cleanup);
5604 : :
5605 : : /* Evaluate EXPR */
5606 [ - + ]: 384 : VISIT(c, expr, item->context_expr);
5607 : : /* Will push bound __exit__ */
5608 : 384 : location loc = LOC(s);
5609 [ - + ]: 384 : ADDOP(c, loc, BEFORE_WITH);
5610 [ - + ]: 384 : ADDOP_JUMP(c, loc, SETUP_WITH, final);
5611 : :
5612 : : /* SETUP_WITH pushes a finally block. */
5613 [ - + ]: 384 : USE_LABEL(c, block);
5614 [ - + ]: 384 : RETURN_IF_ERROR(compiler_push_fblock(c, loc, WITH, block, final, s));
5615 : :
5616 [ + + ]: 384 : if (item->optional_vars) {
5617 [ - + ]: 143 : VISIT(c, expr, item->optional_vars);
5618 : : }
5619 : : else {
5620 : : /* Discard result from context.__enter__() */
5621 [ - + ]: 241 : ADDOP(c, loc, POP_TOP);
5622 : : }
5623 : :
5624 : 384 : pos++;
5625 [ + - + + ]: 384 : if (pos == asdl_seq_LEN(s->v.With.items)) {
5626 : : /* BLOCK code */
5627 [ - + + - : 1131 : VISIT_SEQ(c, stmt, s->v.With.body)
+ + ]
5628 : : }
5629 : : else {
5630 [ - + ]: 5 : RETURN_IF_ERROR(compiler_with(c, s, pos));
5631 : : }
5632 : :
5633 [ - + ]: 384 : ADDOP(c, NO_LOCATION, POP_BLOCK);
5634 : 384 : compiler_pop_fblock(c, WITH, block);
5635 : :
5636 : : /* End of body; start the cleanup. */
5637 : :
5638 : : /* For successful outcome:
5639 : : * call __exit__(None, None, None)
5640 : : */
5641 : 384 : loc = LOC(s);
5642 [ - + ]: 384 : RETURN_IF_ERROR(compiler_call_exit_with_nones(c, loc));
5643 [ - + ]: 384 : ADDOP(c, loc, POP_TOP);
5644 [ - + ]: 384 : ADDOP_JUMP(c, loc, JUMP, exit);
5645 : :
5646 : : /* For exceptional outcome: */
5647 [ - + ]: 384 : USE_LABEL(c, final);
5648 : :
5649 [ - + ]: 384 : ADDOP_JUMP(c, loc, SETUP_CLEANUP, cleanup);
5650 [ - + ]: 384 : ADDOP(c, loc, PUSH_EXC_INFO);
5651 [ - + ]: 384 : ADDOP(c, loc, WITH_EXCEPT_START);
5652 [ - + ]: 384 : RETURN_IF_ERROR(compiler_with_except_finish(c, cleanup));
5653 : :
5654 [ - + ]: 384 : USE_LABEL(c, exit);
5655 : 384 : return SUCCESS;
5656 : : }
5657 : :
5658 : : static int
5659 : 201007 : compiler_visit_expr1(struct compiler *c, expr_ty e)
5660 : : {
5661 : 201007 : location loc = LOC(e);
5662 [ + + + + : 201007 : switch (e->kind) {
+ + + + +
+ + + + +
+ + + + +
+ + + - +
+ + + - ]
5663 : 32 : case NamedExpr_kind:
5664 [ - + ]: 146610 : VISIT(c, expr, e->v.NamedExpr.value);
5665 [ - + ]: 32 : ADDOP_I(c, loc, COPY, 1);
5666 [ - + ]: 32 : VISIT(c, expr, e->v.NamedExpr.target);
5667 : 54429 : break;
5668 : 392 : case BoolOp_kind:
5669 : 392 : return compiler_boolop(c, e);
5670 : 3541 : case BinOp_kind:
5671 [ - + ]: 3541 : VISIT(c, expr, e->v.BinOp.left);
5672 [ - + ]: 3541 : VISIT(c, expr, e->v.BinOp.right);
5673 [ - + ]: 3541 : ADDOP_BINARY(c, loc, e->v.BinOp.op);
5674 : 3541 : break;
5675 : 271 : case UnaryOp_kind:
5676 [ - + ]: 271 : VISIT(c, expr, e->v.UnaryOp.operand);
5677 [ + + ]: 271 : if (e->v.UnaryOp.op == UAdd) {
5678 [ - + ]: 5 : ADDOP_I(c, loc, CALL_INTRINSIC_1, INTRINSIC_UNARY_POSITIVE);
5679 : : }
5680 : : else {
5681 [ - + ]: 266 : ADDOP(c, loc, unaryop(e->v.UnaryOp.op));
5682 : : }
5683 : 271 : break;
5684 : 135 : case Lambda_kind:
5685 : 135 : return compiler_lambda(c, e);
5686 : 231 : case IfExp_kind:
5687 : 231 : return compiler_ifexp(c, e);
5688 : 397 : case Dict_kind:
5689 : 397 : return compiler_dict(c, e);
5690 : 40 : case Set_kind:
5691 : 40 : return compiler_set(c, e);
5692 : 197 : case GeneratorExp_kind:
5693 : 197 : return compiler_genexp(c, e);
5694 : 219 : case ListComp_kind:
5695 : 219 : return compiler_listcomp(c, e);
5696 : 14 : case SetComp_kind:
5697 : 14 : return compiler_setcomp(c, e);
5698 : 23 : case DictComp_kind:
5699 : 23 : return compiler_dictcomp(c, e);
5700 : 252 : case Yield_kind:
5701 [ - + ]: 252 : if (c->u->u_ste->ste_type != FunctionBlock) {
5702 : 0 : return compiler_error(c, loc, "'yield' outside function");
5703 : : }
5704 [ + + ]: 252 : if (e->v.Yield.value) {
5705 [ - + ]: 220 : VISIT(c, expr, e->v.Yield.value);
5706 : : }
5707 : : else {
5708 [ - + ]: 32 : ADDOP_LOAD_CONST(c, loc, Py_None);
5709 : : }
5710 [ - + ]: 252 : ADDOP_YIELD(c, loc);
5711 : 252 : break;
5712 : 44 : case YieldFrom_kind:
5713 [ - + ]: 44 : if (c->u->u_ste->ste_type != FunctionBlock) {
5714 : 0 : return compiler_error(c, loc, "'yield' outside function");
5715 : : }
5716 [ - + ]: 44 : if (c->u->u_scope_type == COMPILER_SCOPE_ASYNC_FUNCTION) {
5717 : 0 : return compiler_error(c, loc, "'yield from' inside async function");
5718 : : }
5719 [ - + ]: 44 : VISIT(c, expr, e->v.YieldFrom.value);
5720 [ - + ]: 44 : ADDOP(c, loc, GET_YIELD_FROM_ITER);
5721 [ - + ]: 44 : ADDOP_LOAD_CONST(c, loc, Py_None);
5722 [ - + ]: 44 : ADD_YIELD_FROM(c, loc, 0);
5723 : 44 : break;
5724 : 133 : case Await_kind:
5725 [ - + - - ]: 133 : if (!IS_TOP_LEVEL_AWAIT(c)){
5726 [ - + ]: 133 : if (c->u->u_ste->ste_type != FunctionBlock){
5727 : 0 : return compiler_error(c, loc, "'await' outside function");
5728 : : }
5729 : :
5730 [ - + ]: 133 : if (c->u->u_scope_type != COMPILER_SCOPE_ASYNC_FUNCTION &&
5731 [ # # ]: 0 : c->u->u_scope_type != COMPILER_SCOPE_COMPREHENSION) {
5732 : 0 : return compiler_error(c, loc, "'await' outside async function");
5733 : : }
5734 : : }
5735 : :
5736 [ - + ]: 133 : VISIT(c, expr, e->v.Await.value);
5737 [ - + ]: 133 : ADDOP_I(c, loc, GET_AWAITABLE, 0);
5738 [ - + ]: 133 : ADDOP_LOAD_CONST(c, loc, Py_None);
5739 [ - + ]: 133 : ADD_YIELD_FROM(c, loc, 1);
5740 : 133 : break;
5741 : 6321 : case Compare_kind:
5742 : 6321 : return compiler_compare(c, e);
5743 : 26546 : case Call_kind:
5744 : 26546 : return compiler_call(c, e);
5745 : 31226 : case Constant_kind:
5746 [ - + ]: 31226 : ADDOP_LOAD_CONST(c, loc, e->v.Constant.value);
5747 : 31226 : break;
5748 : 1188 : case JoinedStr_kind:
5749 : 1188 : return compiler_joined_str(c, e);
5750 : 1826 : case FormattedValue_kind:
5751 : 1826 : return compiler_formatted_value(c, e);
5752 : : /* The following exprs can be assignment targets. */
5753 : 18909 : case Attribute_kind:
5754 [ - + ]: 18909 : VISIT(c, expr, e->v.Attribute.value);
5755 : 18909 : loc = LOC(e);
5756 : 18909 : loc = update_start_location_to_match_attr(c, loc, e);
5757 [ + + + - ]: 18909 : switch (e->v.Attribute.ctx) {
5758 : 15961 : case Load:
5759 [ - + ]: 15961 : ADDOP_NAME(c, loc, LOAD_ATTR, e->v.Attribute.attr, names);
5760 : 15961 : break;
5761 : 2928 : case Store:
5762 [ - + ]: 2928 : if (forbidden_name(c, loc, e->v.Attribute.attr, e->v.Attribute.ctx)) {
5763 : 0 : return ERROR;
5764 : : }
5765 [ - + ]: 2928 : ADDOP_NAME(c, loc, STORE_ATTR, e->v.Attribute.attr, names);
5766 : 2928 : break;
5767 : 20 : case Del:
5768 [ - + ]: 20 : ADDOP_NAME(c, loc, DELETE_ATTR, e->v.Attribute.attr, names);
5769 : 20 : break;
5770 : : }
5771 : 18909 : break;
5772 : 3526 : case Subscript_kind:
5773 : 3526 : return compiler_subscript(c, e);
5774 : 0 : case Starred_kind:
5775 [ # # ]: 0 : switch (e->v.Starred.ctx) {
5776 : 0 : case Store:
5777 : : /* In all legitimate cases, the Starred node was already replaced
5778 : : * by compiler_list/compiler_tuple. XXX: is that okay? */
5779 : 0 : return compiler_error(c, loc,
5780 : : "starred assignment target must be in a list or tuple");
5781 : 0 : default:
5782 : 0 : return compiler_error(c, loc,
5783 : : "can't use starred expression here");
5784 : : }
5785 : : break;
5786 : 21 : case Slice_kind:
5787 : : {
5788 : 21 : int n = compiler_slice(c, e);
5789 [ - + ]: 21 : RETURN_IF_ERROR(n);
5790 [ - + ]: 21 : ADDOP_I(c, loc, BUILD_SLICE, n);
5791 : 21 : break;
5792 : : }
5793 : 101542 : case Name_kind:
5794 : 101542 : return compiler_nameop(c, loc, e->v.Name.id, e->v.Name.ctx);
5795 : : /* child nodes of List and Tuple will have expr_context set */
5796 : 1029 : case List_kind:
5797 : 1029 : return compiler_list(c, e);
5798 : 2952 : case Tuple_kind:
5799 : 2952 : return compiler_tuple(c, e);
5800 : : }
5801 : 54429 : return SUCCESS;
5802 : : }
5803 : :
5804 : : static int
5805 : 201007 : compiler_visit_expr(struct compiler *c, expr_ty e)
5806 : : {
5807 : 201007 : int res = compiler_visit_expr1(c, e);
5808 : 201007 : return res;
5809 : : }
5810 : :
5811 : : static bool
5812 : 3562 : is_two_element_slice(expr_ty s)
5813 : : {
5814 [ + + ]: 4376 : return s->kind == Slice_kind &&
5815 [ + + ]: 814 : s->v.Slice.step == NULL;
5816 : : }
5817 : :
5818 : : static int
5819 : 722 : compiler_augassign(struct compiler *c, stmt_ty s)
5820 : : {
5821 : : assert(s->kind == AugAssign_kind);
5822 : 722 : expr_ty e = s->v.AugAssign.target;
5823 : :
5824 : 722 : location loc = LOC(e);
5825 : :
5826 [ + + + - ]: 722 : switch (e->kind) {
5827 : 116 : case Attribute_kind:
5828 [ - + ]: 116 : VISIT(c, expr, e->v.Attribute.value);
5829 [ - + ]: 116 : ADDOP_I(c, loc, COPY, 1);
5830 : 116 : loc = update_start_location_to_match_attr(c, loc, e);
5831 [ - + ]: 116 : ADDOP_NAME(c, loc, LOAD_ATTR, e->v.Attribute.attr, names);
5832 : 116 : break;
5833 : 18 : case Subscript_kind:
5834 [ - + ]: 18 : VISIT(c, expr, e->v.Subscript.value);
5835 [ - + ]: 18 : if (is_two_element_slice(e->v.Subscript.slice)) {
5836 [ # # ]: 0 : RETURN_IF_ERROR(compiler_slice(c, e->v.Subscript.slice));
5837 [ # # ]: 0 : ADDOP_I(c, loc, COPY, 3);
5838 [ # # ]: 0 : ADDOP_I(c, loc, COPY, 3);
5839 [ # # ]: 0 : ADDOP_I(c, loc, COPY, 3);
5840 [ # # ]: 0 : ADDOP(c, loc, BINARY_SLICE);
5841 : : }
5842 : : else {
5843 [ - + ]: 18 : VISIT(c, expr, e->v.Subscript.slice);
5844 [ - + ]: 18 : ADDOP_I(c, loc, COPY, 2);
5845 [ - + ]: 18 : ADDOP_I(c, loc, COPY, 2);
5846 [ - + ]: 18 : ADDOP(c, loc, BINARY_SUBSCR);
5847 : : }
5848 : 18 : break;
5849 : 588 : case Name_kind:
5850 [ - + ]: 588 : RETURN_IF_ERROR(compiler_nameop(c, loc, e->v.Name.id, Load));
5851 : 588 : break;
5852 : 0 : default:
5853 : 0 : PyErr_Format(PyExc_SystemError,
5854 : : "invalid node type (%d) for augmented assignment",
5855 : 0 : e->kind);
5856 : 0 : return ERROR;
5857 : : }
5858 : :
5859 : 722 : loc = LOC(s);
5860 : :
5861 [ - + ]: 722 : VISIT(c, expr, s->v.AugAssign.value);
5862 [ - + ]: 722 : ADDOP_INPLACE(c, loc, s->v.AugAssign.op);
5863 : :
5864 : 722 : loc = LOC(e);
5865 : :
5866 [ + + + - ]: 722 : switch (e->kind) {
5867 : 116 : case Attribute_kind:
5868 : 116 : loc = update_start_location_to_match_attr(c, loc, e);
5869 [ - + ]: 116 : ADDOP_I(c, loc, SWAP, 2);
5870 [ - + ]: 116 : ADDOP_NAME(c, loc, STORE_ATTR, e->v.Attribute.attr, names);
5871 : 116 : break;
5872 : 18 : case Subscript_kind:
5873 [ - + ]: 18 : if (is_two_element_slice(e->v.Subscript.slice)) {
5874 [ # # ]: 0 : ADDOP_I(c, loc, SWAP, 4);
5875 [ # # ]: 0 : ADDOP_I(c, loc, SWAP, 3);
5876 [ # # ]: 0 : ADDOP_I(c, loc, SWAP, 2);
5877 [ # # ]: 0 : ADDOP(c, loc, STORE_SLICE);
5878 : : }
5879 : : else {
5880 [ - + ]: 18 : ADDOP_I(c, loc, SWAP, 3);
5881 [ - + ]: 18 : ADDOP_I(c, loc, SWAP, 2);
5882 [ - + ]: 18 : ADDOP(c, loc, STORE_SUBSCR);
5883 : : }
5884 : 18 : break;
5885 : 588 : case Name_kind:
5886 : 588 : return compiler_nameop(c, loc, e->v.Name.id, Store);
5887 : 0 : default:
5888 : 0 : Py_UNREACHABLE();
5889 : : }
5890 : 134 : return SUCCESS;
5891 : : }
5892 : :
5893 : : static int
5894 : 0 : check_ann_expr(struct compiler *c, expr_ty e)
5895 : : {
5896 [ # # ]: 0 : VISIT(c, expr, e);
5897 [ # # ]: 0 : ADDOP(c, LOC(e), POP_TOP);
5898 : 0 : return SUCCESS;
5899 : : }
5900 : :
5901 : : static int
5902 : 10 : check_annotation(struct compiler *c, stmt_ty s)
5903 : : {
5904 : : /* Annotations of complex targets does not produce anything
5905 : : under annotations future */
5906 [ - + ]: 10 : if (c->c_future.ff_features & CO_FUTURE_ANNOTATIONS) {
5907 : 0 : return SUCCESS;
5908 : : }
5909 : :
5910 : : /* Annotations are only evaluated in a module or class. */
5911 [ + - ]: 10 : if (c->u->u_scope_type == COMPILER_SCOPE_MODULE ||
5912 [ - + ]: 10 : c->u->u_scope_type == COMPILER_SCOPE_CLASS) {
5913 : 0 : return check_ann_expr(c, s->v.AnnAssign.annotation);
5914 : : }
5915 : 10 : return SUCCESS;
5916 : : }
5917 : :
5918 : : static int
5919 : 0 : check_ann_subscr(struct compiler *c, expr_ty e)
5920 : : {
5921 : : /* We check that everything in a subscript is defined at runtime. */
5922 [ # # # ]: 0 : switch (e->kind) {
5923 : 0 : case Slice_kind:
5924 [ # # # # ]: 0 : if (e->v.Slice.lower && check_ann_expr(c, e->v.Slice.lower) < 0) {
5925 : 0 : return ERROR;
5926 : : }
5927 [ # # # # ]: 0 : if (e->v.Slice.upper && check_ann_expr(c, e->v.Slice.upper) < 0) {
5928 : 0 : return ERROR;
5929 : : }
5930 [ # # # # ]: 0 : if (e->v.Slice.step && check_ann_expr(c, e->v.Slice.step) < 0) {
5931 : 0 : return ERROR;
5932 : : }
5933 : 0 : return SUCCESS;
5934 : 0 : case Tuple_kind: {
5935 : : /* extended slice */
5936 : 0 : asdl_expr_seq *elts = e->v.Tuple.elts;
5937 [ # # ]: 0 : Py_ssize_t i, n = asdl_seq_LEN(elts);
5938 [ # # ]: 0 : for (i = 0; i < n; i++) {
5939 [ # # ]: 0 : RETURN_IF_ERROR(check_ann_subscr(c, asdl_seq_GET(elts, i)));
5940 : : }
5941 : 0 : return SUCCESS;
5942 : : }
5943 : 0 : default:
5944 : 0 : return check_ann_expr(c, e);
5945 : : }
5946 : : }
5947 : :
5948 : : static int
5949 : 17 : compiler_annassign(struct compiler *c, stmt_ty s)
5950 : : {
5951 : 17 : location loc = LOC(s);
5952 : 17 : expr_ty targ = s->v.AnnAssign.target;
5953 : : PyObject* mangled;
5954 : :
5955 : : assert(s->kind == AnnAssign_kind);
5956 : :
5957 : : /* We perform the actual assignment first. */
5958 [ + + ]: 17 : if (s->v.AnnAssign.value) {
5959 [ - + ]: 15 : VISIT(c, expr, s->v.AnnAssign.value);
5960 [ - + ]: 15 : VISIT(c, expr, targ);
5961 : : }
5962 [ + + - - ]: 17 : switch (targ->kind) {
5963 : 7 : case Name_kind:
5964 [ - + ]: 7 : if (forbidden_name(c, loc, targ->v.Name.id, Store)) {
5965 : 0 : return ERROR;
5966 : : }
5967 : : /* If we have a simple name in a module or class, store annotation. */
5968 [ + - ]: 7 : if (s->v.AnnAssign.simple &&
5969 [ + - ]: 7 : (c->u->u_scope_type == COMPILER_SCOPE_MODULE ||
5970 [ + + ]: 7 : c->u->u_scope_type == COMPILER_SCOPE_CLASS)) {
5971 [ - + ]: 2 : if (c->c_future.ff_features & CO_FUTURE_ANNOTATIONS) {
5972 [ # # ]: 0 : VISIT(c, annexpr, s->v.AnnAssign.annotation)
5973 : : }
5974 : : else {
5975 [ - + ]: 2 : VISIT(c, expr, s->v.AnnAssign.annotation);
5976 : : }
5977 [ - + ]: 2 : ADDOP_NAME(c, loc, LOAD_NAME, &_Py_ID(__annotations__), names);
5978 : 2 : mangled = _Py_Mangle(c->u->u_private, targ->v.Name.id);
5979 [ - + - + ]: 2 : ADDOP_LOAD_CONST_NEW(c, loc, mangled);
5980 [ - + ]: 2 : ADDOP(c, loc, STORE_SUBSCR);
5981 : : }
5982 : 7 : break;
5983 : 10 : case Attribute_kind:
5984 [ - + ]: 10 : if (forbidden_name(c, loc, targ->v.Attribute.attr, Store)) {
5985 : 0 : return ERROR;
5986 : : }
5987 [ - + - - ]: 10 : if (!s->v.AnnAssign.value &&
5988 : 0 : check_ann_expr(c, targ->v.Attribute.value) < 0) {
5989 : 0 : return ERROR;
5990 : : }
5991 : 10 : break;
5992 : 0 : case Subscript_kind:
5993 [ # # # # ]: 0 : if (!s->v.AnnAssign.value &&
5994 [ # # ]: 0 : (check_ann_expr(c, targ->v.Subscript.value) < 0 ||
5995 : 0 : check_ann_subscr(c, targ->v.Subscript.slice) < 0)) {
5996 : 0 : return ERROR;
5997 : : }
5998 : 0 : break;
5999 : 0 : default:
6000 : 0 : PyErr_Format(PyExc_SystemError,
6001 : : "invalid node type (%d) for annotated assignment",
6002 : 0 : targ->kind);
6003 : 0 : return ERROR;
6004 : : }
6005 : : /* Annotation is evaluated last. */
6006 [ + + - + ]: 17 : if (!s->v.AnnAssign.simple && check_annotation(c, s) < 0) {
6007 : 0 : return ERROR;
6008 : : }
6009 : 17 : return SUCCESS;
6010 : : }
6011 : :
6012 : : /* Raises a SyntaxError and returns 0.
6013 : : If something goes wrong, a different exception may be raised.
6014 : : */
6015 : :
6016 : : static int
6017 : 0 : compiler_error(struct compiler *c, location loc,
6018 : : const char *format, ...)
6019 : : {
6020 : : va_list vargs;
6021 : 0 : va_start(vargs, format);
6022 : 0 : PyObject *msg = PyUnicode_FromFormatV(format, vargs);
6023 : 0 : va_end(vargs);
6024 [ # # ]: 0 : if (msg == NULL) {
6025 : 0 : return ERROR;
6026 : : }
6027 : 0 : PyObject *loc_obj = PyErr_ProgramTextObject(c->c_filename, loc.lineno);
6028 [ # # ]: 0 : if (loc_obj == NULL) {
6029 : 0 : loc_obj = Py_NewRef(Py_None);
6030 : : }
6031 : 0 : PyObject *args = Py_BuildValue("O(OiiOii)", msg, c->c_filename,
6032 : 0 : loc.lineno, loc.col_offset + 1, loc_obj,
6033 : 0 : loc.end_lineno, loc.end_col_offset + 1);
6034 : 0 : Py_DECREF(msg);
6035 [ # # ]: 0 : if (args == NULL) {
6036 : 0 : goto exit;
6037 : : }
6038 : 0 : PyErr_SetObject(PyExc_SyntaxError, args);
6039 : 0 : exit:
6040 : 0 : Py_DECREF(loc_obj);
6041 : 0 : Py_XDECREF(args);
6042 : 0 : return ERROR;
6043 : : }
6044 : :
6045 : : /* Emits a SyntaxWarning and returns 1 on success.
6046 : : If a SyntaxWarning raised as error, replaces it with a SyntaxError
6047 : : and returns 0.
6048 : : */
6049 : : static int
6050 : 0 : compiler_warn(struct compiler *c, location loc,
6051 : : const char *format, ...)
6052 : : {
6053 : : va_list vargs;
6054 : 0 : va_start(vargs, format);
6055 : 0 : PyObject *msg = PyUnicode_FromFormatV(format, vargs);
6056 : 0 : va_end(vargs);
6057 [ # # ]: 0 : if (msg == NULL) {
6058 : 0 : return ERROR;
6059 : : }
6060 [ # # ]: 0 : if (PyErr_WarnExplicitObject(PyExc_SyntaxWarning, msg, c->c_filename,
6061 : : loc.lineno, NULL, NULL) < 0)
6062 : : {
6063 [ # # ]: 0 : if (PyErr_ExceptionMatches(PyExc_SyntaxWarning)) {
6064 : : /* Replace the SyntaxWarning exception with a SyntaxError
6065 : : to get a more accurate error report */
6066 : 0 : PyErr_Clear();
6067 : : assert(PyUnicode_AsUTF8(msg) != NULL);
6068 : 0 : compiler_error(c, loc, PyUnicode_AsUTF8(msg));
6069 : : }
6070 : 0 : Py_DECREF(msg);
6071 : 0 : return ERROR;
6072 : : }
6073 : 0 : Py_DECREF(msg);
6074 : 0 : return SUCCESS;
6075 : : }
6076 : :
6077 : : static int
6078 : 3526 : compiler_subscript(struct compiler *c, expr_ty e)
6079 : : {
6080 : 3526 : location loc = LOC(e);
6081 : 3526 : expr_context_ty ctx = e->v.Subscript.ctx;
6082 : 3526 : int op = 0;
6083 : :
6084 [ + + ]: 3526 : if (ctx == Load) {
6085 [ - + ]: 2593 : RETURN_IF_ERROR(check_subscripter(c, e->v.Subscript.value));
6086 [ - + ]: 2593 : RETURN_IF_ERROR(check_index(c, e->v.Subscript.value, e->v.Subscript.slice));
6087 : : }
6088 : :
6089 [ - + ]: 3526 : VISIT(c, expr, e->v.Subscript.value);
6090 [ + + + + ]: 3526 : if (is_two_element_slice(e->v.Subscript.slice) && ctx != Del) {
6091 [ - + ]: 793 : RETURN_IF_ERROR(compiler_slice(c, e->v.Subscript.slice));
6092 [ + + ]: 793 : if (ctx == Load) {
6093 [ - + ]: 751 : ADDOP(c, loc, BINARY_SLICE);
6094 : : }
6095 : : else {
6096 : : assert(ctx == Store);
6097 [ - + ]: 42 : ADDOP(c, loc, STORE_SLICE);
6098 : : }
6099 : : }
6100 : : else {
6101 [ - + ]: 2733 : VISIT(c, expr, e->v.Subscript.slice);
6102 [ + + + - ]: 2733 : switch (ctx) {
6103 : 1842 : case Load: op = BINARY_SUBSCR; break;
6104 : 770 : case Store: op = STORE_SUBSCR; break;
6105 : 121 : case Del: op = DELETE_SUBSCR; break;
6106 : : }
6107 : 2733 : assert(op);
6108 [ - + ]: 2733 : ADDOP(c, loc, op);
6109 : : }
6110 : 3526 : return SUCCESS;
6111 : : }
6112 : :
6113 : : /* Returns the number of the values emitted,
6114 : : * thus are needed to build the slice, or -1 if there is an error. */
6115 : : static int
6116 : 814 : compiler_slice(struct compiler *c, expr_ty s)
6117 : : {
6118 : 814 : int n = 2;
6119 : : assert(s->kind == Slice_kind);
6120 : :
6121 : : /* only handles the cases where BUILD_SLICE is emitted */
6122 [ + + ]: 814 : if (s->v.Slice.lower) {
6123 [ - + ]: 450 : VISIT(c, expr, s->v.Slice.lower);
6124 : : }
6125 : : else {
6126 [ - + ]: 364 : ADDOP_LOAD_CONST(c, LOC(s), Py_None);
6127 : : }
6128 : :
6129 [ + + ]: 814 : if (s->v.Slice.upper) {
6130 [ - + ]: 483 : VISIT(c, expr, s->v.Slice.upper);
6131 : : }
6132 : : else {
6133 [ - + ]: 331 : ADDOP_LOAD_CONST(c, LOC(s), Py_None);
6134 : : }
6135 : :
6136 [ + + ]: 814 : if (s->v.Slice.step) {
6137 : 9 : n++;
6138 [ - + ]: 9 : VISIT(c, expr, s->v.Slice.step);
6139 : : }
6140 : 814 : return n;
6141 : : }
6142 : :
6143 : :
6144 : : // PEP 634: Structural Pattern Matching
6145 : :
6146 : : // To keep things simple, all compiler_pattern_* and pattern_helper_* routines
6147 : : // follow the convention of consuming TOS (the subject for the given pattern)
6148 : : // and calling jump_to_fail_pop on failure (no match).
6149 : :
6150 : : // When calling into these routines, it's important that pc->on_top be kept
6151 : : // updated to reflect the current number of items that we are using on the top
6152 : : // of the stack: they will be popped on failure, and any name captures will be
6153 : : // stored *underneath* them on success. This lets us defer all names stores
6154 : : // until the *entire* pattern matches.
6155 : :
6156 : : #define WILDCARD_CHECK(N) \
6157 : : ((N)->kind == MatchAs_kind && !(N)->v.MatchAs.name)
6158 : :
6159 : : #define WILDCARD_STAR_CHECK(N) \
6160 : : ((N)->kind == MatchStar_kind && !(N)->v.MatchStar.name)
6161 : :
6162 : : // Limit permitted subexpressions, even if the parser & AST validator let them through
6163 : : #define MATCH_VALUE_EXPR(N) \
6164 : : ((N)->kind == Constant_kind || (N)->kind == Attribute_kind)
6165 : :
6166 : : // Allocate or resize pc->fail_pop to allow for n items to be popped on failure.
6167 : : static int
6168 : 19 : ensure_fail_pop(struct compiler *c, pattern_context *pc, Py_ssize_t n)
6169 : : {
6170 : 19 : Py_ssize_t size = n + 1;
6171 [ + + ]: 19 : if (size <= pc->fail_pop_size) {
6172 : 8 : return SUCCESS;
6173 : : }
6174 : 11 : Py_ssize_t needed = sizeof(jump_target_label) * size;
6175 : 11 : jump_target_label *resized = PyObject_Realloc(pc->fail_pop, needed);
6176 [ - + ]: 11 : if (resized == NULL) {
6177 : 0 : PyErr_NoMemory();
6178 : 0 : return ERROR;
6179 : : }
6180 : 11 : pc->fail_pop = resized;
6181 [ + + ]: 31 : while (pc->fail_pop_size < size) {
6182 [ - + ]: 20 : NEW_JUMP_TARGET_LABEL(c, new_block);
6183 : 20 : pc->fail_pop[pc->fail_pop_size++] = new_block;
6184 : : }
6185 : 11 : return SUCCESS;
6186 : : }
6187 : :
6188 : : // Use op to jump to the correct fail_pop block.
6189 : : static int
6190 : 18 : jump_to_fail_pop(struct compiler *c, location loc,
6191 : : pattern_context *pc, int op)
6192 : : {
6193 : : // Pop any items on the top of the stack, plus any objects we were going to
6194 : : // capture on success:
6195 : 18 : Py_ssize_t pops = pc->on_top + PyList_GET_SIZE(pc->stores);
6196 [ - + ]: 18 : RETURN_IF_ERROR(ensure_fail_pop(c, pc, pops));
6197 [ - + ]: 18 : ADDOP_JUMP(c, loc, op, pc->fail_pop[pops]);
6198 : 18 : return SUCCESS;
6199 : : }
6200 : :
6201 : : // Build all of the fail_pop blocks and reset fail_pop.
6202 : : static int
6203 : 11 : emit_and_reset_fail_pop(struct compiler *c, location loc,
6204 : : pattern_context *pc)
6205 : : {
6206 [ - + ]: 11 : if (!pc->fail_pop_size) {
6207 : : assert(pc->fail_pop == NULL);
6208 : 0 : return SUCCESS;
6209 : : }
6210 [ + + ]: 20 : while (--pc->fail_pop_size) {
6211 [ - + ]: 9 : USE_LABEL(c, pc->fail_pop[pc->fail_pop_size]);
6212 [ - + ]: 9 : if (codegen_addop_noarg(INSTR_SEQUENCE(c), POP_TOP, loc) < 0) {
6213 : 0 : pc->fail_pop_size = 0;
6214 : 0 : PyObject_Free(pc->fail_pop);
6215 : 0 : pc->fail_pop = NULL;
6216 : 0 : return ERROR;
6217 : : }
6218 : : }
6219 [ - + ]: 11 : USE_LABEL(c, pc->fail_pop[0]);
6220 : 11 : PyObject_Free(pc->fail_pop);
6221 : 11 : pc->fail_pop = NULL;
6222 : 11 : return SUCCESS;
6223 : : }
6224 : :
6225 : : static int
6226 : 0 : compiler_error_duplicate_store(struct compiler *c, location loc, identifier n)
6227 : : {
6228 : 0 : return compiler_error(c, loc,
6229 : : "multiple assignments to name %R in pattern", n);
6230 : : }
6231 : :
6232 : : // Duplicate the effect of 3.10's ROT_* instructions using SWAPs.
6233 : : static int
6234 : 4 : pattern_helper_rotate(struct compiler *c, location loc, Py_ssize_t count)
6235 : : {
6236 [ - + ]: 4 : while (1 < count) {
6237 [ # # ]: 0 : ADDOP_I(c, loc, SWAP, count--);
6238 : : }
6239 : 4 : return SUCCESS;
6240 : : }
6241 : :
6242 : : static int
6243 : 4 : pattern_helper_store_name(struct compiler *c, location loc,
6244 : : identifier n, pattern_context *pc)
6245 : : {
6246 [ - + ]: 4 : if (n == NULL) {
6247 [ # # ]: 0 : ADDOP(c, loc, POP_TOP);
6248 : 0 : return SUCCESS;
6249 : : }
6250 [ - + ]: 4 : if (forbidden_name(c, loc, n, Store)) {
6251 : 0 : return ERROR;
6252 : : }
6253 : : // Can't assign to the same name twice:
6254 : 4 : int duplicate = PySequence_Contains(pc->stores, n);
6255 [ - + ]: 4 : RETURN_IF_ERROR(duplicate);
6256 [ - + ]: 4 : if (duplicate) {
6257 : 0 : return compiler_error_duplicate_store(c, loc, n);
6258 : : }
6259 : : // Rotate this object underneath any items we need to preserve:
6260 : 4 : Py_ssize_t rotations = pc->on_top + PyList_GET_SIZE(pc->stores) + 1;
6261 [ - + ]: 4 : RETURN_IF_ERROR(pattern_helper_rotate(c, loc, rotations));
6262 [ - + ]: 4 : RETURN_IF_ERROR(PyList_Append(pc->stores, n));
6263 : 4 : return SUCCESS;
6264 : : }
6265 : :
6266 : :
6267 : : static int
6268 : 5 : pattern_unpack_helper(struct compiler *c, location loc,
6269 : : asdl_pattern_seq *elts)
6270 : : {
6271 [ + - ]: 5 : Py_ssize_t n = asdl_seq_LEN(elts);
6272 : 5 : int seen_star = 0;
6273 [ + + ]: 10 : for (Py_ssize_t i = 0; i < n; i++) {
6274 : 5 : pattern_ty elt = asdl_seq_GET(elts, i);
6275 [ + + + - ]: 5 : if (elt->kind == MatchStar_kind && !seen_star) {
6276 [ + - ]: 1 : if ((i >= (1 << 8)) ||
6277 [ - + ]: 1 : (n-i-1 >= (INT_MAX >> 8))) {
6278 : 0 : return compiler_error(c, loc,
6279 : : "too many expressions in "
6280 : : "star-unpacking sequence pattern");
6281 : : }
6282 [ - + ]: 1 : ADDOP_I(c, loc, UNPACK_EX, (i + ((n-i-1) << 8)));
6283 : 1 : seen_star = 1;
6284 : : }
6285 [ - + ]: 4 : else if (elt->kind == MatchStar_kind) {
6286 : 0 : return compiler_error(c, loc,
6287 : : "multiple starred expressions in sequence pattern");
6288 : : }
6289 : : }
6290 [ + + ]: 5 : if (!seen_star) {
6291 [ - + ]: 4 : ADDOP_I(c, loc, UNPACK_SEQUENCE, n);
6292 : : }
6293 : 5 : return SUCCESS;
6294 : : }
6295 : :
6296 : : static int
6297 : 5 : pattern_helper_sequence_unpack(struct compiler *c, location loc,
6298 : : asdl_pattern_seq *patterns, Py_ssize_t star,
6299 : : pattern_context *pc)
6300 : : {
6301 [ - + ]: 5 : RETURN_IF_ERROR(pattern_unpack_helper(c, loc, patterns));
6302 [ + - ]: 5 : Py_ssize_t size = asdl_seq_LEN(patterns);
6303 : : // We've now got a bunch of new subjects on the stack. They need to remain
6304 : : // there after each subpattern match:
6305 : 5 : pc->on_top += size;
6306 [ + + ]: 10 : for (Py_ssize_t i = 0; i < size; i++) {
6307 : : // One less item to keep track of each time we loop through:
6308 : 5 : pc->on_top--;
6309 : 5 : pattern_ty pattern = asdl_seq_GET(patterns, i);
6310 [ - + ]: 5 : RETURN_IF_ERROR(compiler_pattern_subpattern(c, pattern, pc));
6311 : : }
6312 : 5 : return SUCCESS;
6313 : : }
6314 : :
6315 : : // Like pattern_helper_sequence_unpack, but uses BINARY_SUBSCR instead of
6316 : : // UNPACK_SEQUENCE / UNPACK_EX. This is more efficient for patterns with a
6317 : : // starred wildcard like [first, *_] / [first, *_, last] / [*_, last] / etc.
6318 : : static int
6319 : 0 : pattern_helper_sequence_subscr(struct compiler *c, location loc,
6320 : : asdl_pattern_seq *patterns, Py_ssize_t star,
6321 : : pattern_context *pc)
6322 : : {
6323 : : // We need to keep the subject around for extracting elements:
6324 : 0 : pc->on_top++;
6325 [ # # ]: 0 : Py_ssize_t size = asdl_seq_LEN(patterns);
6326 [ # # ]: 0 : for (Py_ssize_t i = 0; i < size; i++) {
6327 : 0 : pattern_ty pattern = asdl_seq_GET(patterns, i);
6328 [ # # # # ]: 0 : if (WILDCARD_CHECK(pattern)) {
6329 : 0 : continue;
6330 : : }
6331 [ # # ]: 0 : if (i == star) {
6332 : : assert(WILDCARD_STAR_CHECK(pattern));
6333 : 0 : continue;
6334 : : }
6335 [ # # ]: 0 : ADDOP_I(c, loc, COPY, 1);
6336 [ # # ]: 0 : if (i < star) {
6337 [ # # # # ]: 0 : ADDOP_LOAD_CONST_NEW(c, loc, PyLong_FromSsize_t(i));
6338 : : }
6339 : : else {
6340 : : // The subject may not support negative indexing! Compute a
6341 : : // nonnegative index:
6342 [ # # ]: 0 : ADDOP(c, loc, GET_LEN);
6343 [ # # # # ]: 0 : ADDOP_LOAD_CONST_NEW(c, loc, PyLong_FromSsize_t(size - i));
6344 [ # # ]: 0 : ADDOP_BINARY(c, loc, Sub);
6345 : : }
6346 [ # # ]: 0 : ADDOP(c, loc, BINARY_SUBSCR);
6347 [ # # ]: 0 : RETURN_IF_ERROR(compiler_pattern_subpattern(c, pattern, pc));
6348 : : }
6349 : : // Pop the subject, we're done with it:
6350 : 0 : pc->on_top--;
6351 [ # # ]: 0 : ADDOP(c, loc, POP_TOP);
6352 : 0 : return SUCCESS;
6353 : : }
6354 : :
6355 : : // Like compiler_pattern, but turn off checks for irrefutability.
6356 : : static int
6357 : 7 : compiler_pattern_subpattern(struct compiler *c,
6358 : : pattern_ty p, pattern_context *pc)
6359 : : {
6360 : 7 : int allow_irrefutable = pc->allow_irrefutable;
6361 : 7 : pc->allow_irrefutable = 1;
6362 [ - + ]: 7 : RETURN_IF_ERROR(compiler_pattern(c, p, pc));
6363 : 7 : pc->allow_irrefutable = allow_irrefutable;
6364 : 7 : return SUCCESS;
6365 : : }
6366 : :
6367 : : static int
6368 : 3 : compiler_pattern_as(struct compiler *c, pattern_ty p, pattern_context *pc)
6369 : : {
6370 : : assert(p->kind == MatchAs_kind);
6371 [ + - ]: 3 : if (p->v.MatchAs.pattern == NULL) {
6372 : : // An irrefutable match:
6373 [ - + ]: 3 : if (!pc->allow_irrefutable) {
6374 [ # # ]: 0 : if (p->v.MatchAs.name) {
6375 : 0 : const char *e = "name capture %R makes remaining patterns unreachable";
6376 : 0 : return compiler_error(c, LOC(p), e, p->v.MatchAs.name);
6377 : : }
6378 : 0 : const char *e = "wildcard makes remaining patterns unreachable";
6379 : 0 : return compiler_error(c, LOC(p), e);
6380 : : }
6381 : 3 : return pattern_helper_store_name(c, LOC(p), p->v.MatchAs.name, pc);
6382 : : }
6383 : : // Need to make a copy for (possibly) storing later:
6384 : 0 : pc->on_top++;
6385 [ # # ]: 0 : ADDOP_I(c, LOC(p), COPY, 1);
6386 [ # # ]: 0 : RETURN_IF_ERROR(compiler_pattern(c, p->v.MatchAs.pattern, pc));
6387 : : // Success! Store it:
6388 : 0 : pc->on_top--;
6389 [ # # ]: 0 : RETURN_IF_ERROR(pattern_helper_store_name(c, LOC(p), p->v.MatchAs.name, pc));
6390 : 0 : return SUCCESS;
6391 : : }
6392 : :
6393 : : static int
6394 : 1 : compiler_pattern_star(struct compiler *c, pattern_ty p, pattern_context *pc)
6395 : : {
6396 : : assert(p->kind == MatchStar_kind);
6397 [ - + ]: 1 : RETURN_IF_ERROR(
6398 : : pattern_helper_store_name(c, LOC(p), p->v.MatchStar.name, pc));
6399 : 1 : return SUCCESS;
6400 : : }
6401 : :
6402 : : static int
6403 : 0 : validate_kwd_attrs(struct compiler *c, asdl_identifier_seq *attrs, asdl_pattern_seq* patterns)
6404 : : {
6405 : : // Any errors will point to the pattern rather than the arg name as the
6406 : : // parser is only supplying identifiers rather than Name or keyword nodes
6407 [ # # ]: 0 : Py_ssize_t nattrs = asdl_seq_LEN(attrs);
6408 [ # # ]: 0 : for (Py_ssize_t i = 0; i < nattrs; i++) {
6409 : 0 : identifier attr = ((identifier)asdl_seq_GET(attrs, i));
6410 : 0 : location loc = LOC((pattern_ty) asdl_seq_GET(patterns, i));
6411 [ # # ]: 0 : if (forbidden_name(c, loc, attr, Store)) {
6412 : 0 : return ERROR;
6413 : : }
6414 [ # # ]: 0 : for (Py_ssize_t j = i + 1; j < nattrs; j++) {
6415 : 0 : identifier other = ((identifier)asdl_seq_GET(attrs, j));
6416 [ # # ]: 0 : if (!PyUnicode_Compare(attr, other)) {
6417 : 0 : location loc = LOC((pattern_ty) asdl_seq_GET(patterns, j));
6418 : 0 : compiler_error(c, loc, "attribute name repeated in class pattern: %U", attr);
6419 : 0 : return ERROR;
6420 : : }
6421 : : }
6422 : : }
6423 : 0 : return SUCCESS;
6424 : : }
6425 : :
6426 : : static int
6427 : 4 : compiler_pattern_class(struct compiler *c, pattern_ty p, pattern_context *pc)
6428 : : {
6429 : : assert(p->kind == MatchClass_kind);
6430 : 4 : asdl_pattern_seq *patterns = p->v.MatchClass.patterns;
6431 : 4 : asdl_identifier_seq *kwd_attrs = p->v.MatchClass.kwd_attrs;
6432 : 4 : asdl_pattern_seq *kwd_patterns = p->v.MatchClass.kwd_patterns;
6433 [ + + ]: 4 : Py_ssize_t nargs = asdl_seq_LEN(patterns);
6434 [ - + ]: 4 : Py_ssize_t nattrs = asdl_seq_LEN(kwd_attrs);
6435 [ - + ]: 4 : Py_ssize_t nkwd_patterns = asdl_seq_LEN(kwd_patterns);
6436 [ - + ]: 4 : if (nattrs != nkwd_patterns) {
6437 : : // AST validator shouldn't let this happen, but if it does,
6438 : : // just fail, don't crash out of the interpreter
6439 : 0 : const char * e = "kwd_attrs (%d) / kwd_patterns (%d) length mismatch in class pattern";
6440 : 0 : return compiler_error(c, LOC(p), e, nattrs, nkwd_patterns);
6441 : : }
6442 [ + - - + ]: 4 : if (INT_MAX < nargs || INT_MAX < nargs + nattrs - 1) {
6443 : 0 : const char *e = "too many sub-patterns in class pattern %R";
6444 : 0 : return compiler_error(c, LOC(p), e, p->v.MatchClass.cls);
6445 : : }
6446 [ - + ]: 4 : if (nattrs) {
6447 [ # # ]: 0 : RETURN_IF_ERROR(validate_kwd_attrs(c, kwd_attrs, kwd_patterns));
6448 : : }
6449 [ - + ]: 4 : VISIT(c, expr, p->v.MatchClass.cls);
6450 : 4 : PyObject *attr_names = PyTuple_New(nattrs);
6451 [ - + ]: 4 : if (attr_names == NULL) {
6452 : 0 : return ERROR;
6453 : : }
6454 : : Py_ssize_t i;
6455 [ - + ]: 4 : for (i = 0; i < nattrs; i++) {
6456 : 0 : PyObject *name = asdl_seq_GET(kwd_attrs, i);
6457 : 0 : PyTuple_SET_ITEM(attr_names, i, Py_NewRef(name));
6458 : : }
6459 [ - + - + ]: 4 : ADDOP_LOAD_CONST_NEW(c, LOC(p), attr_names);
6460 [ - + ]: 4 : ADDOP_I(c, LOC(p), MATCH_CLASS, nargs);
6461 [ - + ]: 4 : ADDOP_I(c, LOC(p), COPY, 1);
6462 [ - + ]: 4 : ADDOP_LOAD_CONST(c, LOC(p), Py_None);
6463 [ - + ]: 4 : ADDOP_I(c, LOC(p), IS_OP, 1);
6464 : : // TOS is now a tuple of (nargs + nattrs) attributes (or None):
6465 : 4 : pc->on_top++;
6466 [ - + ]: 4 : RETURN_IF_ERROR(jump_to_fail_pop(c, LOC(p), pc, POP_JUMP_IF_FALSE));
6467 [ - + ]: 4 : ADDOP_I(c, LOC(p), UNPACK_SEQUENCE, nargs + nattrs);
6468 : 4 : pc->on_top += nargs + nattrs - 1;
6469 [ + + ]: 6 : for (i = 0; i < nargs + nattrs; i++) {
6470 : 2 : pc->on_top--;
6471 : : pattern_ty pattern;
6472 [ + - ]: 2 : if (i < nargs) {
6473 : : // Positional:
6474 : 2 : pattern = asdl_seq_GET(patterns, i);
6475 : : }
6476 : : else {
6477 : : // Keyword:
6478 : 0 : pattern = asdl_seq_GET(kwd_patterns, i - nargs);
6479 : : }
6480 [ + - - + ]: 2 : if (WILDCARD_CHECK(pattern)) {
6481 [ # # ]: 0 : ADDOP(c, LOC(p), POP_TOP);
6482 : 0 : continue;
6483 : : }
6484 [ - + ]: 2 : RETURN_IF_ERROR(compiler_pattern_subpattern(c, pattern, pc));
6485 : : }
6486 : : // Success! Pop the tuple of attributes:
6487 : 4 : return SUCCESS;
6488 : : }
6489 : :
6490 : : static int
6491 : 0 : compiler_pattern_mapping(struct compiler *c, pattern_ty p,
6492 : : pattern_context *pc)
6493 : : {
6494 : : assert(p->kind == MatchMapping_kind);
6495 : 0 : asdl_expr_seq *keys = p->v.MatchMapping.keys;
6496 : 0 : asdl_pattern_seq *patterns = p->v.MatchMapping.patterns;
6497 [ # # ]: 0 : Py_ssize_t size = asdl_seq_LEN(keys);
6498 [ # # ]: 0 : Py_ssize_t npatterns = asdl_seq_LEN(patterns);
6499 [ # # ]: 0 : if (size != npatterns) {
6500 : : // AST validator shouldn't let this happen, but if it does,
6501 : : // just fail, don't crash out of the interpreter
6502 : 0 : const char * e = "keys (%d) / patterns (%d) length mismatch in mapping pattern";
6503 : 0 : return compiler_error(c, LOC(p), e, size, npatterns);
6504 : : }
6505 : : // We have a double-star target if "rest" is set
6506 : 0 : PyObject *star_target = p->v.MatchMapping.rest;
6507 : : // We need to keep the subject on top during the mapping and length checks:
6508 : 0 : pc->on_top++;
6509 [ # # ]: 0 : ADDOP(c, LOC(p), MATCH_MAPPING);
6510 [ # # ]: 0 : RETURN_IF_ERROR(jump_to_fail_pop(c, LOC(p), pc, POP_JUMP_IF_FALSE));
6511 [ # # # # ]: 0 : if (!size && !star_target) {
6512 : : // If the pattern is just "{}", we're done! Pop the subject:
6513 : 0 : pc->on_top--;
6514 [ # # ]: 0 : ADDOP(c, LOC(p), POP_TOP);
6515 : 0 : return SUCCESS;
6516 : : }
6517 [ # # ]: 0 : if (size) {
6518 : : // If the pattern has any keys in it, perform a length check:
6519 [ # # ]: 0 : ADDOP(c, LOC(p), GET_LEN);
6520 [ # # # # ]: 0 : ADDOP_LOAD_CONST_NEW(c, LOC(p), PyLong_FromSsize_t(size));
6521 [ # # ]: 0 : ADDOP_COMPARE(c, LOC(p), GtE);
6522 [ # # ]: 0 : RETURN_IF_ERROR(jump_to_fail_pop(c, LOC(p), pc, POP_JUMP_IF_FALSE));
6523 : : }
6524 [ # # ]: 0 : if (INT_MAX < size - 1) {
6525 : 0 : return compiler_error(c, LOC(p), "too many sub-patterns in mapping pattern");
6526 : : }
6527 : : // Collect all of the keys into a tuple for MATCH_KEYS and
6528 : : // **rest. They can either be dotted names or literals:
6529 : :
6530 : : // Maintaining a set of Constant_kind kind keys allows us to raise a
6531 : : // SyntaxError in the case of duplicates.
6532 : 0 : PyObject *seen = PySet_New(NULL);
6533 [ # # ]: 0 : if (seen == NULL) {
6534 : 0 : return ERROR;
6535 : : }
6536 : :
6537 : : // NOTE: goto error on failure in the loop below to avoid leaking `seen`
6538 [ # # ]: 0 : for (Py_ssize_t i = 0; i < size; i++) {
6539 : 0 : expr_ty key = asdl_seq_GET(keys, i);
6540 [ # # ]: 0 : if (key == NULL) {
6541 : 0 : const char *e = "can't use NULL keys in MatchMapping "
6542 : : "(set 'rest' parameter instead)";
6543 : 0 : location loc = LOC((pattern_ty) asdl_seq_GET(patterns, i));
6544 : 0 : compiler_error(c, loc, e);
6545 : 0 : goto error;
6546 : : }
6547 : :
6548 [ # # ]: 0 : if (key->kind == Constant_kind) {
6549 : 0 : int in_seen = PySet_Contains(seen, key->v.Constant.value);
6550 [ # # ]: 0 : if (in_seen < 0) {
6551 : 0 : goto error;
6552 : : }
6553 [ # # ]: 0 : if (in_seen) {
6554 : 0 : const char *e = "mapping pattern checks duplicate key (%R)";
6555 : 0 : compiler_error(c, LOC(p), e, key->v.Constant.value);
6556 : 0 : goto error;
6557 : : }
6558 [ # # ]: 0 : if (PySet_Add(seen, key->v.Constant.value)) {
6559 : 0 : goto error;
6560 : : }
6561 : : }
6562 : :
6563 [ # # ]: 0 : else if (key->kind != Attribute_kind) {
6564 : 0 : const char *e = "mapping pattern keys may only match literals and attribute lookups";
6565 : 0 : compiler_error(c, LOC(p), e);
6566 : 0 : goto error;
6567 : : }
6568 [ # # ]: 0 : if (compiler_visit_expr(c, key) < 0) {
6569 : 0 : goto error;
6570 : : }
6571 : : }
6572 : :
6573 : : // all keys have been checked; there are no duplicates
6574 : 0 : Py_DECREF(seen);
6575 : :
6576 [ # # ]: 0 : ADDOP_I(c, LOC(p), BUILD_TUPLE, size);
6577 [ # # ]: 0 : ADDOP(c, LOC(p), MATCH_KEYS);
6578 : : // There's now a tuple of keys and a tuple of values on top of the subject:
6579 : 0 : pc->on_top += 2;
6580 [ # # ]: 0 : ADDOP_I(c, LOC(p), COPY, 1);
6581 [ # # ]: 0 : ADDOP_LOAD_CONST(c, LOC(p), Py_None);
6582 [ # # ]: 0 : ADDOP_I(c, LOC(p), IS_OP, 1);
6583 [ # # ]: 0 : RETURN_IF_ERROR(jump_to_fail_pop(c, LOC(p), pc, POP_JUMP_IF_FALSE));
6584 : : // So far so good. Use that tuple of values on the stack to match
6585 : : // sub-patterns against:
6586 [ # # ]: 0 : ADDOP_I(c, LOC(p), UNPACK_SEQUENCE, size);
6587 : 0 : pc->on_top += size - 1;
6588 [ # # ]: 0 : for (Py_ssize_t i = 0; i < size; i++) {
6589 : 0 : pc->on_top--;
6590 : 0 : pattern_ty pattern = asdl_seq_GET(patterns, i);
6591 [ # # ]: 0 : RETURN_IF_ERROR(compiler_pattern_subpattern(c, pattern, pc));
6592 : : }
6593 : : // If we get this far, it's a match! Whatever happens next should consume
6594 : : // the tuple of keys and the subject:
6595 : 0 : pc->on_top -= 2;
6596 [ # # ]: 0 : if (star_target) {
6597 : : // If we have a starred name, bind a dict of remaining items to it (this may
6598 : : // seem a bit inefficient, but keys is rarely big enough to actually impact
6599 : : // runtime):
6600 : : // rest = dict(TOS1)
6601 : : // for key in TOS:
6602 : : // del rest[key]
6603 [ # # ]: 0 : ADDOP_I(c, LOC(p), BUILD_MAP, 0); // [subject, keys, empty]
6604 [ # # ]: 0 : ADDOP_I(c, LOC(p), SWAP, 3); // [empty, keys, subject]
6605 [ # # ]: 0 : ADDOP_I(c, LOC(p), DICT_UPDATE, 2); // [copy, keys]
6606 [ # # ]: 0 : ADDOP_I(c, LOC(p), UNPACK_SEQUENCE, size); // [copy, keys...]
6607 [ # # ]: 0 : while (size) {
6608 [ # # ]: 0 : ADDOP_I(c, LOC(p), COPY, 1 + size--); // [copy, keys..., copy]
6609 [ # # ]: 0 : ADDOP_I(c, LOC(p), SWAP, 2); // [copy, keys..., copy, key]
6610 [ # # ]: 0 : ADDOP(c, LOC(p), DELETE_SUBSCR); // [copy, keys...]
6611 : : }
6612 [ # # ]: 0 : RETURN_IF_ERROR(pattern_helper_store_name(c, LOC(p), star_target, pc));
6613 : : }
6614 : : else {
6615 [ # # ]: 0 : ADDOP(c, LOC(p), POP_TOP); // Tuple of keys.
6616 [ # # ]: 0 : ADDOP(c, LOC(p), POP_TOP); // Subject.
6617 : : }
6618 : 0 : return SUCCESS;
6619 : :
6620 : 0 : error:
6621 : 0 : Py_DECREF(seen);
6622 : 0 : return ERROR;
6623 : : }
6624 : :
6625 : : static int
6626 : 0 : compiler_pattern_or(struct compiler *c, pattern_ty p, pattern_context *pc)
6627 : : {
6628 : : assert(p->kind == MatchOr_kind);
6629 [ # # ]: 0 : NEW_JUMP_TARGET_LABEL(c, end);
6630 [ # # ]: 0 : Py_ssize_t size = asdl_seq_LEN(p->v.MatchOr.patterns);
6631 : : assert(size > 1);
6632 : : // We're going to be messing with pc. Keep the original info handy:
6633 : 0 : pattern_context old_pc = *pc;
6634 : 0 : Py_INCREF(pc->stores);
6635 : : // control is the list of names bound by the first alternative. It is used
6636 : : // for checking different name bindings in alternatives, and for correcting
6637 : : // the order in which extracted elements are placed on the stack.
6638 : 0 : PyObject *control = NULL;
6639 : : // NOTE: We can't use returning macros anymore! goto error on error.
6640 [ # # ]: 0 : for (Py_ssize_t i = 0; i < size; i++) {
6641 : 0 : pattern_ty alt = asdl_seq_GET(p->v.MatchOr.patterns, i);
6642 : 0 : PyObject *pc_stores = PyList_New(0);
6643 [ # # ]: 0 : if (pc_stores == NULL) {
6644 : 0 : goto error;
6645 : : }
6646 : 0 : Py_SETREF(pc->stores, pc_stores);
6647 : : // An irrefutable sub-pattern must be last, if it is allowed at all:
6648 [ # # # # ]: 0 : pc->allow_irrefutable = (i == size - 1) && old_pc.allow_irrefutable;
6649 : 0 : pc->fail_pop = NULL;
6650 : 0 : pc->fail_pop_size = 0;
6651 : 0 : pc->on_top = 0;
6652 [ # # # # ]: 0 : if (codegen_addop_i(INSTR_SEQUENCE(c), COPY, 1, LOC(alt)) < 0 ||
6653 : 0 : compiler_pattern(c, alt, pc) < 0) {
6654 : 0 : goto error;
6655 : : }
6656 : : // Success!
6657 : 0 : Py_ssize_t nstores = PyList_GET_SIZE(pc->stores);
6658 [ # # ]: 0 : if (!i) {
6659 : : // This is the first alternative, so save its stores as a "control"
6660 : : // for the others (they can't bind a different set of names, and
6661 : : // might need to be reordered):
6662 : : assert(control == NULL);
6663 : 0 : control = Py_NewRef(pc->stores);
6664 : : }
6665 [ # # ]: 0 : else if (nstores != PyList_GET_SIZE(control)) {
6666 : 0 : goto diff;
6667 : : }
6668 [ # # ]: 0 : else if (nstores) {
6669 : : // There were captures. Check to see if we differ from control:
6670 : 0 : Py_ssize_t icontrol = nstores;
6671 [ # # ]: 0 : while (icontrol--) {
6672 : 0 : PyObject *name = PyList_GET_ITEM(control, icontrol);
6673 : 0 : Py_ssize_t istores = PySequence_Index(pc->stores, name);
6674 [ # # ]: 0 : if (istores < 0) {
6675 : 0 : PyErr_Clear();
6676 : 0 : goto diff;
6677 : : }
6678 [ # # ]: 0 : if (icontrol != istores) {
6679 : : // Reorder the names on the stack to match the order of the
6680 : : // names in control. There's probably a better way of doing
6681 : : // this; the current solution is potentially very
6682 : : // inefficient when each alternative subpattern binds lots
6683 : : // of names in different orders. It's fine for reasonable
6684 : : // cases, though, and the peephole optimizer will ensure
6685 : : // that the final code is as efficient as possible.
6686 : : assert(istores < icontrol);
6687 : 0 : Py_ssize_t rotations = istores + 1;
6688 : : // Perform the same rotation on pc->stores:
6689 : 0 : PyObject *rotated = PyList_GetSlice(pc->stores, 0,
6690 : : rotations);
6691 [ # # # # ]: 0 : if (rotated == NULL ||
6692 [ # # ]: 0 : PyList_SetSlice(pc->stores, 0, rotations, NULL) ||
6693 : 0 : PyList_SetSlice(pc->stores, icontrol - istores,
6694 : : icontrol - istores, rotated))
6695 : : {
6696 : 0 : Py_XDECREF(rotated);
6697 : 0 : goto error;
6698 : : }
6699 : 0 : Py_DECREF(rotated);
6700 : : // That just did:
6701 : : // rotated = pc_stores[:rotations]
6702 : : // del pc_stores[:rotations]
6703 : : // pc_stores[icontrol-istores:icontrol-istores] = rotated
6704 : : // Do the same thing to the stack, using several
6705 : : // rotations:
6706 [ # # ]: 0 : while (rotations--) {
6707 [ # # ]: 0 : if (pattern_helper_rotate(c, LOC(alt), icontrol + 1) < 0) {
6708 : 0 : goto error;
6709 : : }
6710 : : }
6711 : : }
6712 : : }
6713 : : }
6714 : : assert(control);
6715 [ # # # # ]: 0 : if (codegen_addop_j(INSTR_SEQUENCE(c), LOC(alt), JUMP, end) < 0 ||
6716 : 0 : emit_and_reset_fail_pop(c, LOC(alt), pc) < 0)
6717 : : {
6718 : 0 : goto error;
6719 : : }
6720 : : }
6721 : 0 : Py_DECREF(pc->stores);
6722 : 0 : *pc = old_pc;
6723 : 0 : Py_INCREF(pc->stores);
6724 : : // Need to NULL this for the PyObject_Free call in the error block.
6725 : 0 : old_pc.fail_pop = NULL;
6726 : : // No match. Pop the remaining copy of the subject and fail:
6727 [ # # # # ]: 0 : if (codegen_addop_noarg(INSTR_SEQUENCE(c), POP_TOP, LOC(p)) < 0 ||
6728 : 0 : jump_to_fail_pop(c, LOC(p), pc, JUMP) < 0) {
6729 : 0 : goto error;
6730 : : }
6731 : :
6732 [ # # ]: 0 : USE_LABEL(c, end);
6733 : 0 : Py_ssize_t nstores = PyList_GET_SIZE(control);
6734 : : // There's a bunch of stuff on the stack between where the new stores
6735 : : // are and where they need to be:
6736 : : // - The other stores.
6737 : : // - A copy of the subject.
6738 : : // - Anything else that may be on top of the stack.
6739 : : // - Any previous stores we've already stashed away on the stack.
6740 : 0 : Py_ssize_t nrots = nstores + 1 + pc->on_top + PyList_GET_SIZE(pc->stores);
6741 [ # # ]: 0 : for (Py_ssize_t i = 0; i < nstores; i++) {
6742 : : // Rotate this capture to its proper place on the stack:
6743 [ # # ]: 0 : if (pattern_helper_rotate(c, LOC(p), nrots) < 0) {
6744 : 0 : goto error;
6745 : : }
6746 : : // Update the list of previous stores with this new name, checking for
6747 : : // duplicates:
6748 : 0 : PyObject *name = PyList_GET_ITEM(control, i);
6749 : 0 : int dupe = PySequence_Contains(pc->stores, name);
6750 [ # # ]: 0 : if (dupe < 0) {
6751 : 0 : goto error;
6752 : : }
6753 [ # # ]: 0 : if (dupe) {
6754 : 0 : compiler_error_duplicate_store(c, LOC(p), name);
6755 : 0 : goto error;
6756 : : }
6757 [ # # ]: 0 : if (PyList_Append(pc->stores, name)) {
6758 : 0 : goto error;
6759 : : }
6760 : : }
6761 : 0 : Py_DECREF(old_pc.stores);
6762 : 0 : Py_DECREF(control);
6763 : : // NOTE: Returning macros are safe again.
6764 : : // Pop the copy of the subject:
6765 [ # # ]: 0 : ADDOP(c, LOC(p), POP_TOP);
6766 : 0 : return SUCCESS;
6767 : 0 : diff:
6768 : 0 : compiler_error(c, LOC(p), "alternative patterns bind different names");
6769 : 0 : error:
6770 : 0 : PyObject_Free(old_pc.fail_pop);
6771 : 0 : Py_DECREF(old_pc.stores);
6772 : 0 : Py_XDECREF(control);
6773 : 0 : return ERROR;
6774 : : }
6775 : :
6776 : :
6777 : : static int
6778 : 5 : compiler_pattern_sequence(struct compiler *c, pattern_ty p,
6779 : : pattern_context *pc)
6780 : : {
6781 : : assert(p->kind == MatchSequence_kind);
6782 : 5 : asdl_pattern_seq *patterns = p->v.MatchSequence.patterns;
6783 [ + - ]: 5 : Py_ssize_t size = asdl_seq_LEN(patterns);
6784 : 5 : Py_ssize_t star = -1;
6785 : 5 : int only_wildcard = 1;
6786 : 5 : int star_wildcard = 0;
6787 : : // Find a starred name, if it exists. There may be at most one:
6788 [ + + ]: 10 : for (Py_ssize_t i = 0; i < size; i++) {
6789 : 5 : pattern_ty pattern = asdl_seq_GET(patterns, i);
6790 [ + + ]: 5 : if (pattern->kind == MatchStar_kind) {
6791 [ - + ]: 1 : if (star >= 0) {
6792 : 0 : const char *e = "multiple starred names in sequence pattern";
6793 : 0 : return compiler_error(c, LOC(p), e);
6794 : : }
6795 [ + - - + ]: 1 : star_wildcard = WILDCARD_STAR_CHECK(pattern);
6796 : 1 : only_wildcard &= star_wildcard;
6797 : 1 : star = i;
6798 : 1 : continue;
6799 : : }
6800 [ - + - - ]: 4 : only_wildcard &= WILDCARD_CHECK(pattern);
6801 : : }
6802 : : // We need to keep the subject on top during the sequence and length checks:
6803 : 5 : pc->on_top++;
6804 [ - + ]: 5 : ADDOP(c, LOC(p), MATCH_SEQUENCE);
6805 [ - + ]: 5 : RETURN_IF_ERROR(jump_to_fail_pop(c, LOC(p), pc, POP_JUMP_IF_FALSE));
6806 [ + + ]: 5 : if (star < 0) {
6807 : : // No star: len(subject) == size
6808 [ - + ]: 4 : ADDOP(c, LOC(p), GET_LEN);
6809 [ - + - + ]: 4 : ADDOP_LOAD_CONST_NEW(c, LOC(p), PyLong_FromSsize_t(size));
6810 [ - + ]: 4 : ADDOP_COMPARE(c, LOC(p), Eq);
6811 [ - + ]: 4 : RETURN_IF_ERROR(jump_to_fail_pop(c, LOC(p), pc, POP_JUMP_IF_FALSE));
6812 : : }
6813 [ - + ]: 1 : else if (size > 1) {
6814 : : // Star: len(subject) >= size - 1
6815 [ # # ]: 0 : ADDOP(c, LOC(p), GET_LEN);
6816 [ # # # # ]: 0 : ADDOP_LOAD_CONST_NEW(c, LOC(p), PyLong_FromSsize_t(size - 1));
6817 [ # # ]: 0 : ADDOP_COMPARE(c, LOC(p), GtE);
6818 [ # # ]: 0 : RETURN_IF_ERROR(jump_to_fail_pop(c, LOC(p), pc, POP_JUMP_IF_FALSE));
6819 : : }
6820 : : // Whatever comes next should consume the subject:
6821 : 5 : pc->on_top--;
6822 [ - + ]: 5 : if (only_wildcard) {
6823 : : // Patterns like: [] / [_] / [_, _] / [*_] / [_, *_] / [_, _, *_] / etc.
6824 [ # # ]: 0 : ADDOP(c, LOC(p), POP_TOP);
6825 : : }
6826 [ - + ]: 5 : else if (star_wildcard) {
6827 [ # # ]: 0 : RETURN_IF_ERROR(pattern_helper_sequence_subscr(c, LOC(p), patterns, star, pc));
6828 : : }
6829 : : else {
6830 [ - + ]: 5 : RETURN_IF_ERROR(pattern_helper_sequence_unpack(c, LOC(p), patterns, star, pc));
6831 : : }
6832 : 5 : return SUCCESS;
6833 : : }
6834 : :
6835 : : static int
6836 : 4 : compiler_pattern_value(struct compiler *c, pattern_ty p, pattern_context *pc)
6837 : : {
6838 : : assert(p->kind == MatchValue_kind);
6839 : 4 : expr_ty value = p->v.MatchValue.value;
6840 [ - + - - ]: 4 : if (!MATCH_VALUE_EXPR(value)) {
6841 : 0 : const char *e = "patterns may only match literals and attribute lookups";
6842 : 0 : return compiler_error(c, LOC(p), e);
6843 : : }
6844 [ - + ]: 4 : VISIT(c, expr, value);
6845 [ - + ]: 4 : ADDOP_COMPARE(c, LOC(p), Eq);
6846 [ - + ]: 4 : RETURN_IF_ERROR(jump_to_fail_pop(c, LOC(p), pc, POP_JUMP_IF_FALSE));
6847 : 4 : return SUCCESS;
6848 : : }
6849 : :
6850 : : static int
6851 : 1 : compiler_pattern_singleton(struct compiler *c, pattern_ty p, pattern_context *pc)
6852 : : {
6853 : : assert(p->kind == MatchSingleton_kind);
6854 [ - + ]: 1 : ADDOP_LOAD_CONST(c, LOC(p), p->v.MatchSingleton.value);
6855 [ - + ]: 1 : ADDOP_COMPARE(c, LOC(p), Is);
6856 [ - + ]: 1 : RETURN_IF_ERROR(jump_to_fail_pop(c, LOC(p), pc, POP_JUMP_IF_FALSE));
6857 : 1 : return SUCCESS;
6858 : : }
6859 : :
6860 : : static int
6861 : 18 : compiler_pattern(struct compiler *c, pattern_ty p, pattern_context *pc)
6862 : : {
6863 [ + + + - : 18 : switch (p->kind) {
+ + + -
- ]
6864 : 4 : case MatchValue_kind:
6865 : 4 : return compiler_pattern_value(c, p, pc);
6866 : 1 : case MatchSingleton_kind:
6867 : 1 : return compiler_pattern_singleton(c, p, pc);
6868 : 5 : case MatchSequence_kind:
6869 : 5 : return compiler_pattern_sequence(c, p, pc);
6870 : 0 : case MatchMapping_kind:
6871 : 0 : return compiler_pattern_mapping(c, p, pc);
6872 : 4 : case MatchClass_kind:
6873 : 4 : return compiler_pattern_class(c, p, pc);
6874 : 1 : case MatchStar_kind:
6875 : 1 : return compiler_pattern_star(c, p, pc);
6876 : 3 : case MatchAs_kind:
6877 : 3 : return compiler_pattern_as(c, p, pc);
6878 : 0 : case MatchOr_kind:
6879 : 0 : return compiler_pattern_or(c, p, pc);
6880 : : }
6881 : : // AST validator shouldn't let this happen, but if it does,
6882 : : // just fail, don't crash out of the interpreter
6883 : 0 : const char *e = "invalid match pattern node in AST (kind=%d)";
6884 : 0 : return compiler_error(c, LOC(p), e, p->kind);
6885 : : }
6886 : :
6887 : : static int
6888 : 4 : compiler_match_inner(struct compiler *c, stmt_ty s, pattern_context *pc)
6889 : : {
6890 [ - + ]: 4 : VISIT(c, expr, s->v.Match.subject);
6891 [ - + ]: 4 : NEW_JUMP_TARGET_LABEL(c, end);
6892 [ + - ]: 4 : Py_ssize_t cases = asdl_seq_LEN(s->v.Match.cases);
6893 : : assert(cases > 0);
6894 : 4 : match_case_ty m = asdl_seq_GET(s->v.Match.cases, cases - 1);
6895 [ + + + - : 4 : int has_default = WILDCARD_CHECK(m->pattern) && 1 < cases;
+ - ]
6896 [ + + ]: 15 : for (Py_ssize_t i = 0; i < cases - has_default; i++) {
6897 : 11 : m = asdl_seq_GET(s->v.Match.cases, i);
6898 : : // Only copy the subject if we're *not* on the last case:
6899 [ + + ]: 11 : if (i != cases - has_default - 1) {
6900 [ - + ]: 7 : ADDOP_I(c, LOC(m->pattern), COPY, 1);
6901 : : }
6902 : 11 : pc->stores = PyList_New(0);
6903 [ - + ]: 11 : if (pc->stores == NULL) {
6904 : 0 : return ERROR;
6905 : : }
6906 : : // Irrefutable cases must be either guarded, last, or both:
6907 [ + + + + ]: 11 : pc->allow_irrefutable = m->guard != NULL || i == cases - 1;
6908 : 11 : pc->fail_pop = NULL;
6909 : 11 : pc->fail_pop_size = 0;
6910 : 11 : pc->on_top = 0;
6911 : : // NOTE: Can't use returning macros here (they'll leak pc->stores)!
6912 [ - + ]: 11 : if (compiler_pattern(c, m->pattern, pc) < 0) {
6913 : 0 : Py_DECREF(pc->stores);
6914 : 0 : return ERROR;
6915 : : }
6916 : : assert(!pc->on_top);
6917 : : // It's a match! Store all of the captured names (they're on the stack).
6918 : 11 : Py_ssize_t nstores = PyList_GET_SIZE(pc->stores);
6919 [ + + ]: 15 : for (Py_ssize_t n = 0; n < nstores; n++) {
6920 : 4 : PyObject *name = PyList_GET_ITEM(pc->stores, n);
6921 [ - + ]: 4 : if (compiler_nameop(c, LOC(m->pattern), name, Store) < 0) {
6922 : 0 : Py_DECREF(pc->stores);
6923 : 0 : return ERROR;
6924 : : }
6925 : : }
6926 : 11 : Py_DECREF(pc->stores);
6927 : : // NOTE: Returning macros are safe again.
6928 [ + + ]: 11 : if (m->guard) {
6929 [ - + ]: 1 : RETURN_IF_ERROR(ensure_fail_pop(c, pc, 0));
6930 [ - + ]: 1 : RETURN_IF_ERROR(compiler_jump_if(c, LOC(m->pattern), m->guard, pc->fail_pop[0], 0));
6931 : : }
6932 : : // Success! Pop the subject off, we're done with it:
6933 [ + + ]: 11 : if (i != cases - has_default - 1) {
6934 [ - + ]: 7 : ADDOP(c, LOC(m->pattern), POP_TOP);
6935 : : }
6936 [ - + + - : 31 : VISIT_SEQ(c, stmt, m->body);
+ + ]
6937 [ - + ]: 11 : ADDOP_JUMP(c, NO_LOCATION, JUMP, end);
6938 : : // If the pattern fails to match, we want the line number of the
6939 : : // cleanup to be associated with the failed pattern, not the last line
6940 : : // of the body
6941 [ - + ]: 11 : RETURN_IF_ERROR(emit_and_reset_fail_pop(c, LOC(m->pattern), pc));
6942 : : }
6943 [ + + ]: 4 : if (has_default) {
6944 : : // A trailing "case _" is common, and lets us save a bit of redundant
6945 : : // pushing and popping in the loop above:
6946 : 1 : m = asdl_seq_GET(s->v.Match.cases, cases - 1);
6947 [ - + ]: 1 : if (cases == 1) {
6948 : : // No matches. Done with the subject:
6949 [ # # ]: 0 : ADDOP(c, LOC(m->pattern), POP_TOP);
6950 : : }
6951 : : else {
6952 : : // Show line coverage for default case (it doesn't create bytecode)
6953 [ - + ]: 1 : ADDOP(c, LOC(m->pattern), NOP);
6954 : : }
6955 [ - + ]: 1 : if (m->guard) {
6956 [ # # ]: 0 : RETURN_IF_ERROR(compiler_jump_if(c, LOC(m->pattern), m->guard, end, 0));
6957 : : }
6958 [ - + + - : 2 : VISIT_SEQ(c, stmt, m->body);
+ + ]
6959 : : }
6960 [ - + ]: 4 : USE_LABEL(c, end);
6961 : 4 : return SUCCESS;
6962 : : }
6963 : :
6964 : : static int
6965 : 4 : compiler_match(struct compiler *c, stmt_ty s)
6966 : : {
6967 : : pattern_context pc;
6968 : 4 : pc.fail_pop = NULL;
6969 : 4 : int result = compiler_match_inner(c, s, &pc);
6970 : 4 : PyObject_Free(pc.fail_pop);
6971 : 4 : return result;
6972 : : }
6973 : :
6974 : : #undef WILDCARD_CHECK
6975 : : #undef WILDCARD_STAR_CHECK
6976 : :
6977 : :
6978 : : /* End of the compiler section, beginning of the assembler section */
6979 : :
6980 : :
6981 : : struct assembler {
6982 : : PyObject *a_bytecode; /* bytes containing bytecode */
6983 : : int a_offset; /* offset into bytecode */
6984 : : PyObject *a_except_table; /* bytes containing exception table */
6985 : : int a_except_table_off; /* offset into exception table */
6986 : : /* Location Info */
6987 : : int a_lineno; /* lineno of last emitted instruction */
6988 : : PyObject* a_linetable; /* bytes containing location info */
6989 : : int a_location_off; /* offset of last written location info frame */
6990 : : };
6991 : :
6992 : : static basicblock**
6993 : 39288 : make_cfg_traversal_stack(basicblock *entryblock) {
6994 : 39288 : int nblocks = 0;
6995 [ + + ]: 352190 : for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
6996 : 312902 : b->b_visited = 0;
6997 : 312902 : nblocks++;
6998 : : }
6999 : 39288 : basicblock **stack = (basicblock **)PyMem_Malloc(sizeof(basicblock *) * nblocks);
7000 [ - + ]: 39288 : if (!stack) {
7001 : 0 : PyErr_NoMemory();
7002 : : }
7003 : 39288 : return stack;
7004 : : }
7005 : :
7006 : : Py_LOCAL_INLINE(void)
7007 : 61955 : stackdepth_push(basicblock ***sp, basicblock *b, int depth)
7008 : : {
7009 : : assert(b->b_startdepth < 0 || b->b_startdepth == depth);
7010 [ + + + - ]: 61955 : if (b->b_startdepth < depth && b->b_startdepth < 100) {
7011 : : assert(b->b_startdepth < 0);
7012 : 51311 : b->b_startdepth = depth;
7013 : 51311 : *(*sp)++ = b;
7014 : : }
7015 : 61955 : }
7016 : :
7017 : : /* Find the flow path that needs the largest stack. We assume that
7018 : : * cycles in the flow graph have no net effect on the stack depth.
7019 : : */
7020 : : static int
7021 : 8041 : stackdepth(basicblock *entryblock, int code_flags)
7022 : : {
7023 [ + + ]: 59352 : for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
7024 : 51311 : b->b_startdepth = INT_MIN;
7025 : : }
7026 : 8041 : basicblock **stack = make_cfg_traversal_stack(entryblock);
7027 [ - + ]: 8041 : if (!stack) {
7028 : 0 : return ERROR;
7029 : : }
7030 : :
7031 : 8041 : int maxdepth = 0;
7032 : 8041 : basicblock **sp = stack;
7033 [ + + ]: 8041 : if (code_flags & (CO_GENERATOR | CO_COROUTINE | CO_ASYNC_GENERATOR)) {
7034 : 532 : stackdepth_push(&sp, entryblock, 1);
7035 : : } else {
7036 : 7509 : stackdepth_push(&sp, entryblock, 0);
7037 : : }
7038 : :
7039 [ + + ]: 59352 : while (sp != stack) {
7040 : 51311 : basicblock *b = *--sp;
7041 : 51311 : int depth = b->b_startdepth;
7042 : : assert(depth >= 0);
7043 : 51311 : basicblock *next = b->b_next;
7044 [ + + ]: 377664 : for (int i = 0; i < b->b_iused; i++) {
7045 : 349175 : struct cfg_instr *instr = &b->b_instr[i];
7046 : 349175 : int effect = stack_effect(instr->i_opcode, instr->i_oparg, 0);
7047 [ - + ]: 349175 : if (effect == PY_INVALID_STACK_EFFECT) {
7048 : 0 : PyErr_Format(PyExc_SystemError,
7049 : : "compiler stack_effect(opcode=%d, arg=%i) failed",
7050 : : instr->i_opcode, instr->i_oparg);
7051 : 0 : return ERROR;
7052 : : }
7053 : 349175 : int new_depth = depth + effect;
7054 : : assert(new_depth >= 0); /* invalid code or bug in stackdepth() */
7055 [ + + ]: 349175 : if (new_depth > maxdepth) {
7056 : 30259 : maxdepth = new_depth;
7057 : : }
7058 [ + + + + : 349175 : if (HAS_TARGET(instr->i_opcode)) {
+ + + + ]
7059 : 25425 : effect = stack_effect(instr->i_opcode, instr->i_oparg, 1);
7060 : : assert(effect != PY_INVALID_STACK_EFFECT);
7061 : 25425 : int target_depth = depth + effect;
7062 : : assert(target_depth >= 0); /* invalid code or bug in stackdepth() */
7063 [ + + ]: 25425 : if (target_depth > maxdepth) {
7064 : 994 : maxdepth = target_depth;
7065 : : }
7066 : 25425 : stackdepth_push(&sp, instr->i_target, target_depth);
7067 : : }
7068 : 349175 : depth = new_depth;
7069 : : assert(!IS_ASSEMBLER_OPCODE(instr->i_opcode));
7070 [ + + + + : 349175 : if (IS_UNCONDITIONAL_JUMP_OPCODE(instr->i_opcode) ||
+ - + - +
- ]
7071 [ + + + + : 344150 : IS_SCOPE_EXIT_OPCODE(instr->i_opcode))
+ + + + ]
7072 : : {
7073 : : /* remaining code is dead */
7074 : 22822 : next = NULL;
7075 : 22822 : break;
7076 : : }
7077 : : }
7078 [ + + ]: 51311 : if (next != NULL) {
7079 : : assert(BB_HAS_FALLTHROUGH(b));
7080 : 28489 : stackdepth_push(&sp, next, depth);
7081 : : }
7082 : : }
7083 : 8041 : PyMem_Free(stack);
7084 : 8041 : return maxdepth;
7085 : : }
7086 : :
7087 : : static int
7088 : 8041 : assemble_init(struct assembler *a, int firstlineno)
7089 : : {
7090 : 8041 : memset(a, 0, sizeof(struct assembler));
7091 : 8041 : a->a_lineno = firstlineno;
7092 : 8041 : a->a_linetable = NULL;
7093 : 8041 : a->a_location_off = 0;
7094 : 8041 : a->a_except_table = NULL;
7095 : 8041 : a->a_bytecode = PyBytes_FromStringAndSize(NULL, DEFAULT_CODE_SIZE);
7096 [ - + ]: 8041 : if (a->a_bytecode == NULL) {
7097 : 0 : goto error;
7098 : : }
7099 : 8041 : a->a_linetable = PyBytes_FromStringAndSize(NULL, DEFAULT_CNOTAB_SIZE);
7100 [ - + ]: 8041 : if (a->a_linetable == NULL) {
7101 : 0 : goto error;
7102 : : }
7103 : 8041 : a->a_except_table = PyBytes_FromStringAndSize(NULL, DEFAULT_LNOTAB_SIZE);
7104 [ - + ]: 8041 : if (a->a_except_table == NULL) {
7105 : 0 : goto error;
7106 : : }
7107 : 8041 : return SUCCESS;
7108 : 0 : error:
7109 : 0 : Py_XDECREF(a->a_bytecode);
7110 : 0 : Py_XDECREF(a->a_linetable);
7111 : 0 : Py_XDECREF(a->a_except_table);
7112 : 0 : return ERROR;
7113 : : }
7114 : :
7115 : : static void
7116 : 8041 : assemble_free(struct assembler *a)
7117 : : {
7118 : 8041 : Py_XDECREF(a->a_bytecode);
7119 : 8041 : Py_XDECREF(a->a_linetable);
7120 : 8041 : Py_XDECREF(a->a_except_table);
7121 : 8041 : }
7122 : :
7123 : : static int
7124 : 61502 : blocksize(basicblock *b)
7125 : : {
7126 : 61502 : int size = 0;
7127 [ + + ]: 465669 : for (int i = 0; i < b->b_iused; i++) {
7128 : 404167 : size += instr_size(&b->b_instr[i]);
7129 : : }
7130 : 61502 : return size;
7131 : : }
7132 : :
7133 : : static basicblock *
7134 : 4732 : push_except_block(ExceptStack *stack, struct cfg_instr *setup) {
7135 : : assert(is_block_push(setup));
7136 : 4732 : int opcode = setup->i_opcode;
7137 : 4732 : basicblock * target = setup->i_target;
7138 [ + + + + ]: 4732 : if (opcode == SETUP_WITH || opcode == SETUP_CLEANUP) {
7139 : 3055 : target->b_preserve_lasti = 1;
7140 : : }
7141 : 4732 : stack->handlers[++stack->depth] = target;
7142 : 4732 : return target;
7143 : : }
7144 : :
7145 : : static basicblock *
7146 : 3949 : pop_except_block(ExceptStack *stack) {
7147 : : assert(stack->depth > 0);
7148 : 3949 : return stack->handlers[--stack->depth];
7149 : : }
7150 : :
7151 : : static basicblock *
7152 : 54053 : except_stack_top(ExceptStack *stack) {
7153 : 54053 : return stack->handlers[stack->depth];
7154 : : }
7155 : :
7156 : : static ExceptStack *
7157 : 8041 : make_except_stack(void) {
7158 : 8041 : ExceptStack *new = PyMem_Malloc(sizeof(ExceptStack));
7159 [ - + ]: 8041 : if (new == NULL) {
7160 : 0 : PyErr_NoMemory();
7161 : 0 : return NULL;
7162 : : }
7163 : 8041 : new->depth = 0;
7164 : 8041 : new->handlers[0] = NULL;
7165 : 8041 : return new;
7166 : : }
7167 : :
7168 : : static ExceptStack *
7169 : 18779 : copy_except_stack(ExceptStack *stack) {
7170 : 18779 : ExceptStack *copy = PyMem_Malloc(sizeof(ExceptStack));
7171 [ - + ]: 18779 : if (copy == NULL) {
7172 : 0 : PyErr_NoMemory();
7173 : 0 : return NULL;
7174 : : }
7175 : 18779 : memcpy(copy, stack, sizeof(ExceptStack));
7176 : 18779 : return copy;
7177 : : }
7178 : :
7179 : : static int
7180 : 8041 : label_exception_targets(basicblock *entryblock) {
7181 : 8041 : basicblock **todo_stack = make_cfg_traversal_stack(entryblock);
7182 [ - + ]: 8041 : if (todo_stack == NULL) {
7183 : 0 : return ERROR;
7184 : : }
7185 : 8041 : ExceptStack *except_stack = make_except_stack();
7186 [ - + ]: 8041 : if (except_stack == NULL) {
7187 : 0 : PyMem_Free(todo_stack);
7188 : 0 : PyErr_NoMemory();
7189 : 0 : return ERROR;
7190 : : }
7191 : 8041 : except_stack->depth = 0;
7192 : 8041 : todo_stack[0] = entryblock;
7193 : 8041 : entryblock->b_visited = 1;
7194 : 8041 : entryblock->b_exceptstack = except_stack;
7195 : 8041 : basicblock **todo = &todo_stack[1];
7196 : 8041 : basicblock *handler = NULL;
7197 [ + + ]: 62094 : while (todo > todo_stack) {
7198 : 54053 : todo--;
7199 : 54053 : basicblock *b = todo[0];
7200 : : assert(b->b_visited == 1);
7201 : 54053 : except_stack = b->b_exceptstack;
7202 : : assert(except_stack != NULL);
7203 : 54053 : b->b_exceptstack = NULL;
7204 : 54053 : handler = except_stack_top(except_stack);
7205 [ + + ]: 424982 : for (int i = 0; i < b->b_iused; i++) {
7206 : 370929 : struct cfg_instr *instr = &b->b_instr[i];
7207 [ + + ]: 370929 : if (is_block_push(instr)) {
7208 [ + - ]: 4732 : if (!instr->i_target->b_visited) {
7209 : 4732 : ExceptStack *copy = copy_except_stack(except_stack);
7210 [ - + ]: 4732 : if (copy == NULL) {
7211 : 0 : goto error;
7212 : : }
7213 : 4732 : instr->i_target->b_exceptstack = copy;
7214 : 4732 : todo[0] = instr->i_target;
7215 : 4732 : instr->i_target->b_visited = 1;
7216 : 4732 : todo++;
7217 : : }
7218 : 4732 : handler = push_except_block(except_stack, instr);
7219 : : }
7220 [ + + ]: 366197 : else if (instr->i_opcode == POP_BLOCK) {
7221 : 3949 : handler = pop_except_block(except_stack);
7222 : : }
7223 [ + + ]: 362248 : else if (is_jump(instr)) {
7224 : 23254 : instr->i_except = handler;
7225 : : assert(i == b->b_iused -1);
7226 [ + + ]: 23254 : if (!instr->i_target->b_visited) {
7227 [ + + ]: 17544 : if (BB_HAS_FALLTHROUGH(b)) {
7228 : 14047 : ExceptStack *copy = copy_except_stack(except_stack);
7229 [ - + ]: 14047 : if (copy == NULL) {
7230 : 0 : goto error;
7231 : : }
7232 : 14047 : instr->i_target->b_exceptstack = copy;
7233 : : }
7234 : : else {
7235 : 3497 : instr->i_target->b_exceptstack = except_stack;
7236 : 3497 : except_stack = NULL;
7237 : : }
7238 : 17544 : todo[0] = instr->i_target;
7239 : 17544 : instr->i_target->b_visited = 1;
7240 : 17544 : todo++;
7241 : : }
7242 : : }
7243 : : else {
7244 [ + + ]: 338994 : if (instr->i_opcode == YIELD_VALUE) {
7245 : 640 : instr->i_oparg = except_stack->depth;
7246 : : }
7247 : 338994 : instr->i_except = handler;
7248 : : }
7249 : : }
7250 [ + + + + ]: 54053 : if (BB_HAS_FALLTHROUGH(b) && !b->b_next->b_visited) {
7251 : : assert(except_stack != NULL);
7252 : 23736 : b->b_next->b_exceptstack = except_stack;
7253 : 23736 : todo[0] = b->b_next;
7254 : 23736 : b->b_next->b_visited = 1;
7255 : 23736 : todo++;
7256 : : }
7257 [ + + ]: 30317 : else if (except_stack != NULL) {
7258 : 26820 : PyMem_Free(except_stack);
7259 : : }
7260 : : }
7261 : : #ifdef Py_DEBUG
7262 : : for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
7263 : : assert(b->b_exceptstack == NULL);
7264 : : }
7265 : : #endif
7266 : 8041 : PyMem_Free(todo_stack);
7267 : 8041 : return SUCCESS;
7268 : 0 : error:
7269 : 0 : PyMem_Free(todo_stack);
7270 : 0 : PyMem_Free(except_stack);
7271 : 0 : return ERROR;
7272 : : }
7273 : :
7274 : :
7275 : : static int
7276 : 8041 : mark_except_handlers(basicblock *entryblock) {
7277 : : #ifndef NDEBUG
7278 : : for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
7279 : : assert(!b->b_except_handler);
7280 : : }
7281 : : #endif
7282 [ + + ]: 69608 : for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
7283 [ + + ]: 448179 : for (int i=0; i < b->b_iused; i++) {
7284 : 386612 : struct cfg_instr *instr = &b->b_instr[i];
7285 [ + + ]: 386612 : if (is_block_push(instr)) {
7286 : 4742 : instr->i_target->b_except_handler = 1;
7287 : : }
7288 : : }
7289 : : }
7290 : 8041 : return SUCCESS;
7291 : : }
7292 : :
7293 : : static int
7294 : 4163 : mark_warm(basicblock *entryblock) {
7295 : 4163 : basicblock **stack = make_cfg_traversal_stack(entryblock);
7296 [ - + ]: 4163 : if (stack == NULL) {
7297 : 0 : return ERROR;
7298 : : }
7299 : 4163 : basicblock **sp = stack;
7300 : :
7301 : 4163 : *sp++ = entryblock;
7302 : 4163 : entryblock->b_visited = 1;
7303 [ + + ]: 40123 : while (sp > stack) {
7304 : 35960 : basicblock *b = *(--sp);
7305 : : assert(!b->b_except_handler);
7306 : 35960 : b->b_warm = 1;
7307 : 35960 : basicblock *next = b->b_next;
7308 [ + + + + : 35960 : if (next && BB_HAS_FALLTHROUGH(b) && !next->b_visited) {
+ + ]
7309 : 19933 : *sp++ = next;
7310 : 19933 : next->b_visited = 1;
7311 : : }
7312 [ + + ]: 270596 : for (int i=0; i < b->b_iused; i++) {
7313 : 234636 : struct cfg_instr *instr = &b->b_instr[i];
7314 [ + + + + ]: 234636 : if (is_jump(instr) && !instr->i_target->b_visited) {
7315 : 11864 : *sp++ = instr->i_target;
7316 : 11864 : instr->i_target->b_visited = 1;
7317 : : }
7318 : : }
7319 : : }
7320 : 4163 : PyMem_Free(stack);
7321 : 4163 : return SUCCESS;
7322 : : }
7323 : :
7324 : : static int
7325 : 4163 : mark_cold(basicblock *entryblock) {
7326 [ + + ]: 50901 : for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
7327 : : assert(!b->b_cold && !b->b_warm);
7328 : : }
7329 [ - + ]: 4163 : if (mark_warm(entryblock) < 0) {
7330 : 0 : return ERROR;
7331 : : }
7332 : :
7333 : 4163 : basicblock **stack = make_cfg_traversal_stack(entryblock);
7334 [ - + ]: 4163 : if (stack == NULL) {
7335 : 0 : return ERROR;
7336 : : }
7337 : :
7338 : 4163 : basicblock **sp = stack;
7339 [ + + ]: 50901 : for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
7340 [ + + ]: 46738 : if (b->b_except_handler) {
7341 : : assert(!b->b_warm);
7342 : 4731 : *sp++ = b;
7343 : 4731 : b->b_visited = 1;
7344 : : }
7345 : : }
7346 : :
7347 [ + + ]: 14941 : while (sp > stack) {
7348 : 10778 : basicblock *b = *(--sp);
7349 : 10778 : b->b_cold = 1;
7350 : 10778 : basicblock *next = b->b_next;
7351 [ + + + + ]: 10778 : if (next && BB_HAS_FALLTHROUGH(b)) {
7352 [ + + + + ]: 4154 : if (!next->b_warm && !next->b_visited) {
7353 : 3828 : *sp++ = next;
7354 : 3828 : next->b_visited = 1;
7355 : : }
7356 : : }
7357 [ + + ]: 49664 : for (int i = 0; i < b->b_iused; i++) {
7358 : 38886 : struct cfg_instr *instr = &b->b_instr[i];
7359 [ + + ]: 38886 : if (is_jump(instr)) {
7360 : : assert(i == b->b_iused - 1);
7361 : 3191 : basicblock *target = b->b_instr[i].i_target;
7362 [ + + + + ]: 3191 : if (!target->b_warm && !target->b_visited) {
7363 : 2219 : *sp++ = target;
7364 : 2219 : target->b_visited = 1;
7365 : : }
7366 : : }
7367 : : }
7368 : : }
7369 : 4163 : PyMem_Free(stack);
7370 : 4163 : return SUCCESS;
7371 : : }
7372 : :
7373 : : static int
7374 : : remove_redundant_jumps(cfg_builder *g);
7375 : :
7376 : : static int
7377 : 8041 : push_cold_blocks_to_end(cfg_builder *g, int code_flags) {
7378 : 8041 : basicblock *entryblock = g->g_entryblock;
7379 [ + + ]: 8041 : if (entryblock->b_next == NULL) {
7380 : : /* single basicblock, no need to reorder */
7381 : 3878 : return SUCCESS;
7382 : : }
7383 [ - + ]: 4163 : RETURN_IF_ERROR(mark_cold(entryblock));
7384 : :
7385 : : /* If we have a cold block with fallthrough to a warm block, add */
7386 : : /* an explicit jump instead of fallthrough */
7387 [ + + ]: 51082 : for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
7388 [ + + + + : 46919 : if (b->b_cold && BB_HAS_FALLTHROUGH(b) && b->b_next && b->b_next->b_warm) {
+ - + + ]
7389 : 181 : basicblock *explicit_jump = cfg_builder_new_block(g);
7390 [ - + ]: 181 : if (explicit_jump == NULL) {
7391 : 0 : return ERROR;
7392 : : }
7393 : 181 : basicblock_addop(explicit_jump, JUMP, b->b_next->b_label.id, NO_LOCATION);
7394 : 181 : explicit_jump->b_cold = 1;
7395 : 181 : explicit_jump->b_next = b->b_next;
7396 : 181 : b->b_next = explicit_jump;
7397 : :
7398 : : /* set target */
7399 : 181 : struct cfg_instr *last = basicblock_last_instr(explicit_jump);
7400 : 181 : last->i_target = explicit_jump->b_next;
7401 : : }
7402 : : }
7403 : :
7404 : : assert(!entryblock->b_cold); /* First block can't be cold */
7405 : 4163 : basicblock *cold_blocks = NULL;
7406 : 4163 : basicblock *cold_blocks_tail = NULL;
7407 : :
7408 : 4163 : basicblock *b = entryblock;
7409 [ + + ]: 6539 : while(b->b_next) {
7410 : : assert(!b->b_cold);
7411 [ + + + + ]: 37263 : while (b->b_next && !b->b_next->b_cold) {
7412 : 31797 : b = b->b_next;
7413 : : }
7414 [ + + ]: 5466 : if (b->b_next == NULL) {
7415 : : /* no more cold blocks */
7416 : 3090 : break;
7417 : : }
7418 : :
7419 : : /* b->b_next is the beginning of a cold streak */
7420 : : assert(!b->b_cold && b->b_next->b_cold);
7421 : :
7422 : 2376 : basicblock *b_end = b->b_next;
7423 [ + + + + ]: 10959 : while (b_end->b_next && b_end->b_next->b_cold) {
7424 : 8583 : b_end = b_end->b_next;
7425 : : }
7426 : :
7427 : : /* b_end is the end of the cold streak */
7428 : : assert(b_end && b_end->b_cold);
7429 : : assert(b_end->b_next == NULL || !b_end->b_next->b_cold);
7430 : :
7431 [ + + ]: 2376 : if (cold_blocks == NULL) {
7432 : 1599 : cold_blocks = b->b_next;
7433 : : }
7434 : : else {
7435 : 777 : cold_blocks_tail->b_next = b->b_next;
7436 : : }
7437 : 2376 : cold_blocks_tail = b_end;
7438 : 2376 : b->b_next = b_end->b_next;
7439 : 2376 : b_end->b_next = NULL;
7440 : : }
7441 : : assert(b != NULL && b->b_next == NULL);
7442 : 4163 : b->b_next = cold_blocks;
7443 : :
7444 [ + + ]: 4163 : if (cold_blocks != NULL) {
7445 [ - + ]: 1599 : RETURN_IF_ERROR(remove_redundant_jumps(g));
7446 : : }
7447 : 4163 : return SUCCESS;
7448 : : }
7449 : :
7450 : : static void
7451 : 8041 : convert_exception_handlers_to_nops(basicblock *entryblock) {
7452 [ + + ]: 59352 : for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
7453 [ + + ]: 400486 : for (int i = 0; i < b->b_iused; i++) {
7454 : 349175 : struct cfg_instr *instr = &b->b_instr[i];
7455 [ + + + + ]: 349175 : if (is_block_push(instr) || instr->i_opcode == POP_BLOCK) {
7456 : 8731 : INSTR_SET_OP0(instr, NOP);
7457 : : }
7458 : : }
7459 : : }
7460 [ + + ]: 59352 : for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
7461 : 51311 : remove_redundant_nops(b);
7462 : : }
7463 : 8041 : }
7464 : :
7465 : : static inline void
7466 : 41949 : write_except_byte(struct assembler *a, int byte) {
7467 : 41949 : unsigned char *p = (unsigned char *) PyBytes_AS_STRING(a->a_except_table);
7468 : 41949 : p[a->a_except_table_off++] = byte;
7469 : 41949 : }
7470 : :
7471 : : #define CONTINUATION_BIT 64
7472 : :
7473 : : static void
7474 : 29760 : assemble_emit_exception_table_item(struct assembler *a, int value, int msb)
7475 : : {
7476 : : assert ((msb | 128) == 128);
7477 : : assert(value >= 0 && value < (1 << 30));
7478 [ - + ]: 29760 : if (value >= 1 << 24) {
7479 : 0 : write_except_byte(a, (value >> 24) | CONTINUATION_BIT | msb);
7480 : 0 : msb = 0;
7481 : : }
7482 [ - + ]: 29760 : if (value >= 1 << 18) {
7483 : 0 : write_except_byte(a, ((value >> 18)&0x3f) | CONTINUATION_BIT | msb);
7484 : 0 : msb = 0;
7485 : : }
7486 [ + + ]: 29760 : if (value >= 1 << 12) {
7487 : 21 : write_except_byte(a, ((value >> 12)&0x3f) | CONTINUATION_BIT | msb);
7488 : 21 : msb = 0;
7489 : : }
7490 [ + + ]: 29760 : if (value >= 1 << 6) {
7491 : 12168 : write_except_byte(a, ((value >> 6)&0x3f) | CONTINUATION_BIT | msb);
7492 : 12168 : msb = 0;
7493 : : }
7494 : 29760 : write_except_byte(a, (value&0x3f) | msb);
7495 : 29760 : }
7496 : :
7497 : : /* See Objects/exception_handling_notes.txt for details of layout */
7498 : : #define MAX_SIZE_OF_ENTRY 20
7499 : :
7500 : : static int
7501 : 7440 : assemble_emit_exception_table_entry(struct assembler *a, int start, int end, basicblock *handler)
7502 : : {
7503 : 7440 : Py_ssize_t len = PyBytes_GET_SIZE(a->a_except_table);
7504 [ + + ]: 7440 : if (a->a_except_table_off + MAX_SIZE_OF_ENTRY >= len) {
7505 [ - + ]: 2546 : RETURN_IF_ERROR(_PyBytes_Resize(&a->a_except_table, len * 2));
7506 : : }
7507 : 7440 : int size = end-start;
7508 : : assert(end > start);
7509 : 7440 : int target = handler->b_offset;
7510 : 7440 : int depth = handler->b_startdepth - 1;
7511 [ + + ]: 7440 : if (handler->b_preserve_lasti) {
7512 : 5296 : depth -= 1;
7513 : : }
7514 : : assert(depth >= 0);
7515 : 7440 : int depth_lasti = (depth<<1) | handler->b_preserve_lasti;
7516 : 7440 : assemble_emit_exception_table_item(a, start, (1<<7));
7517 : 7440 : assemble_emit_exception_table_item(a, size, 0);
7518 : 7440 : assemble_emit_exception_table_item(a, target, 0);
7519 : 7440 : assemble_emit_exception_table_item(a, depth_lasti, 0);
7520 : 7440 : return SUCCESS;
7521 : : }
7522 : :
7523 : : static int
7524 : 8041 : assemble_exception_table(struct assembler *a, basicblock *entryblock)
7525 : : {
7526 : : basicblock *b;
7527 : 8041 : int ioffset = 0;
7528 : 8041 : basicblock *handler = NULL;
7529 : 8041 : int start = -1;
7530 [ + + ]: 60209 : for (b = entryblock; b != NULL; b = b->b_next) {
7531 : 52168 : ioffset = b->b_offset;
7532 [ + + ]: 394204 : for (int i = 0; i < b->b_iused; i++) {
7533 : 342036 : struct cfg_instr *instr = &b->b_instr[i];
7534 [ + + ]: 342036 : if (instr->i_except != handler) {
7535 [ + + ]: 12492 : if (handler != NULL) {
7536 [ - + ]: 7440 : RETURN_IF_ERROR(
7537 : : assemble_emit_exception_table_entry(a, start, ioffset, handler));
7538 : : }
7539 : 12492 : start = ioffset;
7540 : 12492 : handler = instr->i_except;
7541 : : }
7542 : 342036 : ioffset += instr_size(instr);
7543 : : }
7544 : : }
7545 [ - + ]: 8041 : if (handler != NULL) {
7546 [ # # ]: 0 : RETURN_IF_ERROR(assemble_emit_exception_table_entry(a, start, ioffset, handler));
7547 : : }
7548 : 8041 : return SUCCESS;
7549 : : }
7550 : :
7551 : : /* Code location emitting code. See locations.md for a description of the format. */
7552 : :
7553 : : #define MSB 0x80
7554 : :
7555 : : static void
7556 : 346578 : write_location_byte(struct assembler* a, int val)
7557 : : {
7558 : 346578 : PyBytes_AS_STRING(a->a_linetable)[a->a_location_off] = val&255;
7559 : 346578 : a->a_location_off++;
7560 : 346578 : }
7561 : :
7562 : :
7563 : : static uint8_t *
7564 : 445463 : location_pointer(struct assembler* a)
7565 : : {
7566 : 445463 : return (uint8_t *)PyBytes_AS_STRING(a->a_linetable) +
7567 : 445463 : a->a_location_off;
7568 : : }
7569 : :
7570 : : static void
7571 : 286095 : write_location_first_byte(struct assembler* a, int code, int length)
7572 : : {
7573 : 286095 : a->a_location_off += write_location_entry_start(
7574 : : location_pointer(a), code, length);
7575 : 286095 : }
7576 : :
7577 : : static void
7578 : 119127 : write_location_varint(struct assembler* a, unsigned int val)
7579 : : {
7580 : 119127 : uint8_t *ptr = location_pointer(a);
7581 : 119127 : a->a_location_off += write_varint(ptr, val);
7582 : 119127 : }
7583 : :
7584 : :
7585 : : static void
7586 : 40241 : write_location_signed_varint(struct assembler* a, int val)
7587 : : {
7588 : 40241 : uint8_t *ptr = location_pointer(a);
7589 : 40241 : a->a_location_off += write_signed_varint(ptr, val);
7590 : 40241 : }
7591 : :
7592 : : static void
7593 : 133188 : write_location_info_short_form(struct assembler* a, int length, int column, int end_column)
7594 : : {
7595 : : assert(length > 0 && length <= 8);
7596 : 133188 : int column_low_bits = column & 7;
7597 : 133188 : int column_group = column >> 3;
7598 : : assert(column < 80);
7599 : : assert(end_column >= column);
7600 : : assert(end_column - column < 16);
7601 : 133188 : write_location_first_byte(a, PY_CODE_LOCATION_INFO_SHORT0 + column_group, length);
7602 : 133188 : write_location_byte(a, (column_low_bits << 4) | (end_column - column));
7603 : 133188 : }
7604 : :
7605 : : static void
7606 : 106695 : write_location_info_oneline_form(struct assembler* a, int length, int line_delta, int column, int end_column)
7607 : : {
7608 : : assert(length > 0 && length <= 8);
7609 : : assert(line_delta >= 0 && line_delta < 3);
7610 : : assert(column < 128);
7611 : : assert(end_column < 128);
7612 : 106695 : write_location_first_byte(a, PY_CODE_LOCATION_INFO_ONE_LINE0 + line_delta, length);
7613 : 106695 : write_location_byte(a, column);
7614 : 106695 : write_location_byte(a, end_column);
7615 : 106695 : }
7616 : :
7617 : : static void
7618 : 39709 : write_location_info_long_form(struct assembler* a, location loc, int length)
7619 : : {
7620 : : assert(length > 0 && length <= 8);
7621 : 39709 : write_location_first_byte(a, PY_CODE_LOCATION_INFO_LONG, length);
7622 : 39709 : write_location_signed_varint(a, loc.lineno - a->a_lineno);
7623 : : assert(loc.end_lineno >= loc.lineno);
7624 : 39709 : write_location_varint(a, loc.end_lineno - loc.lineno);
7625 : 39709 : write_location_varint(a, loc.col_offset + 1);
7626 : 39709 : write_location_varint(a, loc.end_col_offset + 1);
7627 : 39709 : }
7628 : :
7629 : : static void
7630 : 5971 : write_location_info_none(struct assembler* a, int length)
7631 : : {
7632 : 5971 : write_location_first_byte(a, PY_CODE_LOCATION_INFO_NONE, length);
7633 : 5971 : }
7634 : :
7635 : : static void
7636 : 532 : write_location_info_no_column(struct assembler* a, int length, int line_delta)
7637 : : {
7638 : 532 : write_location_first_byte(a, PY_CODE_LOCATION_INFO_NO_COLUMNS, length);
7639 : 532 : write_location_signed_varint(a, line_delta);
7640 : 532 : }
7641 : :
7642 : : #define THEORETICAL_MAX_ENTRY_SIZE 25 /* 1 + 6 + 6 + 6 + 6 */
7643 : :
7644 : : static int
7645 : 286095 : write_location_info_entry(struct assembler* a, location loc, int isize)
7646 : : {
7647 : 286095 : Py_ssize_t len = PyBytes_GET_SIZE(a->a_linetable);
7648 [ + + ]: 286095 : if (a->a_location_off + THEORETICAL_MAX_ENTRY_SIZE >= len) {
7649 : : assert(len > THEORETICAL_MAX_ENTRY_SIZE);
7650 [ - + ]: 14595 : RETURN_IF_ERROR(_PyBytes_Resize(&a->a_linetable, len*2));
7651 : : }
7652 [ + + ]: 286095 : if (loc.lineno < 0) {
7653 : 5971 : write_location_info_none(a, isize);
7654 : 5971 : return SUCCESS;
7655 : : }
7656 : 280124 : int line_delta = loc.lineno - a->a_lineno;
7657 : 280124 : int column = loc.col_offset;
7658 : 280124 : int end_column = loc.end_col_offset;
7659 : : assert(column >= -1);
7660 : : assert(end_column >= -1);
7661 [ + + - + ]: 280124 : if (column < 0 || end_column < 0) {
7662 [ - + - - ]: 532 : if (loc.end_lineno == loc.lineno || loc.end_lineno == -1) {
7663 : 532 : write_location_info_no_column(a, isize, line_delta);
7664 : 532 : a->a_lineno = loc.lineno;
7665 : 532 : return SUCCESS;
7666 : : }
7667 : : }
7668 [ + + ]: 279592 : else if (loc.end_lineno == loc.lineno) {
7669 [ + + + + : 254138 : if (line_delta == 0 && column < 80 && end_column - column < 16 && end_column >= column) {
+ + + - ]
7670 : 133188 : write_location_info_short_form(a, isize, column, end_column);
7671 : 133188 : return SUCCESS;
7672 : : }
7673 [ + + + + : 120950 : if (line_delta >= 0 && line_delta < 3 && column < 128 && end_column < 128) {
+ + + + ]
7674 : 106695 : write_location_info_oneline_form(a, isize, line_delta, column, end_column);
7675 : 106695 : a->a_lineno = loc.lineno;
7676 : 106695 : return SUCCESS;
7677 : : }
7678 : : }
7679 : 39709 : write_location_info_long_form(a, loc, isize);
7680 : 39709 : a->a_lineno = loc.lineno;
7681 : 39709 : return SUCCESS;
7682 : : }
7683 : :
7684 : : static int
7685 : 264465 : assemble_emit_location(struct assembler* a, location loc, int isize)
7686 : : {
7687 [ + + ]: 264465 : if (isize == 0) {
7688 : 7033 : return SUCCESS;
7689 : : }
7690 [ + + ]: 286095 : while (isize > 8) {
7691 [ - + ]: 28663 : RETURN_IF_ERROR(write_location_info_entry(a, loc, 8));
7692 : 28663 : isize -= 8;
7693 : : }
7694 : 257432 : return write_location_info_entry(a, loc, isize);
7695 : : }
7696 : :
7697 : : static int
7698 : 8041 : assemble_location_info(struct assembler *a, basicblock *entryblock, int firstlineno)
7699 : : {
7700 : 8041 : a->a_lineno = firstlineno;
7701 : 8041 : location loc = NO_LOCATION;
7702 : 8041 : int size = 0;
7703 [ + + ]: 60209 : for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
7704 [ + + ]: 394204 : for (int j = 0; j < b->b_iused; j++) {
7705 [ + + ]: 342036 : if (!same_location(loc, b->b_instr[j].i_loc)) {
7706 [ - + ]: 256424 : RETURN_IF_ERROR(assemble_emit_location(a, loc, size));
7707 : 256424 : loc = b->b_instr[j].i_loc;
7708 : 256424 : size = 0;
7709 : : }
7710 : 342036 : size += instr_size(&b->b_instr[j]);
7711 : : }
7712 : : }
7713 [ - + ]: 8041 : RETURN_IF_ERROR(assemble_emit_location(a, loc, size));
7714 : 8041 : return SUCCESS;
7715 : : }
7716 : :
7717 : : /* assemble_emit_instr()
7718 : : Extend the bytecode with a new instruction.
7719 : : Update lnotab if necessary.
7720 : : */
7721 : :
7722 : : static int
7723 : 342036 : assemble_emit_instr(struct assembler *a, struct cfg_instr *i)
7724 : : {
7725 : 342036 : Py_ssize_t len = PyBytes_GET_SIZE(a->a_bytecode);
7726 : : _Py_CODEUNIT *code;
7727 : :
7728 : 342036 : int size = instr_size(i);
7729 [ + + ]: 342036 : if (a->a_offset + size >= len / (int)sizeof(_Py_CODEUNIT)) {
7730 [ - + ]: 5892 : if (len > PY_SSIZE_T_MAX / 2) {
7731 : 0 : return ERROR;
7732 : : }
7733 [ - + ]: 5892 : RETURN_IF_ERROR(_PyBytes_Resize(&a->a_bytecode, len * 2));
7734 : : }
7735 : 342036 : code = (_Py_CODEUNIT *)PyBytes_AS_STRING(a->a_bytecode) + a->a_offset;
7736 : 342036 : a->a_offset += size;
7737 : 342036 : write_instr(code, i, size);
7738 : 342036 : return SUCCESS;
7739 : : }
7740 : :
7741 : : static int merge_const_one(PyObject *const_cache, PyObject **obj);
7742 : :
7743 : : static int
7744 : 8041 : assemble_emit(struct assembler *a, basicblock *entryblock, int first_lineno,
7745 : : PyObject *const_cache)
7746 : : {
7747 [ - + ]: 8041 : RETURN_IF_ERROR(assemble_init(a, first_lineno));
7748 : :
7749 [ + + ]: 60209 : for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
7750 [ + + ]: 394204 : for (int j = 0; j < b->b_iused; j++) {
7751 [ - + ]: 342036 : RETURN_IF_ERROR(assemble_emit_instr(a, &b->b_instr[j]));
7752 : : }
7753 : : }
7754 : :
7755 [ - + ]: 8041 : RETURN_IF_ERROR(assemble_location_info(a, entryblock, a->a_lineno));
7756 : :
7757 [ - + ]: 8041 : RETURN_IF_ERROR(assemble_exception_table(a, entryblock));
7758 : :
7759 [ - + ]: 8041 : RETURN_IF_ERROR(_PyBytes_Resize(&a->a_except_table, a->a_except_table_off));
7760 [ - + ]: 8041 : RETURN_IF_ERROR(merge_const_one(const_cache, &a->a_except_table));
7761 : :
7762 [ - + ]: 8041 : RETURN_IF_ERROR(_PyBytes_Resize(&a->a_linetable, a->a_location_off));
7763 [ - + ]: 8041 : RETURN_IF_ERROR(merge_const_one(const_cache, &a->a_linetable));
7764 : :
7765 [ - + ]: 8041 : RETURN_IF_ERROR(_PyBytes_Resize(&a->a_bytecode, a->a_offset * sizeof(_Py_CODEUNIT)));
7766 [ - + ]: 8041 : RETURN_IF_ERROR(merge_const_one(const_cache, &a->a_bytecode));
7767 : 8041 : return SUCCESS;
7768 : : }
7769 : :
7770 : : static int
7771 : 52168 : normalize_jumps_in_block(cfg_builder *g, basicblock *b) {
7772 : 52168 : struct cfg_instr *last = basicblock_last_instr(b);
7773 [ + + + + ]: 52168 : if (last == NULL || !is_jump(last)) {
7774 : 30617 : return SUCCESS;
7775 : : }
7776 : : assert(!IS_ASSEMBLER_OPCODE(last->i_opcode));
7777 : 21551 : bool is_forward = last->i_target->b_visited == 0;
7778 [ + + + ]: 21551 : switch(last->i_opcode) {
7779 : 5692 : case JUMP:
7780 [ + + ]: 5692 : last->i_opcode = is_forward ? JUMP_FORWARD : JUMP_BACKWARD;
7781 : 5692 : return SUCCESS;
7782 : 190 : case JUMP_NO_INTERRUPT:
7783 : 190 : last->i_opcode = is_forward ?
7784 [ - + ]: 190 : JUMP_FORWARD : JUMP_BACKWARD_NO_INTERRUPT;
7785 : 190 : return SUCCESS;
7786 : : }
7787 : 15669 : int reversed_opcode = 0;
7788 [ + + + + : 15669 : switch(last->i_opcode) {
+ + ]
7789 : 884 : case POP_JUMP_IF_NOT_NONE:
7790 : 884 : reversed_opcode = POP_JUMP_IF_NONE;
7791 : 884 : break;
7792 : 889 : case POP_JUMP_IF_NONE:
7793 : 889 : reversed_opcode = POP_JUMP_IF_NOT_NONE;
7794 : 889 : break;
7795 : 9096 : case POP_JUMP_IF_FALSE:
7796 : 9096 : reversed_opcode = POP_JUMP_IF_TRUE;
7797 : 9096 : break;
7798 : 2468 : case POP_JUMP_IF_TRUE:
7799 : 2468 : reversed_opcode = POP_JUMP_IF_FALSE;
7800 : 2468 : break;
7801 : 437 : case JUMP_IF_TRUE_OR_POP:
7802 : : case JUMP_IF_FALSE_OR_POP:
7803 [ - + ]: 437 : if (!is_forward) {
7804 : : /* As far as we can tell, the compiler never emits
7805 : : * these jumps with a backwards target. If/when this
7806 : : * exception is raised, we have found a use case for
7807 : : * a backwards version of this jump (or to replace
7808 : : * it with the sequence (COPY 1, POP_JUMP_IF_T/F, POP)
7809 : : */
7810 : 0 : PyErr_Format(PyExc_SystemError,
7811 : : "unexpected %s jumping backwards",
7812 [ # # ]: 0 : last->i_opcode == JUMP_IF_TRUE_OR_POP ?
7813 : : "JUMP_IF_TRUE_OR_POP" : "JUMP_IF_FALSE_OR_POP");
7814 : : }
7815 : 437 : return SUCCESS;
7816 : : }
7817 [ + + ]: 15232 : if (is_forward) {
7818 : 14375 : return SUCCESS;
7819 : : }
7820 : :
7821 : : /* transform 'conditional jump T' to
7822 : : * 'reversed_jump b_next' followed by 'jump_backwards T'
7823 : : */
7824 : :
7825 : 857 : basicblock *target = last->i_target;
7826 : 857 : basicblock *backwards_jump = cfg_builder_new_block(g);
7827 [ - + ]: 857 : if (backwards_jump == NULL) {
7828 : 0 : return ERROR;
7829 : : }
7830 : 857 : basicblock_addop(backwards_jump, JUMP, target->b_label.id, NO_LOCATION);
7831 : 857 : backwards_jump->b_instr[0].i_target = target;
7832 : 857 : last->i_opcode = reversed_opcode;
7833 : 857 : last->i_target = b->b_next;
7834 : :
7835 : 857 : backwards_jump->b_cold = b->b_cold;
7836 : 857 : backwards_jump->b_next = b->b_next;
7837 : 857 : b->b_next = backwards_jump;
7838 : 857 : return SUCCESS;
7839 : : }
7840 : :
7841 : : static int
7842 : 8041 : normalize_jumps(cfg_builder *g)
7843 : : {
7844 : 8041 : basicblock *entryblock = g->g_entryblock;
7845 [ + + ]: 59352 : for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
7846 : 51311 : b->b_visited = 0;
7847 : : }
7848 [ + + ]: 60209 : for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
7849 : 52168 : b->b_visited = 1;
7850 [ - + ]: 52168 : RETURN_IF_ERROR(normalize_jumps_in_block(g, b));
7851 : : }
7852 : 8041 : return SUCCESS;
7853 : : }
7854 : :
7855 : : static void
7856 : 8225 : assemble_jump_offsets(basicblock *entryblock)
7857 : : {
7858 : : int bsize, totsize, extended_arg_recompile;
7859 : :
7860 : : /* Compute the size of each block and fixup jump args.
7861 : : Replace block pointer with position in bytecode. */
7862 : : do {
7863 : 8225 : totsize = 0;
7864 [ + + ]: 69727 : for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
7865 : 61502 : bsize = blocksize(b);
7866 : 61502 : b->b_offset = totsize;
7867 : 61502 : totsize += bsize;
7868 : : }
7869 : 8225 : extended_arg_recompile = 0;
7870 [ + + ]: 69727 : for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
7871 : 61502 : bsize = b->b_offset;
7872 [ + + ]: 465669 : for (int i = 0; i < b->b_iused; i++) {
7873 : 404167 : struct cfg_instr *instr = &b->b_instr[i];
7874 : 404167 : int isize = instr_size(instr);
7875 : : /* Relative jumps are computed relative to
7876 : : the instruction pointer after fetching
7877 : : the jump instruction.
7878 : : */
7879 : 404167 : bsize += isize;
7880 [ + + ]: 404167 : if (is_jump(instr)) {
7881 : 26506 : instr->i_oparg = instr->i_target->b_offset;
7882 [ + - ]: 26506 : if (is_relative_jump(instr)) {
7883 [ + + ]: 26506 : if (instr->i_oparg < bsize) {
7884 : : assert(IS_BACKWARDS_JUMP_OPCODE(instr->i_opcode));
7885 : 5048 : instr->i_oparg = bsize - instr->i_oparg;
7886 : : }
7887 : : else {
7888 : : assert(!IS_BACKWARDS_JUMP_OPCODE(instr->i_opcode));
7889 : 21458 : instr->i_oparg -= bsize;
7890 : : }
7891 : : }
7892 : : else {
7893 : : assert(!IS_BACKWARDS_JUMP_OPCODE(instr->i_opcode));
7894 : : }
7895 [ + + ]: 26506 : if (instr_size(instr) != isize) {
7896 : 647 : extended_arg_recompile = 1;
7897 : : }
7898 : : }
7899 : : }
7900 : : }
7901 : :
7902 : : /* XXX: This is an awful hack that could hurt performance, but
7903 : : on the bright side it should work until we come up
7904 : : with a better solution.
7905 : :
7906 : : The issue is that in the first loop blocksize() is called
7907 : : which calls instr_size() which requires i_oparg be set
7908 : : appropriately. There is a bootstrap problem because
7909 : : i_oparg is calculated in the second loop above.
7910 : :
7911 : : So we loop until we stop seeing new EXTENDED_ARGs.
7912 : : The only EXTENDED_ARGs that could be popping up are
7913 : : ones in jump instructions. So this should converge
7914 : : fairly quickly.
7915 : : */
7916 [ + + ]: 8225 : } while (extended_arg_recompile);
7917 : 8041 : }
7918 : :
7919 : :
7920 : : // helper functions for add_checks_for_loads_of_unknown_variables
7921 : : static inline void
7922 : 204644 : maybe_push(basicblock *b, uint64_t unsafe_mask, basicblock ***sp)
7923 : : {
7924 : : // Push b if the unsafe mask is giving us any new information.
7925 : : // To avoid overflowing the stack, only allow each block once.
7926 : : // Use b->b_visited=1 to mean that b is currently on the stack.
7927 : 204644 : uint64_t both = b->b_unsafe_locals_mask | unsafe_mask;
7928 [ + + ]: 204644 : if (b->b_unsafe_locals_mask != both) {
7929 : 33427 : b->b_unsafe_locals_mask = both;
7930 : : // More work left to do.
7931 [ + + ]: 33427 : if (!b->b_visited) {
7932 : : // not on the stack, so push it.
7933 : 33175 : *(*sp)++ = b;
7934 : 33175 : b->b_visited = 1;
7935 : : }
7936 : : }
7937 : 204644 : }
7938 : :
7939 : : static void
7940 : 80806 : scan_block_for_locals(basicblock *b, basicblock ***sp)
7941 : : {
7942 : : // bit i is set if local i is potentially uninitialized
7943 : 80806 : uint64_t unsafe_mask = b->b_unsafe_locals_mask;
7944 [ + + ]: 549175 : for (int i = 0; i < b->b_iused; i++) {
7945 : 468369 : struct cfg_instr *instr = &b->b_instr[i];
7946 : : assert(instr->i_opcode != EXTENDED_ARG);
7947 : : assert(!IS_SUPERINSTRUCTION_OPCODE(instr->i_opcode));
7948 [ + + ]: 468369 : if (instr->i_except != NULL) {
7949 : 114747 : maybe_push(instr->i_except, unsafe_mask, sp);
7950 : : }
7951 [ + + ]: 468369 : if (instr->i_oparg >= 64) {
7952 : 3041 : continue;
7953 : : }
7954 : : assert(instr->i_oparg >= 0);
7955 : 465328 : uint64_t bit = (uint64_t)1 << instr->i_oparg;
7956 [ + + + + : 465328 : switch (instr->i_opcode) {
+ ]
7957 : 817 : case DELETE_FAST:
7958 : 817 : unsafe_mask |= bit;
7959 : 817 : break;
7960 : 29474 : case STORE_FAST:
7961 : 29474 : unsafe_mask &= ~bit;
7962 : 29474 : break;
7963 : 157 : case LOAD_FAST_CHECK:
7964 : : // If this doesn't raise, then the local is defined.
7965 : 157 : unsafe_mask &= ~bit;
7966 : 157 : break;
7967 : 94654 : case LOAD_FAST:
7968 [ + + ]: 94654 : if (unsafe_mask & bit) {
7969 : 157 : instr->i_opcode = LOAD_FAST_CHECK;
7970 : : }
7971 : 94654 : unsafe_mask &= ~bit;
7972 : 94654 : break;
7973 : : }
7974 : 468369 : }
7975 [ + + + + ]: 80806 : if (b->b_next && BB_HAS_FALLTHROUGH(b)) {
7976 : 46996 : maybe_push(b->b_next, unsafe_mask, sp);
7977 : : }
7978 : 80806 : struct cfg_instr *last = basicblock_last_instr(b);
7979 [ + - + + ]: 80806 : if (last && is_jump(last)) {
7980 : : assert(last->i_target != NULL);
7981 : 36062 : maybe_push(last->i_target, unsafe_mask, sp);
7982 : : }
7983 : 80806 : }
7984 : :
7985 : : static int
7986 : 0 : fast_scan_many_locals(basicblock *entryblock, int nlocals)
7987 : : {
7988 : : assert(nlocals > 64);
7989 : 0 : Py_ssize_t *states = PyMem_Calloc(nlocals - 64, sizeof(Py_ssize_t));
7990 [ # # ]: 0 : if (states == NULL) {
7991 : 0 : PyErr_NoMemory();
7992 : 0 : return ERROR;
7993 : : }
7994 : 0 : Py_ssize_t blocknum = 0;
7995 : : // state[i - 64] == blocknum if local i is guaranteed to
7996 : : // be initialized, i.e., if it has had a previous LOAD_FAST or
7997 : : // STORE_FAST within that basicblock (not followed by DELETE_FAST).
7998 [ # # ]: 0 : for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
7999 : 0 : blocknum++;
8000 [ # # ]: 0 : for (int i = 0; i < b->b_iused; i++) {
8001 : 0 : struct cfg_instr *instr = &b->b_instr[i];
8002 : : assert(instr->i_opcode != EXTENDED_ARG);
8003 : : assert(!IS_SUPERINSTRUCTION_OPCODE(instr->i_opcode));
8004 : 0 : int arg = instr->i_oparg;
8005 [ # # ]: 0 : if (arg < 64) {
8006 : 0 : continue;
8007 : : }
8008 : : assert(arg >= 0);
8009 [ # # # # ]: 0 : switch (instr->i_opcode) {
8010 : 0 : case DELETE_FAST:
8011 : 0 : states[arg - 64] = blocknum - 1;
8012 : 0 : break;
8013 : 0 : case STORE_FAST:
8014 : 0 : states[arg - 64] = blocknum;
8015 : 0 : break;
8016 : 0 : case LOAD_FAST:
8017 [ # # ]: 0 : if (states[arg - 64] != blocknum) {
8018 : 0 : instr->i_opcode = LOAD_FAST_CHECK;
8019 : : }
8020 : 0 : states[arg - 64] = blocknum;
8021 : 0 : break;
8022 : : case LOAD_FAST_CHECK:
8023 : : Py_UNREACHABLE();
8024 : : }
8025 : 0 : }
8026 : : }
8027 : 0 : PyMem_Free(states);
8028 : 0 : return SUCCESS;
8029 : : }
8030 : :
8031 : : static int
8032 : 8041 : add_checks_for_loads_of_uninitialized_variables(basicblock *entryblock,
8033 : : int nlocals,
8034 : : int nparams)
8035 : : {
8036 [ + + ]: 8041 : if (nlocals == 0) {
8037 : 1202 : return SUCCESS;
8038 : : }
8039 [ - + ]: 6839 : if (nlocals > 64) {
8040 : : // To avoid O(nlocals**2) compilation, locals beyond the first
8041 : : // 64 are only analyzed one basicblock at a time: initialization
8042 : : // info is not passed between basicblocks.
8043 [ # # ]: 0 : if (fast_scan_many_locals(entryblock, nlocals) < 0) {
8044 : 0 : return ERROR;
8045 : : }
8046 : 0 : nlocals = 64;
8047 : : }
8048 : 6839 : basicblock **stack = make_cfg_traversal_stack(entryblock);
8049 [ - + ]: 6839 : if (stack == NULL) {
8050 : 0 : return ERROR;
8051 : : }
8052 : 6839 : basicblock **sp = stack;
8053 : :
8054 : : // First origin of being uninitialized:
8055 : : // The non-parameter locals in the entry block.
8056 : 6839 : uint64_t start_mask = 0;
8057 [ + + ]: 16575 : for (int i = nparams; i < nlocals; i++) {
8058 : 9736 : start_mask |= (uint64_t)1 << i;
8059 : : }
8060 : 6839 : maybe_push(entryblock, start_mask, &sp);
8061 : :
8062 : : // Second origin of being uninitialized:
8063 : : // There could be DELETE_FAST somewhere, so
8064 : : // be sure to scan each basicblock at least once.
8065 [ + + ]: 54470 : for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
8066 : 47631 : scan_block_for_locals(b, &sp);
8067 : : }
8068 : :
8069 : : // Now propagate the uncertainty from the origins we found: Use
8070 : : // LOAD_FAST_CHECK for any LOAD_FAST where the local could be undefined.
8071 [ + + ]: 40014 : while (sp > stack) {
8072 : 33175 : basicblock *b = *--sp;
8073 : : // mark as no longer on stack
8074 : 33175 : b->b_visited = 0;
8075 : 33175 : scan_block_for_locals(b, &sp);
8076 : : }
8077 : 6839 : PyMem_Free(stack);
8078 : 6839 : return SUCCESS;
8079 : : }
8080 : :
8081 : : static PyObject *
8082 : 8041 : dict_keys_inorder(PyObject *dict, Py_ssize_t offset)
8083 : : {
8084 : : PyObject *tuple, *k, *v;
8085 : 8041 : Py_ssize_t i, pos = 0, size = PyDict_GET_SIZE(dict);
8086 : :
8087 : 8041 : tuple = PyTuple_New(size);
8088 [ - + ]: 8041 : if (tuple == NULL)
8089 : 0 : return NULL;
8090 [ + + ]: 58190 : while (PyDict_Next(dict, &pos, &k, &v)) {
8091 : 50149 : i = PyLong_AS_LONG(v);
8092 : : assert((i - offset) < size);
8093 : : assert((i - offset) >= 0);
8094 : 50149 : PyTuple_SET_ITEM(tuple, i - offset, Py_NewRef(k));
8095 : : }
8096 : 8041 : return tuple;
8097 : : }
8098 : :
8099 : : static PyObject *
8100 : 8041 : consts_dict_keys_inorder(PyObject *dict)
8101 : : {
8102 : : PyObject *consts, *k, *v;
8103 : 8041 : Py_ssize_t i, pos = 0, size = PyDict_GET_SIZE(dict);
8104 : :
8105 : 8041 : consts = PyList_New(size); /* PyCode_Optimize() requires a list */
8106 [ - + ]: 8041 : if (consts == NULL)
8107 : 0 : return NULL;
8108 [ + + ]: 50324 : while (PyDict_Next(dict, &pos, &k, &v)) {
8109 : 42283 : i = PyLong_AS_LONG(v);
8110 : : /* The keys of the dictionary can be tuples wrapping a constant.
8111 : : * (see dict_add_o and _PyCode_ConstantKey). In that case
8112 : : * the object we want is always second. */
8113 [ + + ]: 42283 : if (PyTuple_CheckExact(k)) {
8114 : 4446 : k = PyTuple_GET_ITEM(k, 1);
8115 : : }
8116 : : assert(i < size);
8117 : : assert(i >= 0);
8118 : 42283 : PyList_SET_ITEM(consts, i, Py_NewRef(k));
8119 : : }
8120 : 8041 : return consts;
8121 : : }
8122 : :
8123 : : static int
8124 : 8041 : compute_code_flags(struct compiler *c)
8125 : : {
8126 : 8041 : PySTEntryObject *ste = c->u->u_ste;
8127 : 8041 : int flags = 0;
8128 [ + + ]: 8041 : if (ste->ste_type == FunctionBlock) {
8129 : 6989 : flags |= CO_NEWLOCALS | CO_OPTIMIZED;
8130 [ + + ]: 6989 : if (ste->ste_nested)
8131 : 758 : flags |= CO_NESTED;
8132 [ + + + + ]: 6989 : if (ste->ste_generator && !ste->ste_coroutine)
8133 : 374 : flags |= CO_GENERATOR;
8134 [ + + + + ]: 6989 : if (!ste->ste_generator && ste->ste_coroutine)
8135 : 155 : flags |= CO_COROUTINE;
8136 [ + + + + ]: 6989 : if (ste->ste_generator && ste->ste_coroutine)
8137 : 3 : flags |= CO_ASYNC_GENERATOR;
8138 [ + + ]: 6989 : if (ste->ste_varargs)
8139 : 309 : flags |= CO_VARARGS;
8140 [ + + ]: 6989 : if (ste->ste_varkeywords)
8141 : 216 : flags |= CO_VARKEYWORDS;
8142 : : }
8143 : :
8144 : : /* (Only) inherit compilerflags in PyCF_MASK */
8145 : 8041 : flags |= (c->c_flags.cf_flags & PyCF_MASK);
8146 : :
8147 [ - + - - : 8041 : if ((IS_TOP_LEVEL_AWAIT(c)) &&
- - ]
8148 : 0 : ste->ste_coroutine &&
8149 [ # # ]: 0 : !ste->ste_generator) {
8150 : 0 : flags |= CO_COROUTINE;
8151 : : }
8152 : :
8153 : 8041 : return flags;
8154 : : }
8155 : :
8156 : : // Merge *obj* with constant cache.
8157 : : // Unlike merge_consts_recursive(), this function doesn't work recursively.
8158 : : static int
8159 : 49146 : merge_const_one(PyObject *const_cache, PyObject **obj)
8160 : : {
8161 : : assert(PyDict_CheckExact(const_cache));
8162 : 49146 : PyObject *key = _PyCode_ConstantKey(*obj);
8163 [ - + ]: 49146 : if (key == NULL) {
8164 : 0 : return ERROR;
8165 : : }
8166 : :
8167 : : // t is borrowed reference
8168 : 49146 : PyObject *t = PyDict_SetDefault(const_cache, key, key);
8169 : 49146 : Py_DECREF(key);
8170 [ - + ]: 49146 : if (t == NULL) {
8171 : 0 : return ERROR;
8172 : : }
8173 [ + + ]: 49146 : if (t == key) { // obj is new constant.
8174 : 33484 : return SUCCESS;
8175 : : }
8176 : :
8177 [ + - ]: 15662 : if (PyTuple_CheckExact(t)) {
8178 : : // t is still borrowed reference
8179 : 15662 : t = PyTuple_GET_ITEM(t, 1);
8180 : : }
8181 : :
8182 : 15662 : Py_SETREF(*obj, Py_NewRef(t));
8183 : 15662 : return SUCCESS;
8184 : : }
8185 : :
8186 : : // This is in codeobject.c.
8187 : : extern void _Py_set_localsplus_info(int, PyObject *, unsigned char,
8188 : : PyObject *, PyObject *);
8189 : :
8190 : : static void
8191 : 8041 : compute_localsplus_info(struct compiler_unit *u, int nlocalsplus,
8192 : : PyObject *names, PyObject *kinds)
8193 : : {
8194 : : PyObject *k, *v;
8195 : 8041 : Py_ssize_t pos = 0;
8196 [ + + ]: 31750 : while (PyDict_Next(u->u_varnames, &pos, &k, &v)) {
8197 : 23709 : int offset = (int)PyLong_AS_LONG(v);
8198 : : assert(offset >= 0);
8199 : : assert(offset < nlocalsplus);
8200 : : // For now we do not distinguish arg kinds.
8201 : 23709 : _PyLocals_Kind kind = CO_FAST_LOCAL;
8202 [ + + ]: 23709 : if (PyDict_GetItem(u->u_cellvars, k) != NULL) {
8203 : 303 : kind |= CO_FAST_CELL;
8204 : : }
8205 : 23709 : _Py_set_localsplus_info(offset, k, kind, names, kinds);
8206 : : }
8207 : 8041 : int nlocals = (int)PyDict_GET_SIZE(u->u_varnames);
8208 : :
8209 : : // This counter mirrors the fix done in fix_cell_offsets().
8210 : 8041 : int numdropped = 0;
8211 : 8041 : pos = 0;
8212 [ + + ]: 8740 : while (PyDict_Next(u->u_cellvars, &pos, &k, &v)) {
8213 [ + + ]: 699 : if (PyDict_GetItem(u->u_varnames, k) != NULL) {
8214 : : // Skip cells that are already covered by locals.
8215 : 303 : numdropped += 1;
8216 : 303 : continue;
8217 : : }
8218 : 396 : int offset = (int)PyLong_AS_LONG(v);
8219 : : assert(offset >= 0);
8220 : 396 : offset += nlocals - numdropped;
8221 : : assert(offset < nlocalsplus);
8222 : 396 : _Py_set_localsplus_info(offset, k, CO_FAST_CELL, names, kinds);
8223 : : }
8224 : :
8225 : 8041 : pos = 0;
8226 [ + + ]: 8979 : while (PyDict_Next(u->u_freevars, &pos, &k, &v)) {
8227 : 938 : int offset = (int)PyLong_AS_LONG(v);
8228 : : assert(offset >= 0);
8229 : 938 : offset += nlocals - numdropped;
8230 : : assert(offset < nlocalsplus);
8231 : 938 : _Py_set_localsplus_info(offset, k, CO_FAST_FREE, names, kinds);
8232 : : }
8233 : 8041 : }
8234 : :
8235 : : static PyCodeObject *
8236 : 8041 : makecode(struct compiler_unit *u, struct assembler *a, PyObject *const_cache,
8237 : : PyObject *constslist, int maxdepth, int nlocalsplus, int code_flags,
8238 : : PyObject *filename)
8239 : : {
8240 : 8041 : PyCodeObject *co = NULL;
8241 : 8041 : PyObject *names = NULL;
8242 : 8041 : PyObject *consts = NULL;
8243 : 8041 : PyObject *localsplusnames = NULL;
8244 : 8041 : PyObject *localspluskinds = NULL;
8245 : 8041 : names = dict_keys_inorder(u->u_names, 0);
8246 [ - + ]: 8041 : if (!names) {
8247 : 0 : goto error;
8248 : : }
8249 [ - + ]: 8041 : if (merge_const_one(const_cache, &names) < 0) {
8250 : 0 : goto error;
8251 : : }
8252 : :
8253 : 8041 : consts = PyList_AsTuple(constslist); /* PyCode_New requires a tuple */
8254 [ - + ]: 8041 : if (consts == NULL) {
8255 : 0 : goto error;
8256 : : }
8257 [ - + ]: 8041 : if (merge_const_one(const_cache, &consts) < 0) {
8258 : 0 : goto error;
8259 : : }
8260 : :
8261 : : assert(u->u_posonlyargcount < INT_MAX);
8262 : : assert(u->u_argcount < INT_MAX);
8263 : : assert(u->u_kwonlyargcount < INT_MAX);
8264 : 8041 : int posonlyargcount = (int)u->u_posonlyargcount;
8265 : 8041 : int posorkwargcount = (int)u->u_argcount;
8266 : : assert(INT_MAX - posonlyargcount - posorkwargcount > 0);
8267 : 8041 : int kwonlyargcount = (int)u->u_kwonlyargcount;
8268 : :
8269 : 8041 : localsplusnames = PyTuple_New(nlocalsplus);
8270 [ - + ]: 8041 : if (localsplusnames == NULL) {
8271 : 0 : goto error;
8272 : : }
8273 : 8041 : localspluskinds = PyBytes_FromStringAndSize(NULL, nlocalsplus);
8274 [ - + ]: 8041 : if (localspluskinds == NULL) {
8275 : 0 : goto error;
8276 : : }
8277 : 8041 : compute_localsplus_info(u, nlocalsplus, localsplusnames, localspluskinds);
8278 : :
8279 : 16082 : struct _PyCodeConstructor con = {
8280 : : .filename = filename,
8281 : 8041 : .name = u->u_name,
8282 [ + + ]: 8041 : .qualname = u->u_qualname ? u->u_qualname : u->u_name,
8283 : : .flags = code_flags,
8284 : :
8285 : 8041 : .code = a->a_bytecode,
8286 : 8041 : .firstlineno = u->u_firstlineno,
8287 : 8041 : .linetable = a->a_linetable,
8288 : :
8289 : : .consts = consts,
8290 : : .names = names,
8291 : :
8292 : : .localsplusnames = localsplusnames,
8293 : : .localspluskinds = localspluskinds,
8294 : :
8295 : 8041 : .argcount = posonlyargcount + posorkwargcount,
8296 : : .posonlyargcount = posonlyargcount,
8297 : : .kwonlyargcount = kwonlyargcount,
8298 : :
8299 : : .stacksize = maxdepth,
8300 : :
8301 : 8041 : .exceptiontable = a->a_except_table,
8302 : : };
8303 : :
8304 [ - + ]: 8041 : if (_PyCode_Validate(&con) < 0) {
8305 : 0 : goto error;
8306 : : }
8307 : :
8308 [ - + ]: 8041 : if (merge_const_one(const_cache, &localsplusnames) < 0) {
8309 : 0 : goto error;
8310 : : }
8311 : 8041 : con.localsplusnames = localsplusnames;
8312 : :
8313 : 8041 : co = _PyCode_New(&con);
8314 [ + - ]: 8041 : if (co == NULL) {
8315 : 0 : goto error;
8316 : : }
8317 : :
8318 : 8041 : error:
8319 : 8041 : Py_XDECREF(names);
8320 : 8041 : Py_XDECREF(consts);
8321 : 8041 : Py_XDECREF(localsplusnames);
8322 : 8041 : Py_XDECREF(localspluskinds);
8323 : 8041 : return co;
8324 : : }
8325 : :
8326 : :
8327 : : /* For debugging purposes only */
8328 : : #if 0
8329 : : static void
8330 : : dump_instr(struct cfg_instr *i)
8331 : : {
8332 : : const char *jrel = (is_relative_jump(i)) ? "jrel " : "";
8333 : : const char *jabs = (is_jump(i) && !is_relative_jump(i))? "jabs " : "";
8334 : :
8335 : : char arg[128];
8336 : :
8337 : : *arg = '\0';
8338 : : if (HAS_ARG(i->i_opcode)) {
8339 : : sprintf(arg, "arg: %d ", i->i_oparg);
8340 : : }
8341 : : if (HAS_TARGET(i->i_opcode)) {
8342 : : sprintf(arg, "target: %p [%d] ", i->i_target, i->i_oparg);
8343 : : }
8344 : : fprintf(stderr, "line: %d, opcode: %d %s%s%s\n",
8345 : : i->i_loc.lineno, i->i_opcode, arg, jabs, jrel);
8346 : : }
8347 : :
8348 : : static inline int
8349 : : basicblock_returns(const basicblock *b) {
8350 : : struct cfg_instr *last = basicblock_last_instr(b);
8351 : : return last && (last->i_opcode == RETURN_VALUE || last->i_opcode == RETURN_CONST);
8352 : : }
8353 : :
8354 : : static void
8355 : : dump_basicblock(const basicblock *b)
8356 : : {
8357 : : const char *b_return = basicblock_returns(b) ? "return " : "";
8358 : : fprintf(stderr, "%d: [EH=%d CLD=%d WRM=%d NO_FT=%d %p] used: %d, depth: %d, offset: %d %s\n",
8359 : : b->b_label.id, b->b_except_handler, b->b_cold, b->b_warm, BB_NO_FALLTHROUGH(b), b, b->b_iused,
8360 : : b->b_startdepth, b->b_offset, b_return);
8361 : : if (b->b_instr) {
8362 : : int i;
8363 : : for (i = 0; i < b->b_iused; i++) {
8364 : : fprintf(stderr, " [%02d] ", i);
8365 : : dump_instr(b->b_instr + i);
8366 : : }
8367 : : }
8368 : : }
8369 : : #endif
8370 : :
8371 : :
8372 : : static int
8373 : : translate_jump_labels_to_targets(basicblock *entryblock);
8374 : :
8375 : : static int
8376 : : optimize_cfg(cfg_builder *g, PyObject *consts, PyObject *const_cache);
8377 : :
8378 : : static int
8379 : : remove_unused_consts(basicblock *entryblock, PyObject *consts);
8380 : :
8381 : : /* Duplicates exit BBs, so that line numbers can be propagated to them */
8382 : : static int
8383 : : duplicate_exits_without_lineno(cfg_builder *g);
8384 : :
8385 : : static int *
8386 : 8041 : build_cellfixedoffsets(struct compiler_unit *u)
8387 : : {
8388 : 8041 : int nlocals = (int)PyDict_GET_SIZE(u->u_varnames);
8389 : 8041 : int ncellvars = (int)PyDict_GET_SIZE(u->u_cellvars);
8390 : 8041 : int nfreevars = (int)PyDict_GET_SIZE(u->u_freevars);
8391 : :
8392 : 8041 : int noffsets = ncellvars + nfreevars;
8393 [ + - ]: 8041 : int *fixed = PyMem_New(int, noffsets);
8394 [ - + ]: 8041 : if (fixed == NULL) {
8395 : 0 : PyErr_NoMemory();
8396 : 0 : return NULL;
8397 : : }
8398 [ + + ]: 9678 : for (int i = 0; i < noffsets; i++) {
8399 : 1637 : fixed[i] = nlocals + i;
8400 : : }
8401 : :
8402 : : PyObject *varname, *cellindex;
8403 : 8041 : Py_ssize_t pos = 0;
8404 [ + + ]: 8740 : while (PyDict_Next(u->u_cellvars, &pos, &varname, &cellindex)) {
8405 : 699 : PyObject *varindex = PyDict_GetItem(u->u_varnames, varname);
8406 [ + + ]: 699 : if (varindex != NULL) {
8407 : : assert(PyLong_AS_LONG(cellindex) < INT_MAX);
8408 : : assert(PyLong_AS_LONG(varindex) < INT_MAX);
8409 : 303 : int oldindex = (int)PyLong_AS_LONG(cellindex);
8410 : 303 : int argoffset = (int)PyLong_AS_LONG(varindex);
8411 : 303 : fixed[oldindex] = argoffset;
8412 : : }
8413 : : }
8414 : :
8415 : 8041 : return fixed;
8416 : : }
8417 : :
8418 : : static int
8419 : 8041 : insert_prefix_instructions(struct compiler_unit *u, basicblock *entryblock,
8420 : : int *fixed, int nfreevars, int code_flags)
8421 : : {
8422 : : assert(u->u_firstlineno > 0);
8423 : :
8424 : : /* Add the generator prefix instructions. */
8425 [ + + ]: 8041 : if (code_flags & (CO_GENERATOR | CO_COROUTINE | CO_ASYNC_GENERATOR)) {
8426 : 532 : struct cfg_instr make_gen = {
8427 : : .i_opcode = RETURN_GENERATOR,
8428 : : .i_oparg = 0,
8429 : 532 : .i_loc = LOCATION(u->u_firstlineno, u->u_firstlineno, -1, -1),
8430 : : .i_target = NULL,
8431 : : };
8432 [ - + ]: 532 : RETURN_IF_ERROR(insert_instruction(entryblock, 0, &make_gen));
8433 : 532 : struct cfg_instr pop_top = {
8434 : : .i_opcode = POP_TOP,
8435 : : .i_oparg = 0,
8436 : : .i_loc = NO_LOCATION,
8437 : : .i_target = NULL,
8438 : : };
8439 [ - + ]: 532 : RETURN_IF_ERROR(insert_instruction(entryblock, 1, &pop_top));
8440 : : }
8441 : :
8442 : : /* Set up cells for any variable that escapes, to be put in a closure. */
8443 : 8041 : const int ncellvars = (int)PyDict_GET_SIZE(u->u_cellvars);
8444 [ + + ]: 8041 : if (ncellvars) {
8445 : : // u->u_cellvars has the cells out of order so we sort them
8446 : : // before adding the MAKE_CELL instructions. Note that we
8447 : : // adjust for arg cells, which come first.
8448 : 399 : const int nvars = ncellvars + (int)PyDict_GET_SIZE(u->u_varnames);
8449 : 399 : int *sorted = PyMem_RawCalloc(nvars, sizeof(int));
8450 [ - + ]: 399 : if (sorted == NULL) {
8451 : 0 : PyErr_NoMemory();
8452 : 0 : return ERROR;
8453 : : }
8454 [ + + ]: 1098 : for (int i = 0; i < ncellvars; i++) {
8455 : 699 : sorted[fixed[i]] = i + 1;
8456 : : }
8457 [ + + ]: 2146 : for (int i = 0, ncellsused = 0; ncellsused < ncellvars; i++) {
8458 : 1747 : int oldindex = sorted[i] - 1;
8459 [ + + ]: 1747 : if (oldindex == -1) {
8460 : 1048 : continue;
8461 : : }
8462 : 699 : struct cfg_instr make_cell = {
8463 : : .i_opcode = MAKE_CELL,
8464 : : // This will get fixed in offset_derefs().
8465 : : .i_oparg = oldindex,
8466 : : .i_loc = NO_LOCATION,
8467 : : .i_target = NULL,
8468 : : };
8469 [ - + ]: 699 : RETURN_IF_ERROR(insert_instruction(entryblock, ncellsused, &make_cell));
8470 : 699 : ncellsused += 1;
8471 : : }
8472 : 399 : PyMem_RawFree(sorted);
8473 : : }
8474 : :
8475 [ + + ]: 8041 : if (nfreevars) {
8476 : 627 : struct cfg_instr copy_frees = {
8477 : : .i_opcode = COPY_FREE_VARS,
8478 : : .i_oparg = nfreevars,
8479 : : .i_loc = NO_LOCATION,
8480 : : .i_target = NULL,
8481 : : };
8482 [ - + ]: 627 : RETURN_IF_ERROR(insert_instruction(entryblock, 0, ©_frees));
8483 : : }
8484 : :
8485 : 8041 : return SUCCESS;
8486 : : }
8487 : :
8488 : : /* Make sure that all returns have a line number, even if early passes
8489 : : * have failed to propagate a correct line number.
8490 : : * The resulting line number may not be correct according to PEP 626,
8491 : : * but should be "good enough", and no worse than in older versions. */
8492 : : static void
8493 : 8041 : guarantee_lineno_for_exits(basicblock *entryblock, int firstlineno) {
8494 : 8041 : int lineno = firstlineno;
8495 : : assert(lineno > 0);
8496 [ + + ]: 59352 : for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
8497 : 51311 : struct cfg_instr *last = basicblock_last_instr(b);
8498 [ - + ]: 51311 : if (last == NULL) {
8499 : 0 : continue;
8500 : : }
8501 [ + + ]: 51311 : if (last->i_loc.lineno < 0) {
8502 [ - + ]: 2747 : if (last->i_opcode == RETURN_VALUE) {
8503 [ # # ]: 0 : for (int i = 0; i < b->b_iused; i++) {
8504 : : assert(b->b_instr[i].i_loc.lineno < 0);
8505 : :
8506 : 0 : b->b_instr[i].i_loc.lineno = lineno;
8507 : : }
8508 : : }
8509 : : }
8510 : : else {
8511 : 48564 : lineno = last->i_loc.lineno;
8512 : : }
8513 : : }
8514 : 8041 : }
8515 : :
8516 : : static int
8517 : 8041 : fix_cell_offsets(struct compiler_unit *u, basicblock *entryblock, int *fixedmap)
8518 : : {
8519 : 8041 : int nlocals = (int)PyDict_GET_SIZE(u->u_varnames);
8520 : 8041 : int ncellvars = (int)PyDict_GET_SIZE(u->u_cellvars);
8521 : 8041 : int nfreevars = (int)PyDict_GET_SIZE(u->u_freevars);
8522 : 8041 : int noffsets = ncellvars + nfreevars;
8523 : :
8524 : : // First deal with duplicates (arg cells).
8525 : 8041 : int numdropped = 0;
8526 [ + + ]: 9678 : for (int i = 0; i < noffsets ; i++) {
8527 [ + + ]: 1637 : if (fixedmap[i] == i + nlocals) {
8528 : 1334 : fixedmap[i] -= numdropped;
8529 : : }
8530 : : else {
8531 : : // It was a duplicate (cell/arg).
8532 : 303 : numdropped += 1;
8533 : : }
8534 : : }
8535 : :
8536 : : // Then update offsets, either relative to locals or by cell2arg.
8537 [ + + ]: 59352 : for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
8538 [ + + ]: 400486 : for (int i = 0; i < b->b_iused; i++) {
8539 : 349175 : struct cfg_instr *inst = &b->b_instr[i];
8540 : : // This is called before extended args are generated.
8541 : : assert(inst->i_opcode != EXTENDED_ARG);
8542 : 349175 : int oldoffset = inst->i_oparg;
8543 [ + + ]: 349175 : switch(inst->i_opcode) {
8544 : 4195 : case MAKE_CELL:
8545 : : case LOAD_CLOSURE:
8546 : : case LOAD_DEREF:
8547 : : case STORE_DEREF:
8548 : : case DELETE_DEREF:
8549 : : case LOAD_CLASSDEREF:
8550 : : assert(oldoffset >= 0);
8551 : : assert(oldoffset < noffsets);
8552 : : assert(fixedmap[oldoffset] >= 0);
8553 : 4195 : inst->i_oparg = fixedmap[oldoffset];
8554 : : }
8555 : : }
8556 : : }
8557 : :
8558 : 8041 : return numdropped;
8559 : : }
8560 : :
8561 : :
8562 : : #ifndef NDEBUG
8563 : :
8564 : : static bool
8565 : : no_redundant_nops(cfg_builder *g) {
8566 : : for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
8567 : : if (remove_redundant_nops(b) != 0) {
8568 : : return false;
8569 : : }
8570 : : }
8571 : : return true;
8572 : : }
8573 : :
8574 : : static bool
8575 : : no_redundant_jumps(cfg_builder *g) {
8576 : : for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
8577 : : struct cfg_instr *last = basicblock_last_instr(b);
8578 : : if (last != NULL) {
8579 : : if (IS_UNCONDITIONAL_JUMP_OPCODE(last->i_opcode)) {
8580 : : assert(last->i_target != b->b_next);
8581 : : if (last->i_target == b->b_next) {
8582 : : return false;
8583 : : }
8584 : : }
8585 : : }
8586 : : }
8587 : : return true;
8588 : : }
8589 : :
8590 : : static bool
8591 : : opcode_metadata_is_sane(cfg_builder *g) {
8592 : : bool result = true;
8593 : : for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
8594 : : for (int i = 0; i < b->b_iused; i++) {
8595 : : struct cfg_instr *instr = &b->b_instr[i];
8596 : : int opcode = instr->i_opcode;
8597 : : int oparg = instr->i_oparg;
8598 : : assert(opcode <= MAX_REAL_OPCODE);
8599 : : for (int jump = 0; jump <= 1; jump++) {
8600 : : int popped = _PyOpcode_num_popped(opcode, oparg, jump ? true : false);
8601 : : int pushed = _PyOpcode_num_pushed(opcode, oparg, jump ? true : false);
8602 : : assert((pushed < 0) == (popped < 0));
8603 : : if (pushed >= 0) {
8604 : : assert(_PyOpcode_opcode_metadata[opcode].valid_entry);
8605 : : int effect = stack_effect(opcode, instr->i_oparg, jump);
8606 : : if (effect != pushed - popped) {
8607 : : fprintf(stderr,
8608 : : "op=%d arg=%d jump=%d: stack_effect (%d) != pushed (%d) - popped (%d)\n",
8609 : : opcode, oparg, jump, effect, pushed, popped);
8610 : : result = false;
8611 : : }
8612 : : }
8613 : : }
8614 : : }
8615 : : }
8616 : : return result;
8617 : : }
8618 : :
8619 : : static bool
8620 : : no_empty_basic_blocks(cfg_builder *g) {
8621 : : for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
8622 : : if (b->b_iused == 0) {
8623 : : return false;
8624 : : }
8625 : : }
8626 : : return true;
8627 : : }
8628 : : #endif
8629 : :
8630 : : static int
8631 : 9640 : remove_redundant_jumps(cfg_builder *g) {
8632 : : /* If a non-empty block ends with a jump instruction, check if the next
8633 : : * non-empty block reached through normal flow control is the target
8634 : : * of that jump. If it is, then the jump instruction is redundant and
8635 : : * can be deleted.
8636 : : */
8637 : : assert(no_empty_basic_blocks(g));
8638 [ + + ]: 87571 : for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
8639 : 77931 : struct cfg_instr *last = basicblock_last_instr(b);
8640 : : assert(last != NULL);
8641 : : assert(!IS_ASSEMBLER_OPCODE(last->i_opcode));
8642 [ + + + + : 77931 : if (IS_UNCONDITIONAL_JUMP_OPCODE(last->i_opcode)) {
+ - + - -
+ ]
8643 [ - + ]: 9591 : if (last->i_target == NULL) {
8644 : 0 : PyErr_SetString(PyExc_SystemError, "jump with NULL target");
8645 : 0 : return ERROR;
8646 : : }
8647 [ + + ]: 9591 : if (last->i_target == b->b_next) {
8648 : : assert(b->b_next->b_iused);
8649 : 871 : INSTR_SET_OP0(last, NOP);
8650 : : }
8651 : : }
8652 : : }
8653 : 9640 : return SUCCESS;
8654 : : }
8655 : :
8656 : : static int
8657 : 8041 : prepare_localsplus(struct compiler_unit* u, cfg_builder *g, int code_flags)
8658 : : {
8659 : : assert(PyDict_GET_SIZE(u->u_varnames) < INT_MAX);
8660 : : assert(PyDict_GET_SIZE(u->u_cellvars) < INT_MAX);
8661 : : assert(PyDict_GET_SIZE(u->u_freevars) < INT_MAX);
8662 : 8041 : int nlocals = (int)PyDict_GET_SIZE(u->u_varnames);
8663 : 8041 : int ncellvars = (int)PyDict_GET_SIZE(u->u_cellvars);
8664 : 8041 : int nfreevars = (int)PyDict_GET_SIZE(u->u_freevars);
8665 : : assert(INT_MAX - nlocals - ncellvars > 0);
8666 : : assert(INT_MAX - nlocals - ncellvars - nfreevars > 0);
8667 : 8041 : int nlocalsplus = nlocals + ncellvars + nfreevars;
8668 : 8041 : int* cellfixedoffsets = build_cellfixedoffsets(u);
8669 [ - + ]: 8041 : if (cellfixedoffsets == NULL) {
8670 : 0 : return ERROR;
8671 : : }
8672 : :
8673 : :
8674 : : // This must be called before fix_cell_offsets().
8675 [ - + ]: 8041 : if (insert_prefix_instructions(u, g->g_entryblock, cellfixedoffsets, nfreevars, code_flags)) {
8676 : 0 : PyMem_Free(cellfixedoffsets);
8677 : 0 : return ERROR;
8678 : : }
8679 : :
8680 : 8041 : int numdropped = fix_cell_offsets(u, g->g_entryblock, cellfixedoffsets);
8681 : 8041 : PyMem_Free(cellfixedoffsets); // At this point we're done with it.
8682 : 8041 : cellfixedoffsets = NULL;
8683 [ - + ]: 8041 : if (numdropped < 0) {
8684 : 0 : return ERROR;
8685 : : }
8686 : :
8687 : 8041 : nlocalsplus -= numdropped;
8688 : 8041 : return nlocalsplus;
8689 : : }
8690 : :
8691 : : static int
8692 : 8041 : add_return_at_end(struct compiler *c, int addNone)
8693 : : {
8694 : : /* Make sure every instruction stream that falls off the end returns None.
8695 : : * This also ensures that no jump target offsets are out of bounds.
8696 : : */
8697 [ + + ]: 8041 : if (addNone) {
8698 [ - + ]: 7982 : ADDOP_LOAD_CONST(c, NO_LOCATION, Py_None);
8699 : : }
8700 [ - + ]: 8041 : ADDOP(c, NO_LOCATION, RETURN_VALUE);
8701 : 8041 : return SUCCESS;
8702 : : }
8703 : :
8704 : : static void propagate_line_numbers(basicblock *entryblock);
8705 : :
8706 : : static int
8707 : 8041 : resolve_line_numbers(struct compiler_unit *u, cfg_builder *g)
8708 : : {
8709 : : /* Set firstlineno if it wasn't explicitly set. */
8710 [ - + ]: 8041 : if (!u->u_firstlineno) {
8711 [ # # # # ]: 0 : if (g->g_entryblock->b_instr && g->g_entryblock->b_instr->i_loc.lineno) {
8712 : 0 : u->u_firstlineno = g->g_entryblock->b_instr->i_loc.lineno;
8713 : : }
8714 : : else {
8715 : 0 : u->u_firstlineno = 1;
8716 : : }
8717 : : }
8718 [ - + ]: 8041 : RETURN_IF_ERROR(duplicate_exits_without_lineno(g));
8719 : 8041 : propagate_line_numbers(g->g_entryblock);
8720 : 8041 : guarantee_lineno_for_exits(g->g_entryblock, u->u_firstlineno);
8721 : 8041 : return SUCCESS;
8722 : : }
8723 : :
8724 : : static int
8725 : 8041 : optimize_code_unit(cfg_builder *g, PyObject *consts, PyObject *const_cache,
8726 : : int code_flags, int nlocals, int nparams)
8727 : : {
8728 : : assert(cfg_builder_check(g));
8729 : : /** Preprocessing **/
8730 : : /* Map labels to targets and mark exception handlers */
8731 [ - + ]: 8041 : RETURN_IF_ERROR(translate_jump_labels_to_targets(g->g_entryblock));
8732 [ - + ]: 8041 : RETURN_IF_ERROR(mark_except_handlers(g->g_entryblock));
8733 [ - + ]: 8041 : RETURN_IF_ERROR(label_exception_targets(g->g_entryblock));
8734 : :
8735 : : /** Optimization **/
8736 [ - + ]: 8041 : RETURN_IF_ERROR(optimize_cfg(g, consts, const_cache));
8737 [ - + ]: 8041 : RETURN_IF_ERROR(remove_unused_consts(g->g_entryblock, consts));
8738 [ - + ]: 8041 : RETURN_IF_ERROR(
8739 : : add_checks_for_loads_of_uninitialized_variables(
8740 : : g->g_entryblock, nlocals, nparams));
8741 : :
8742 [ - + ]: 8041 : RETURN_IF_ERROR(push_cold_blocks_to_end(g, code_flags));
8743 : 8041 : return SUCCESS;
8744 : : }
8745 : :
8746 : : static PyCodeObject *
8747 : 8041 : assemble_code_unit(struct compiler_unit *u, PyObject *const_cache,
8748 : : int code_flags, PyObject *filename)
8749 : : {
8750 : 8041 : PyCodeObject *co = NULL;
8751 : 8041 : PyObject *consts = consts_dict_keys_inorder(u->u_consts);
8752 [ - + ]: 8041 : if (consts == NULL) {
8753 : 0 : goto error;
8754 : : }
8755 : : cfg_builder g;
8756 [ - + ]: 8041 : if (instr_sequence_to_cfg(&u->u_instr_sequence, &g) < 0) {
8757 : 0 : goto error;
8758 : : }
8759 : 8041 : int nparams = (int)PyList_GET_SIZE(u->u_ste->ste_varnames);
8760 : 8041 : int nlocals = (int)PyDict_GET_SIZE(u->u_varnames);
8761 [ - + ]: 8041 : if (optimize_code_unit(&g, consts, const_cache, code_flags, nlocals, nparams) < 0) {
8762 : 0 : goto error;
8763 : : }
8764 : :
8765 : : /** Assembly **/
8766 : :
8767 [ - + ]: 8041 : if (resolve_line_numbers(u, &g) < 0) {
8768 : 0 : goto error;
8769 : : }
8770 : :
8771 : 8041 : int nlocalsplus = prepare_localsplus(u, &g, code_flags);
8772 [ - + ]: 8041 : if (nlocalsplus < 0) {
8773 : 0 : goto error;
8774 : : }
8775 : :
8776 : 8041 : int maxdepth = stackdepth(g.g_entryblock, code_flags);
8777 [ - + ]: 8041 : if (maxdepth < 0) {
8778 : 0 : goto error;
8779 : : }
8780 : : /* TO DO -- For 3.12, make sure that `maxdepth <= MAX_ALLOWED_STACK_USE` */
8781 : :
8782 : 8041 : convert_exception_handlers_to_nops(g.g_entryblock);
8783 : :
8784 : : /* Order of basic blocks must have been determined by now */
8785 [ - + ]: 8041 : if (normalize_jumps(&g) < 0) {
8786 : 0 : goto error;
8787 : : }
8788 : : assert(no_redundant_jumps(&g));
8789 : : assert(opcode_metadata_is_sane(&g));
8790 : :
8791 : : /* Can't modify the bytecode after computing jump offsets. */
8792 : 8041 : assemble_jump_offsets(g.g_entryblock);
8793 : :
8794 : : struct assembler a;
8795 : 8041 : int res = assemble_emit(&a, g.g_entryblock, u->u_firstlineno, const_cache);
8796 [ + - ]: 8041 : if (res == SUCCESS) {
8797 : 8041 : co = makecode(u, &a, const_cache, consts, maxdepth, nlocalsplus,
8798 : : code_flags, filename);
8799 : : }
8800 : 8041 : assemble_free(&a);
8801 : :
8802 : 8041 : error:
8803 : 8041 : Py_XDECREF(consts);
8804 : 8041 : cfg_builder_fini(&g);
8805 : 8041 : return co;
8806 : : }
8807 : :
8808 : : static PyCodeObject *
8809 : 8041 : assemble(struct compiler *c, int addNone)
8810 : : {
8811 : 8041 : struct compiler_unit *u = c->u;
8812 : 8041 : PyObject *const_cache = c->c_const_cache;
8813 : 8041 : PyObject *filename = c->c_filename;
8814 : :
8815 : 8041 : int code_flags = compute_code_flags(c);
8816 [ - + ]: 8041 : if (code_flags < 0) {
8817 : 0 : return NULL;
8818 : : }
8819 : :
8820 [ - + ]: 8041 : if (add_return_at_end(c, addNone) < 0) {
8821 : 0 : return NULL;
8822 : : }
8823 : :
8824 : 8041 : return assemble_code_unit(u, const_cache, code_flags, filename);
8825 : : }
8826 : :
8827 : : static PyObject*
8828 : 3579 : get_const_value(int opcode, int oparg, PyObject *co_consts)
8829 : : {
8830 : 3579 : PyObject *constant = NULL;
8831 : : assert(HAS_CONST(opcode));
8832 [ + - ]: 3579 : if (opcode == LOAD_CONST) {
8833 : 3579 : constant = PyList_GET_ITEM(co_consts, oparg);
8834 : : }
8835 : :
8836 [ - + ]: 3579 : if (constant == NULL) {
8837 : 0 : PyErr_SetString(PyExc_SystemError,
8838 : : "Internal error: failed to get value of a constant");
8839 : 0 : return NULL;
8840 : : }
8841 : 3579 : return Py_NewRef(constant);
8842 : : }
8843 : :
8844 : : /* Replace LOAD_CONST c1, LOAD_CONST c2 ... LOAD_CONST cn, BUILD_TUPLE n
8845 : : with LOAD_CONST (c1, c2, ... cn).
8846 : : The consts table must still be in list form so that the
8847 : : new constant (c1, c2, ... cn) can be appended.
8848 : : Called with codestr pointing to the first LOAD_CONST.
8849 : : */
8850 : : static int
8851 : 3656 : fold_tuple_on_constants(PyObject *const_cache,
8852 : : struct cfg_instr *inst,
8853 : : int n, PyObject *consts)
8854 : : {
8855 : : /* Pre-conditions */
8856 : : assert(PyDict_CheckExact(const_cache));
8857 : : assert(PyList_CheckExact(consts));
8858 : : assert(inst[n].i_opcode == BUILD_TUPLE);
8859 : : assert(inst[n].i_oparg == n);
8860 : :
8861 [ + + ]: 5606 : for (int i = 0; i < n; i++) {
8862 [ + + + - : 4706 : if (!HAS_CONST(inst[i].i_opcode)) {
+ + ]
8863 : 2756 : return SUCCESS;
8864 : : }
8865 : : }
8866 : :
8867 : : /* Buildup new tuple of constants */
8868 : 900 : PyObject *newconst = PyTuple_New(n);
8869 [ - + ]: 900 : if (newconst == NULL) {
8870 : 0 : return ERROR;
8871 : : }
8872 [ + + ]: 2412 : for (int i = 0; i < n; i++) {
8873 : 1512 : int op = inst[i].i_opcode;
8874 : 1512 : int arg = inst[i].i_oparg;
8875 : 1512 : PyObject *constant = get_const_value(op, arg, consts);
8876 [ - + ]: 1512 : if (constant == NULL) {
8877 : 0 : return ERROR;
8878 : : }
8879 : 1512 : PyTuple_SET_ITEM(newconst, i, constant);
8880 : : }
8881 [ - + ]: 900 : if (merge_const_one(const_cache, &newconst) < 0) {
8882 : 0 : Py_DECREF(newconst);
8883 : 0 : return ERROR;
8884 : : }
8885 : :
8886 : : Py_ssize_t index;
8887 [ + + ]: 60079 : for (index = 0; index < PyList_GET_SIZE(consts); index++) {
8888 [ + + ]: 59427 : if (PyList_GET_ITEM(consts, index) == newconst) {
8889 : 248 : break;
8890 : : }
8891 : : }
8892 [ + + ]: 900 : if (index == PyList_GET_SIZE(consts)) {
8893 [ - + ]: 652 : if ((size_t)index >= (size_t)INT_MAX - 1) {
8894 : 0 : Py_DECREF(newconst);
8895 : 0 : PyErr_SetString(PyExc_OverflowError, "too many constants");
8896 : 0 : return ERROR;
8897 : : }
8898 [ - + ]: 652 : if (PyList_Append(consts, newconst)) {
8899 : 0 : Py_DECREF(newconst);
8900 : 0 : return ERROR;
8901 : : }
8902 : : }
8903 : 900 : Py_DECREF(newconst);
8904 [ + + ]: 2412 : for (int i = 0; i < n; i++) {
8905 : 1512 : INSTR_SET_OP0(&inst[i], NOP);
8906 : : }
8907 : 900 : INSTR_SET_OP1(&inst[n], LOAD_CONST, (int)index);
8908 : 900 : return SUCCESS;
8909 : : }
8910 : :
8911 : : #define VISITED (-1)
8912 : :
8913 : : // Replace an arbitrary run of SWAPs and NOPs with an optimal one that has the
8914 : : // same effect.
8915 : : static int
8916 : 774 : swaptimize(basicblock *block, int *ix)
8917 : : {
8918 : : // NOTE: "./python -m test test_patma" serves as a good, quick stress test
8919 : : // for this function. Make sure to blow away cached *.pyc files first!
8920 : : assert(*ix < block->b_iused);
8921 : 774 : struct cfg_instr *instructions = &block->b_instr[*ix];
8922 : : // Find the length of the current sequence of SWAPs and NOPs, and record the
8923 : : // maximum depth of the stack manipulations:
8924 : : assert(instructions[0].i_opcode == SWAP);
8925 : 774 : int depth = instructions[0].i_oparg;
8926 : 774 : int len = 0;
8927 : 774 : int more = false;
8928 : 774 : int limit = block->b_iused - *ix;
8929 [ + - ]: 792 : while (++len < limit) {
8930 : 792 : int opcode = instructions[len].i_opcode;
8931 [ + + ]: 792 : if (opcode == SWAP) {
8932 : 18 : depth = Py_MAX(depth, instructions[len].i_oparg);
8933 : 18 : more = true;
8934 : : }
8935 [ + - ]: 774 : else if (opcode != NOP) {
8936 : 774 : break;
8937 : : }
8938 : : }
8939 : : // It's already optimal if there's only one SWAP:
8940 [ + + ]: 774 : if (!more) {
8941 : 756 : return SUCCESS;
8942 : : }
8943 : : // Create an array with elements {0, 1, 2, ..., depth - 1}:
8944 : 18 : int *stack = PyMem_Malloc(depth * sizeof(int));
8945 [ - + ]: 18 : if (stack == NULL) {
8946 : 0 : PyErr_NoMemory();
8947 : 0 : return ERROR;
8948 : : }
8949 [ + + ]: 72 : for (int i = 0; i < depth; i++) {
8950 : 54 : stack[i] = i;
8951 : : }
8952 : : // Simulate the combined effect of these instructions by "running" them on
8953 : : // our "stack":
8954 [ + + ]: 54 : for (int i = 0; i < len; i++) {
8955 [ + - ]: 36 : if (instructions[i].i_opcode == SWAP) {
8956 : 36 : int oparg = instructions[i].i_oparg;
8957 : 36 : int top = stack[0];
8958 : : // SWAPs are 1-indexed:
8959 : 36 : stack[0] = stack[oparg - 1];
8960 : 36 : stack[oparg - 1] = top;
8961 : : }
8962 : : }
8963 : : // Now we can begin! Our approach here is based on a solution to a closely
8964 : : // related problem (https://cs.stackexchange.com/a/13938). It's easiest to
8965 : : // think of this algorithm as determining the steps needed to efficiently
8966 : : // "un-shuffle" our stack. By performing the moves in *reverse* order,
8967 : : // though, we can efficiently *shuffle* it! For this reason, we will be
8968 : : // replacing instructions starting from the *end* of the run. Since the
8969 : : // solution is optimal, we don't need to worry about running out of space:
8970 : 18 : int current = len - 1;
8971 [ + + ]: 72 : for (int i = 0; i < depth; i++) {
8972 : : // Skip items that have already been visited, or just happen to be in
8973 : : // the correct location:
8974 [ + + - + ]: 54 : if (stack[i] == VISITED || stack[i] == i) {
8975 : 36 : continue;
8976 : : }
8977 : : // Okay, we've found an item that hasn't been visited. It forms a cycle
8978 : : // with other items; traversing the cycle and swapping each item with
8979 : : // the next will put them all in the correct place. The weird
8980 : : // loop-and-a-half is necessary to insert 0 into every cycle, since we
8981 : : // can only swap from that position:
8982 : 18 : int j = i;
8983 : 54 : while (true) {
8984 : : // Skip the actual swap if our item is zero, since swapping the top
8985 : : // item with itself is pointless:
8986 [ + + ]: 72 : if (j) {
8987 : : assert(0 <= current);
8988 : : // SWAPs are 1-indexed:
8989 : 36 : instructions[current].i_opcode = SWAP;
8990 : 36 : instructions[current--].i_oparg = j + 1;
8991 : : }
8992 [ + + ]: 72 : if (stack[j] == VISITED) {
8993 : : // Completed the cycle:
8994 : : assert(j == i);
8995 : 18 : break;
8996 : : }
8997 : 54 : int next_j = stack[j];
8998 : 54 : stack[j] = VISITED;
8999 : 54 : j = next_j;
9000 : : }
9001 : : }
9002 : : // NOP out any unused instructions:
9003 [ - + ]: 18 : while (0 <= current) {
9004 : 0 : INSTR_SET_OP0(&instructions[current--], NOP);
9005 : : }
9006 : 18 : PyMem_Free(stack);
9007 : 18 : *ix += len - 1;
9008 : 18 : return SUCCESS;
9009 : : }
9010 : :
9011 : : // This list is pretty small, since it's only okay to reorder opcodes that:
9012 : : // - can't affect control flow (like jumping or raising exceptions)
9013 : : // - can't invoke arbitrary code (besides finalizers)
9014 : : // - only touch the TOS (and pop it when finished)
9015 : : #define SWAPPABLE(opcode) \
9016 : : ((opcode) == STORE_FAST || (opcode) == POP_TOP)
9017 : :
9018 : : static int
9019 : 1174 : next_swappable_instruction(basicblock *block, int i, int lineno)
9020 : : {
9021 [ + + ]: 1174 : while (++i < block->b_iused) {
9022 : 1170 : struct cfg_instr *instruction = &block->b_instr[i];
9023 [ + + + + ]: 1170 : if (0 <= lineno && instruction->i_loc.lineno != lineno) {
9024 : : // Optimizing across this instruction could cause user-visible
9025 : : // changes in the names bound between line tracing events!
9026 : 120 : return -1;
9027 : : }
9028 [ - + ]: 1050 : if (instruction->i_opcode == NOP) {
9029 : 0 : continue;
9030 : : }
9031 [ + + + + ]: 1050 : if (SWAPPABLE(instruction->i_opcode)) {
9032 : 528 : return i;
9033 : : }
9034 : 522 : return -1;
9035 : : }
9036 : 4 : return -1;
9037 : : }
9038 : :
9039 : : // Attempt to apply SWAPs statically by swapping *instructions* rather than
9040 : : // stack items. For example, we can replace SWAP(2), POP_TOP, STORE_FAST(42)
9041 : : // with the more efficient NOP, STORE_FAST(42), POP_TOP.
9042 : : static void
9043 : 774 : apply_static_swaps(basicblock *block, int i)
9044 : : {
9045 : : // SWAPs are to our left, and potential swaperands are to our right:
9046 [ + + ]: 1002 : for (; 0 <= i; i--) {
9047 : : assert(i < block->b_iused);
9048 : 974 : struct cfg_instr *swap = &block->b_instr[i];
9049 [ + + ]: 974 : if (swap->i_opcode != SWAP) {
9050 [ + + + - : 200 : if (swap->i_opcode == NOP || SWAPPABLE(swap->i_opcode)) {
- + ]
9051 : : // Nope, but we know how to handle these. Keep looking:
9052 : 100 : continue;
9053 : : }
9054 : : // We can't reason about what this instruction does. Bail:
9055 : 746 : return;
9056 : : }
9057 : 774 : int j = next_swappable_instruction(block, i, -1);
9058 [ + + ]: 774 : if (j < 0) {
9059 : 390 : return;
9060 : : }
9061 : 384 : int k = j;
9062 : 384 : int lineno = block->b_instr[j].i_loc.lineno;
9063 [ + + ]: 528 : for (int count = swap->i_oparg - 1; 0 < count; count--) {
9064 : 400 : k = next_swappable_instruction(block, k, lineno);
9065 [ + + ]: 400 : if (k < 0) {
9066 : 256 : return;
9067 : : }
9068 : : }
9069 : : // Success!
9070 : 128 : INSTR_SET_OP0(swap, NOP);
9071 : 128 : struct cfg_instr temp = block->b_instr[j];
9072 : 128 : block->b_instr[j] = block->b_instr[k];
9073 : 128 : block->b_instr[k] = temp;
9074 : : }
9075 : : }
9076 : :
9077 : : // Attempt to eliminate jumps to jumps by updating inst to jump to
9078 : : // target->i_target using the provided opcode. Return whether or not the
9079 : : // optimization was successful.
9080 : : static bool
9081 : 1741 : jump_thread(struct cfg_instr *inst, struct cfg_instr *target, int opcode)
9082 : : {
9083 : : assert(is_jump(inst));
9084 : : assert(is_jump(target));
9085 : : // bpo-45773: If inst->i_target == target->i_target, then nothing actually
9086 : : // changes (and we fall into an infinite loop):
9087 [ + + + + ]: 1741 : if ((inst->i_loc.lineno == target->i_loc.lineno || target->i_loc.lineno == -1) &&
9088 [ + - ]: 1686 : inst->i_target != target->i_target)
9089 : : {
9090 : 1686 : inst->i_target = target->i_target;
9091 : 1686 : inst->i_opcode = opcode;
9092 : 1686 : return true;
9093 : : }
9094 : 55 : return false;
9095 : : }
9096 : :
9097 : : /* Maximum size of basic block that should be copied in optimizer */
9098 : : #define MAX_COPY_SIZE 4
9099 : :
9100 : : /* Optimization */
9101 : : static int
9102 : 58917 : optimize_basic_block(PyObject *const_cache, basicblock *bb, PyObject *consts)
9103 : : {
9104 : : assert(PyDict_CheckExact(const_cache));
9105 : : assert(PyList_CheckExact(consts));
9106 : : struct cfg_instr nop;
9107 : 58917 : INSTR_SET_OP0(&nop, NOP);
9108 : : struct cfg_instr *target;
9109 [ + + ]: 439462 : for (int i = 0; i < bb->b_iused; i++) {
9110 : 380545 : struct cfg_instr *inst = &bb->b_instr[i];
9111 : 380545 : int oparg = inst->i_oparg;
9112 [ + + ]: 380545 : int nextop = i+1 < bb->b_iused ? bb->b_instr[i+1].i_opcode : 0;
9113 [ + + + + : 380545 : if (HAS_TARGET(inst->i_opcode)) {
+ + + + ]
9114 : : assert(inst->i_target->b_iused > 0);
9115 : 29208 : target = &inst->i_target->b_instr[0];
9116 : 29208 : assert(!IS_ASSEMBLER_OPCODE(target->i_opcode));
9117 : : }
9118 : : else {
9119 : 351337 : target = &nop;
9120 : : }
9121 : : assert(!IS_ASSEMBLER_OPCODE(inst->i_opcode));
9122 [ + + + + : 380545 : switch (inst->i_opcode) {
+ + + + +
+ + + + ]
9123 : : /* Remove LOAD_CONST const; conditional jump */
9124 [ + - + + : 59096 : case LOAD_CONST:
+ ]
9125 : : {
9126 : : PyObject* cnt;
9127 : : int is_true;
9128 : : int jump_if_true;
9129 : : switch(nextop) {
9130 : 225 : case POP_JUMP_IF_FALSE:
9131 : : case POP_JUMP_IF_TRUE:
9132 : 225 : cnt = get_const_value(inst->i_opcode, oparg, consts);
9133 [ - + ]: 225 : if (cnt == NULL) {
9134 : 0 : goto error;
9135 : : }
9136 : 225 : is_true = PyObject_IsTrue(cnt);
9137 : 225 : Py_DECREF(cnt);
9138 [ - + ]: 225 : if (is_true == -1) {
9139 : 0 : goto error;
9140 : : }
9141 : 225 : INSTR_SET_OP0(inst, NOP);
9142 : 225 : jump_if_true = nextop == POP_JUMP_IF_TRUE;
9143 [ + + ]: 225 : if (is_true == jump_if_true) {
9144 : 111 : bb->b_instr[i+1].i_opcode = JUMP;
9145 : : }
9146 : : else {
9147 : 114 : INSTR_SET_OP0(&bb->b_instr[i + 1], NOP);
9148 : : }
9149 : 225 : break;
9150 : 0 : case JUMP_IF_FALSE_OR_POP:
9151 : : case JUMP_IF_TRUE_OR_POP:
9152 : 0 : cnt = get_const_value(inst->i_opcode, oparg, consts);
9153 [ # # ]: 0 : if (cnt == NULL) {
9154 : 0 : goto error;
9155 : : }
9156 : 0 : is_true = PyObject_IsTrue(cnt);
9157 : 0 : Py_DECREF(cnt);
9158 [ # # ]: 0 : if (is_true == -1) {
9159 : 0 : goto error;
9160 : : }
9161 : 0 : jump_if_true = nextop == JUMP_IF_TRUE_OR_POP;
9162 [ # # ]: 0 : if (is_true == jump_if_true) {
9163 : 0 : bb->b_instr[i+1].i_opcode = JUMP;
9164 : : }
9165 : : else {
9166 : 0 : INSTR_SET_OP0(inst, NOP);
9167 : 0 : INSTR_SET_OP0(&bb->b_instr[i + 1], NOP);
9168 : : }
9169 : 0 : break;
9170 : 1842 : case IS_OP:
9171 : 1842 : cnt = get_const_value(inst->i_opcode, oparg, consts);
9172 [ - + ]: 1842 : if (cnt == NULL) {
9173 : 0 : goto error;
9174 : : }
9175 [ + + ]: 1842 : int jump_op = i+2 < bb->b_iused ? bb->b_instr[i+2].i_opcode : 0;
9176 [ + + + + : 1842 : if (Py_IsNone(cnt) && (jump_op == POP_JUMP_IF_FALSE || jump_op == POP_JUMP_IF_TRUE)) {
+ + ]
9177 : 1776 : unsigned char nextarg = bb->b_instr[i+1].i_oparg;
9178 : 1776 : INSTR_SET_OP0(inst, NOP);
9179 : 1776 : INSTR_SET_OP0(&bb->b_instr[i + 1], NOP);
9180 : 1776 : bb->b_instr[i+2].i_opcode = nextarg ^ (jump_op == POP_JUMP_IF_FALSE) ?
9181 [ + + ]: 1776 : POP_JUMP_IF_NOT_NONE : POP_JUMP_IF_NONE;
9182 : : }
9183 : 1842 : Py_DECREF(cnt);
9184 : 1842 : break;
9185 : 11689 : case RETURN_VALUE:
9186 : 11689 : INSTR_SET_OP0(inst, NOP);
9187 : 11689 : INSTR_SET_OP1(&bb->b_instr[++i], RETURN_CONST, oparg);
9188 : 11689 : break;
9189 : : }
9190 : 59096 : break;
9191 : : }
9192 : :
9193 : : /* Try to fold tuples of constants.
9194 : : Skip over BUILD_TUPLE(1) UNPACK_SEQUENCE(1).
9195 : : Replace BUILD_TUPLE(2) UNPACK_SEQUENCE(2) with SWAP(2).
9196 : : Replace BUILD_TUPLE(3) UNPACK_SEQUENCE(3) with SWAP(3). */
9197 : 3790 : case BUILD_TUPLE:
9198 [ + + + - ]: 3790 : if (nextop == UNPACK_SEQUENCE && oparg == bb->b_instr[i+1].i_oparg) {
9199 : : switch(oparg) {
9200 : 0 : case 1:
9201 : 0 : INSTR_SET_OP0(inst, NOP);
9202 : 0 : INSTR_SET_OP0(&bb->b_instr[i + 1], NOP);
9203 : 0 : continue;
9204 : 116 : case 2:
9205 : : case 3:
9206 : 116 : INSTR_SET_OP0(inst, NOP);
9207 : 116 : bb->b_instr[i+1].i_opcode = SWAP;
9208 : 116 : continue;
9209 : : }
9210 : : }
9211 [ + + ]: 3674 : if (i >= oparg) {
9212 [ - + ]: 3656 : if (fold_tuple_on_constants(const_cache, inst-oparg, oparg, consts)) {
9213 : 0 : goto error;
9214 : : }
9215 : : }
9216 : 3674 : break;
9217 : :
9218 : : /* Simplify conditional jump to conditional jump where the
9219 : : result of the first test implies the success of a similar
9220 : : test or the failure of the opposite test.
9221 : : Arises in code like:
9222 : : "a and b or c"
9223 : : "(a and b) and c"
9224 : : "(a or b) or c"
9225 : : "(a or b) and c"
9226 : : x:JUMP_IF_FALSE_OR_POP y y:JUMP_IF_FALSE_OR_POP z
9227 : : --> x:JUMP_IF_FALSE_OR_POP z
9228 : : x:JUMP_IF_FALSE_OR_POP y y:JUMP_IF_TRUE_OR_POP z
9229 : : --> x:POP_JUMP_IF_FALSE y+1
9230 : : where y+1 is the instruction following the second test.
9231 : : */
9232 : 198 : case JUMP_IF_FALSE_OR_POP:
9233 [ - - + + ]: 198 : switch (target->i_opcode) {
9234 : 0 : case POP_JUMP_IF_FALSE:
9235 : 0 : i -= jump_thread(inst, target, POP_JUMP_IF_FALSE);
9236 : 0 : break;
9237 : 0 : case JUMP:
9238 : : case JUMP_IF_FALSE_OR_POP:
9239 : 0 : i -= jump_thread(inst, target, JUMP_IF_FALSE_OR_POP);
9240 : 0 : break;
9241 : 23 : case JUMP_IF_TRUE_OR_POP:
9242 : : case POP_JUMP_IF_TRUE:
9243 [ + + ]: 23 : if (inst->i_loc.lineno == target->i_loc.lineno) {
9244 : : // We don't need to bother checking for loops here,
9245 : : // since a block's b_next cannot point to itself:
9246 : : assert(inst->i_target != inst->i_target->b_next);
9247 : 20 : inst->i_opcode = POP_JUMP_IF_FALSE;
9248 : 20 : inst->i_target = inst->i_target->b_next;
9249 : 20 : --i;
9250 : : }
9251 : 23 : break;
9252 : : }
9253 : 198 : break;
9254 : 260 : case JUMP_IF_TRUE_OR_POP:
9255 [ - - + + ]: 260 : switch (target->i_opcode) {
9256 : 0 : case POP_JUMP_IF_TRUE:
9257 : 0 : i -= jump_thread(inst, target, POP_JUMP_IF_TRUE);
9258 : 0 : break;
9259 : 0 : case JUMP:
9260 : : case JUMP_IF_TRUE_OR_POP:
9261 : 0 : i -= jump_thread(inst, target, JUMP_IF_TRUE_OR_POP);
9262 : 0 : break;
9263 : 3 : case JUMP_IF_FALSE_OR_POP:
9264 : : case POP_JUMP_IF_FALSE:
9265 [ + + ]: 3 : if (inst->i_loc.lineno == target->i_loc.lineno) {
9266 : : // We don't need to bother checking for loops here,
9267 : : // since a block's b_next cannot point to itself:
9268 : : assert(inst->i_target != inst->i_target->b_next);
9269 : 1 : inst->i_opcode = POP_JUMP_IF_TRUE;
9270 : 1 : inst->i_target = inst->i_target->b_next;
9271 : 1 : --i;
9272 : : }
9273 : 3 : break;
9274 : : }
9275 : 260 : break;
9276 : 1858 : case POP_JUMP_IF_NOT_NONE:
9277 : : case POP_JUMP_IF_NONE:
9278 [ + + ]: 1858 : switch (target->i_opcode) {
9279 : 88 : case JUMP:
9280 : 88 : i -= jump_thread(inst, target, inst->i_opcode);
9281 : : }
9282 : 1858 : break;
9283 : 9842 : case POP_JUMP_IF_FALSE:
9284 [ + + ]: 9842 : switch (target->i_opcode) {
9285 : 770 : case JUMP:
9286 : 770 : i -= jump_thread(inst, target, POP_JUMP_IF_FALSE);
9287 : : }
9288 : 9842 : break;
9289 : 2568 : case POP_JUMP_IF_TRUE:
9290 [ + + ]: 2568 : switch (target->i_opcode) {
9291 : 102 : case JUMP:
9292 : 102 : i -= jump_thread(inst, target, POP_JUMP_IF_TRUE);
9293 : : }
9294 : 2568 : break;
9295 : 7643 : case JUMP:
9296 [ + + ]: 7643 : switch (target->i_opcode) {
9297 : 781 : case JUMP:
9298 : 781 : i -= jump_thread(inst, target, JUMP);
9299 : : }
9300 : 7643 : break;
9301 : 1707 : case FOR_ITER:
9302 : 1707 : if (target->i_opcode == JUMP) {
9303 : : /* This will not work now because the jump (at target) could
9304 : : * be forward or backward and FOR_ITER only jumps forward. We
9305 : : * can re-enable this if ever we implement a backward version
9306 : : * of FOR_ITER.
9307 : : */
9308 : : /*
9309 : : i -= jump_thread(inst, target, FOR_ITER);
9310 : : */
9311 : : }
9312 : 1707 : break;
9313 : 774 : case SWAP:
9314 [ - + ]: 774 : if (oparg == 1) {
9315 : 0 : INSTR_SET_OP0(inst, NOP);
9316 : 0 : break;
9317 : : }
9318 [ - + ]: 774 : if (swaptimize(bb, &i) < 0) {
9319 : 0 : goto error;
9320 : : }
9321 : 774 : apply_static_swaps(bb, i);
9322 : 774 : break;
9323 : 1196 : case KW_NAMES:
9324 : 1196 : break;
9325 : 16270 : case PUSH_NULL:
9326 [ + + + - ]: 16270 : if (nextop == LOAD_GLOBAL && (inst[1].i_opcode & 1) == 0) {
9327 : 12538 : INSTR_SET_OP0(inst, NOP);
9328 : 12538 : inst[1].i_oparg |= 1;
9329 : : }
9330 : 16270 : break;
9331 : 380545 : default:
9332 : : /* All HAS_CONST opcodes should be handled with LOAD_CONST */
9333 : : assert (!HAS_CONST(inst->i_opcode));
9334 : : }
9335 : : }
9336 : 58917 : return SUCCESS;
9337 : 0 : error:
9338 : 0 : return ERROR;
9339 : : }
9340 : :
9341 : : /* If this block ends with an unconditional jump to a small exit block, then
9342 : : * remove the jump and extend this block with the target.
9343 : : * Returns 1 if extended, 0 if no change, and -1 on error.
9344 : : */
9345 : : static int
9346 : 117834 : inline_small_exit_blocks(basicblock *bb) {
9347 : 117834 : struct cfg_instr *last = basicblock_last_instr(bb);
9348 [ + + ]: 117834 : if (last == NULL) {
9349 : 2 : return 0;
9350 : : }
9351 [ + + + + : 117832 : if (!IS_UNCONDITIONAL_JUMP_OPCODE(last->i_opcode)) {
+ - + - +
- ]
9352 : 101919 : return 0;
9353 : : }
9354 : 15913 : basicblock *target = last->i_target;
9355 [ + + + + ]: 15913 : if (basicblock_exits_scope(target) && target->b_iused <= MAX_COPY_SIZE) {
9356 : 2155 : INSTR_SET_OP0(last, NOP);
9357 [ - + ]: 2155 : RETURN_IF_ERROR(basicblock_append_instructions(bb, target));
9358 : 2155 : return 1;
9359 : : }
9360 : 13758 : return 0;
9361 : : }
9362 : :
9363 : : static int
9364 : 169145 : remove_redundant_nops(basicblock *bb) {
9365 : : /* Remove NOPs when legal to do so. */
9366 : 169145 : int dest = 0;
9367 : 169145 : int prev_lineno = -1;
9368 [ + + ]: 1255026 : for (int src = 0; src < bb->b_iused; src++) {
9369 : 1085881 : int lineno = bb->b_instr[src].i_loc.lineno;
9370 [ + + ]: 1085881 : if (bb->b_instr[src].i_opcode == NOP) {
9371 : : /* Eliminate no-op if it doesn't have a line number */
9372 [ + + ]: 44398 : if (lineno < 0) {
9373 : 14631 : continue;
9374 : : }
9375 : : /* or, if the previous instruction had the same line number. */
9376 [ + + ]: 29767 : if (prev_lineno == lineno) {
9377 : 10829 : continue;
9378 : : }
9379 : : /* or, if the next instruction has same line number or no line number */
9380 [ + + ]: 18938 : if (src < bb->b_iused - 1) {
9381 : 17062 : int next_lineno = bb->b_instr[src+1].i_loc.lineno;
9382 [ + + ]: 17062 : if (next_lineno == lineno) {
9383 : 15529 : continue;
9384 : : }
9385 [ + + ]: 1533 : if (next_lineno < 0) {
9386 : 620 : bb->b_instr[src+1].i_loc = bb->b_instr[src].i_loc;
9387 : 620 : continue;
9388 : : }
9389 : : }
9390 : : else {
9391 : 1876 : basicblock* next = bb->b_next;
9392 [ + - - + ]: 1876 : while (next && next->b_iused == 0) {
9393 : 0 : next = next->b_next;
9394 : : }
9395 : : /* or if last instruction in BB and next BB has same line number */
9396 [ + - ]: 1876 : if (next) {
9397 [ + + ]: 1876 : if (lineno == next->b_instr[0].i_loc.lineno) {
9398 : 26 : continue;
9399 : : }
9400 : : }
9401 : : }
9402 : :
9403 : : }
9404 [ + + ]: 1044246 : if (dest != src) {
9405 : 150272 : bb->b_instr[dest] = bb->b_instr[src];
9406 : : }
9407 : 1044246 : dest++;
9408 : 1044246 : prev_lineno = lineno;
9409 : : }
9410 : : assert(dest <= bb->b_iused);
9411 : 169145 : int num_removed = bb->b_iused - dest;
9412 : 169145 : bb->b_iused = dest;
9413 : 169145 : return num_removed;
9414 : : }
9415 : :
9416 : : static int
9417 : 8041 : check_cfg(cfg_builder *g) {
9418 [ + + ]: 69608 : for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
9419 : : /* Raise SystemError if jump or exit is not last instruction in the block. */
9420 [ + + ]: 448179 : for (int i = 0; i < b->b_iused; i++) {
9421 : 386612 : int opcode = b->b_instr[i].i_opcode;
9422 : : assert(!IS_ASSEMBLER_OPCODE(opcode));
9423 [ + + + + : 386612 : if (IS_TERMINATOR_OPCODE(opcode)) {
+ - + + +
+ ]
9424 [ - + ]: 47043 : if (i != b->b_iused - 1) {
9425 : 0 : PyErr_SetString(PyExc_SystemError, "malformed control flow graph.");
9426 : 0 : return ERROR;
9427 : : }
9428 : : }
9429 : : }
9430 : : }
9431 : 8041 : return SUCCESS;
9432 : : }
9433 : :
9434 : : static int
9435 : 8041 : mark_reachable(basicblock *entryblock) {
9436 : 8041 : basicblock **stack = make_cfg_traversal_stack(entryblock);
9437 [ - + ]: 8041 : if (stack == NULL) {
9438 : 0 : return ERROR;
9439 : : }
9440 : 8041 : basicblock **sp = stack;
9441 : 8041 : entryblock->b_predecessors = 1;
9442 : 8041 : *sp++ = entryblock;
9443 [ + + ]: 58659 : while (sp > stack) {
9444 : 50618 : basicblock *b = *(--sp);
9445 : 50618 : b->b_visited = 1;
9446 [ + + + + ]: 50618 : if (b->b_next && BB_HAS_FALLTHROUGH(b)) {
9447 [ + + ]: 27620 : if (!b->b_next->b_visited) {
9448 : : assert(b->b_next->b_predecessors == 0);
9449 : 23751 : *sp++ = b->b_next;
9450 : : }
9451 : 27620 : b->b_next->b_predecessors++;
9452 : : }
9453 [ + + ]: 396779 : for (int i = 0; i < b->b_iused; i++) {
9454 : : basicblock *target;
9455 : 346161 : struct cfg_instr *instr = &b->b_instr[i];
9456 [ + + + + ]: 346161 : if (is_jump(instr) || is_block_push(instr)) {
9457 : 26115 : target = instr->i_target;
9458 [ + + ]: 26115 : if (!target->b_visited) {
9459 : : assert(target->b_predecessors == 0 || target == b->b_next);
9460 : 18826 : *sp++ = target;
9461 : : }
9462 : 26115 : target->b_predecessors++;
9463 : : }
9464 : : }
9465 : : }
9466 : 8041 : PyMem_Free(stack);
9467 : 8041 : return SUCCESS;
9468 : : }
9469 : :
9470 : : static void
9471 : 16082 : eliminate_empty_basic_blocks(cfg_builder *g) {
9472 : : /* Eliminate empty blocks */
9473 [ + + ]: 125615 : for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
9474 : 109533 : basicblock *next = b->b_next;
9475 [ + + + + ]: 120484 : while (next && next->b_iused == 0) {
9476 : 10951 : next = next->b_next;
9477 : : }
9478 : 109533 : b->b_next = next;
9479 : : }
9480 [ + - - + ]: 16082 : while(g->g_entryblock && g->g_entryblock->b_iused == 0) {
9481 : 0 : g->g_entryblock = g->g_entryblock->b_next;
9482 : : }
9483 [ + + ]: 125615 : for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
9484 : : assert(b->b_iused > 0);
9485 [ + + ]: 842148 : for (int i = 0; i < b->b_iused; i++) {
9486 : 732615 : struct cfg_instr *instr = &b->b_instr[i];
9487 [ + + + + : 732615 : if (HAS_TARGET(instr->i_opcode)) {
+ + + + ]
9488 : 55640 : basicblock *target = instr->i_target;
9489 [ + + ]: 59816 : while (target->b_iused == 0) {
9490 : 4176 : target = target->b_next;
9491 : : }
9492 : 55640 : instr->i_target = target;
9493 : : assert(instr->i_target && instr->i_target->b_iused > 0);
9494 : : }
9495 : : }
9496 : : }
9497 : 16082 : }
9498 : :
9499 : :
9500 : : /* If an instruction has no line number, but it's predecessor in the BB does,
9501 : : * then copy the line number. If a successor block has no line number, and only
9502 : : * one predecessor, then inherit the line number.
9503 : : * This ensures that all exit blocks (with one predecessor) receive a line number.
9504 : : * Also reduces the size of the line number table,
9505 : : * but has no impact on the generated line number events.
9506 : : */
9507 : : static void
9508 : 8041 : propagate_line_numbers(basicblock *entryblock) {
9509 [ + + ]: 59352 : for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
9510 : 51311 : struct cfg_instr *last = basicblock_last_instr(b);
9511 [ - + ]: 51311 : if (last == NULL) {
9512 : 0 : continue;
9513 : : }
9514 : :
9515 : 51311 : location prev_location = NO_LOCATION;
9516 [ + + ]: 398096 : for (int i = 0; i < b->b_iused; i++) {
9517 [ + + ]: 346785 : if (b->b_instr[i].i_loc.lineno < 0) {
9518 : 32742 : b->b_instr[i].i_loc = prev_location;
9519 : : }
9520 : : else {
9521 : 314043 : prev_location = b->b_instr[i].i_loc;
9522 : : }
9523 : : }
9524 [ + + + + ]: 51311 : if (BB_HAS_FALLTHROUGH(b) && b->b_next->b_predecessors == 1) {
9525 : : assert(b->b_next->b_iused);
9526 [ + + ]: 21271 : if (b->b_next->b_instr[0].i_loc.lineno < 0) {
9527 : 1752 : b->b_next->b_instr[0].i_loc = prev_location;
9528 : : }
9529 : : }
9530 [ + + ]: 51311 : if (is_jump(last)) {
9531 : 20694 : basicblock *target = last->i_target;
9532 [ + + ]: 20694 : if (target->b_predecessors == 1) {
9533 [ + + ]: 9137 : if (target->b_instr[0].i_loc.lineno < 0) {
9534 : 3522 : target->b_instr[0].i_loc = prev_location;
9535 : : }
9536 : : }
9537 : : }
9538 : : }
9539 : 8041 : }
9540 : :
9541 : :
9542 : : /* Calculate the actual jump target from the target_label */
9543 : : static int
9544 : 8041 : translate_jump_labels_to_targets(basicblock *entryblock)
9545 : : {
9546 : 8041 : int max_label = -1;
9547 [ + + ]: 69608 : for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
9548 [ + + ]: 61567 : if (b->b_label.id > max_label) {
9549 : 20366 : max_label = b->b_label.id;
9550 : : }
9551 : : }
9552 : 8041 : size_t mapsize = sizeof(basicblock *) * (max_label + 1);
9553 : 8041 : basicblock **label2block = (basicblock **)PyMem_Malloc(mapsize);
9554 [ - + ]: 8041 : if (!label2block) {
9555 : 0 : PyErr_NoMemory();
9556 : 0 : return ERROR;
9557 : : }
9558 : 8041 : memset(label2block, 0, mapsize);
9559 [ + + ]: 69608 : for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
9560 [ + + ]: 61567 : if (b->b_label.id >= 0) {
9561 : 33597 : label2block[b->b_label.id] = b;
9562 : : }
9563 : : }
9564 [ + + ]: 69608 : for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
9565 [ + + ]: 448179 : for (int i = 0; i < b->b_iused; i++) {
9566 : 386612 : struct cfg_instr *instr = &b->b_instr[i];
9567 : : assert(instr->i_target == NULL);
9568 [ + + + + : 386612 : if (HAS_TARGET(instr->i_opcode)) {
+ + + + ]
9569 : 29525 : int lbl = instr->i_oparg;
9570 : : assert(lbl >= 0 && lbl <= max_label);
9571 : 29525 : instr->i_target = label2block[lbl];
9572 : : assert(instr->i_target != NULL);
9573 : : assert(instr->i_target->b_label.id == lbl);
9574 : : }
9575 : : }
9576 : : }
9577 : 8041 : PyMem_Free(label2block);
9578 : 8041 : return SUCCESS;
9579 : : }
9580 : :
9581 : : /* Perform optimizations on a control flow graph.
9582 : : The consts object should still be in list form to allow new constants
9583 : : to be appended.
9584 : :
9585 : : Code trasnformations that reduce code size initially fill the gaps with
9586 : : NOPs. Later those NOPs are removed.
9587 : : */
9588 : :
9589 : : static int
9590 : 8041 : optimize_cfg(cfg_builder *g, PyObject *consts, PyObject *const_cache)
9591 : : {
9592 : : assert(PyDict_CheckExact(const_cache));
9593 [ - + ]: 8041 : RETURN_IF_ERROR(check_cfg(g));
9594 : 8041 : eliminate_empty_basic_blocks(g);
9595 [ + + ]: 66958 : for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
9596 [ - + ]: 58917 : RETURN_IF_ERROR(inline_small_exit_blocks(b));
9597 : : }
9598 : : assert(no_empty_basic_blocks(g));
9599 [ + + ]: 66958 : for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
9600 [ - + ]: 58917 : RETURN_IF_ERROR(optimize_basic_block(const_cache, b, consts));
9601 : 58917 : remove_redundant_nops(b);
9602 : : assert(b->b_predecessors == 0);
9603 : : }
9604 [ + + ]: 66958 : for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
9605 [ - + ]: 58917 : RETURN_IF_ERROR(inline_small_exit_blocks(b));
9606 : : }
9607 [ - + ]: 8041 : RETURN_IF_ERROR(mark_reachable(g->g_entryblock));
9608 : :
9609 : : /* Delete unreachable instructions */
9610 [ + + ]: 66958 : for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
9611 [ + + ]: 58917 : if (b->b_predecessors == 0) {
9612 : 8299 : b->b_iused = 0;
9613 : : }
9614 : : }
9615 [ + + ]: 66958 : for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
9616 : 58917 : remove_redundant_nops(b);
9617 : : }
9618 : 8041 : eliminate_empty_basic_blocks(g);
9619 : : assert(no_redundant_nops(g));
9620 [ - + ]: 8041 : RETURN_IF_ERROR(remove_redundant_jumps(g));
9621 : 8041 : return SUCCESS;
9622 : : }
9623 : :
9624 : :
9625 : : static int
9626 : 8041 : remove_unused_consts(basicblock *entryblock, PyObject *consts)
9627 : : {
9628 : : assert(PyList_CheckExact(consts));
9629 : 8041 : Py_ssize_t nconsts = PyList_GET_SIZE(consts);
9630 [ - + ]: 8041 : if (nconsts == 0) {
9631 : 0 : return SUCCESS; /* nothing to do */
9632 : : }
9633 : :
9634 : 8041 : Py_ssize_t *index_map = NULL;
9635 : 8041 : Py_ssize_t *reverse_index_map = NULL;
9636 : 8041 : int err = ERROR;
9637 : :
9638 : 8041 : index_map = PyMem_Malloc(nconsts * sizeof(Py_ssize_t));
9639 [ - + ]: 8041 : if (index_map == NULL) {
9640 : 0 : goto end;
9641 : : }
9642 [ + + ]: 42935 : for (Py_ssize_t i = 1; i < nconsts; i++) {
9643 : 34894 : index_map[i] = -1;
9644 : : }
9645 : : // The first constant may be docstring; keep it always.
9646 : 8041 : index_map[0] = 0;
9647 : :
9648 : : /* mark used consts */
9649 [ + + ]: 58657 : for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
9650 [ + + ]: 396619 : for (int i = 0; i < b->b_iused; i++) {
9651 [ + + + + : 346003 : if (HAS_CONST(b->b_instr[i].i_opcode)) {
+ + ]
9652 : 50633 : int index = b->b_instr[i].i_oparg;
9653 : 50633 : index_map[index] = index;
9654 : : }
9655 : : }
9656 : : }
9657 : : /* now index_map[i] == i if consts[i] is used, -1 otherwise */
9658 : :
9659 : : /* condense consts */
9660 : 8041 : Py_ssize_t n_used_consts = 0;
9661 [ + + ]: 50976 : for (int i = 0; i < nconsts; i++) {
9662 [ + + ]: 42935 : if (index_map[i] != -1) {
9663 : : assert(index_map[i] == i);
9664 : 41021 : index_map[n_used_consts++] = index_map[i];
9665 : : }
9666 : : }
9667 [ + + ]: 8041 : if (n_used_consts == nconsts) {
9668 : : /* nothing to do */
9669 : 6315 : err = SUCCESS;
9670 : 6315 : goto end;
9671 : : }
9672 : :
9673 : : /* move all used consts to the beginning of the consts list */
9674 : : assert(n_used_consts < nconsts);
9675 [ + + ]: 13141 : for (Py_ssize_t i = 0; i < n_used_consts; i++) {
9676 : 11415 : Py_ssize_t old_index = index_map[i];
9677 : : assert(i <= old_index && old_index < nconsts);
9678 [ + + ]: 11415 : if (i != old_index) {
9679 : 5660 : PyObject *value = PyList_GET_ITEM(consts, index_map[i]);
9680 : : assert(value != NULL);
9681 : 5660 : PyList_SetItem(consts, i, Py_NewRef(value));
9682 : : }
9683 : : }
9684 : :
9685 : : /* truncate the consts list at its new size */
9686 [ - + ]: 1726 : if (PyList_SetSlice(consts, n_used_consts, nconsts, NULL) < 0) {
9687 : 0 : goto end;
9688 : : }
9689 : :
9690 : : /* adjust const indices in the bytecode */
9691 : 1726 : reverse_index_map = PyMem_Malloc(nconsts * sizeof(Py_ssize_t));
9692 [ - + ]: 1726 : if (reverse_index_map == NULL) {
9693 : 0 : goto end;
9694 : : }
9695 [ + + ]: 15055 : for (Py_ssize_t i = 0; i < nconsts; i++) {
9696 : 13329 : reverse_index_map[i] = -1;
9697 : : }
9698 [ + + ]: 13141 : for (Py_ssize_t i = 0; i < n_used_consts; i++) {
9699 : : assert(index_map[i] != -1);
9700 : : assert(reverse_index_map[index_map[i]] == -1);
9701 : 11415 : reverse_index_map[index_map[i]] = i;
9702 : : }
9703 : :
9704 [ + + ]: 10610 : for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
9705 [ + + ]: 81122 : for (int i = 0; i < b->b_iused; i++) {
9706 [ + + + + : 72238 : if (HAS_CONST(b->b_instr[i].i_opcode)) {
+ + ]
9707 : 12700 : int index = b->b_instr[i].i_oparg;
9708 : : assert(reverse_index_map[index] >= 0);
9709 : : assert(reverse_index_map[index] < n_used_consts);
9710 : 12700 : b->b_instr[i].i_oparg = (int)reverse_index_map[index];
9711 : : }
9712 : : }
9713 : : }
9714 : :
9715 : 1726 : err = SUCCESS;
9716 : 8041 : end:
9717 : 8041 : PyMem_Free(index_map);
9718 : 8041 : PyMem_Free(reverse_index_map);
9719 : 8041 : return err;
9720 : : }
9721 : :
9722 : : static inline bool
9723 : 49183 : is_exit_without_lineno(basicblock *b) {
9724 [ + + ]: 49183 : if (!basicblock_exits_scope(b)) {
9725 : 35956 : return false;
9726 : : }
9727 [ + + ]: 18439 : for (int i = 0; i < b->b_iused; i++) {
9728 [ + + ]: 15101 : if (b->b_instr[i].i_loc.lineno >= 0) {
9729 : 9889 : return false;
9730 : : }
9731 : : }
9732 : 3338 : return true;
9733 : : }
9734 : :
9735 : : /* PEP 626 mandates that the f_lineno of a frame is correct
9736 : : * after a frame terminates. It would be prohibitively expensive
9737 : : * to continuously update the f_lineno field at runtime,
9738 : : * so we make sure that all exiting instruction (raises and returns)
9739 : : * have a valid line number, allowing us to compute f_lineno lazily.
9740 : : * We can do this by duplicating the exit blocks without line number
9741 : : * so that none have more than one predecessor. We can then safely
9742 : : * copy the line number from the sole predecessor block.
9743 : : */
9744 : : static int
9745 : 8041 : duplicate_exits_without_lineno(cfg_builder *g)
9746 : : {
9747 : : assert(no_empty_basic_blocks(g));
9748 : : /* Copy all exit blocks without line number that are targets of a jump.
9749 : : */
9750 : 8041 : basicblock *entryblock = g->g_entryblock;
9751 [ + + ]: 59351 : for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
9752 : 51310 : struct cfg_instr *last = basicblock_last_instr(b);
9753 : : assert(last != NULL);
9754 [ + + ]: 51310 : if (is_jump(last)) {
9755 : 20694 : basicblock *target = last->i_target;
9756 [ + + + + ]: 20694 : if (is_exit_without_lineno(target) && target->b_predecessors > 1) {
9757 : 514 : basicblock *new_target = copy_basicblock(g, target);
9758 [ - + ]: 514 : if (new_target == NULL) {
9759 : 0 : return ERROR;
9760 : : }
9761 : 514 : new_target->b_instr[0].i_loc = last->i_loc;
9762 : 514 : last->i_target = new_target;
9763 : 514 : target->b_predecessors--;
9764 : 514 : new_target->b_predecessors = 1;
9765 : 514 : new_target->b_next = target->b_next;
9766 : 514 : target->b_next = new_target;
9767 : : }
9768 : : }
9769 : : }
9770 : :
9771 : : /* Any remaining reachable exit blocks without line number can only be reached by
9772 : : * fall through, and thus can only have a single predecessor */
9773 [ + + ]: 59352 : for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
9774 [ + + + - : 51311 : if (BB_HAS_FALLTHROUGH(b) && b->b_next && b->b_iused > 0) {
+ - ]
9775 [ + + ]: 28489 : if (is_exit_without_lineno(b->b_next)) {
9776 : 1096 : struct cfg_instr *last = basicblock_last_instr(b);
9777 : : assert(last != NULL);
9778 : 1096 : b->b_next->b_instr[0].i_loc = last->i_loc;
9779 : : }
9780 : : }
9781 : : }
9782 : 8041 : return SUCCESS;
9783 : : }
9784 : :
9785 : :
9786 : : /* Access to compiler optimizations for unit tests.
9787 : : *
9788 : : * _PyCompile_CodeGen takes and AST, applies code-gen and
9789 : : * returns the unoptimized CFG as an instruction list.
9790 : : *
9791 : : * _PyCompile_OptimizeCfg takes an instruction list, constructs
9792 : : * a CFG, optimizes it and converts back to an instruction list.
9793 : : *
9794 : : * An instruction list is a PyList where each item is either
9795 : : * a tuple describing a single instruction:
9796 : : * (opcode, oparg, lineno, end_lineno, col, end_col), or
9797 : : * a jump target label marking the beginning of a basic block.
9798 : : */
9799 : :
9800 : : static int
9801 : 0 : instructions_to_cfg(PyObject *instructions, cfg_builder *g)
9802 : : {
9803 : : assert(PyList_Check(instructions));
9804 : :
9805 : 0 : Py_ssize_t num_insts = PyList_GET_SIZE(instructions);
9806 : 0 : bool *is_target = PyMem_Calloc(num_insts, sizeof(bool));
9807 [ # # ]: 0 : if (is_target == NULL) {
9808 : 0 : return ERROR;
9809 : : }
9810 [ # # ]: 0 : for (Py_ssize_t i = 0; i < num_insts; i++) {
9811 : 0 : PyObject *item = PyList_GET_ITEM(instructions, i);
9812 [ # # # # ]: 0 : if (!PyTuple_Check(item) || PyTuple_GET_SIZE(item) != 6) {
9813 : 0 : PyErr_SetString(PyExc_ValueError, "expected a 6-tuple");
9814 : 0 : goto error;
9815 : : }
9816 : 0 : int opcode = PyLong_AsLong(PyTuple_GET_ITEM(item, 0));
9817 [ # # ]: 0 : if (PyErr_Occurred()) {
9818 : 0 : goto error;
9819 : : }
9820 [ # # # # : 0 : if (HAS_TARGET(opcode)) {
# # # # ]
9821 : 0 : int oparg = PyLong_AsLong(PyTuple_GET_ITEM(item, 1));
9822 [ # # ]: 0 : if (PyErr_Occurred()) {
9823 : 0 : goto error;
9824 : : }
9825 [ # # # # ]: 0 : if (oparg < 0 || oparg >= num_insts) {
9826 : 0 : PyErr_SetString(PyExc_ValueError, "label out of range");
9827 : 0 : goto error;
9828 : : }
9829 : 0 : is_target[oparg] = true;
9830 : : }
9831 : : }
9832 : :
9833 [ # # ]: 0 : for (int i = 0; i < num_insts; i++) {
9834 [ # # ]: 0 : if (is_target[i]) {
9835 : 0 : jump_target_label lbl = {i};
9836 [ # # ]: 0 : RETURN_IF_ERROR(cfg_builder_use_label(g, lbl));
9837 : : }
9838 : 0 : PyObject *item = PyList_GET_ITEM(instructions, i);
9839 [ # # # # ]: 0 : if (!PyTuple_Check(item) || PyTuple_GET_SIZE(item) != 6) {
9840 : 0 : PyErr_SetString(PyExc_ValueError, "expected a 6-tuple");
9841 : 0 : goto error;
9842 : : }
9843 : 0 : int opcode = PyLong_AsLong(PyTuple_GET_ITEM(item, 0));
9844 [ # # ]: 0 : if (PyErr_Occurred()) {
9845 : 0 : goto error;
9846 : : }
9847 : : int oparg;
9848 [ # # # # : 0 : if (HAS_ARG(opcode)) {
# # # # #
# # # ]
9849 : 0 : oparg = PyLong_AsLong(PyTuple_GET_ITEM(item, 1));
9850 [ # # ]: 0 : if (PyErr_Occurred()) {
9851 : 0 : goto error;
9852 : : }
9853 : : }
9854 : : else {
9855 : 0 : oparg = 0;
9856 : : }
9857 : : location loc;
9858 : 0 : loc.lineno = PyLong_AsLong(PyTuple_GET_ITEM(item, 2));
9859 [ # # ]: 0 : if (PyErr_Occurred()) {
9860 : 0 : goto error;
9861 : : }
9862 : 0 : loc.end_lineno = PyLong_AsLong(PyTuple_GET_ITEM(item, 3));
9863 [ # # ]: 0 : if (PyErr_Occurred()) {
9864 : 0 : goto error;
9865 : : }
9866 : 0 : loc.col_offset = PyLong_AsLong(PyTuple_GET_ITEM(item, 4));
9867 [ # # ]: 0 : if (PyErr_Occurred()) {
9868 : 0 : goto error;
9869 : : }
9870 : 0 : loc.end_col_offset = PyLong_AsLong(PyTuple_GET_ITEM(item, 5));
9871 [ # # ]: 0 : if (PyErr_Occurred()) {
9872 : 0 : goto error;
9873 : : }
9874 [ # # ]: 0 : RETURN_IF_ERROR(cfg_builder_addop(g, opcode, oparg, loc));
9875 : : }
9876 : 0 : struct cfg_instr *last = basicblock_last_instr(g->g_curblock);
9877 [ # # # # : 0 : if (last && !IS_TERMINATOR_OPCODE(last->i_opcode)) {
# # # # #
# # # ]
9878 [ # # ]: 0 : RETURN_IF_ERROR(cfg_builder_addop(g, RETURN_VALUE, 0, NO_LOCATION));
9879 : : }
9880 : 0 : PyMem_Free(is_target);
9881 : 0 : return SUCCESS;
9882 : 0 : error:
9883 : 0 : PyMem_Free(is_target);
9884 : 0 : return ERROR;
9885 : : }
9886 : :
9887 : : static PyObject *
9888 : 0 : instr_sequence_to_instructions(instr_sequence *seq) {
9889 : 0 : PyObject *instructions = PyList_New(0);
9890 [ # # ]: 0 : if (instructions == NULL) {
9891 : 0 : return NULL;
9892 : : }
9893 [ # # ]: 0 : for (int i = 0; i < seq->s_used; i++) {
9894 : 0 : instruction *instr = &seq->s_instrs[i];
9895 : 0 : location loc = instr->i_loc;
9896 [ # # # # : 0 : int arg = HAS_TARGET(instr->i_opcode) ?
# # ]
9897 [ # # ]: 0 : seq->s_labelmap[instr->i_oparg] : instr->i_oparg;
9898 : :
9899 : 0 : PyObject *inst_tuple = Py_BuildValue(
9900 : : "(iiiiii)", instr->i_opcode, arg,
9901 : : loc.lineno, loc.end_lineno,
9902 : : loc.col_offset, loc.end_col_offset);
9903 [ # # ]: 0 : if (inst_tuple == NULL) {
9904 : 0 : goto error;
9905 : : }
9906 : :
9907 : 0 : int res = PyList_Append(instructions, inst_tuple);
9908 : 0 : Py_DECREF(inst_tuple);
9909 [ # # ]: 0 : if (res != 0) {
9910 : 0 : goto error;
9911 : : }
9912 : : }
9913 : 0 : return instructions;
9914 : 0 : error:
9915 : 0 : Py_XDECREF(instructions);
9916 : 0 : return NULL;
9917 : : }
9918 : :
9919 : : static PyObject *
9920 : 0 : cfg_to_instructions(cfg_builder *g)
9921 : : {
9922 : 0 : PyObject *instructions = PyList_New(0);
9923 [ # # ]: 0 : if (instructions == NULL) {
9924 : 0 : return NULL;
9925 : : }
9926 : 0 : int lbl = 0;
9927 [ # # ]: 0 : for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
9928 : 0 : b->b_label = (jump_target_label){lbl};
9929 : 0 : lbl += b->b_iused;
9930 : : }
9931 [ # # ]: 0 : for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
9932 [ # # ]: 0 : for (int i = 0; i < b->b_iused; i++) {
9933 : 0 : struct cfg_instr *instr = &b->b_instr[i];
9934 : 0 : location loc = instr->i_loc;
9935 [ # # # # : 0 : int arg = HAS_TARGET(instr->i_opcode) ?
# # ]
9936 [ # # ]: 0 : instr->i_target->b_label.id : instr->i_oparg;
9937 : :
9938 : 0 : PyObject *inst_tuple = Py_BuildValue(
9939 : : "(iiiiii)", instr->i_opcode, arg,
9940 : : loc.lineno, loc.end_lineno,
9941 : : loc.col_offset, loc.end_col_offset);
9942 [ # # ]: 0 : if (inst_tuple == NULL) {
9943 : 0 : goto error;
9944 : : }
9945 : :
9946 [ # # ]: 0 : if (PyList_Append(instructions, inst_tuple) != 0) {
9947 : 0 : Py_DECREF(inst_tuple);
9948 : 0 : goto error;
9949 : : }
9950 : 0 : Py_DECREF(inst_tuple);
9951 : : }
9952 : : }
9953 : :
9954 : 0 : return instructions;
9955 : 0 : error:
9956 : 0 : Py_DECREF(instructions);
9957 : 0 : return NULL;
9958 : : }
9959 : :
9960 : : PyObject *
9961 : 0 : _PyCompile_CodeGen(PyObject *ast, PyObject *filename, PyCompilerFlags *pflags,
9962 : : int optimize)
9963 : : {
9964 : 0 : PyObject *res = NULL;
9965 : :
9966 [ # # ]: 0 : if (!PyAST_Check(ast)) {
9967 : 0 : PyErr_SetString(PyExc_TypeError, "expected an AST");
9968 : 0 : return NULL;
9969 : : }
9970 : :
9971 : 0 : PyArena *arena = _PyArena_New();
9972 [ # # ]: 0 : if (arena == NULL) {
9973 : 0 : return NULL;
9974 : : }
9975 : :
9976 : 0 : mod_ty mod = PyAST_obj2mod(ast, arena, 0 /* exec */);
9977 [ # # # # ]: 0 : if (mod == NULL || !_PyAST_Validate(mod)) {
9978 : 0 : _PyArena_Free(arena);
9979 : 0 : return NULL;
9980 : : }
9981 : :
9982 : 0 : struct compiler *c = new_compiler(mod, filename, pflags, optimize, arena);
9983 [ # # ]: 0 : if (c == NULL) {
9984 : 0 : _PyArena_Free(arena);
9985 : 0 : return NULL;
9986 : : }
9987 : :
9988 [ # # ]: 0 : if (compiler_codegen(c, mod) < 0) {
9989 : 0 : goto finally;
9990 : : }
9991 : :
9992 : 0 : res = instr_sequence_to_instructions(INSTR_SEQUENCE(c));
9993 : :
9994 : 0 : finally:
9995 : 0 : compiler_exit_scope(c);
9996 : 0 : compiler_free(c);
9997 : 0 : _PyArena_Free(arena);
9998 : 0 : return res;
9999 : : }
10000 : :
10001 : : PyObject *
10002 : 0 : _PyCompile_OptimizeCfg(PyObject *instructions, PyObject *consts)
10003 : : {
10004 : 0 : PyObject *res = NULL;
10005 : 0 : PyObject *const_cache = PyDict_New();
10006 [ # # ]: 0 : if (const_cache == NULL) {
10007 : 0 : return NULL;
10008 : : }
10009 : :
10010 : : cfg_builder g;
10011 : 0 : memset(&g, 0, sizeof(cfg_builder));
10012 [ # # ]: 0 : if (cfg_builder_init(&g) < 0) {
10013 : 0 : goto error;
10014 : : }
10015 [ # # ]: 0 : if (instructions_to_cfg(instructions, &g) < 0) {
10016 : 0 : goto error;
10017 : : }
10018 : 0 : int code_flags = 0, nlocals = 0, nparams = 0;
10019 [ # # ]: 0 : if (optimize_code_unit(&g, consts, const_cache, code_flags, nlocals, nparams) < 0) {
10020 : 0 : goto error;
10021 : : }
10022 : 0 : res = cfg_to_instructions(&g);
10023 : 0 : error:
10024 : 0 : Py_DECREF(const_cache);
10025 : 0 : cfg_builder_fini(&g);
10026 : 0 : return res;
10027 : : }
10028 : :
10029 : :
10030 : : /* Retained for API compatibility.
10031 : : * Optimization is now done in optimize_cfg */
10032 : :
10033 : : PyObject *
10034 : 0 : PyCode_Optimize(PyObject *code, PyObject* Py_UNUSED(consts),
10035 : : PyObject *Py_UNUSED(names), PyObject *Py_UNUSED(lnotab_obj))
10036 : : {
10037 : 0 : return Py_NewRef(code);
10038 : : }
|