diff --git a/Include/Python.h b/Include/Python.h
index 868e31bfa4e..dcd0a57ac1f 100644
--- a/Include/Python.h
+++ b/Include/Python.h
@@ -114,6 +114,7 @@
#include "classobject.h"
#include "fileobject.h"
#include "pycapsule.h"
+#include "code.h"
#include "pyframe.h"
#include "traceback.h"
#include "sliceobject.h"
diff --git a/Include/code.h b/Include/code.h
index b268a6aedff..b9e23eb8165 100644
--- a/Include/code.h
+++ b/Include/code.h
@@ -1,180 +1,20 @@
/* Definitions for bytecode */
-#ifndef Py_LIMITED_API
#ifndef Py_CODE_H
#define Py_CODE_H
#ifdef __cplusplus
extern "C" {
#endif
-typedef uint16_t _Py_CODEUNIT;
-
-#ifdef WORDS_BIGENDIAN
-# define _Py_OPCODE(word) ((word) >> 8)
-# define _Py_OPARG(word) ((word) & 255)
-#else
-# define _Py_OPCODE(word) ((word) & 255)
-# define _Py_OPARG(word) ((word) >> 8)
-#endif
-
-typedef struct _PyOpcache _PyOpcache;
-
-/* Bytecode object */
-typedef struct {
- PyObject_HEAD
- int co_argcount; /* #arguments, except *args */
- int co_posonlyargcount; /* #positional only arguments */
- int co_kwonlyargcount; /* #keyword only arguments */
- int co_nlocals; /* #local variables */
- int co_stacksize; /* #entries needed for evaluation stack */
- int co_flags; /* CO_..., see below */
- int co_firstlineno; /* first source line number */
- PyObject *co_code; /* instruction opcodes */
- PyObject *co_consts; /* list (constants used) */
- PyObject *co_names; /* list of strings (names used) */
- PyObject *co_varnames; /* tuple of strings (local variable names) */
- PyObject *co_freevars; /* tuple of strings (free variable names) */
- PyObject *co_cellvars; /* tuple of strings (cell variable names) */
- /* The rest aren't used in either hash or comparisons, except for co_name,
- used in both. This is done to preserve the name and line number
- for tracebacks and debuggers; otherwise, constant de-duplication
- would collapse identical functions/lambdas defined on different lines.
- */
- Py_ssize_t *co_cell2arg; /* Maps cell vars which are arguments. */
- PyObject *co_filename; /* unicode (where it was loaded from) */
- PyObject *co_name; /* unicode (name, for reference) */
- PyObject *co_lnotab; /* string (encoding addr<->lineno mapping) See
- Objects/lnotab_notes.txt for details. */
- void *co_zombieframe; /* for optimization only (see frameobject.c) */
- PyObject *co_weakreflist; /* to support weakrefs to code objects */
- /* Scratch space for extra data relating to the code object.
- Type is a void* to keep the format private in codeobject.c to force
- people to go through the proper APIs. */
- void *co_extra;
-
- /* Per opcodes just-in-time cache
- *
- * To reduce cache size, we use indirect mapping from opcode index to
- * cache object:
- * cache = co_opcache[co_opcache_map[next_instr - first_instr] - 1]
- */
-
- // co_opcache_map is indexed by (next_instr - first_instr).
- // * 0 means there is no cache for this opcode.
- // * n > 0 means there is cache in co_opcache[n-1].
- unsigned char *co_opcache_map;
- _PyOpcache *co_opcache;
- int co_opcache_flag; // used to determine when create a cache.
- unsigned char co_opcache_size; // length of co_opcache.
-} PyCodeObject;
-
-/* Masks for co_flags above */
-#define CO_OPTIMIZED 0x0001
-#define CO_NEWLOCALS 0x0002
-#define CO_VARARGS 0x0004
-#define CO_VARKEYWORDS 0x0008
-#define CO_NESTED 0x0010
-#define CO_GENERATOR 0x0020
-/* The CO_NOFREE flag is set if there are no free or cell variables.
- This information is redundant, but it allows a single flag test
- to determine whether there is any extra work to be done when the
- call frame it setup.
-*/
-#define CO_NOFREE 0x0040
-
-/* The CO_COROUTINE flag is set for coroutine functions (defined with
- ``async def`` keywords) */
-#define CO_COROUTINE 0x0080
-#define CO_ITERABLE_COROUTINE 0x0100
-#define CO_ASYNC_GENERATOR 0x0200
-
-/* bpo-39562: These constant values are changed in Python 3.9
- to prevent collision with compiler flags. CO_FUTURE_ and PyCF_
- constants must be kept unique. PyCF_ constants can use bits from
- 0x0100 to 0x10000. CO_FUTURE_ constants use bits starting at 0x20000. */
-#define CO_FUTURE_DIVISION 0x20000
-#define CO_FUTURE_ABSOLUTE_IMPORT 0x40000 /* do absolute imports by default */
-#define CO_FUTURE_WITH_STATEMENT 0x80000
-#define CO_FUTURE_PRINT_FUNCTION 0x100000
-#define CO_FUTURE_UNICODE_LITERALS 0x200000
-
-#define CO_FUTURE_BARRY_AS_BDFL 0x400000
-#define CO_FUTURE_GENERATOR_STOP 0x800000
-#define CO_FUTURE_ANNOTATIONS 0x1000000
-
-/* This value is found in the co_cell2arg array when the associated cell
- variable does not correspond to an argument. */
-#define CO_CELL_NOT_AN_ARG (-1)
-
-/* This should be defined if a future statement modifies the syntax.
- For example, when a keyword is added.
-*/
-#define PY_PARSER_REQUIRES_FUTURE_KEYWORD
-
-#define CO_MAXBLOCKS 20 /* Max static block nesting within a function */
-
-PyAPI_DATA(PyTypeObject) PyCode_Type;
-
-#define PyCode_Check(op) Py_IS_TYPE(op, &PyCode_Type)
-#define PyCode_GetNumFree(op) (PyTuple_GET_SIZE((op)->co_freevars))
-
-/* Public interface */
-PyAPI_FUNC(PyCodeObject *) PyCode_New(
- int, int, int, int, int, PyObject *, PyObject *,
- PyObject *, PyObject *, PyObject *, PyObject *,
- PyObject *, PyObject *, int, PyObject *);
-
-PyAPI_FUNC(PyCodeObject *) PyCode_NewWithPosOnlyArgs(
- int, int, int, int, int, int, PyObject *, PyObject *,
- PyObject *, PyObject *, PyObject *, PyObject *,
- PyObject *, PyObject *, int, PyObject *);
- /* same as struct above */
-
-/* Creates a new empty code object with the specified source location. */
-PyAPI_FUNC(PyCodeObject *)
-PyCode_NewEmpty(const char *filename, const char *funcname, int firstlineno);
-
-/* Return the line number associated with the specified bytecode index
- in this code object. If you just need the line number of a frame,
- use PyFrame_GetLineNumber() instead. */
-PyAPI_FUNC(int) PyCode_Addr2Line(PyCodeObject *, int);
-
-/* for internal use only */
-typedef struct _addr_pair {
- int ap_lower;
- int ap_upper;
-} PyAddrPair;
+typedef struct PyCodeObject PyCodeObject;
#ifndef Py_LIMITED_API
-/* Update *bounds to describe the first and one-past-the-last instructions in the
- same line as lasti. Return the number of that line.
-*/
-PyAPI_FUNC(int) _PyCode_CheckLineNumber(PyCodeObject* co,
- int lasti, PyAddrPair *bounds);
-
-/* Create a comparable key used to compare constants taking in account the
- * object type. It is used to make sure types are not coerced (e.g., float and
- * complex) _and_ to distinguish 0.0 from -0.0 e.g. on IEEE platforms
- *
- * Return (type(obj), obj, ...): a tuple with variable size (at least 2 items)
- * depending on the type and the value. The type is the first item to not
- * compare bytes and str which can raise a BytesWarning exception. */
-PyAPI_FUNC(PyObject*) _PyCode_ConstantKey(PyObject *obj);
-#endif
-
-PyAPI_FUNC(PyObject*) PyCode_Optimize(PyObject *code, PyObject* consts,
- PyObject *names, PyObject *lnotab);
-
-
-#ifndef Py_LIMITED_API
-PyAPI_FUNC(int) _PyCode_GetExtra(PyObject *code, Py_ssize_t index,
- void **extra);
-PyAPI_FUNC(int) _PyCode_SetExtra(PyObject *code, Py_ssize_t index,
- void *extra);
+# define Py_CPYTHON_CODE_H
+# include "cpython/code.h"
+# undef Py_CPYTHON_CODE_H
#endif
#ifdef __cplusplus
}
#endif
#endif /* !Py_CODE_H */
-#endif /* Py_LIMITED_API */
diff --git a/Include/compile.h b/Include/compile.h
index dbba85bb5f6..12417ce8054 100644
--- a/Include/compile.h
+++ b/Include/compile.h
@@ -2,7 +2,6 @@
#define Py_COMPILE_H
#ifndef Py_LIMITED_API
-#include "code.h"
#ifdef __cplusplus
extern "C" {
diff --git a/Include/cpython/code.h b/Include/cpython/code.h
new file mode 100644
index 00000000000..cda28ac6ee9
--- /dev/null
+++ b/Include/cpython/code.h
@@ -0,0 +1,165 @@
+#ifndef Py_CPYTHON_CODE_H
+# error "this header file must not be included directly"
+#endif
+
+typedef uint16_t _Py_CODEUNIT;
+
+#ifdef WORDS_BIGENDIAN
+# define _Py_OPCODE(word) ((word) >> 8)
+# define _Py_OPARG(word) ((word) & 255)
+#else
+# define _Py_OPCODE(word) ((word) & 255)
+# define _Py_OPARG(word) ((word) >> 8)
+#endif
+
+typedef struct _PyOpcache _PyOpcache;
+
+/* Bytecode object */
+struct PyCodeObject {
+ PyObject_HEAD
+ int co_argcount; /* #arguments, except *args */
+ int co_posonlyargcount; /* #positional only arguments */
+ int co_kwonlyargcount; /* #keyword only arguments */
+ int co_nlocals; /* #local variables */
+ int co_stacksize; /* #entries needed for evaluation stack */
+ int co_flags; /* CO_..., see below */
+ int co_firstlineno; /* first source line number */
+ PyObject *co_code; /* instruction opcodes */
+ PyObject *co_consts; /* list (constants used) */
+ PyObject *co_names; /* list of strings (names used) */
+ PyObject *co_varnames; /* tuple of strings (local variable names) */
+ PyObject *co_freevars; /* tuple of strings (free variable names) */
+ PyObject *co_cellvars; /* tuple of strings (cell variable names) */
+ /* The rest aren't used in either hash or comparisons, except for co_name,
+ used in both. This is done to preserve the name and line number
+ for tracebacks and debuggers; otherwise, constant de-duplication
+ would collapse identical functions/lambdas defined on different lines.
+ */
+ Py_ssize_t *co_cell2arg; /* Maps cell vars which are arguments. */
+ PyObject *co_filename; /* unicode (where it was loaded from) */
+ PyObject *co_name; /* unicode (name, for reference) */
+ PyObject *co_lnotab; /* string (encoding addr<->lineno mapping) See
+ Objects/lnotab_notes.txt for details. */
+ void *co_zombieframe; /* for optimization only (see frameobject.c) */
+ PyObject *co_weakreflist; /* to support weakrefs to code objects */
+ /* Scratch space for extra data relating to the code object.
+ Type is a void* to keep the format private in codeobject.c to force
+ people to go through the proper APIs. */
+ void *co_extra;
+
+ /* Per opcodes just-in-time cache
+ *
+ * To reduce cache size, we use indirect mapping from opcode index to
+ * cache object:
+ * cache = co_opcache[co_opcache_map[next_instr - first_instr] - 1]
+ */
+
+ // co_opcache_map is indexed by (next_instr - first_instr).
+ // * 0 means there is no cache for this opcode.
+ // * n > 0 means there is cache in co_opcache[n-1].
+ unsigned char *co_opcache_map;
+ _PyOpcache *co_opcache;
+ int co_opcache_flag; // used to determine when create a cache.
+ unsigned char co_opcache_size; // length of co_opcache.
+};
+
+/* Masks for co_flags above */
+#define CO_OPTIMIZED 0x0001
+#define CO_NEWLOCALS 0x0002
+#define CO_VARARGS 0x0004
+#define CO_VARKEYWORDS 0x0008
+#define CO_NESTED 0x0010
+#define CO_GENERATOR 0x0020
+/* The CO_NOFREE flag is set if there are no free or cell variables.
+ This information is redundant, but it allows a single flag test
+ to determine whether there is any extra work to be done when the
+ call frame it setup.
+*/
+#define CO_NOFREE 0x0040
+
+/* The CO_COROUTINE flag is set for coroutine functions (defined with
+ ``async def`` keywords) */
+#define CO_COROUTINE 0x0080
+#define CO_ITERABLE_COROUTINE 0x0100
+#define CO_ASYNC_GENERATOR 0x0200
+
+/* bpo-39562: These constant values are changed in Python 3.9
+ to prevent collision with compiler flags. CO_FUTURE_ and PyCF_
+ constants must be kept unique. PyCF_ constants can use bits from
+ 0x0100 to 0x10000. CO_FUTURE_ constants use bits starting at 0x20000. */
+#define CO_FUTURE_DIVISION 0x20000
+#define CO_FUTURE_ABSOLUTE_IMPORT 0x40000 /* do absolute imports by default */
+#define CO_FUTURE_WITH_STATEMENT 0x80000
+#define CO_FUTURE_PRINT_FUNCTION 0x100000
+#define CO_FUTURE_UNICODE_LITERALS 0x200000
+
+#define CO_FUTURE_BARRY_AS_BDFL 0x400000
+#define CO_FUTURE_GENERATOR_STOP 0x800000
+#define CO_FUTURE_ANNOTATIONS 0x1000000
+
+/* This value is found in the co_cell2arg array when the associated cell
+ variable does not correspond to an argument. */
+#define CO_CELL_NOT_AN_ARG (-1)
+
+/* This should be defined if a future statement modifies the syntax.
+ For example, when a keyword is added.
+*/
+#define PY_PARSER_REQUIRES_FUTURE_KEYWORD
+
+#define CO_MAXBLOCKS 20 /* Max static block nesting within a function */
+
+PyAPI_DATA(PyTypeObject) PyCode_Type;
+
+#define PyCode_Check(op) Py_IS_TYPE(op, &PyCode_Type)
+#define PyCode_GetNumFree(op) (PyTuple_GET_SIZE((op)->co_freevars))
+
+/* Public interface */
+PyAPI_FUNC(PyCodeObject *) PyCode_New(
+ int, int, int, int, int, PyObject *, PyObject *,
+ PyObject *, PyObject *, PyObject *, PyObject *,
+ PyObject *, PyObject *, int, PyObject *);
+
+PyAPI_FUNC(PyCodeObject *) PyCode_NewWithPosOnlyArgs(
+ int, int, int, int, int, int, PyObject *, PyObject *,
+ PyObject *, PyObject *, PyObject *, PyObject *,
+ PyObject *, PyObject *, int, PyObject *);
+ /* same as struct above */
+
+/* Creates a new empty code object with the specified source location. */
+PyAPI_FUNC(PyCodeObject *)
+PyCode_NewEmpty(const char *filename, const char *funcname, int firstlineno);
+
+/* Return the line number associated with the specified bytecode index
+ in this code object. If you just need the line number of a frame,
+ use PyFrame_GetLineNumber() instead. */
+PyAPI_FUNC(int) PyCode_Addr2Line(PyCodeObject *, int);
+
+/* for internal use only */
+typedef struct _addr_pair {
+ int ap_lower;
+ int ap_upper;
+} PyAddrPair;
+
+/* Update *bounds to describe the first and one-past-the-last instructions in the
+ same line as lasti. Return the number of that line.
+*/
+PyAPI_FUNC(int) _PyCode_CheckLineNumber(PyCodeObject* co,
+ int lasti, PyAddrPair *bounds);
+
+/* Create a comparable key used to compare constants taking in account the
+ * object type. It is used to make sure types are not coerced (e.g., float and
+ * complex) _and_ to distinguish 0.0 from -0.0 e.g. on IEEE platforms
+ *
+ * Return (type(obj), obj, ...): a tuple with variable size (at least 2 items)
+ * depending on the type and the value. The type is the first item to not
+ * compare bytes and str which can raise a BytesWarning exception. */
+PyAPI_FUNC(PyObject*) _PyCode_ConstantKey(PyObject *obj);
+
+PyAPI_FUNC(PyObject*) PyCode_Optimize(PyObject *code, PyObject* consts,
+ PyObject *names, PyObject *lnotab);
+
+
+PyAPI_FUNC(int) _PyCode_GetExtra(PyObject *code, Py_ssize_t index,
+ void **extra);
+PyAPI_FUNC(int) _PyCode_SetExtra(PyObject *code, Py_ssize_t index,
+ void *extra);
diff --git a/Makefile.pre.in b/Makefile.pre.in
index 5db381f90f9..fa7fb1fcc16 100644
--- a/Makefile.pre.in
+++ b/Makefile.pre.in
@@ -1086,6 +1086,7 @@ PYTHON_HEADERS= \
$(srcdir)/Include/cpython/bytearrayobject.h \
$(srcdir)/Include/cpython/bytesobject.h \
$(srcdir)/Include/cpython/ceval.h \
+ $(srcdir)/Include/cpython/code.h \
$(srcdir)/Include/cpython/dictobject.h \
$(srcdir)/Include/cpython/fileobject.h \
$(srcdir)/Include/cpython/fileutils.h \
diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj
index f54f1554130..21b51bf5e6d 100644
--- a/PCbuild/pythoncore.vcxproj
+++ b/PCbuild/pythoncore.vcxproj
@@ -131,6 +131,7 @@
+
diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters
index c8758dab3b3..f5c76fa34eb 100644
--- a/PCbuild/pythoncore.vcxproj.filters
+++ b/PCbuild/pythoncore.vcxproj.filters
@@ -90,6 +90,9 @@
Include
+
+ Include
+
Include