{#-  Copyright 2026, Kay Hayen, mailto:kay.hayen@gmail.com find license text at end of file -#}

/* This file is auto-generated by bin/generate-specialized-c-code. Do not edit. */
#ifndef NUITKA_PYTHON_INTERNALS_ACCESS_H
#define NUITKA_PYTHON_INTERNALS_ACCESS_H

#undef _PyRuntime

// spell-checker: ignore PYRUNTIME,offsetof,GNUC,ceval,stoptheworld,Qsbr,Reftracer

#if _NUITKA_MODULE_MODE && PYTHON_VERSION >= 0x3e0 && PYTHON_VERSION < 0x3f0 && !defined(Py_GIL_DISABLED)
static inline struct _Py_interp_cached_objects *Nuitka_PyInterpreterState_GetCachedObjects(PyInterpreterState *interp) {
    return (struct _Py_interp_cached_objects *)Nuitka_PyInterpreterState_AdjustPostQsbrPointer(&interp->cached_objects);
}

static inline struct _Py_interp_static_objects *Nuitka_PyInterpreterState_GetStaticObjects(PyInterpreterState *interp) {
    return (struct _Py_interp_static_objects *)Nuitka_PyInterpreterState_AdjustPostQsbrPointer(&interp->static_objects);
}
#endif

#if PYTHON_VERSION >= 0x3c0
static inline bool Nuitka_RuntimeHasPerfTrampoline(void) {
    static int cached_result = -1;
    if (cached_result != -1) {
        return cached_result != 0;
    }
    PyObject *func = PySys_GetObject("activate_stack_trampoline");
    assert(func != NULL);

    // Deliberately use an invalid backend, so we can detect support without
    // activating the trampoline.
    NUITKA_MAY_BE_UNUSED PyObject *res = PyObject_CallFunction(func, "s", "s");
    assert(res == NULL);
    bool has_perf = true;

    PyThreadState *tstate = PyThreadState_GET();
    PyObject *exception_value = tstate->current_exception;
    assert(exception_value != NULL);
    assert((PyObject *)Py_TYPE(exception_value) == PyExc_ValueError);

    PyObject *args = ((PyBaseExceptionObject *)exception_value)->args;
    assert(PyTuple_CheckExact(args) && PyTuple_GET_SIZE(args) > 0);
    PyObject *arg = PyTuple_GET_ITEM(args, 0);
    assert(PyUnicode_CheckExact(arg));

    const char *msg = PyUnicode_AsUTF8(arg);
    assert(msg != NULL);
    if (strcmp(msg, "perf trampoline not available") == 0) {
        has_perf = false;
    }

    tstate->current_exception = NULL;
    Py_DECREF(exception_value);

    cached_result = has_perf ? 1 : 0;
    return has_perf;
}
#endif

{% for group in template_groups %}
#if PYTHON_VERSION >= 0x{{ group.python_version_hex }} && PYTHON_VERSION < 0x{{ group.next_python_version_hex }}{% if group.is_gil %} && !defined(Py_GIL_DISABLED){% else %} && defined(Py_GIL_DISABLED){% endif %}

{% if group.os_arch_macro and group.os_arch_macro != "1" %}
#if {{ group.os_arch_macro }}
{% endif %}

{% for key in group.offset_keys %}
#define NUITKA_PYRUNTIME_OFFSET_{{ key.name }} {{ key.val }}
{% endfor %}

{% if group.os_arch_macro and group.os_arch_macro != "1" %}
#endif /* {{ group.os_arch_macro }} */
{% endif %}

#endif

{% endfor %}

#if defined(__linux__) && _NUITKA_MODULE_MODE

#if PYTHON_VERSION >= 0x3c0 && PYTHON_VERSION < 0x3d0
struct _Nuitka_perf_trampoline_missing_delta {
    int status;
    Py_ssize_t extra_code_index;
    void *code_arena;
    void *trampoline_api[5];
    FILE *map_file;
};
#elif PYTHON_VERSION >= 0x3d0
struct _Nuitka_perf_trampoline_missing_delta_early {
    int status;
    int perf_trampoline_type;
    Py_ssize_t extra_code_index;
    void *code_arena;
    void *trampoline_api[5];
    FILE *map_file;
    Py_ssize_t persist_after_fork;
};
struct _Nuitka_perf_trampoline_missing_delta_late {
    int status;
    int perf_trampoline_type;
    Py_ssize_t extra_code_index;
    void *code_arena;
    void *trampoline_api[5];
    FILE *map_file;
    Py_ssize_t persist_after_fork;
    void *prev_eval_frame;
    Py_ssize_t trampoline_refcount;
    int code_watcher_id;
};
#endif

#if PYTHON_VERSION >= 0x3c0
static inline size_t _Nuitka_perf_trampoline_get_deduction(void) {
#if PYTHON_VERSION < 0x3d0 || PYTHON_VERSION >= 0x3f0
    return sizeof(struct _Nuitka_perf_trampoline_missing_delta) - sizeof(int);
#else
    int ver = Nuitka_GetRuntimeVersion();
    // 3.13 micro-version cutoff is 3.13.12
    // 3.14 micro-version cutoff is 3.14.3
    if ((ver >= 0x3d0 && ver < 0x3e0 && ver >= 0x3dc) ||
        (ver >= 0x3e0 && ver < 0x3f0 && ver >= 0x3e3)) {
        return sizeof(struct _Nuitka_perf_trampoline_missing_delta_late) - sizeof(int);
    } else {
        return sizeof(struct _Nuitka_perf_trampoline_missing_delta_early) - sizeof(int);
    }
#endif
}

static inline size_t _Nuitka_perf_trampoline_get_deduction_compile_time(void) {
#if PYTHON_VERSION < 0x3d0 || PYTHON_VERSION >= 0x3f0
    return sizeof(struct _Nuitka_perf_trampoline_missing_delta) - sizeof(int);
#else
    // Use PYTHON_VERSION macro for compile-time deduction
#if (PYTHON_VERSION >= 0x3d0 && PYTHON_VERSION < 0x3e0 && PYTHON_VERSION >= 0x3dc) || \
    (PYTHON_VERSION >= 0x3e0 && PYTHON_VERSION < 0x3f0 && PYTHON_VERSION >= 0x3e3)
    return sizeof(struct _Nuitka_perf_trampoline_missing_delta_late) - sizeof(int);
#else
    return sizeof(struct _Nuitka_perf_trampoline_missing_delta_early) - sizeof(int);
#endif
#endif
}
#endif

{% for linux_key in linux_keys %}
{% if linux_key == "stoptheworld" %}
#if PYTHON_VERSION >= 0x3d0
{% elif linux_key == "ref_tracer" %}
#if PYTHON_VERSION >= 0x3e0
{% endif %}
    static inline size_t Nuitka_PyRuntime_GetOffset__PyRuntimeState_{{ linux_key }}(void) {
        size_t c_offset = offsetof(_PyRuntimeState, {{ linux_key }});
#if PYTHON_VERSION >= 0x3c0
        if (c_offset > offsetof(_PyRuntimeState, ceval)) {
#if defined(PY_HAVE_PERF_TRAMPOLINE)
                c_offset -= _Nuitka_perf_trampoline_get_deduction_compile_time();
#endif
                if (Nuitka_RuntimeHasPerfTrampoline()) {
                    c_offset += _Nuitka_perf_trampoline_get_deduction();
                }
        }
#endif
        return c_offset;
    }
    #define NUITKA_PYRUNTIME_OFFSET__PyRuntimeState_{{ linux_key }} Nuitka_PyRuntime_GetOffset__PyRuntimeState_{{ linux_key }}()
{% if linux_key == "stoptheworld" or linux_key == "ref_tracer" %}
#endif
{% endif %}
{% endfor %}
#endif
#if (!_NUITKA_MODULE_MODE && !defined(__MINGW64__)) || defined(_MSC_VER) || (!defined(__linux__) && !defined(_WIN32))
    #define NUITKA_PYRUNTIME_PTR(struct_start, comp) ((char *)(struct_start) + offsetof(_PyRuntimeState, comp))
#else
    #define NUITKA_PYRUNTIME_PTR(struct_start, comp) ((char *)(struct_start) + NUITKA_PYRUNTIME_OFFSET__PyRuntimeState_ ## comp)
#endif

/*
 * Dynamic offset extraction with compiler-enforced Type Safety.
 * If Nuitka developer casts to the wrong structural C type, CI triggers an incompatible-pointer error natively.
 */
#if defined(__GNUC__) || defined(__clang__)
#define NUITKA_PYRUNTIME_DYNAMIC(var, comp, type) ({ \
    __typeof__(((_PyRuntimeState*)0)->comp) *_type_check = (type*)0; \
    (void)_type_check; \
    (type *) NUITKA_PYRUNTIME_PTR(var, comp); \
})
#else
#define NUITKA_PYRUNTIME_DYNAMIC(var, comp, type) \
    ( (type *) NUITKA_PYRUNTIME_PTR(var, comp) )
