• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <stdbool.h>
2 
3 #include "Python.h"
4 #include "pycore_code.h"            // write_location_entry_start()
5 #include "pycore_compile.h"
6 #include "pycore_instruction_sequence.h"
7 #include "pycore_opcode_utils.h"    // IS_BACKWARDS_JUMP_OPCODE
8 #include "pycore_opcode_metadata.h" // is_pseudo_target, _PyOpcode_Caches
9 #include "pycore_symtable.h"        // _Py_SourceLocation
10 
11 
12 #define DEFAULT_CODE_SIZE 128
13 #define DEFAULT_LNOTAB_SIZE 16
14 #define DEFAULT_CNOTAB_SIZE 32
15 
16 #undef SUCCESS
17 #undef ERROR
18 #define SUCCESS 0
19 #define ERROR -1
20 
21 #define RETURN_IF_ERROR(X)  \
22     if ((X) < 0) {          \
23         return ERROR;       \
24     }
25 
26 typedef _Py_SourceLocation location;
27 typedef _PyInstruction instruction;
28 typedef _PyInstructionSequence instr_sequence;
29 
30 static inline bool
same_location(location a,location b)31 same_location(location a, location b)
32 {
33     return a.lineno == b.lineno &&
34            a.end_lineno == b.end_lineno &&
35            a.col_offset == b.col_offset &&
36            a.end_col_offset == b.end_col_offset;
37 }
38 
39 static int
instr_size(instruction * instr)40 instr_size(instruction *instr)
41 {
42     int opcode = instr->i_opcode;
43     int oparg = instr->i_oparg;
44     assert(!IS_PSEUDO_INSTR(opcode));
45     assert(OPCODE_HAS_ARG(opcode) || oparg == 0);
46     int extended_args = (0xFFFFFF < oparg) + (0xFFFF < oparg) + (0xFF < oparg);
47     int caches = _PyOpcode_Caches[opcode];
48     return extended_args + 1 + caches;
49 }
50 
51 struct assembler {
52     PyObject *a_bytecode;  /* bytes containing bytecode */
53     int a_offset;              /* offset into bytecode */
54     PyObject *a_except_table;  /* bytes containing exception table */
55     int a_except_table_off;    /* offset into exception table */
56     /* Location Info */
57     int a_lineno;          /* lineno of last emitted instruction */
58     PyObject* a_linetable; /* bytes containing location info */
59     int a_location_off;    /* offset of last written location info frame */
60 };
61 
62 static int
assemble_init(struct assembler * a,int firstlineno)63 assemble_init(struct assembler *a, int firstlineno)
64 {
65     memset(a, 0, sizeof(struct assembler));
66     a->a_lineno = firstlineno;
67     a->a_linetable = NULL;
68     a->a_location_off = 0;
69     a->a_except_table = NULL;
70     a->a_bytecode = PyBytes_FromStringAndSize(NULL, DEFAULT_CODE_SIZE);
71     if (a->a_bytecode == NULL) {
72         goto error;
73     }
74     a->a_linetable = PyBytes_FromStringAndSize(NULL, DEFAULT_CNOTAB_SIZE);
75     if (a->a_linetable == NULL) {
76         goto error;
77     }
78     a->a_except_table = PyBytes_FromStringAndSize(NULL, DEFAULT_LNOTAB_SIZE);
79     if (a->a_except_table == NULL) {
80         goto error;
81     }
82     return SUCCESS;
83 error:
84     Py_XDECREF(a->a_bytecode);
85     Py_XDECREF(a->a_linetable);
86     Py_XDECREF(a->a_except_table);
87     return ERROR;
88 }
89 
90 static void
assemble_free(struct assembler * a)91 assemble_free(struct assembler *a)
92 {
93     Py_XDECREF(a->a_bytecode);
94     Py_XDECREF(a->a_linetable);
95     Py_XDECREF(a->a_except_table);
96 }
97 
98 static inline void
write_except_byte(struct assembler * a,int byte)99 write_except_byte(struct assembler *a, int byte) {
100     unsigned char *p = (unsigned char *) PyBytes_AS_STRING(a->a_except_table);
101     p[a->a_except_table_off++] = byte;
102 }
103 
104 #define CONTINUATION_BIT 64
105 
106 static void
assemble_emit_exception_table_item(struct assembler * a,int value,int msb)107 assemble_emit_exception_table_item(struct assembler *a, int value, int msb)
108 {
109     assert ((msb | 128) == 128);
110     assert(value >= 0 && value < (1 << 30));
111     if (value >= 1 << 24) {
112         write_except_byte(a, (value >> 24) | CONTINUATION_BIT | msb);
113         msb = 0;
114     }
115     if (value >= 1 << 18) {
116         write_except_byte(a, ((value >> 18)&0x3f) | CONTINUATION_BIT | msb);
117         msb = 0;
118     }
119     if (value >= 1 << 12) {
120         write_except_byte(a, ((value >> 12)&0x3f) | CONTINUATION_BIT | msb);
121         msb = 0;
122     }
123     if (value >= 1 << 6) {
124         write_except_byte(a, ((value >> 6)&0x3f) | CONTINUATION_BIT | msb);
125         msb = 0;
126     }
127     write_except_byte(a, (value&0x3f) | msb);
128 }
129 
130 /* See Objects/exception_handling_notes.txt for details of layout */
131 #define MAX_SIZE_OF_ENTRY 20
132 
133 static int
assemble_emit_exception_table_entry(struct assembler * a,int start,int end,int handler_offset,_PyExceptHandlerInfo * handler)134 assemble_emit_exception_table_entry(struct assembler *a, int start, int end,
135                                     int handler_offset,
136                                     _PyExceptHandlerInfo *handler)
137 {
138     Py_ssize_t len = PyBytes_GET_SIZE(a->a_except_table);
139     if (a->a_except_table_off + MAX_SIZE_OF_ENTRY >= len) {
140         RETURN_IF_ERROR(_PyBytes_Resize(&a->a_except_table, len * 2));
141     }
142     int size = end-start;
143     assert(end > start);
144     int target = handler_offset;
145     int depth = handler->h_startdepth - 1;
146     if (handler->h_preserve_lasti > 0) {
147         depth -= 1;
148     }
149     assert(depth >= 0);
150     int depth_lasti = (depth<<1) | handler->h_preserve_lasti;
151     assemble_emit_exception_table_item(a, start, (1<<7));
152     assemble_emit_exception_table_item(a, size, 0);
153     assemble_emit_exception_table_item(a, target, 0);
154     assemble_emit_exception_table_item(a, depth_lasti, 0);
155     return SUCCESS;
156 }
157 
158 static int
assemble_exception_table(struct assembler * a,instr_sequence * instrs)159 assemble_exception_table(struct assembler *a, instr_sequence *instrs)
160 {
161     int ioffset = 0;
162     _PyExceptHandlerInfo handler;
163     handler.h_label = -1;
164     handler.h_startdepth = -1;
165     handler.h_preserve_lasti = -1;
166     int start = -1;
167     for (int i = 0; i < instrs->s_used; i++) {
168         instruction *instr = &instrs->s_instrs[i];
169         if (instr->i_except_handler_info.h_label != handler.h_label) {
170             if (handler.h_label >= 0) {
171                 int handler_offset = instrs->s_instrs[handler.h_label].i_offset;
172                 RETURN_IF_ERROR(
173                     assemble_emit_exception_table_entry(a, start, ioffset,
174                                                         handler_offset,
175                                                         &handler));
176             }
177             start = ioffset;
178             handler = instr->i_except_handler_info;
179         }
180         ioffset += instr_size(instr);
181     }
182     if (handler.h_label >= 0) {
183         int handler_offset = instrs->s_instrs[handler.h_label].i_offset;
184         RETURN_IF_ERROR(assemble_emit_exception_table_entry(a, start, ioffset,
185                                                             handler_offset,
186                                                             &handler));
187     }
188     return SUCCESS;
189 }
190 
191 
192 /* Code location emitting code. See locations.md for a description of the format. */
193 
194 #define MSB 0x80
195 
196 static void
write_location_byte(struct assembler * a,int val)197 write_location_byte(struct assembler* a, int val)
198 {
199     PyBytes_AS_STRING(a->a_linetable)[a->a_location_off] = val&255;
200     a->a_location_off++;
201 }
202 
203 
204 static uint8_t *
location_pointer(struct assembler * a)205 location_pointer(struct assembler* a)
206 {
207     return (uint8_t *)PyBytes_AS_STRING(a->a_linetable) +
208         a->a_location_off;
209 }
210 
211 static void
write_location_first_byte(struct assembler * a,int code,int length)212 write_location_first_byte(struct assembler* a, int code, int length)
213 {
214     a->a_location_off += write_location_entry_start(
215         location_pointer(a), code, length);
216 }
217 
218 static void
write_location_varint(struct assembler * a,unsigned int val)219 write_location_varint(struct assembler* a, unsigned int val)
220 {
221     uint8_t *ptr = location_pointer(a);
222     a->a_location_off += write_varint(ptr, val);
223 }
224 
225 
226 static void
write_location_signed_varint(struct assembler * a,int val)227 write_location_signed_varint(struct assembler* a, int val)
228 {
229     uint8_t *ptr = location_pointer(a);
230     a->a_location_off += write_signed_varint(ptr, val);
231 }
232 
233 static void
write_location_info_short_form(struct assembler * a,int length,int column,int end_column)234 write_location_info_short_form(struct assembler* a, int length, int column, int end_column)
235 {
236     assert(length > 0 &&  length <= 8);
237     int column_low_bits = column & 7;
238     int column_group = column >> 3;
239     assert(column < 80);
240     assert(end_column >= column);
241     assert(end_column - column < 16);
242     write_location_first_byte(a, PY_CODE_LOCATION_INFO_SHORT0 + column_group, length);
243     write_location_byte(a, (column_low_bits << 4) | (end_column - column));
244 }
245 
246 static void
write_location_info_oneline_form(struct assembler * a,int length,int line_delta,int column,int end_column)247 write_location_info_oneline_form(struct assembler* a, int length, int line_delta, int column, int end_column)
248 {
249     assert(length > 0 &&  length <= 8);
250     assert(line_delta >= 0 && line_delta < 3);
251     assert(column < 128);
252     assert(end_column < 128);
253     write_location_first_byte(a, PY_CODE_LOCATION_INFO_ONE_LINE0 + line_delta, length);
254     write_location_byte(a, column);
255     write_location_byte(a, end_column);
256 }
257 
258 static void
write_location_info_long_form(struct assembler * a,location loc,int length)259 write_location_info_long_form(struct assembler* a, location loc, int length)
260 {
261     assert(length > 0 &&  length <= 8);
262     write_location_first_byte(a, PY_CODE_LOCATION_INFO_LONG, length);
263     write_location_signed_varint(a, loc.lineno - a->a_lineno);
264     assert(loc.end_lineno >= loc.lineno);
265     write_location_varint(a, loc.end_lineno - loc.lineno);
266     write_location_varint(a, loc.col_offset + 1);
267     write_location_varint(a, loc.end_col_offset + 1);
268 }
269 
270 static void
write_location_info_none(struct assembler * a,int length)271 write_location_info_none(struct assembler* a, int length)
272 {
273     write_location_first_byte(a, PY_CODE_LOCATION_INFO_NONE, length);
274 }
275 
276 static void
write_location_info_no_column(struct assembler * a,int length,int line_delta)277 write_location_info_no_column(struct assembler* a, int length, int line_delta)
278 {
279     write_location_first_byte(a, PY_CODE_LOCATION_INFO_NO_COLUMNS, length);
280     write_location_signed_varint(a, line_delta);
281 }
282 
283 #define THEORETICAL_MAX_ENTRY_SIZE 25 /* 1 + 6 + 6 + 6 + 6 */
284 
285 
286 static int
write_location_info_entry(struct assembler * a,location loc,int isize)287 write_location_info_entry(struct assembler* a, location loc, int isize)
288 {
289     Py_ssize_t len = PyBytes_GET_SIZE(a->a_linetable);
290     if (a->a_location_off + THEORETICAL_MAX_ENTRY_SIZE >= len) {
291         assert(len > THEORETICAL_MAX_ENTRY_SIZE);
292         RETURN_IF_ERROR(_PyBytes_Resize(&a->a_linetable, len*2));
293     }
294     if (loc.lineno < 0) {
295         write_location_info_none(a, isize);
296         return SUCCESS;
297     }
298     int line_delta = loc.lineno - a->a_lineno;
299     int column = loc.col_offset;
300     int end_column = loc.end_col_offset;
301     assert(column >= -1);
302     assert(end_column >= -1);
303     if (column < 0 || end_column < 0) {
304         if (loc.end_lineno == loc.lineno || loc.end_lineno == -1) {
305             write_location_info_no_column(a, isize, line_delta);
306             a->a_lineno = loc.lineno;
307             return SUCCESS;
308         }
309     }
310     else if (loc.end_lineno == loc.lineno) {
311         if (line_delta == 0 && column < 80 && end_column - column < 16 && end_column >= column) {
312             write_location_info_short_form(a, isize, column, end_column);
313             return SUCCESS;
314         }
315         if (line_delta >= 0 && line_delta < 3 && column < 128 && end_column < 128) {
316             write_location_info_oneline_form(a, isize, line_delta, column, end_column);
317             a->a_lineno = loc.lineno;
318             return SUCCESS;
319         }
320     }
321     write_location_info_long_form(a, loc, isize);
322     a->a_lineno = loc.lineno;
323     return SUCCESS;
324 }
325 
326 static int
assemble_emit_location(struct assembler * a,location loc,int isize)327 assemble_emit_location(struct assembler* a, location loc, int isize)
328 {
329     if (isize == 0) {
330         return SUCCESS;
331     }
332     while (isize > 8) {
333         RETURN_IF_ERROR(write_location_info_entry(a, loc, 8));
334         isize -= 8;
335     }
336     return write_location_info_entry(a, loc, isize);
337 }
338 
339 static int
assemble_location_info(struct assembler * a,instr_sequence * instrs,int firstlineno)340 assemble_location_info(struct assembler *a, instr_sequence *instrs,
341                        int firstlineno)
342 {
343     a->a_lineno = firstlineno;
344     location loc = NO_LOCATION;
345     int size = 0;
346     for (int i = 0; i < instrs->s_used; i++) {
347         instruction *instr = &instrs->s_instrs[i];
348         if (!same_location(loc, instr->i_loc)) {
349                 RETURN_IF_ERROR(assemble_emit_location(a, loc, size));
350                 loc = instr->i_loc;
351                 size = 0;
352         }
353         size += instr_size(instr);
354     }
355     RETURN_IF_ERROR(assemble_emit_location(a, loc, size));
356     return SUCCESS;
357 }
358 
359 static void
write_instr(_Py_CODEUNIT * codestr,instruction * instr,int ilen)360 write_instr(_Py_CODEUNIT *codestr, instruction *instr, int ilen)
361 {
362     int opcode = instr->i_opcode;
363     assert(!IS_PSEUDO_INSTR(opcode));
364     int oparg = instr->i_oparg;
365     assert(OPCODE_HAS_ARG(opcode) || oparg == 0);
366     int caches = _PyOpcode_Caches[opcode];
367     switch (ilen - caches) {
368         case 4:
369             codestr->op.code = EXTENDED_ARG;
370             codestr->op.arg = (oparg >> 24) & 0xFF;
371             codestr++;
372             /* fall through */
373         case 3:
374             codestr->op.code = EXTENDED_ARG;
375             codestr->op.arg = (oparg >> 16) & 0xFF;
376             codestr++;
377             /* fall through */
378         case 2:
379             codestr->op.code = EXTENDED_ARG;
380             codestr->op.arg = (oparg >> 8) & 0xFF;
381             codestr++;
382             /* fall through */
383         case 1:
384             codestr->op.code = opcode;
385             codestr->op.arg = oparg & 0xFF;
386             codestr++;
387             break;
388         default:
389             Py_UNREACHABLE();
390     }
391     while (caches--) {
392         codestr->op.code = CACHE;
393         codestr->op.arg = 0;
394         codestr++;
395     }
396 }
397 
398 /* assemble_emit_instr()
399    Extend the bytecode with a new instruction.
400    Update lnotab if necessary.
401 */
402 
403 static int
assemble_emit_instr(struct assembler * a,instruction * instr)404 assemble_emit_instr(struct assembler *a, instruction *instr)
405 {
406     Py_ssize_t len = PyBytes_GET_SIZE(a->a_bytecode);
407     _Py_CODEUNIT *code;
408 
409     int size = instr_size(instr);
410     if (a->a_offset + size >= len / (int)sizeof(_Py_CODEUNIT)) {
411         if (len > PY_SSIZE_T_MAX / 2) {
412             return ERROR;
413         }
414         RETURN_IF_ERROR(_PyBytes_Resize(&a->a_bytecode, len * 2));
415     }
416     code = (_Py_CODEUNIT *)PyBytes_AS_STRING(a->a_bytecode) + a->a_offset;
417     a->a_offset += size;
418     write_instr(code, instr, size);
419     return SUCCESS;
420 }
421 
422 static int
assemble_emit(struct assembler * a,instr_sequence * instrs,int first_lineno,PyObject * const_cache)423 assemble_emit(struct assembler *a, instr_sequence *instrs,
424               int first_lineno, PyObject *const_cache)
425 {
426     RETURN_IF_ERROR(assemble_init(a, first_lineno));
427 
428     for (int i = 0; i < instrs->s_used; i++) {
429         instruction *instr = &instrs->s_instrs[i];
430         RETURN_IF_ERROR(assemble_emit_instr(a, instr));
431     }
432 
433     RETURN_IF_ERROR(assemble_location_info(a, instrs, a->a_lineno));
434 
435     RETURN_IF_ERROR(assemble_exception_table(a, instrs));
436 
437     RETURN_IF_ERROR(_PyBytes_Resize(&a->a_except_table, a->a_except_table_off));
438     RETURN_IF_ERROR(_PyCompile_ConstCacheMergeOne(const_cache, &a->a_except_table));
439 
440     RETURN_IF_ERROR(_PyBytes_Resize(&a->a_linetable, a->a_location_off));
441     RETURN_IF_ERROR(_PyCompile_ConstCacheMergeOne(const_cache, &a->a_linetable));
442 
443     RETURN_IF_ERROR(_PyBytes_Resize(&a->a_bytecode, a->a_offset * sizeof(_Py_CODEUNIT)));
444     RETURN_IF_ERROR(_PyCompile_ConstCacheMergeOne(const_cache, &a->a_bytecode));
445     return SUCCESS;
446 }
447 
448 static PyObject *
dict_keys_inorder(PyObject * dict,Py_ssize_t offset)449 dict_keys_inorder(PyObject *dict, Py_ssize_t offset)
450 {
451     PyObject *tuple, *k, *v;
452     Py_ssize_t pos = 0, size = PyDict_GET_SIZE(dict);
453 
454     tuple = PyTuple_New(size);
455     if (tuple == NULL)
456         return NULL;
457     while (PyDict_Next(dict, &pos, &k, &v)) {
458         Py_ssize_t i = PyLong_AsSsize_t(v);
459         if (i == -1 && PyErr_Occurred()) {
460             Py_DECREF(tuple);
461             return NULL;
462         }
463         assert((i - offset) < size);
464         assert((i - offset) >= 0);
465         PyTuple_SET_ITEM(tuple, i - offset, Py_NewRef(k));
466     }
467     return tuple;
468 }
469 
470 // This is in codeobject.c.
471 extern void _Py_set_localsplus_info(int, PyObject *, unsigned char,
472                                    PyObject *, PyObject *);
473 
474 static int
compute_localsplus_info(_PyCompile_CodeUnitMetadata * umd,int nlocalsplus,PyObject * names,PyObject * kinds)475 compute_localsplus_info(_PyCompile_CodeUnitMetadata *umd, int nlocalsplus,
476                         PyObject *names, PyObject *kinds)
477 {
478     PyObject *k, *v;
479     Py_ssize_t pos = 0;
480     while (PyDict_Next(umd->u_varnames, &pos, &k, &v)) {
481         int offset = PyLong_AsInt(v);
482         if (offset == -1 && PyErr_Occurred()) {
483             return ERROR;
484         }
485         assert(offset >= 0);
486         assert(offset < nlocalsplus);
487 
488         // For now we do not distinguish arg kinds.
489         _PyLocals_Kind kind = CO_FAST_LOCAL;
490         int has_key = PyDict_Contains(umd->u_fasthidden, k);
491         RETURN_IF_ERROR(has_key);
492         if (has_key) {
493             kind |= CO_FAST_HIDDEN;
494         }
495 
496         has_key = PyDict_Contains(umd->u_cellvars, k);
497         RETURN_IF_ERROR(has_key);
498         if (has_key) {
499             kind |= CO_FAST_CELL;
500         }
501 
502         _Py_set_localsplus_info(offset, k, kind, names, kinds);
503     }
504     int nlocals = (int)PyDict_GET_SIZE(umd->u_varnames);
505 
506     // This counter mirrors the fix done in fix_cell_offsets().
507     int numdropped = 0;
508     pos = 0;
509     while (PyDict_Next(umd->u_cellvars, &pos, &k, &v)) {
510         int has_name = PyDict_Contains(umd->u_varnames, k);
511         RETURN_IF_ERROR(has_name);
512         if (has_name) {
513             // Skip cells that are already covered by locals.
514             numdropped += 1;
515             continue;
516         }
517 
518         int offset = PyLong_AsInt(v);
519         if (offset == -1 && PyErr_Occurred()) {
520             return ERROR;
521         }
522         assert(offset >= 0);
523         offset += nlocals - numdropped;
524         assert(offset < nlocalsplus);
525         _Py_set_localsplus_info(offset, k, CO_FAST_CELL, names, kinds);
526     }
527 
528     pos = 0;
529     while (PyDict_Next(umd->u_freevars, &pos, &k, &v)) {
530         int offset = PyLong_AsInt(v);
531         if (offset == -1 && PyErr_Occurred()) {
532             return ERROR;
533         }
534         assert(offset >= 0);
535         offset += nlocals - numdropped;
536         assert(offset < nlocalsplus);
537         _Py_set_localsplus_info(offset, k, CO_FAST_FREE, names, kinds);
538     }
539     return SUCCESS;
540 }
541 
542 static PyCodeObject *
makecode(_PyCompile_CodeUnitMetadata * umd,struct assembler * a,PyObject * const_cache,PyObject * constslist,int maxdepth,int nlocalsplus,int code_flags,PyObject * filename)543 makecode(_PyCompile_CodeUnitMetadata *umd, struct assembler *a, PyObject *const_cache,
544          PyObject *constslist, int maxdepth, int nlocalsplus, int code_flags,
545          PyObject *filename)
546 {
547     PyCodeObject *co = NULL;
548     PyObject *names = NULL;
549     PyObject *consts = NULL;
550     PyObject *localsplusnames = NULL;
551     PyObject *localspluskinds = NULL;
552     names = dict_keys_inorder(umd->u_names, 0);
553     if (!names) {
554         goto error;
555     }
556     if (_PyCompile_ConstCacheMergeOne(const_cache, &names) < 0) {
557         goto error;
558     }
559 
560     consts = PyList_AsTuple(constslist); /* PyCode_New requires a tuple */
561     if (consts == NULL) {
562         goto error;
563     }
564     if (_PyCompile_ConstCacheMergeOne(const_cache, &consts) < 0) {
565         goto error;
566     }
567 
568     assert(umd->u_posonlyargcount < INT_MAX);
569     assert(umd->u_argcount < INT_MAX);
570     assert(umd->u_kwonlyargcount < INT_MAX);
571     int posonlyargcount = (int)umd->u_posonlyargcount;
572     int posorkwargcount = (int)umd->u_argcount;
573     assert(INT_MAX - posonlyargcount - posorkwargcount > 0);
574     int kwonlyargcount = (int)umd->u_kwonlyargcount;
575 
576     localsplusnames = PyTuple_New(nlocalsplus);
577     if (localsplusnames == NULL) {
578         goto error;
579     }
580     localspluskinds = PyBytes_FromStringAndSize(NULL, nlocalsplus);
581     if (localspluskinds == NULL) {
582         goto error;
583     }
584     if (compute_localsplus_info(umd, nlocalsplus,
585                                 localsplusnames, localspluskinds) == ERROR) {
586         goto error;
587     }
588 
589     struct _PyCodeConstructor con = {
590         .filename = filename,
591         .name = umd->u_name,
592         .qualname = umd->u_qualname ? umd->u_qualname : umd->u_name,
593         .flags = code_flags,
594 
595         .code = a->a_bytecode,
596         .firstlineno = umd->u_firstlineno,
597         .linetable = a->a_linetable,
598 
599         .consts = consts,
600         .names = names,
601 
602         .localsplusnames = localsplusnames,
603         .localspluskinds = localspluskinds,
604 
605         .argcount = posonlyargcount + posorkwargcount,
606         .posonlyargcount = posonlyargcount,
607         .kwonlyargcount = kwonlyargcount,
608 
609         .stacksize = maxdepth,
610 
611         .exceptiontable = a->a_except_table,
612     };
613 
614    if (_PyCode_Validate(&con) < 0) {
615         goto error;
616     }
617 
618     if (_PyCompile_ConstCacheMergeOne(const_cache, &localsplusnames) < 0) {
619         goto error;
620     }
621     con.localsplusnames = localsplusnames;
622 
623     co = _PyCode_New(&con);
624     if (co == NULL) {
625         goto error;
626     }
627 
628 error:
629     Py_XDECREF(names);
630     Py_XDECREF(consts);
631     Py_XDECREF(localsplusnames);
632     Py_XDECREF(localspluskinds);
633     return co;
634 }
635 
636 static int
resolve_jump_offsets(instr_sequence * instrs)637 resolve_jump_offsets(instr_sequence *instrs)
638 {
639     /* Compute the size of each instruction and fixup jump args.
640      * Replace instruction index with position in bytecode.
641      */
642 
643     for (int i = 0; i < instrs->s_used; i++) {
644         instruction *instr = &instrs->s_instrs[i];
645         if (OPCODE_HAS_JUMP(instr->i_opcode)) {
646             instr->i_target = instr->i_oparg;
647         }
648     }
649 
650     int extended_arg_recompile;
651 
652     do {
653         int totsize = 0;
654         for (int i = 0; i < instrs->s_used; i++) {
655             instruction *instr = &instrs->s_instrs[i];
656             instr->i_offset = totsize;
657             int isize = instr_size(instr);
658             totsize += isize;
659         }
660         extended_arg_recompile = 0;
661 
662         int offset = 0;
663         for (int i = 0; i < instrs->s_used; i++) {
664             instruction *instr = &instrs->s_instrs[i];
665             int isize = instr_size(instr);
666             /* jump offsets are computed relative to
667              * the instruction pointer after fetching
668              * the jump instruction.
669              */
670             offset += isize;
671             if (OPCODE_HAS_JUMP(instr->i_opcode)) {
672                 instruction *target = &instrs->s_instrs[instr->i_target];
673                 instr->i_oparg = target->i_offset;
674                 if (instr->i_oparg < offset) {
675                     assert(IS_BACKWARDS_JUMP_OPCODE(instr->i_opcode));
676                     instr->i_oparg = offset - instr->i_oparg;
677                 }
678                 else {
679                     assert(!IS_BACKWARDS_JUMP_OPCODE(instr->i_opcode));
680                     instr->i_oparg = instr->i_oparg - offset;
681                 }
682                 if (instr_size(instr) != isize) {
683                     extended_arg_recompile = 1;
684                 }
685             }
686         }
687     /* XXX: This is an awful hack that could hurt performance, but
688         on the bright side it should work until we come up
689         with a better solution.
690 
691         The issue is that in the first loop instr_size() is
692         called, and it requires i_oparg be set appropriately.
693         There is a bootstrap problem because i_oparg is
694         calculated in the second loop above.
695 
696         So we loop until we stop seeing new EXTENDED_ARGs.
697         The only EXTENDED_ARGs that could be popping up are
698         ones in jump instructions.  So this should converge
699         fairly quickly.
700     */
701     } while (extended_arg_recompile);
702     return SUCCESS;
703 }
704 
705 static int
resolve_unconditional_jumps(instr_sequence * instrs)706 resolve_unconditional_jumps(instr_sequence *instrs)
707 {
708     /* Resolve directions of unconditional jumps */
709 
710     for (int i = 0; i < instrs->s_used; i++) {
711         instruction *instr = &instrs->s_instrs[i];
712         bool is_forward = (instr->i_oparg > i);
713         switch(instr->i_opcode) {
714             case JUMP:
715                 assert(is_pseudo_target(JUMP, JUMP_FORWARD));
716                 assert(is_pseudo_target(JUMP, JUMP_BACKWARD));
717                 instr->i_opcode = is_forward ? JUMP_FORWARD : JUMP_BACKWARD;
718                 break;
719             case JUMP_NO_INTERRUPT:
720                 assert(is_pseudo_target(JUMP_NO_INTERRUPT, JUMP_FORWARD));
721                 assert(is_pseudo_target(JUMP_NO_INTERRUPT, JUMP_BACKWARD_NO_INTERRUPT));
722                 instr->i_opcode = is_forward ?
723                     JUMP_FORWARD : JUMP_BACKWARD_NO_INTERRUPT;
724                 break;
725             default:
726                 if (OPCODE_HAS_JUMP(instr->i_opcode) &&
727                     IS_PSEUDO_INSTR(instr->i_opcode)) {
728                     Py_UNREACHABLE();
729                 }
730         }
731     }
732     return SUCCESS;
733 }
734 
735 PyCodeObject *
_PyAssemble_MakeCodeObject(_PyCompile_CodeUnitMetadata * umd,PyObject * const_cache,PyObject * consts,int maxdepth,instr_sequence * instrs,int nlocalsplus,int code_flags,PyObject * filename)736 _PyAssemble_MakeCodeObject(_PyCompile_CodeUnitMetadata *umd, PyObject *const_cache,
737                            PyObject *consts, int maxdepth, instr_sequence *instrs,
738                            int nlocalsplus, int code_flags, PyObject *filename)
739 {
740     if (_PyInstructionSequence_ApplyLabelMap(instrs) < 0) {
741         return NULL;
742     }
743     if (resolve_unconditional_jumps(instrs) < 0) {
744         return NULL;
745     }
746     if (resolve_jump_offsets(instrs) < 0) {
747         return NULL;
748     }
749     PyCodeObject *co = NULL;
750 
751     struct assembler a;
752     int res = assemble_emit(&a, instrs, umd->u_firstlineno, const_cache);
753     if (res == SUCCESS) {
754         co = makecode(umd, &a, const_cache, consts, maxdepth, nlocalsplus,
755                       code_flags, filename);
756     }
757     assemble_free(&a);
758     return co;
759 }
760