Skip to content

gh-121404: rename compiler_addop* to codegen_addop*, and replace direct usages by the macros #123043

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 2 commits into from
Aug 16, 2024
Merged
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
198 changes: 102 additions & 96 deletions Python/compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,13 @@
return ERROR; \
}

#define RETURN_IF_ERROR_IN_SCOPE(C, CALL) { \
if ((CALL) < 0) { \
compiler_exit_scope((C)); \
return ERROR; \
} \
}

#define IS_TOP_LEVEL_AWAIT(C) ( \
((C)->c_flags.cf_flags & PyCF_ALLOW_TOP_LEVEL_AWAIT) \
&& ((C)->u->u_ste->ste_type == ModuleBlock))
Expand Down Expand Up @@ -291,8 +298,6 @@ typedef struct {
Py_ssize_t on_top;
} pattern_context;

static int codegen_addop_i(instr_sequence *seq, int opcode, Py_ssize_t oparg, location loc);

static void compiler_free(struct compiler *);
static int compiler_error(struct compiler *, location loc, const char *, ...);
static int compiler_warn(struct compiler *, location loc, const char *, ...);
Expand Down Expand Up @@ -685,6 +690,29 @@ compiler_set_qualname(struct compiler *c)
return SUCCESS;
}

/* Add an opcode with an integer argument */
static int
codegen_addop_i(instr_sequence *seq, int opcode, Py_ssize_t oparg, location loc)
{
/* oparg value is unsigned, but a signed C int is usually used to store
it in the C code (like Python/ceval.c).

Limit to 32-bit signed C int (rather than INT_MAX) for portability.

The argument of a concrete bytecode instruction is limited to 8-bit.
EXTENDED_ARG is used for 16, 24, and 32-bit arguments. */

int oparg_ = Py_SAFE_DOWNCAST(oparg, Py_ssize_t, int);
assert(!IS_ASSEMBLER_OPCODE(opcode));
return _PyInstructionSequence_Addop(seq, opcode, oparg_, loc);
}

#define ADDOP_I(C, LOC, OP, O) \
RETURN_IF_ERROR(codegen_addop_i(INSTR_SEQUENCE(C), (OP), (O), (LOC)))

#define ADDOP_I_IN_SCOPE(C, LOC, OP, O) \
RETURN_IF_ERROR_IN_SCOPE(C, codegen_addop_i(INSTR_SEQUENCE(C), (OP), (O), (LOC)));

static int
codegen_addop_noarg(instr_sequence *seq, int opcode, location loc)
{
Expand All @@ -693,6 +721,12 @@ codegen_addop_noarg(instr_sequence *seq, int opcode, location loc)
return _PyInstructionSequence_Addop(seq, opcode, 0, loc);
}

#define ADDOP(C, LOC, OP) \
RETURN_IF_ERROR(codegen_addop_noarg(INSTR_SEQUENCE(C), (OP), (LOC)))

#define ADDOP_IN_SCOPE(C, LOC, OP) \
RETURN_IF_ERROR_IN_SCOPE((C), codegen_addop_noarg(INSTR_SEQUENCE(C), (OP), (LOC)))

static Py_ssize_t
dict_add_o(PyObject *dict, PyObject *o)
{
Expand Down Expand Up @@ -854,24 +888,57 @@ compiler_add_const(struct compiler *c, PyObject *o)
}

static int
compiler_addop_load_const(struct compiler *c, location loc, PyObject *o)
codegen_addop_load_const(struct compiler *c, location loc, PyObject *o)
{
Py_ssize_t arg = compiler_add_const(c, o);
if (arg < 0) {
return ERROR;
}
return codegen_addop_i(INSTR_SEQUENCE(c), LOAD_CONST, arg, loc);
ADDOP_I(c, loc, LOAD_CONST, arg);
return SUCCESS;
}

#define ADDOP_LOAD_CONST(C, LOC, O) \
RETURN_IF_ERROR(codegen_addop_load_const((C), (LOC), (O)))

#define ADDOP_LOAD_CONST_IN_SCOPE(C, LOC, O) \
RETURN_IF_ERROR_IN_SCOPE((C), codegen_addop_load_const((C), (LOC), (O)))

