Skip to content

gh-119744: move a few functions from compile.c to flowgraph.c #119745

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
May 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions Include/internal/pycore_compile.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,12 +101,6 @@ PyAPI_FUNC(PyObject*) _PyCompile_CodeGen(
int optimize,
int compile_mode);

// Export for '_testinternalcapi' shared extension
PyAPI_FUNC(PyObject*) _PyCompile_OptimizeCfg(
PyObject *instructions,
PyObject *consts,
int nlocals);

// Export for '_testinternalcapi' shared extension
PyAPI_FUNC(PyCodeObject*)
_PyCompile_Assemble(_PyCompile_CodeUnitMetadata *umd, PyObject *filename,
Expand Down
7 changes: 7 additions & 0 deletions Include/internal/pycore_flowgraph.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ int _PyCfgBuilder_CheckSize(struct _PyCfgBuilder* g);
int _PyCfg_OptimizeCodeUnit(struct _PyCfgBuilder *g, PyObject *consts, PyObject *const_cache,
int nlocals, int nparams, int firstlineno);

struct _PyCfgBuilder* _PyCfg_FromInstructionSequence(_PyInstructionSequence *seq);
int _PyCfg_ToInstructionSequence(struct _PyCfgBuilder *g, _PyInstructionSequence *seq);
int _PyCfg_OptimizedCfgToInstructionSequence(struct _PyCfgBuilder *g, _PyCompile_CodeUnitMetadata *umd,
int code_flags, int *stackdepth, int *nlocalsplus,
Expand All @@ -34,6 +35,12 @@ _PyAssemble_MakeCodeObject(_PyCompile_CodeUnitMetadata *u, PyObject *const_cache
PyObject *consts, int maxdepth, _PyInstructionSequence *instrs,
int nlocalsplus, int code_flags, PyObject *filename);

// Export for '_testinternalcapi' shared extension
PyAPI_FUNC(PyObject*) _PyCompile_OptimizeCfg(
PyObject *instructions,
PyObject *consts,
int nlocals);

#ifdef __cplusplus
}
#endif
Expand Down
1 change: 1 addition & 0 deletions Modules/_testinternalcapi.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "pycore_context.h" // _PyContext_NewHamtForTests()
#include "pycore_dict.h" // _PyManagedDictPointer_GetValues()
#include "pycore_fileutils.h" // _Py_normpath()
#include "pycore_flowgraph.h" // _PyCompile_OptimizeCfg()
#include "pycore_frame.h" // _PyInterpreterFrame
#include "pycore_gc.h" // PyGC_Head
#include "pycore_hashtable.h" // _Py_hashtable_new()
Expand Down
155 changes: 8 additions & 147 deletions Python/compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -197,47 +197,6 @@ _PyCompile_EnsureArrayLargeEnough(int idx, void **array, int *alloc,
return SUCCESS;
}

static cfg_builder*
instr_sequence_to_cfg(instr_sequence *seq) {
if (_PyInstructionSequence_ApplyLabelMap(seq) < 0) {
return NULL;
}
cfg_builder *g = _PyCfgBuilder_New();
if (g == NULL) {
return NULL;
}
for (int i = 0; i < seq->s_used; i++) {
seq->s_instrs[i].i_target = 0;
}
for (int i = 0; i < seq->s_used; i++) {
instruction *instr = &seq->s_instrs[i];
if (HAS_TARGET(instr->i_opcode)) {
assert(instr->i_oparg >= 0 && instr->i_oparg < seq->s_used);
seq->s_instrs[instr->i_oparg].i_target = 1;
}
}
for (int i = 0; i < seq->s_used; i++) {
instruction *instr = &seq->s_instrs[i];
if (instr->i_target) {
jump_target_label lbl_ = {i};
if (_PyCfgBuilder_UseLabel(g, lbl_) < 0) {
goto error;
}
}
int opcode = instr->i_opcode;
int oparg = instr->i_oparg;
if (_PyCfgBuilder_Addop(g, opcode, oparg, instr->i_loc) < 0) {
goto error;
}
}
if (_PyCfgBuilder_CheckSize(g) < 0) {
goto error;
}
return g;
error:
_PyCfgBuilder_Free(g);
return NULL;
}

/* The following items change on entry and exit of code blocks.
They must be saved and restored when returning to a block.
Expand Down Expand Up @@ -691,48 +650,6 @@ compiler_set_qualname(struct compiler *c)
return SUCCESS;
}

/* Return the stack effect of opcode with argument oparg.

Some opcodes have different stack effect when jump to the target and
when not jump. The 'jump' parameter specifies the case:

* 0 -- when not jump
* 1 -- when jump
* -1 -- maximal
*/
static int
stack_effect(int opcode, int oparg, int jump)
{
if (opcode < 0) {
return PY_INVALID_STACK_EFFECT;
}
if ((opcode <= MAX_REAL_OPCODE) && (_PyOpcode_Deopt[opcode] != opcode)) {
// Specialized instructions are not supported.
return PY_INVALID_STACK_EFFECT;
}
int popped = _PyOpcode_num_popped(opcode, oparg);
int pushed = _PyOpcode_num_pushed(opcode, oparg);
if (popped < 0 || pushed < 0) {
return PY_INVALID_STACK_EFFECT;
}
if (IS_BLOCK_PUSH_OPCODE(opcode) && !jump) {
return 0;
}
return pushed - popped;
}

int
PyCompile_OpcodeStackEffectWithJump(int opcode, int oparg, int jump)
{
return stack_effect(opcode, oparg, jump);
}

int
PyCompile_OpcodeStackEffect(int opcode, int oparg)
{
return stack_effect(opcode, oparg, -1);
}

int
_PyCompile_OpcodeIsValid(int opcode)
{
Expand Down Expand Up @@ -7592,7 +7509,7 @@ optimize_and_assemble_code_unit(struct compiler_unit *u, PyObject *const_cache,
if (consts == NULL) {
goto error;
}
g = instr_sequence_to_cfg(u->u_instr_sequence);
g = _PyCfg_FromInstructionSequence(u->u_instr_sequence);
if (g == NULL) {
goto error;
}
Expand Down Expand Up @@ -7645,39 +7562,6 @@ optimize_and_assemble(struct compiler *c, int addNone)
return optimize_and_assemble_code_unit(u, const_cache, code_flags, filename);
}

/* Access to compiler optimizations for unit tests.
*
* _PyCompile_CodeGen takes and AST, applies code-gen and
* returns the unoptimized CFG as an instruction list.
*
* _PyCompile_OptimizeCfg takes an instruction list, constructs
* a CFG, optimizes it and converts back to an instruction list.
*
* An instruction list is a PyList where each item is either
* a tuple describing a single instruction:
* (opcode, oparg, lineno, end_lineno, col, end_col), or
* a jump target label marking the beginning of a basic block.
*/


static PyObject *
cfg_to_instruction_sequence(cfg_builder *g)
{
instr_sequence *seq = (instr_sequence *)_PyInstructionSequence_New();
if (seq != NULL) {
if (_PyCfg_ToInstructionSequence(g, seq) < 0) {
goto error;
}
if (_PyInstructionSequence_ApplyLabelMap(seq) < 0) {
goto error;
}
}
return (PyObject*)seq;
error:
PyInstructionSequence_Fini(seq);
return NULL;
}

// C implementation of inspect.cleandoc()
//
// Difference from inspect.cleandoc():
Expand Down Expand Up @@ -7768,6 +7652,12 @@ _PyCompile_CleanDoc(PyObject *doc)
return res;
}

/* Access to compiler optimizations for unit tests.
*
* _PyCompile_CodeGen takes an AST, applies code-gen and
* returns the unoptimized CFG as an instruction list.
*
*/

PyObject *
_PyCompile_CodeGen(PyObject *ast, PyObject *filename, PyCompilerFlags *pflags,
Expand Down Expand Up @@ -7859,35 +7749,6 @@ _PyCompile_CodeGen(PyObject *ast, PyObject *filename, PyCompilerFlags *pflags,
return res;
}

PyObject *
_PyCompile_OptimizeCfg(PyObject *seq, PyObject *consts, int nlocals)
{
if (!_PyInstructionSequence_Check(seq)) {
PyErr_SetString(PyExc_ValueError, "expected an instruction sequence");
return NULL;
}
PyObject *const_cache = PyDict_New();
if (const_cache == NULL) {
return NULL;
}

PyObject *res = NULL;
cfg_builder *g = instr_sequence_to_cfg((instr_sequence*)seq);
if (g == NULL) {
goto error;
}
int nparams = 0, firstlineno = 1;
if (_PyCfg_OptimizeCodeUnit(g, consts, const_cache, nlocals,
nparams, firstlineno) < 0) {
goto error;
}
res = cfg_to_instruction_sequence(g);
error:
Py_DECREF(const_cache);
_PyCfgBuilder_Free(g);
return res;
}

int _PyCfg_JumpLabelsToTargets(cfg_builder *g);

PyCodeObject *
Expand All @@ -7908,7 +7769,7 @@ _PyCompile_Assemble(_PyCompile_CodeUnitMetadata *umd, PyObject *filename,
return NULL;
}

g = instr_sequence_to_cfg((instr_sequence*)seq);
g = _PyCfg_FromInstructionSequence((instr_sequence*)seq);
if (g == NULL) {
goto error;
}
Expand Down
Loading
Loading