From 9c81fc2dbee3ac8a2f30ad24b0876d80628a94ac Mon Sep 17 00:00:00 2001 From: Irit Katriel <1055913+iritkatriel@users.noreply.github.com> Date: Thu, 20 Jul 2023 17:46:04 +0100 Subject: [PATCH] gh-105481: do not auto-generate pycore_intrinsics.h (#106913) --- Include/cpython/compile.h | 2 + Include/internal/pycore_intrinsics.h | 20 ++++++-- Lib/opcode.py | 26 ++--------- Makefile.pre.in | 4 +- Modules/_opcode.c | 57 +++++++++++++++++++++++ Modules/clinic/_opcode.c.h | 38 ++++++++++++++- Python/bytecodes.c | 4 +- Python/executor_cases.c.h | 4 +- Python/generated_cases.c.h | 4 +- Python/intrinsics.c | 69 ++++++++++++++++++++-------- Tools/build/generate_opcode_h.py | 37 ++------------- 11 files changed, 174 insertions(+), 91 deletions(-) diff --git a/Include/cpython/compile.h b/Include/cpython/compile.h index fd526978402..e6cd39af2ba 100644 --- a/Include/cpython/compile.h +++ b/Include/cpython/compile.h @@ -77,3 +77,5 @@ PyAPI_FUNC(int) PyUnstable_OpcodeHasFree(int opcode); PyAPI_FUNC(int) PyUnstable_OpcodeHasLocal(int opcode); PyAPI_FUNC(int) PyUnstable_OpcodeHasExc(int opcode); +PyAPI_FUNC(PyObject*) _PyUnstable_GetUnaryIntrinsicName(int index); +PyAPI_FUNC(PyObject*) _PyUnstable_GetBinaryIntrinsicName(int index); diff --git a/Include/internal/pycore_intrinsics.h b/Include/internal/pycore_intrinsics.h index 39f15681b7b..37d4efc12bb 100644 --- a/Include/internal/pycore_intrinsics.h +++ b/Include/internal/pycore_intrinsics.h @@ -1,4 +1,3 @@ -// Auto-generated by Tools/build/generate_opcode_h.py from Lib/opcode.py /* Unary Functions: */ #define INTRINSIC_1_INVALID 0 @@ -26,7 +25,18 @@ #define MAX_INTRINSIC_2 4 -typedef PyObject *(*instrinsic_func1)(PyThreadState* tstate, PyObject *value); -typedef PyObject *(*instrinsic_func2)(PyThreadState* tstate, PyObject *value1, PyObject *value2); -extern const instrinsic_func1 _PyIntrinsics_UnaryFunctions[]; -extern const instrinsic_func2 _PyIntrinsics_BinaryFunctions[]; +typedef PyObject *(*intrinsic_func1)(PyThreadState* tstate, PyObject *value); +typedef PyObject *(*intrinsic_func2)(PyThreadState* tstate, PyObject *value1, PyObject *value2); + +typedef struct { + intrinsic_func1 func; + const char *name; +} intrinsic_func1_info; + +typedef struct { + intrinsic_func2 func; + const char *name; +} intrinsic_func2_info; + +extern const intrinsic_func1_info _PyIntrinsics_UnaryFunctions[]; +extern const intrinsic_func2_info _PyIntrinsics_BinaryFunctions[]; diff --git a/Lib/opcode.py b/Lib/opcode.py index 08dfd2674dc..36831d8a122 100644 --- a/Lib/opcode.py +++ b/Lib/opcode.py @@ -257,6 +257,9 @@ if sys.version_info[:2] >= (3, 13): __all__.extend(["hasarg", "hasconst", "hasname", "hasjump", "hasjrel", "hasjabs", "hasfree", "haslocal", "hasexc"]) + _intrinsic_1_descs = _opcode.get_intrinsic1_descs() + _intrinsic_2_descs = _opcode.get_intrinsic2_descs() + hascompare = [opmap["COMPARE_OP"]] _nb_ops = [ @@ -288,29 +291,6 @@ _nb_ops = [ ("NB_INPLACE_XOR", "^="), ] -_intrinsic_1_descs = [ - "INTRINSIC_1_INVALID", - "INTRINSIC_PRINT", - "INTRINSIC_IMPORT_STAR", - "INTRINSIC_STOPITERATION_ERROR", - "INTRINSIC_ASYNC_GEN_WRAP", - "INTRINSIC_UNARY_POSITIVE", - "INTRINSIC_LIST_TO_TUPLE", - "INTRINSIC_TYPEVAR", - "INTRINSIC_PARAMSPEC", - "INTRINSIC_TYPEVARTUPLE", - "INTRINSIC_SUBSCRIPT_GENERIC", - "INTRINSIC_TYPEALIAS", -] - -_intrinsic_2_descs = [ - "INTRINSIC_2_INVALID", - "INTRINSIC_PREP_RERAISE_STAR", - "INTRINSIC_TYPEVAR_WITH_BOUND", - "INTRINSIC_TYPEVAR_WITH_CONSTRAINTS", - "INTRINSIC_SET_FUNCTION_TYPE_PARAMS", -] - _cache_format = { "LOAD_GLOBAL": { diff --git a/Makefile.pre.in b/Makefile.pre.in index 553b2aa480c..f4f6ff595b0 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -1427,11 +1427,9 @@ regen-opcode: $(srcdir)/Lib/opcode.py \ $(srcdir)/Lib/_opcode_metadata.py \ $(srcdir)/Include/opcode.h.new \ - $(srcdir)/Include/internal/pycore_opcode.h.new \ - $(srcdir)/Include/internal/pycore_intrinsics.h.new + $(srcdir)/Include/internal/pycore_opcode.h.new $(UPDATE_FILE) $(srcdir)/Include/opcode.h $(srcdir)/Include/opcode.h.new $(UPDATE_FILE) $(srcdir)/Include/internal/pycore_opcode.h $(srcdir)/Include/internal/pycore_opcode.h.new - $(UPDATE_FILE) $(srcdir)/Include/internal/pycore_intrinsics.h $(srcdir)/Include/internal/pycore_intrinsics.h.new .PHONY: regen-token regen-token: diff --git a/Modules/_opcode.c b/Modules/_opcode.c index daabdce1655..b8d95a048ec 100644 --- a/Modules/_opcode.c +++ b/Modules/_opcode.c @@ -2,6 +2,7 @@ #include "compile.h" #include "opcode.h" #include "internal/pycore_code.h" +#include "internal/pycore_intrinsics.h" /*[clinic input] module _opcode @@ -220,6 +221,60 @@ _opcode_get_specialization_stats_impl(PyObject *module) #endif } +/*[clinic input] + +_opcode.get_intrinsic1_descs + +Return a list of names of the unary intrinsics. +[clinic start generated code]*/ + +static PyObject * +_opcode_get_intrinsic1_descs_impl(PyObject *module) +/*[clinic end generated code: output=bd1ddb6b4447d18b input=13b51c712618459b]*/ +{ + PyObject *list = PyList_New(MAX_INTRINSIC_1 + 1); + if (list == NULL) { + return NULL; + } + for (int i=0; i <= MAX_INTRINSIC_1; i++) { + PyObject *name = _PyUnstable_GetUnaryIntrinsicName(i); + if (name == NULL) { + Py_DECREF(list); + return NULL; + } + PyList_SET_ITEM(list, i, name); + } + return list; +} + + +/*[clinic input] + +_opcode.get_intrinsic2_descs + +Return a list of names of the binary intrinsics. +[clinic start generated code]*/ + +static PyObject * +_opcode_get_intrinsic2_descs_impl(PyObject *module) +/*[clinic end generated code: output=40e62bc27584c8a0 input=e83068f249f5471b]*/ +{ + PyObject *list = PyList_New(MAX_INTRINSIC_2 + 1); + if (list == NULL) { + return NULL; + } + for (int i=0; i <= MAX_INTRINSIC_2; i++) { + PyObject *name = _PyUnstable_GetBinaryIntrinsicName(i); + if (name == NULL) { + Py_DECREF(list); + return NULL; + } + PyList_SET_ITEM(list, i, name); + } + return list; +} + + static PyMethodDef opcode_functions[] = { _OPCODE_STACK_EFFECT_METHODDEF @@ -232,6 +287,8 @@ opcode_functions[] = { _OPCODE_HAS_LOCAL_METHODDEF _OPCODE_HAS_EXC_METHODDEF _OPCODE_GET_SPECIALIZATION_STATS_METHODDEF + _OPCODE_GET_INTRINSIC1_DESCS_METHODDEF + _OPCODE_GET_INTRINSIC2_DESCS_METHODDEF {NULL, NULL, 0, NULL} }; diff --git a/Modules/clinic/_opcode.c.h b/Modules/clinic/_opcode.c.h index e6381fa73a5..e1fc5ba17f7 100644 --- a/Modules/clinic/_opcode.c.h +++ b/Modules/clinic/_opcode.c.h @@ -612,4 +612,40 @@ _opcode_get_specialization_stats(PyObject *module, PyObject *Py_UNUSED(ignored)) { return _opcode_get_specialization_stats_impl(module); } -/*[clinic end generated code: output=e507bf14fb2796f8 input=a9049054013a1b77]*/ + +PyDoc_STRVAR(_opcode_get_intrinsic1_descs__doc__, +"get_intrinsic1_descs($module, /)\n" +"--\n" +"\n" +"Return a list of names of the unary intrinsics."); + +#define _OPCODE_GET_INTRINSIC1_DESCS_METHODDEF \ + {"get_intrinsic1_descs", (PyCFunction)_opcode_get_intrinsic1_descs, METH_NOARGS, _opcode_get_intrinsic1_descs__doc__}, + +static PyObject * +_opcode_get_intrinsic1_descs_impl(PyObject *module); + +static PyObject * +_opcode_get_intrinsic1_descs(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _opcode_get_intrinsic1_descs_impl(module); +} + +PyDoc_STRVAR(_opcode_get_intrinsic2_descs__doc__, +"get_intrinsic2_descs($module, /)\n" +"--\n" +"\n" +"Return a list of names of the binary intrinsics."); + +#define _OPCODE_GET_INTRINSIC2_DESCS_METHODDEF \ + {"get_intrinsic2_descs", (PyCFunction)_opcode_get_intrinsic2_descs, METH_NOARGS, _opcode_get_intrinsic2_descs__doc__}, + +static PyObject * +_opcode_get_intrinsic2_descs_impl(PyObject *module); + +static PyObject * +_opcode_get_intrinsic2_descs(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _opcode_get_intrinsic2_descs_impl(module); +} +/*[clinic end generated code: output=d85de5f2887b3661 input=a9049054013a1b77]*/ diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 81d6f80709a..b9434390ea4 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -698,14 +698,14 @@ dummy_func( inst(CALL_INTRINSIC_1, (value -- res)) { assert(oparg <= MAX_INTRINSIC_1); - res = _PyIntrinsics_UnaryFunctions[oparg](tstate, value); + res = _PyIntrinsics_UnaryFunctions[oparg].func(tstate, value); DECREF_INPUTS(); ERROR_IF(res == NULL, error); } inst(CALL_INTRINSIC_2, (value2, value1 -- res)) { assert(oparg <= MAX_INTRINSIC_2); - res = _PyIntrinsics_BinaryFunctions[oparg](tstate, value2, value1); + res = _PyIntrinsics_BinaryFunctions[oparg].func(tstate, value2, value1); DECREF_INPUTS(); ERROR_IF(res == NULL, error); } diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index 90607e86c04..5b38c6a5fd8 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -558,7 +558,7 @@ PyObject *value = stack_pointer[-1]; PyObject *res; assert(oparg <= MAX_INTRINSIC_1); - res = _PyIntrinsics_UnaryFunctions[oparg](tstate, value); + res = _PyIntrinsics_UnaryFunctions[oparg].func(tstate, value); Py_DECREF(value); if (res == NULL) goto pop_1_error; stack_pointer[-1] = res; @@ -570,7 +570,7 @@ PyObject *value2 = stack_pointer[-2]; PyObject *res; assert(oparg <= MAX_INTRINSIC_2); - res = _PyIntrinsics_BinaryFunctions[oparg](tstate, value2, value1); + res = _PyIntrinsics_BinaryFunctions[oparg].func(tstate, value2, value1); Py_DECREF(value2); Py_DECREF(value1); if (res == NULL) goto pop_2_error; diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index c35b81aee88..2d70966aa09 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -849,7 +849,7 @@ PyObject *value = stack_pointer[-1]; PyObject *res; assert(oparg <= MAX_INTRINSIC_1); - res = _PyIntrinsics_UnaryFunctions[oparg](tstate, value); + res = _PyIntrinsics_UnaryFunctions[oparg].func(tstate, value); Py_DECREF(value); if (res == NULL) goto pop_1_error; stack_pointer[-1] = res; @@ -861,7 +861,7 @@ PyObject *value2 = stack_pointer[-2]; PyObject *res; assert(oparg <= MAX_INTRINSIC_2); - res = _PyIntrinsics_BinaryFunctions[oparg](tstate, value2, value1); + res = _PyIntrinsics_BinaryFunctions[oparg].func(tstate, value2, value1); Py_DECREF(value2); Py_DECREF(value1); if (res == NULL) goto pop_2_error; diff --git a/Python/intrinsics.c b/Python/intrinsics.c index 037b74ca820..61a8e75872d 100644 --- a/Python/intrinsics.c +++ b/Python/intrinsics.c @@ -14,7 +14,7 @@ /******** Unary functions ********/ static PyObject * -no_intrinsic(PyThreadState* tstate, PyObject *unused) +no_intrinsic1(PyThreadState* tstate, PyObject *unused) { _PyErr_SetString(tstate, PyExc_SystemError, "invalid intrinsic function"); return NULL; @@ -203,25 +203,35 @@ make_typevar(PyThreadState* Py_UNUSED(ignored), PyObject *v) return _Py_make_typevar(v, NULL, NULL); } -const instrinsic_func1 + +#define INTRINSIC_FUNC_ENTRY(N, F) \ + [N] = {F, #N}, + +const intrinsic_func1_info _PyIntrinsics_UnaryFunctions[] = { - [0] = no_intrinsic, - [INTRINSIC_PRINT] = print_expr, - [INTRINSIC_IMPORT_STAR] = import_star, - [INTRINSIC_STOPITERATION_ERROR] = stopiteration_error, - [INTRINSIC_ASYNC_GEN_WRAP] = _PyAsyncGenValueWrapperNew, - [INTRINSIC_UNARY_POSITIVE] = unary_pos, - [INTRINSIC_LIST_TO_TUPLE] = list_to_tuple, - [INTRINSIC_TYPEVAR] = make_typevar, - [INTRINSIC_PARAMSPEC] = _Py_make_paramspec, - [INTRINSIC_TYPEVARTUPLE] = _Py_make_typevartuple, - [INTRINSIC_SUBSCRIPT_GENERIC] = _Py_subscript_generic, - [INTRINSIC_TYPEALIAS] = _Py_make_typealias, + INTRINSIC_FUNC_ENTRY(INTRINSIC_1_INVALID, no_intrinsic1) + INTRINSIC_FUNC_ENTRY(INTRINSIC_PRINT, print_expr) + INTRINSIC_FUNC_ENTRY(INTRINSIC_IMPORT_STAR, import_star) + INTRINSIC_FUNC_ENTRY(INTRINSIC_STOPITERATION_ERROR, stopiteration_error) + INTRINSIC_FUNC_ENTRY(INTRINSIC_ASYNC_GEN_WRAP, _PyAsyncGenValueWrapperNew) + INTRINSIC_FUNC_ENTRY(INTRINSIC_UNARY_POSITIVE, unary_pos) + INTRINSIC_FUNC_ENTRY(INTRINSIC_LIST_TO_TUPLE, list_to_tuple) + INTRINSIC_FUNC_ENTRY(INTRINSIC_TYPEVAR, make_typevar) + INTRINSIC_FUNC_ENTRY(INTRINSIC_PARAMSPEC, _Py_make_paramspec) + INTRINSIC_FUNC_ENTRY(INTRINSIC_TYPEVARTUPLE, _Py_make_typevartuple) + INTRINSIC_FUNC_ENTRY(INTRINSIC_SUBSCRIPT_GENERIC, _Py_subscript_generic) + INTRINSIC_FUNC_ENTRY(INTRINSIC_TYPEALIAS, _Py_make_typealias) }; /******** Binary functions ********/ +static PyObject * +no_intrinsic2(PyThreadState* tstate, PyObject *unused1, PyObject *unused2) +{ + _PyErr_SetString(tstate, PyExc_SystemError, "invalid intrinsic function"); + return NULL; +} static PyObject * prep_reraise_star(PyThreadState* unused, PyObject *orig, PyObject *excs) @@ -246,10 +256,31 @@ make_typevar_with_constraints(PyThreadState* Py_UNUSED(ignored), PyObject *name, return _Py_make_typevar(name, NULL, evaluate_constraints); } -const instrinsic_func2 +const intrinsic_func2_info _PyIntrinsics_BinaryFunctions[] = { - [INTRINSIC_PREP_RERAISE_STAR] = prep_reraise_star, - [INTRINSIC_TYPEVAR_WITH_BOUND] = make_typevar_with_bound, - [INTRINSIC_TYPEVAR_WITH_CONSTRAINTS] = make_typevar_with_constraints, - [INTRINSIC_SET_FUNCTION_TYPE_PARAMS] = _Py_set_function_type_params, + INTRINSIC_FUNC_ENTRY(INTRINSIC_2_INVALID, no_intrinsic2) + INTRINSIC_FUNC_ENTRY(INTRINSIC_PREP_RERAISE_STAR, prep_reraise_star) + INTRINSIC_FUNC_ENTRY(INTRINSIC_TYPEVAR_WITH_BOUND, make_typevar_with_bound) + INTRINSIC_FUNC_ENTRY(INTRINSIC_TYPEVAR_WITH_CONSTRAINTS, make_typevar_with_constraints) + INTRINSIC_FUNC_ENTRY(INTRINSIC_SET_FUNCTION_TYPE_PARAMS, _Py_set_function_type_params) }; + +#undef INTRINSIC_FUNC_ENTRY + +PyObject* +_PyUnstable_GetUnaryIntrinsicName(int index) +{ + if (index < 0 || index > MAX_INTRINSIC_1) { + return NULL; + } + return PyUnicode_FromString(_PyIntrinsics_UnaryFunctions[index].name); +} + +PyObject* +_PyUnstable_GetBinaryIntrinsicName(int index) +{ + if (index < 0 || index > MAX_INTRINSIC_2) { + return NULL; + } + return PyUnicode_FromString(_PyIntrinsics_BinaryFunctions[index].name); +} diff --git a/Tools/build/generate_opcode_h.py b/Tools/build/generate_opcode_h.py index 5b0560e6b21..179abcf989e 100644 --- a/Tools/build/generate_opcode_h.py +++ b/Tools/build/generate_opcode_h.py @@ -50,18 +50,6 @@ internal_footer = """ #endif // !Py_INTERNAL_OPCODE_H """ -intrinsic_header = f""" -// Auto-generated by {SCRIPT_NAME} from {PYTHON_OPCODE} - -""".lstrip() - -intrinsic_footer = """ -typedef PyObject *(*instrinsic_func1)(PyThreadState* tstate, PyObject *value); -typedef PyObject *(*instrinsic_func2)(PyThreadState* tstate, PyObject *value1, PyObject *value2); -extern const instrinsic_func1 _PyIntrinsics_UnaryFunctions[]; -extern const instrinsic_func2 _PyIntrinsics_BinaryFunctions[]; -""" - DEFINE = "#define {:<38} {:>3}\n" UINT32_MASK = (1<<32)-1 @@ -76,8 +64,7 @@ def get_python_module_dict(filename): def main(opcode_py, _opcode_metadata_py='Lib/_opcode_metadata.py', outfile='Include/opcode.h', - internaloutfile='Include/internal/pycore_opcode.h', - intrinsicoutfile='Include/internal/pycore_intrinsics.h'): + internaloutfile='Include/internal/pycore_opcode.h'): _opcode_metadata = get_python_module_dict(_opcode_metadata_py) @@ -107,11 +94,9 @@ def main(opcode_py, opname_including_specialized[next_op] = name used[next_op] = True - with open(outfile, 'w') as fobj, open(internaloutfile, 'w') as iobj, open( - intrinsicoutfile, "w") as nobj: + with open(outfile, 'w') as fobj, open(internaloutfile, 'w') as iobj: fobj.write(header) iobj.write(internal_header) - nobj.write(intrinsic_header) for name in opname: if name in opmap: @@ -157,22 +142,6 @@ def main(opcode_py, for i, (op, _) in enumerate(opcode["_nb_ops"]): fobj.write(DEFINE.format(op, i)) - nobj.write("/* Unary Functions: */") - nobj.write("\n") - for i, op in enumerate(opcode["_intrinsic_1_descs"]): - nobj.write(DEFINE.format(op, i)) - nobj.write("\n") - nobj.write(DEFINE.format("MAX_INTRINSIC_1", i)) - - nobj.write("\n\n") - nobj.write("/* Binary Functions: */\n") - for i, op in enumerate(opcode["_intrinsic_2_descs"]): - nobj.write(DEFINE.format(op, i)) - nobj.write("\n") - nobj.write(DEFINE.format("MAX_INTRINSIC_2", i)) - - nobj.write(intrinsic_footer) - fobj.write("\n") fobj.write("/* Defined in Lib/opcode.py */\n") fobj.write(f"#define ENABLE_SPECIALIZATION {int(ENABLE_SPECIALIZATION)}") @@ -203,4 +172,4 @@ def main(opcode_py, if __name__ == '__main__': - main(sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4], sys.argv[5]) + main(sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4])