summaryrefslogtreecommitdiffstats
path: root/Python/compile.c
diff options
context:
space:
mode:
Diffstat (limited to 'Python/compile.c')
-rw-r--r--Python/compile.c432
1 files changed, 68 insertions, 364 deletions
diff --git a/Python/compile.c b/Python/compile.c
index 68af5d6..83cf455 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -70,9 +70,7 @@
&& ((C)->u->u_ste->ste_type == ModuleBlock))
typedef _PyCompilerSrcLocation location;
-typedef _PyCfgInstruction cfg_instr;
-typedef _PyCfgBasicblock basicblock;
-typedef _PyCfgBuilder cfg_builder;
+typedef struct _PyCfgBuilder cfg_builder;
#define LOCATION(LNO, END_LNO, COL, END_COL) \
((const _PyCompilerSrcLocation){(LNO), (END_LNO), (COL), (END_COL)})
@@ -101,7 +99,7 @@ static jump_target_label NO_LABEL = {-1};
}
#define USE_LABEL(C, LBL) \
- RETURN_IF_ERROR(instr_sequence_use_label(INSTR_SEQUENCE(C), (LBL).id))
+ RETURN_IF_ERROR(_PyCompile_InstructionSequence_UseLabel(INSTR_SEQUENCE(C), (LBL).id))
/* fblockinfo tracks the current frame block.
@@ -218,8 +216,9 @@ instr_sequence_new_label(instr_sequence *seq)
return lbl;
}
-static int
-instr_sequence_use_label(instr_sequence *seq, int lbl) {
+int
+_PyCompile_InstructionSequence_UseLabel(instr_sequence *seq, int lbl)
+{
int old_size = seq->s_labelmap_size;
RETURN_IF_ERROR(
_PyCompile_EnsureArrayLargeEnough(lbl,
@@ -238,8 +237,9 @@ instr_sequence_use_label(instr_sequence *seq, int lbl) {
#define MAX_OPCODE 511
-static int
-instr_sequence_addop(instr_sequence *seq, int opcode, int oparg, location loc)
+int
+_PyCompile_InstructionSequence_Addop(instr_sequence *seq, int opcode, int oparg,
+ location loc)
{
assert(0 <= opcode && opcode <= MAX_OPCODE);
assert(IS_WITHIN_OPCODE_RANGE(opcode));
@@ -288,10 +288,12 @@ instr_sequence_fini(instr_sequence *seq) {
seq->s_instrs = NULL;
}
-static int
-instr_sequence_to_cfg(instr_sequence *seq, cfg_builder *g) {
- memset(g, 0, sizeof(cfg_builder));
- RETURN_IF_ERROR(_PyCfgBuilder_Init(g));
+static cfg_builder*
+instr_sequence_to_cfg(instr_sequence *seq) {
+ cfg_builder *g = _PyCfgBuilder_New();
+ if (g == NULL) {
+ return NULL;
+ }
/* There can be more than one label for the same offset. The
* offset2lbl maping selects one of them which we use consistently.
@@ -300,7 +302,7 @@ instr_sequence_to_cfg(instr_sequence *seq, cfg_builder *g) {
int *offset2lbl = PyMem_Malloc(seq->s_used * sizeof(int));
if (offset2lbl == NULL) {
PyErr_NoMemory();
- return ERROR;
+ goto error;
}
for (int i = 0; i < seq->s_used; i++) {
offset2lbl[i] = -1;
@@ -336,23 +338,17 @@ instr_sequence_to_cfg(instr_sequence *seq, cfg_builder *g) {
goto error;
}
}
- PyMem_Free(offset2lbl);
-
- int nblocks = 0;
- for (basicblock *b = g->g_block_list; b != NULL; b = b->b_list) {
- nblocks++;
- }
- if ((size_t)nblocks > SIZE_MAX / sizeof(basicblock *)) {
- PyErr_NoMemory();
- return ERROR;
+ if (_PyCfgBuilder_CheckSize(g) < 0) {
+ goto error;
}
- return SUCCESS;
+ PyMem_Free(offset2lbl);
+ return g;
error:
+ _PyCfgBuilder_Free(g);
PyMem_Free(offset2lbl);
- return ERROR;
+ return NULL;
}
-
/* The following items change on entry and exit of code blocks.
They must be saved and restored when returning to a block.
*/
@@ -920,7 +916,7 @@ codegen_addop_noarg(instr_sequence *seq, int opcode, location loc)
{
assert(!OPCODE_HAS_ARG(opcode));
assert(!IS_ASSEMBLER_OPCODE(opcode));
- return instr_sequence_addop(seq, opcode, 0, loc);
+ return _PyCompile_InstructionSequence_Addop(seq, opcode, 0, loc);
}
static Py_ssize_t
@@ -1153,7 +1149,7 @@ codegen_addop_i(instr_sequence *seq, int opcode, Py_ssize_t oparg, location loc)
int oparg_ = Py_SAFE_DOWNCAST(oparg, Py_ssize_t, int);
assert(!IS_ASSEMBLER_OPCODE(opcode));
- return instr_sequence_addop(seq, opcode, oparg_, loc);
+ return _PyCompile_InstructionSequence_Addop(seq, opcode, oparg_, loc);
}
static int
@@ -1163,7 +1159,7 @@ codegen_addop_j(instr_sequence *seq, location loc,
assert(IS_LABEL(target));
assert(OPCODE_HAS_JUMP(opcode) || IS_BLOCK_PUSH_OPCODE(opcode));
assert(!IS_ASSEMBLER_OPCODE(opcode));
- return instr_sequence_addop(seq, opcode, target.id, loc);
+ return _PyCompile_InstructionSequence_Addop(seq, opcode, target.id, loc);
}
#define RETURN_IF_ERROR_IN_SCOPE(C, CALL) { \
@@ -7492,201 +7488,6 @@ _PyCompile_ConstCacheMergeOne(PyObject *const_cache, PyObject **obj)
return SUCCESS;
}
-
-static int *
-build_cellfixedoffsets(_PyCompile_CodeUnitMetadata *umd)
-{
- int nlocals = (int)PyDict_GET_SIZE(umd->u_varnames);
- int ncellvars = (int)PyDict_GET_SIZE(umd->u_cellvars);
- int nfreevars = (int)PyDict_GET_SIZE(umd->u_freevars);
-
- int noffsets = ncellvars + nfreevars;
- int *fixed = PyMem_New(int, noffsets);
- if (fixed == NULL) {
- PyErr_NoMemory();
- return NULL;
- }
- for (int i = 0; i < noffsets; i++) {
- fixed[i] = nlocals + i;
- }
-
- PyObject *varname, *cellindex;
- Py_ssize_t pos = 0;
- while (PyDict_Next(umd->u_cellvars, &pos, &varname, &cellindex)) {
- PyObject *varindex = PyDict_GetItem(umd->u_varnames, varname);
- if (varindex != NULL) {
- assert(PyLong_AS_LONG(cellindex) < INT_MAX);
- assert(PyLong_AS_LONG(varindex) < INT_MAX);
- int oldindex = (int)PyLong_AS_LONG(cellindex);
- int argoffset = (int)PyLong_AS_LONG(varindex);
- fixed[oldindex] = argoffset;
- }
- }
-
- return fixed;
-}
-
-#define IS_GENERATOR(CF) \
- ((CF) & (CO_GENERATOR | CO_COROUTINE | CO_ASYNC_GENERATOR))
-
-static int
-insert_prefix_instructions(_PyCompile_CodeUnitMetadata *umd, basicblock *entryblock,
- int *fixed, int nfreevars, int code_flags)
-{
- assert(umd->u_firstlineno > 0);
-
- /* Add the generator prefix instructions. */
- if (IS_GENERATOR(code_flags)) {
- /* Note that RETURN_GENERATOR + POP_TOP have a net stack effect
- * of 0. This is because RETURN_GENERATOR pushes an element
- * with _PyFrame_StackPush before switching stacks.
- */
- cfg_instr make_gen = {
- .i_opcode = RETURN_GENERATOR,
- .i_oparg = 0,
- .i_loc = LOCATION(umd->u_firstlineno, umd->u_firstlineno, -1, -1),
- .i_target = NULL,
- };
- RETURN_IF_ERROR(_PyBasicblock_InsertInstruction(entryblock, 0, &make_gen));
- cfg_instr pop_top = {
- .i_opcode = POP_TOP,
- .i_oparg = 0,
- .i_loc = NO_LOCATION,
- .i_target = NULL,
- };
- RETURN_IF_ERROR(_PyBasicblock_InsertInstruction(entryblock, 1, &pop_top));
- }
-
- /* Set up cells for any variable that escapes, to be put in a closure. */
- const int ncellvars = (int)PyDict_GET_SIZE(umd->u_cellvars);
- if (ncellvars) {
- // umd->u_cellvars has the cells out of order so we sort them
- // before adding the MAKE_CELL instructions. Note that we
- // adjust for arg cells, which come first.
- const int nvars = ncellvars + (int)PyDict_GET_SIZE(umd->u_varnames);
- int *sorted = PyMem_RawCalloc(nvars, sizeof(int));
- if (sorted == NULL) {
- PyErr_NoMemory();
- return ERROR;
- }
- for (int i = 0; i < ncellvars; i++) {
- sorted[fixed[i]] = i + 1;
- }
- for (int i = 0, ncellsused = 0; ncellsused < ncellvars; i++) {
- int oldindex = sorted[i] - 1;
- if (oldindex == -1) {
- continue;
- }
- cfg_instr make_cell = {
- .i_opcode = MAKE_CELL,
- // This will get fixed in offset_derefs().
- .i_oparg = oldindex,
- .i_loc = NO_LOCATION,
- .i_target = NULL,
- };
- if (_PyBasicblock_InsertInstruction(entryblock, ncellsused, &make_cell) < 0) {
- PyMem_RawFree(sorted);
- return ERROR;
- }
- ncellsused += 1;
- }
- PyMem_RawFree(sorted);
- }
-
- if (nfreevars) {
- cfg_instr copy_frees = {
- .i_opcode = COPY_FREE_VARS,
- .i_oparg = nfreevars,
- .i_loc = NO_LOCATION,
- .i_target = NULL,
- };
- RETURN_IF_ERROR(_PyBasicblock_InsertInstruction(entryblock, 0, &copy_frees));
- }
-
- return SUCCESS;
-}
-
-static int
-fix_cell_offsets(_PyCompile_CodeUnitMetadata *umd, basicblock *entryblock, int *fixedmap)
-{
- int nlocals = (int)PyDict_GET_SIZE(umd->u_varnames);
- int ncellvars = (int)PyDict_GET_SIZE(umd->u_cellvars);
- int nfreevars = (int)PyDict_GET_SIZE(umd->u_freevars);
- int noffsets = ncellvars + nfreevars;
-
- // First deal with duplicates (arg cells).
- int numdropped = 0;
- for (int i = 0; i < noffsets ; i++) {
- if (fixedmap[i] == i + nlocals) {
- fixedmap[i] -= numdropped;
- }
- else {
- // It was a duplicate (cell/arg).
- numdropped += 1;
- }
- }
-
- // Then update offsets, either relative to locals or by cell2arg.
- for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
- for (int i = 0; i < b->b_iused; i++) {
- cfg_instr *inst = &b->b_instr[i];
- // This is called before extended args are generated.
- assert(inst->i_opcode != EXTENDED_ARG);
- int oldoffset = inst->i_oparg;
- switch(inst->i_opcode) {
- case MAKE_CELL:
- case LOAD_CLOSURE:
- case LOAD_DEREF:
- case STORE_DEREF:
- case DELETE_DEREF:
- case LOAD_FROM_DICT_OR_DEREF:
- assert(oldoffset >= 0);
- assert(oldoffset < noffsets);
- assert(fixedmap[oldoffset] >= 0);
- inst->i_oparg = fixedmap[oldoffset];
- }
- }
- }
-
- return numdropped;
-}
-
-
-static int
-prepare_localsplus(_PyCompile_CodeUnitMetadata *umd, cfg_builder *g, int code_flags)
-{
- assert(PyDict_GET_SIZE(umd->u_varnames) < INT_MAX);
- assert(PyDict_GET_SIZE(umd->u_cellvars) < INT_MAX);
- assert(PyDict_GET_SIZE(umd->u_freevars) < INT_MAX);
- int nlocals = (int)PyDict_GET_SIZE(umd->u_varnames);
- int ncellvars = (int)PyDict_GET_SIZE(umd->u_cellvars);
- int nfreevars = (int)PyDict_GET_SIZE(umd->u_freevars);
- assert(INT_MAX - nlocals - ncellvars > 0);
- assert(INT_MAX - nlocals - ncellvars - nfreevars > 0);
- int nlocalsplus = nlocals + ncellvars + nfreevars;
- int* cellfixedoffsets = build_cellfixedoffsets(umd);
- if (cellfixedoffsets == NULL) {
- return ERROR;
- }
-
-
- // This must be called before fix_cell_offsets().
- if (insert_prefix_instructions(umd, g->g_entryblock, cellfixedoffsets, nfreevars, code_flags)) {
- PyMem_Free(cellfixedoffsets);
- return ERROR;
- }
-
- int numdropped = fix_cell_offsets(umd, g->g_entryblock, cellfixedoffsets);
- PyMem_Free(cellfixedoffsets); // At this point we're done with it.
- cellfixedoffsets = NULL;
- if (numdropped < 0) {
- return ERROR;
- }
-
- nlocalsplus -= numdropped;
- return nlocalsplus;
-}
-
static int
add_return_at_end(struct compiler *c, int addNone)
{
@@ -7700,12 +7501,11 @@ add_return_at_end(struct compiler *c, int addNone)
return SUCCESS;
}
-static int cfg_to_instr_sequence(cfg_builder *g, instr_sequence *seq);
-
static PyCodeObject *
optimize_and_assemble_code_unit(struct compiler_unit *u, PyObject *const_cache,
int code_flags, PyObject *filename)
{
+ cfg_builder *g = NULL;
instr_sequence optimized_instrs;
memset(&optimized_instrs, 0, sizeof(instr_sequence));
@@ -7714,51 +7514,28 @@ optimize_and_assemble_code_unit(struct compiler_unit *u, PyObject *const_cache,
if (consts == NULL) {
goto error;
}
- cfg_builder g;
- if (instr_sequence_to_cfg(&u->u_instr_sequence, &g) < 0) {
+ g = instr_sequence_to_cfg(&u->u_instr_sequence);
+ if (g == NULL) {
goto error;
}
- int nparams = (int)PyList_GET_SIZE(u->u_ste->ste_varnames);
int nlocals = (int)PyDict_GET_SIZE(u->u_metadata.u_varnames);
+ int nparams = (int)PyList_GET_SIZE(u->u_ste->ste_varnames);
assert(u->u_metadata.u_firstlineno);
- if (_PyCfg_OptimizeCodeUnit(&g, consts, const_cache, nlocals,
+
+ if (_PyCfg_OptimizeCodeUnit(g, consts, const_cache, nlocals,
nparams, u->u_metadata.u_firstlineno) < 0) {
goto error;
}
- int stackdepth = _PyCfg_Stackdepth(&g);
- if (stackdepth < 0) {
+ int stackdepth;
+ int nlocalsplus;
+ if (_PyCfg_OptimizedCfgToInstructionSequence(g, &u->u_metadata, code_flags,
+ &stackdepth, &nlocalsplus,
+ &optimized_instrs) < 0) {
goto error;
}
- /* prepare_localsplus adds instructions for generators that push
- * and pop an item on the stack. This assertion makes sure there
- * is space on the stack for that.
- * It should always be true, because a generator must have at
- * least one expression or call to INTRINSIC_STOPITERATION_ERROR,
- * which requires stackspace.
- */
- assert(!(IS_GENERATOR(code_flags) && stackdepth == 0));
-
/** Assembly **/
- int nlocalsplus = prepare_localsplus(&u->u_metadata, &g, code_flags);
- if (nlocalsplus < 0) {
- goto error;
- }
-
- _PyCfg_ConvertPseudoOps(g.g_entryblock);
-
- /* Order of basic blocks must have been determined by now */
-
- if (_PyCfg_ResolveJumps(&g) < 0) {
- goto error;
- }
-
- /* Can't modify the bytecode after computing jump offsets. */
-
- if (cfg_to_instr_sequence(&g, &optimized_instrs) < 0) {
- goto error;
- }
co = _PyAssemble_MakeCodeObject(&u->u_metadata, const_cache, consts,
stackdepth, &optimized_instrs, nlocalsplus,
@@ -7767,7 +7544,7 @@ optimize_and_assemble_code_unit(struct compiler_unit *u, PyObject *const_cache,
error:
Py_XDECREF(consts);
instr_sequence_fini(&optimized_instrs);
- _PyCfgBuilder_Fini(&g);
+ _PyCfgBuilder_Free(g);
return co;
}
@@ -7790,39 +7567,6 @@ optimize_and_assemble(struct compiler *c, int addNone)
return optimize_and_assemble_code_unit(u, const_cache, code_flags, filename);
}
-static int
-cfg_to_instr_sequence(cfg_builder *g, instr_sequence *seq)
-{
- int lbl = 0;
- for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
- b->b_label = (jump_target_label){lbl};
- lbl += b->b_iused;
- }
- for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
- RETURN_IF_ERROR(instr_sequence_use_label(seq, b->b_label.id));
- for (int i = 0; i < b->b_iused; i++) {
- cfg_instr *instr = &b->b_instr[i];
- if (OPCODE_HAS_JUMP(instr->i_opcode)) {
- instr->i_oparg = instr->i_target->b_label.id;
- }
- RETURN_IF_ERROR(
- instr_sequence_addop(seq, instr->i_opcode, instr->i_oparg, instr->i_loc));
-
- _PyCompile_ExceptHandlerInfo *hi = &seq->s_instrs[seq->s_used-1].i_except_handler_info;
- if (instr->i_except != NULL) {
- hi->h_label = instr->i_except->b_label.id;
- hi->h_startdepth = instr->i_except->b_startdepth;
- hi->h_preserve_lasti = instr->i_except->b_preserve_lasti;
- }
- else {
- hi->h_label = -1;
- }
- }
- }
- return SUCCESS;
-}
-
-
/* Access to compiler optimizations for unit tests.
*
* _PyCompile_CodeGen takes and AST, applies code-gen and
@@ -7872,7 +7616,7 @@ instructions_to_instr_sequence(PyObject *instructions, instr_sequence *seq)
for (int i = 0; i < num_insts; i++) {
if (is_target[i]) {
- if (instr_sequence_use_label(seq, i) < 0) {
+ if (_PyCompile_InstructionSequence_UseLabel(seq, i) < 0) {
goto error;
}
}
@@ -7912,7 +7656,7 @@ instructions_to_instr_sequence(PyObject *instructions, instr_sequence *seq)
if (PyErr_Occurred()) {
goto error;
}
- if (instr_sequence_addop(seq, opcode, oparg, loc) < 0) {
+ if (_PyCompile_InstructionSequence_Addop(seq, opcode, oparg, loc) < 0) {
goto error;
}
}
@@ -7923,23 +7667,26 @@ error:
return ERROR;
}
-static int
-instructions_to_cfg(PyObject *instructions, cfg_builder *g)
+static cfg_builder*
+instructions_to_cfg(PyObject *instructions)
{
+ cfg_builder *g = NULL;
instr_sequence seq;
memset(&seq, 0, sizeof(instr_sequence));
if (instructions_to_instr_sequence(instructions, &seq) < 0) {
goto error;
}
- if (instr_sequence_to_cfg(&seq, g) < 0) {
+ g = instr_sequence_to_cfg(&seq);
+ if (g == NULL) {
goto error;
}
instr_sequence_fini(&seq);
- return SUCCESS;
+ return g;
error:
+ _PyCfgBuilder_Free(g);
instr_sequence_fini(&seq);
- return ERROR;
+ return NULL;
}
static PyObject *
@@ -7978,42 +7725,14 @@ error:
static PyObject *
cfg_to_instructions(cfg_builder *g)
{
- PyObject *instructions = PyList_New(0);
- if (instructions == NULL) {
+ instr_sequence seq;
+ memset(&seq, 0, sizeof(seq));
+ if (_PyCfg_ToInstructionSequence(g, &seq) < 0) {
return NULL;
}
- int lbl = 0;
- for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
- b->b_label = (jump_target_label){lbl};
- lbl += b->b_iused;
- }
- for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
- for (int i = 0; i < b->b_iused; i++) {
- cfg_instr *instr = &b->b_instr[i];
- location loc = instr->i_loc;
- int arg = HAS_TARGET(instr->i_opcode) ?
- instr->i_target->b_label.id : instr->i_oparg;
-
- PyObject *inst_tuple = Py_BuildValue(
- "(iiiiii)", instr->i_opcode, arg,
- loc.lineno, loc.end_lineno,
- loc.col_offset, loc.end_col_offset);
- if (inst_tuple == NULL) {
- goto error;
- }
-
- if (PyList_Append(instructions, inst_tuple) != 0) {
- Py_DECREF(inst_tuple);
- goto error;
- }
- Py_DECREF(inst_tuple);
- }
- }
-
- return instructions;
-error:
- Py_DECREF(instructions);
- return NULL;
+ PyObject *res = instr_sequence_to_instructions(&seq);
+ instr_sequence_fini(&seq);
+ return res;
}
// C implementation of inspect.cleandoc()
@@ -8195,34 +7914,36 @@ finally:
PyObject *
_PyCompile_OptimizeCfg(PyObject *instructions, PyObject *consts, int nlocals)
{
+ cfg_builder *g = NULL;
PyObject *res = NULL;
PyObject *const_cache = PyDict_New();
if (const_cache == NULL) {
return NULL;
}
- cfg_builder g;
- if (instructions_to_cfg(instructions, &g) < 0) {
+ g = instructions_to_cfg(instructions);
+ if (g == NULL) {
goto error;
}
int nparams = 0, firstlineno = 1;
- if (_PyCfg_OptimizeCodeUnit(&g, consts, const_cache, nlocals,
+ if (_PyCfg_OptimizeCodeUnit(g, consts, const_cache, nlocals,
nparams, firstlineno) < 0) {
goto error;
}
- res = cfg_to_instructions(&g);
+ res = cfg_to_instructions(g);
error:
Py_DECREF(const_cache);
- _PyCfgBuilder_Fini(&g);
+ _PyCfgBuilder_Free(g);
return res;
}
-int _PyCfg_JumpLabelsToTargets(basicblock *entryblock);
+int _PyCfg_JumpLabelsToTargets(cfg_builder *g);
PyCodeObject *
_PyCompile_Assemble(_PyCompile_CodeUnitMetadata *umd, PyObject *filename,
PyObject *instructions)
{
+ cfg_builder *g = NULL;
PyCodeObject *co = NULL;
instr_sequence optimized_instrs;
memset(&optimized_instrs, 0, sizeof(instr_sequence));
@@ -8232,37 +7953,20 @@ _PyCompile_Assemble(_PyCompile_CodeUnitMetadata *umd, PyObject *filename,
return NULL;
}
- cfg_builder g;
- if (instructions_to_cfg(instructions, &g) < 0) {
+ g = instructions_to_cfg(instructions);
+ if (g == NULL) {
goto error;
}
- if (_PyCfg_JumpLabelsToTargets(g.g_entryblock) < 0) {
- goto error;
- }
-
- int stackdepth = _PyCfg_Stackdepth(&g);
- if (stackdepth < 0) {
+ if (_PyCfg_JumpLabelsToTargets(g) < 0) {
goto error;
}
int code_flags = 0;
- int nlocalsplus = prepare_localsplus(umd, &g, code_flags);
- if (nlocalsplus < 0) {
- goto error;
- }
-
- _PyCfg_ConvertPseudoOps(g.g_entryblock);
-
- /* Order of basic blocks must have been determined by now */
-
- if (_PyCfg_ResolveJumps(&g) < 0) {
- goto error;
- }
-
- /* Can't modify the bytecode after computing jump offsets. */
-
- if (cfg_to_instr_sequence(&g, &optimized_instrs) < 0) {
+ int stackdepth, nlocalsplus;
+ if (_PyCfg_OptimizedCfgToInstructionSequence(g, umd, code_flags,
+ &stackdepth, &nlocalsplus,
+ &optimized_instrs) < 0) {
goto error;
}
@@ -8277,7 +7981,7 @@ _PyCompile_Assemble(_PyCompile_CodeUnitMetadata *umd, PyObject *filename,
error:
Py_DECREF(const_cache);
- _PyCfgBuilder_Fini(&g);
+ _PyCfgBuilder_Free(g);
instr_sequence_fini(&optimized_instrs);
return co;
}