#endif


/*
 * Poison direct access to _PyRuntime.
 * This guarantees any direct references in the Nuitka codebase cause a compile
 * error, enforcing cross-compiler ABI safety via NUITKA_PYRUNTIME_PTR.
 */
PyAPI_DATA(_PyRuntimeState) _PyRuntime;

#ifndef _Nuitka_PyRuntime_PTR
static inline _PyRuntimeState *_Nuitka_Get_PyRuntime_PTR(void) { return &_PyRuntime; }
#define _Nuitka_PyRuntime_PTR (_Nuitka_Get_PyRuntime_PTR())
#endif

/* Nuitka C API strongly-typed access macros */
#if PYTHON_VERSION >= 0x3c0
#define Nuitka_PyRuntime__imports NUITKA_PYRUNTIME_DYNAMIC(_Nuitka_PyRuntime_PTR, imports, struct _import_runtime_state)
#define Nuitka_PyRuntime__static_objects NUITKA_PYRUNTIME_DYNAMIC(_Nuitka_PyRuntime_PTR, static_objects, struct _Py_static_objects)
#endif

#if PYTHON_VERSION >= 0x3d0
#define _PyRuntime (*((struct NUITKA_ERROR_Do_not_use_PyRuntime_directly_use_NUITKA_PYRUNTIME_PTR *)0))
#endif

