pyo3_ffi/cpython/
code.rs

1use crate::object::*;
2use crate::pyport::Py_ssize_t;
3
4#[allow(unused_imports)]
5use libc::uintptr_t;
6#[allow(unused_imports)]
7use std::os::raw::{c_char, c_int, c_short, c_uchar, c_void};
8#[cfg(not(any(PyPy, GraalPy)))]
9use std::ptr::addr_of_mut;
10
11#[cfg(all(Py_3_8, not(any(PyPy, GraalPy)), not(Py_3_11)))]
12opaque_struct!(_PyOpcache);
13
14#[cfg(Py_3_14)]
15pub const _PY_MONITORING_TOOL_IDS: usize = 8;
16#[cfg(Py_3_14)]
17pub const _PY_MONITORING_LOCAL_EVENTS: usize = 11;
18#[cfg(all(Py_3_12, not(Py_3_14)))]
19pub const _PY_MONITORING_LOCAL_EVENTS: usize = 10;
20#[cfg(Py_3_14)]
21pub const _PY_MONITORING_UNGROUPED_EVENTS: usize = 16;
22#[cfg(all(Py_3_12, not(Py_3_14)))]
23pub const _PY_MONITORING_UNGROUPED_EVENTS: usize = 15;
24#[cfg(Py_3_14)]
25pub const _PY_MONITORING_EVENTS: usize = 17;
26#[cfg(all(Py_3_12, not(Py_3_14)))]
27pub const _PY_MONITORING_EVENTS: usize = 19;
28
29#[cfg(Py_3_12)]
30#[repr(C)]
31#[derive(Clone, Copy)]
32pub struct _Py_LocalMonitors {
33    pub tools: [u8; if cfg!(Py_3_13) {
34        _PY_MONITORING_LOCAL_EVENTS
35    } else {
36        _PY_MONITORING_UNGROUPED_EVENTS
37    }],
38}
39
40#[cfg(Py_3_12)]
41#[repr(C)]
42#[derive(Clone, Copy)]
43pub struct _Py_GlobalMonitors {
44    pub tools: [u8; _PY_MONITORING_UNGROUPED_EVENTS],
45}
46
47// skipped _Py_CODEUNIT
48
49// skipped _Py_OPCODE
50// skipped _Py_OPARG
51
52// skipped _py_make_codeunit
53
54// skipped _py_set_opcode
55
56// skipped _Py_MAKE_CODEUNIT
57// skipped _Py_SET_OPCODE
58
59#[cfg(Py_3_12)]
60#[repr(C)]
61#[derive(Copy, Clone)]
62pub struct _PyCoCached {
63    pub _co_code: *mut PyObject,
64    pub _co_varnames: *mut PyObject,
65    pub _co_cellvars: *mut PyObject,
66    pub _co_freevars: *mut PyObject,
67}
68
69#[cfg(all(Py_3_12, not(Py_3_14)))]
70#[repr(C)]
71#[derive(Copy, Clone)]
72pub struct _PyCoLineInstrumentationData {
73    pub original_opcode: u8,
74    pub line_delta: i8,
75}
76
77#[cfg(Py_3_14)]
78#[repr(C)]
79pub struct _PyCoLineInstrumentationData {
80    pub bytes_per_entry: u8,
81    pub data: [i8; 1],
82}
83
84#[cfg(Py_3_12)]
85#[repr(C)]
86#[derive(Copy, Clone)]
87pub struct _PyCoMonitoringData {
88    pub local_monitors: _Py_LocalMonitors,
89    pub active_monitors: _Py_LocalMonitors,
90    pub tools: *mut u8,
91    #[cfg(Py_3_14)]
92    pub tool_versions: [uintptr_t; _PY_MONITORING_TOOL_IDS],
93    pub lines: *mut _PyCoLineInstrumentationData,
94    pub line_tools: *mut u8,
95    pub per_instruction_opcodes: *mut u8,
96    pub per_instruction_tools: *mut u8,
97}
98
99#[repr(C)]
100#[cfg(all(Py_GIL_DISABLED, Py_3_14))]
101pub struct _PyCodeArray {
102    size: Py_ssize_t,
103    entries: [c_char; 1],
104}
105
106#[cfg(all(not(any(PyPy, GraalPy)), not(Py_3_7)))]
107opaque_struct!(PyCodeObject);
108
109#[cfg(all(not(any(PyPy, GraalPy)), Py_3_7, not(Py_3_8)))]
110#[repr(C)]
111pub struct PyCodeObject {
112    pub ob_base: PyObject,
113    pub co_argcount: c_int,
114    pub co_kwonlyargcount: c_int,
115    pub co_nlocals: c_int,
116    pub co_stacksize: c_int,
117    pub co_flags: c_int,
118    pub co_firstlineno: c_int,
119    pub co_code: *mut PyObject,
120    pub co_consts: *mut PyObject,
121    pub co_names: *mut PyObject,
122    pub co_varnames: *mut PyObject,
123    pub co_freevars: *mut PyObject,
124    pub co_cellvars: *mut PyObject,
125    pub co_cell2arg: *mut Py_ssize_t,
126    pub co_filename: *mut PyObject,
127    pub co_name: *mut PyObject,
128    pub co_lnotab: *mut PyObject,
129    pub co_zombieframe: *mut c_void,
130    pub co_weakreflist: *mut PyObject,
131    pub co_extra: *mut c_void,
132}
133
134#[cfg(Py_3_13)]
135opaque_struct!(_PyExecutorArray);
136
137#[cfg(all(not(any(PyPy, GraalPy)), Py_3_8, not(Py_3_11)))]
138#[repr(C)]
139pub struct PyCodeObject {
140    pub ob_base: PyObject,
141    pub co_argcount: c_int,
142    pub co_posonlyargcount: c_int,
143    pub co_kwonlyargcount: c_int,
144    pub co_nlocals: c_int,
145    pub co_stacksize: c_int,
146    pub co_flags: c_int,
147    pub co_firstlineno: c_int,
148    pub co_code: *mut PyObject,
149    pub co_consts: *mut PyObject,
150    pub co_names: *mut PyObject,
151    pub co_varnames: *mut PyObject,
152    pub co_freevars: *mut PyObject,
153    pub co_cellvars: *mut PyObject,
154    pub co_cell2arg: *mut Py_ssize_t,
155    pub co_filename: *mut PyObject,
156    pub co_name: *mut PyObject,
157    #[cfg(not(Py_3_10))]
158    pub co_lnotab: *mut PyObject,
159    #[cfg(Py_3_10)]
160    pub co_linetable: *mut PyObject,
161    pub co_zombieframe: *mut c_void,
162    pub co_weakreflist: *mut PyObject,
163    pub co_extra: *mut c_void,
164    pub co_opcache_map: *mut c_uchar,
165    pub co_opcache: *mut _PyOpcache,
166    pub co_opcache_flag: c_int,
167    pub co_opcache_size: c_uchar,
168}
169
170#[cfg(all(not(any(PyPy, GraalPy)), Py_3_11))]
171#[repr(C)]
172pub struct PyCodeObject {
173    pub ob_base: PyVarObject,
174    pub co_consts: *mut PyObject,
175    pub co_names: *mut PyObject,
176    pub co_exceptiontable: *mut PyObject,
177    pub co_flags: c_int,
178    #[cfg(not(Py_3_12))]
179    pub co_warmup: c_int,
180
181    pub co_argcount: c_int,
182    pub co_posonlyargcount: c_int,
183    pub co_kwonlyargcount: c_int,
184    pub co_stacksize: c_int,
185    pub co_firstlineno: c_int,
186
187    pub co_nlocalsplus: c_int,
188    #[cfg(Py_3_12)]
189    pub co_framesize: c_int,
190    pub co_nlocals: c_int,
191    #[cfg(not(Py_3_12))]
192    pub co_nplaincellvars: c_int,
193    pub co_ncellvars: c_int,
194    pub co_nfreevars: c_int,
195    #[cfg(Py_3_12)]
196    pub co_version: u32,
197
198    pub co_localsplusnames: *mut PyObject,
199    pub co_localspluskinds: *mut PyObject,
200    pub co_filename: *mut PyObject,
201    pub co_name: *mut PyObject,
202    pub co_qualname: *mut PyObject,
203    pub co_linetable: *mut PyObject,
204    pub co_weakreflist: *mut PyObject,
205    #[cfg(not(Py_3_12))]
206    pub _co_code: *mut PyObject,
207    #[cfg(not(Py_3_12))]
208    pub _co_linearray: *mut c_char,
209    #[cfg(Py_3_13)]
210    pub co_executors: *mut _PyExecutorArray,
211    #[cfg(Py_3_12)]
212    pub _co_cached: *mut _PyCoCached,
213    #[cfg(Py_3_12)]
214    pub _co_instrumentation_version: u64,
215    #[cfg(Py_3_12)]
216    pub _co_monitoring: *mut _PyCoMonitoringData,
217    #[cfg(Py_3_14)]
218    pub _co_unique_id: Py_ssize_t,
219    pub _co_firsttraceable: c_int,
220    pub co_extra: *mut c_void,
221    #[cfg(all(Py_GIL_DISABLED, Py_3_14))]
222    pub co_tlbc: *mut _PyCodeArray,
223    pub co_code_adaptive: [c_char; 1],
224}
225
226#[cfg(PyPy)]
227#[repr(C)]
228pub struct PyCodeObject {
229    pub ob_base: PyObject,
230    pub co_name: *mut PyObject,
231    pub co_filename: *mut PyObject,
232    pub co_argcount: c_int,
233    pub co_flags: c_int,
234}
235
236/* Masks for co_flags */
237pub const CO_OPTIMIZED: c_int = 0x0001;
238pub const CO_NEWLOCALS: c_int = 0x0002;
239pub const CO_VARARGS: c_int = 0x0004;
240pub const CO_VARKEYWORDS: c_int = 0x0008;
241pub const CO_NESTED: c_int = 0x0010;
242pub const CO_GENERATOR: c_int = 0x0020;
243/* The CO_NOFREE flag is set if there are no free or cell variables.
244   This information is redundant, but it allows a single flag test
245   to determine whether there is any extra work to be done when the
246   call frame it setup.
247*/
248pub const CO_NOFREE: c_int = 0x0040;
249/* The CO_COROUTINE flag is set for coroutine functions (defined with
250``async def`` keywords) */
251pub const CO_COROUTINE: c_int = 0x0080;
252pub const CO_ITERABLE_COROUTINE: c_int = 0x0100;
253pub const CO_ASYNC_GENERATOR: c_int = 0x0200;
254
255pub const CO_FUTURE_DIVISION: c_int = 0x2000;
256pub const CO_FUTURE_ABSOLUTE_IMPORT: c_int = 0x4000; /* do absolute imports by default */
257pub const CO_FUTURE_WITH_STATEMENT: c_int = 0x8000;
258pub const CO_FUTURE_PRINT_FUNCTION: c_int = 0x1_0000;
259pub const CO_FUTURE_UNICODE_LITERALS: c_int = 0x2_0000;
260
261pub const CO_FUTURE_BARRY_AS_BDFL: c_int = 0x4_0000;
262pub const CO_FUTURE_GENERATOR_STOP: c_int = 0x8_0000;
263// skipped CO_FUTURE_ANNOTATIONS
264// skipped CO_CELL_NOT_AN_ARG
265
266pub const CO_MAXBLOCKS: usize = 20;
267
268#[cfg(not(any(PyPy, GraalPy)))]
269#[cfg_attr(windows, link(name = "pythonXY"))]
270extern "C" {
271    pub static mut PyCode_Type: PyTypeObject;
272}
273
274#[inline]
275#[cfg(not(any(PyPy, GraalPy)))]
276pub unsafe fn PyCode_Check(op: *mut PyObject) -> c_int {
277    (Py_TYPE(op) == addr_of_mut!(PyCode_Type)) as c_int
278}
279
280#[inline]
281#[cfg(all(not(any(PyPy, GraalPy)), Py_3_10, not(Py_3_11)))]
282pub unsafe fn PyCode_GetNumFree(op: *mut PyCodeObject) -> Py_ssize_t {
283    crate::PyTuple_GET_SIZE((*op).co_freevars)
284}
285
286#[inline]
287#[cfg(all(not(Py_3_10), Py_3_11, not(any(PyPy, GraalPy))))]
288pub unsafe fn PyCode_GetNumFree(op: *mut PyCodeObject) -> c_int {
289    (*op).co_nfreevars
290}
291
292extern "C" {
293    #[cfg(PyPy)]
294    #[link_name = "PyPyCode_Check"]
295    pub fn PyCode_Check(op: *mut PyObject) -> c_int;
296
297    #[cfg(PyPy)]
298    #[link_name = "PyPyCode_GetNumFree"]
299    pub fn PyCode_GetNumFree(op: *mut PyCodeObject) -> Py_ssize_t;
300}
301
302extern "C" {
303    #[cfg(not(GraalPy))]
304    #[cfg_attr(PyPy, link_name = "PyPyCode_New")]
305    pub fn PyCode_New(
306        argcount: c_int,
307        kwonlyargcount: c_int,
308        nlocals: c_int,
309        stacksize: c_int,
310        flags: c_int,
311        code: *mut PyObject,
312        consts: *mut PyObject,
313        names: *mut PyObject,
314        varnames: *mut PyObject,
315        freevars: *mut PyObject,
316        cellvars: *mut PyObject,
317        filename: *mut PyObject,
318        name: *mut PyObject,
319        firstlineno: c_int,
320        lnotab: *mut PyObject,
321    ) -> *mut PyCodeObject;
322    #[cfg(not(GraalPy))]
323    #[cfg(Py_3_8)]
324    pub fn PyCode_NewWithPosOnlyArgs(
325        argcount: c_int,
326        posonlyargcount: c_int,
327        kwonlyargcount: c_int,
328        nlocals: c_int,
329        stacksize: c_int,
330        flags: c_int,
331        code: *mut PyObject,
332        consts: *mut PyObject,
333        names: *mut PyObject,
334        varnames: *mut PyObject,
335        freevars: *mut PyObject,
336        cellvars: *mut PyObject,
337        filename: *mut PyObject,
338        name: *mut PyObject,
339        firstlineno: c_int,
340        lnotab: *mut PyObject,
341    ) -> *mut PyCodeObject;
342    #[cfg(not(GraalPy))]
343    #[cfg_attr(PyPy, link_name = "PyPyCode_NewEmpty")]
344    pub fn PyCode_NewEmpty(
345        filename: *const c_char,
346        funcname: *const c_char,
347        firstlineno: c_int,
348    ) -> *mut PyCodeObject;
349    #[cfg(not(GraalPy))]
350    pub fn PyCode_Addr2Line(arg1: *mut PyCodeObject, arg2: c_int) -> c_int;
351    // skipped PyCodeAddressRange "for internal use only"
352    // skipped _PyCode_CheckLineNumber
353    // skipped _PyCode_ConstantKey
354    pub fn PyCode_Optimize(
355        code: *mut PyObject,
356        consts: *mut PyObject,
357        names: *mut PyObject,
358        lnotab: *mut PyObject,
359    ) -> *mut PyObject;
360    pub fn _PyCode_GetExtra(
361        code: *mut PyObject,
362        index: Py_ssize_t,
363        extra: *const *mut c_void,
364    ) -> c_int;
365    pub fn _PyCode_SetExtra(code: *mut PyObject, index: Py_ssize_t, extra: *mut c_void) -> c_int;
366}