/* Same as ADDOP_LOAD_CONST, but steals a reference. */
#define ADDOP_LOAD_CONST_NEW(C, LOC, O) { \
PyObject *__new_const = (O); \
if (__new_const == NULL) { \
return ERROR; \
} \
if (codegen_addop_load_const((C), (LOC), __new_const) < 0) { \
Py_DECREF(__new_const); \
return ERROR; \
} \
Py_DECREF(__new_const); \
}

static int
compiler_addop_o(struct compiler *c, location loc,
int opcode, PyObject *dict, PyObject *o)
codegen_addop_o(struct compiler *c, location loc,
int opcode, PyObject *dict, PyObject *o)
{
Py_ssize_t arg = dict_add_o(dict, o);
if (arg < 0) {
return ERROR;
}
return codegen_addop_i(INSTR_SEQUENCE(c), opcode, arg, loc);
RETURN_IF_ERROR(arg);
ADDOP_I(c, loc, opcode, arg);
return SUCCESS;
}

#define ADDOP_N(C, LOC, OP, O, TYPE) { \
assert(!OPCODE_HAS_CONST(OP)); /* use ADDOP_LOAD_CONST_NEW */ \
int ret = codegen_addop_o((C), (LOC), (OP), (C)->u->u_metadata.u_ ## TYPE, (O)); \
Py_DECREF((O)); \
RETURN_IF_ERROR(ret); \
}

#define ADDOP_N_IN_SCOPE(C, LOC, OP, O, TYPE) { \
assert(!OPCODE_HAS_CONST(OP)); /* use ADDOP_LOAD_CONST_NEW */ \
int ret = codegen_addop_o((C), (LOC), (OP), (C)->u->u_metadata.u_ ## TYPE, (O)); \
Py_DECREF((O)); \
RETURN_IF_ERROR_IN_SCOPE((C), ret); \
}