// The adapted header already rewrites _PyReftracerTrack's body, but only
// to a compile-time _Nuitka_PyRuntime_PTR->ref_tracer dereference.
// Replace it here with the NUITKA_PYRUNTIME_DYNAMIC variant so the offset
// survives 3.14 micro-version _PyRuntimeState layout changes (ref_tracer
// shifts between e.g. 3.14.2/3.14.3 by 3 pointer widths).
#if PYTHON_VERSION >= 0x3e0
#ifdef _PyReftracerTrack
#undef _PyReftracerTrack
#endif
#define _PyReftracerTrack(obj, operation)                                                                              \
    do {                                                                                                               \
        struct _reftracer_runtime_state *tracer =                                                                      \
            NUITKA_PYRUNTIME_DYNAMIC(_Nuitka_PyRuntime_PTR, ref_tracer, struct _reftracer_runtime_state);              \
        if (tracer->tracer_func != NULL) {                                                                             \
            void *data = tracer->tracer_data;                                                                          \
            tracer->tracer_func((obj), (operation), data);                                                             \
        }                                                                                                              \
    } while (0)
#endif

#endif

{#-  Part of "Nuitka", an optimizing Python compiler that is compatible and           -#}
{#-  integrates with CPython, but also works on its own.                              -#}
{#-                                                                                   -#}
{#-  Licensed under the GNU Affero General Public License, Version 3 (the "License"); -#}
{#-  you may not use this file except in compliance with the License.                 -#}
{#-  You may obtain a copy of the License at                                          -#}
{#-                                                                                   -#}
{#-  https://www.gnu.org/licenses/agpl-3.0.txt                                        -#}
{#-                                                                                   -#}
{#-  See also: "Nuitka Runtime Library Exception, Version 1.0" in file                -#}
{#-  "LICENSE-RUNTIME.txt" for additional permissions granted under Section 7.        -#}
{#-                                                                                   -#}
{#-  Unless required by applicable law or agreed to in writing, software              -#}
{#-  distributed under the License is distributed on an "AS IS" BASIS,                -#}
{#-  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.         -#}
{#-  See the License for the specific language governing permissions and              -#}
{#-  limitations under the License.                                                   -#}