#define LOAD_METHOD -1
Expand All @@ -880,8 +947,8 @@ compiler_addop_o(struct compiler *c, location loc,
#define LOAD_ZERO_SUPER_METHOD -4

static int
compiler_addop_name(struct compiler *c, location loc,
int opcode, PyObject *dict, PyObject *o)
codegen_addop_name(struct compiler *c, location loc,
int opcode, PyObject *dict, PyObject *o)
{
PyObject *mangled = compiler_maybe_mangle(c, o);
if (!mangled) {
Expand Down Expand Up @@ -918,25 +985,12 @@ compiler_addop_name(struct compiler *c, location loc,
arg <<= 2;
arg |= 1;
}
return codegen_addop_i(INSTR_SEQUENCE(c), opcode, arg, loc);
ADDOP_I(c, loc, opcode, arg);
return SUCCESS;
}

/* Add an opcode with an integer argument */
static int
codegen_addop_i(instr_sequence *seq, int opcode, Py_ssize_t oparg, location loc)
{
/* oparg value is unsigned, but a signed C int is usually used to store
it in the C code (like Python/ceval.c).

Limit to 32-bit signed C int (rather than INT_MAX) for portability.

The argument of a concrete bytecode instruction is limited to 8-bit.
EXTENDED_ARG is used for 16, 24, and 32-bit arguments. */

int oparg_ = Py_SAFE_DOWNCAST(oparg, Py_ssize_t, int);
assert(!IS_ASSEMBLER_OPCODE(opcode));
return _PyInstructionSequence_Addop(seq, opcode, oparg_, loc);
}
#define ADDOP_NAME(C, LOC, OP, O, TYPE) \
RETURN_IF_ERROR(codegen_addop_name((C), (LOC), (OP), (C)->u->u_metadata.u_ ## TYPE, (O)))

static int
codegen_addop_j(instr_sequence *seq, location loc,
Expand All @@ -948,49 +1002,6 @@ codegen_addop_j(instr_sequence *seq, location loc,
return _PyInstructionSequence_Addop(seq, opcode, target.id, loc);
}

#define RETURN_IF_ERROR_IN_SCOPE(C, CALL) { \
if ((CALL) < 0) { \
compiler_exit_scope((C)); \
return ERROR; \
} \
}

#define ADDOP(C, LOC, OP) \
RETURN_IF_ERROR(codegen_addop_noarg(INSTR_SEQUENCE(C), (OP), (LOC)))

#define ADDOP_IN_SCOPE(C, LOC, OP) RETURN_IF_ERROR_IN_SCOPE((C), codegen_addop_noarg(INSTR_SEQUENCE(C), (OP), (LOC)))

#define ADDOP_LOAD_CONST(C, LOC, O) \
RETURN_IF_ERROR(compiler_addop_load_const((C), (LOC), (O)))

/* Same as ADDOP_LOAD_CONST, but steals a reference. */
#define ADDOP_LOAD_CONST_NEW(C, LOC, O) { \
PyObject *__new_const = (O); \
if (__new_const == NULL) { \
return ERROR; \
} \
if (compiler_addop_load_const((C), (LOC), __new_const) < 0) { \
Py_DECREF(__new_const); \
return ERROR; \
} \
Py_DECREF(__new_const); \
}

#define ADDOP_N(C, LOC, OP, O, TYPE) { \
assert(!OPCODE_HAS_CONST(OP)); /* use ADDOP_LOAD_CONST_NEW */ \
if (compiler_addop_o((C), (LOC), (OP), (C)->u->u_metadata.u_ ## TYPE, (O)) < 0) { \
Py_DECREF((O)); \
return ERROR; \
} \
Py_DECREF((O)); \
}

#define ADDOP_NAME(C, LOC, OP, O, TYPE) \
RETURN_IF_ERROR(compiler_addop_name((C), (LOC), (OP), (C)->u->u_metadata.u_ ## TYPE, (O)))

#define ADDOP_I(C, LOC, OP, O) \
RETURN_IF_ERROR(codegen_addop_i(INSTR_SEQUENCE(C), (OP), (O), (LOC)))

#define ADDOP_JUMP(C, LOC, OP, O) \
RETURN_IF_ERROR(codegen_addop_j(INSTR_SEQUENCE(C), (LOC), (OP), (O)))

Expand Down Expand Up @@ -2279,7 +2290,7 @@ compiler_function(struct compiler *c, stmt_ty s, int is_async)
Py_DECREF(type_params_name);
RETURN_IF_ERROR_IN_SCOPE(c, compiler_type_params(c, type_params));
for (int i = 0; i < num_typeparam_args; i++) {
RETURN_IF_ERROR_IN_SCOPE(c, codegen_addop_i(INSTR_SEQUENCE(c), LOAD_FAST, i, loc));
ADDOP_I_IN_SCOPE(c, loc, LOAD_FAST, i);
}
}

Expand All @@ -2300,10 +2311,8 @@ compiler_function(struct compiler *c, stmt_ty s, int is_async)
}

if (is_generic) {
RETURN_IF_ERROR_IN_SCOPE(c, codegen_addop_i(
INSTR_SEQUENCE(c), SWAP, 2, loc));
RETURN_IF_ERROR_IN_SCOPE(c, codegen_addop_i(
INSTR_SEQUENCE(c), CALL_INTRINSIC_2, INTRINSIC_SET_FUNCTION_TYPE_PARAMS, loc));
ADDOP_I_IN_SCOPE(c, loc, SWAP, 2);
ADDOP_I_IN_SCOPE(c, loc, CALL_INTRINSIC_2, INTRINSIC_SET_FUNCTION_TYPE_PARAMS);

c->u->u_metadata.u_argcount = num_typeparam_args;
PyCodeObject *co = optimize_and_assemble(c, 0);
Expand Down Expand Up @@ -2393,12 +2402,7 @@ compiler_class_body(struct compiler *c, stmt_ty s, int firstlineno)
// We can't use compiler_nameop here because we need to generate a
// STORE_DEREF in a class namespace, and compiler_nameop() won't do
// that by default.
PyObject *cellvars = c->u->u_metadata.u_cellvars;
if (compiler_addop_o(c, loc, STORE_DEREF, cellvars,
&_Py_ID(__classdict__)) < 0) {
compiler_exit_scope(c);
return ERROR;
}
ADDOP_N_IN_SCOPE(c, loc, STORE_DEREF, &_Py_ID(__classdict__), cellvars);
}
/* compile the body proper */
if (compiler_body(c, loc, s->v.ClassDef.body) < 0) {
Expand Down Expand Up @@ -2527,9 +2531,7 @@ compiler_class(struct compiler *c, stmt_ty s)
_Py_DECLARE_STR(type_params, ".type_params");
_Py_DECLARE_STR(generic_base, ".generic_base");
RETURN_IF_ERROR_IN_SCOPE(c, compiler_nameop(c, loc, &_Py_STR(type_params), Load));
RETURN_IF_ERROR_IN_SCOPE(
c, codegen_addop_i(INSTR_SEQUENCE(c), CALL_INTRINSIC_1, INTRINSIC_SUBSCRIPT_GENERIC, loc)
)
ADDOP_I_IN_SCOPE(c, loc, CALL_INTRINSIC_1, INTRINSIC_SUBSCRIPT_GENERIC);
RETURN_IF_ERROR_IN_SCOPE(c, compiler_nameop(c, loc, &_Py_STR(generic_base), Store));

Py_ssize_t original_len = asdl_seq_LEN(s->v.ClassDef.bases);
Expand Down Expand Up @@ -2630,9 +2632,7 @@ compiler_typealias(struct compiler *c, stmt_ty s)
return ERROR;
}
Py_DECREF(type_params_name);
RETURN_IF_ERROR_IN_SCOPE(
c, compiler_addop_load_const(c, loc, name)
);
ADDOP_LOAD_CONST_IN_SCOPE(c, loc, name);
RETURN_IF_ERROR_IN_SCOPE(c, compiler_type_params(c, type_params));
}
else {
Expand Down Expand Up @@ -2713,8 +2713,8 @@ check_compare(struct compiler *c, expr_ty e)
return SUCCESS;
}

static int compiler_addcompare(struct compiler *c, location loc,
cmpop_ty op)
static int
compiler_addcompare(struct compiler *c, location loc, cmpop_ty op)
{
int cmp;
switch (op) {
Expand Down Expand Up @@ -4040,6 +4040,13 @@ addop_yield(struct compiler *c, location loc) {
return SUCCESS;
}

static int
compiler_load_classdict_freevar(struct compiler *c, location loc)
{
ADDOP_N(c, loc, LOAD_DEREF, &_Py_ID(__classdict__), freevars);
return SUCCESS;
}

static int
compiler_nameop(struct compiler *c, location loc,
identifier name, expr_context_ty ctx)
Expand Down Expand Up @@ -4119,8 +4126,7 @@ compiler_nameop(struct compiler *c, location loc,
else if (SYMTABLE_ENTRY(c)->ste_can_see_class_scope) {
op = LOAD_FROM_DICT_OR_DEREF;
// First load the classdict
if (compiler_addop_o(c, loc, LOAD_DEREF,
c->u->u_metadata.u_freevars, &_Py_ID(__classdict__)) < 0) {
if (compiler_load_classdict_freevar(c, loc) < 0) {
goto error;
}
}
Expand All @@ -4146,8 +4152,7 @@ compiler_nameop(struct compiler *c, location loc,
if (SYMTABLE_ENTRY(c)->ste_can_see_class_scope && scope == GLOBAL_IMPLICIT) {
op = LOAD_FROM_DICT_OR_GLOBALS;
// First load the classdict
if (compiler_addop_o(c, loc, LOAD_DEREF,
c->u->u_metadata.u_freevars, &_Py_ID(__classdict__)) < 0) {
if (compiler_load_classdict_freevar(c, loc) < 0) {
goto error;
}
} else {
Expand Down Expand Up @@ -4181,7 +4186,8 @@ compiler_nameop(struct compiler *c, location loc,
if (op == LOAD_GLOBAL) {
arg <<= 1;
}
return codegen_addop_i(INSTR_SEQUENCE(c), op, arg, loc);
ADDOP_I(c, loc, op, arg);
return SUCCESS;

error:
Py_DECREF(mangled);
Expand Down
Loading