2828extern "C" {
2929#endif
3030
31- #ifndef HPY_UNIVERSAL_ABI
32- /* It would be nice if we could include hpy.h WITHOUT bringing in all the
33- stuff from Python.h, to make sure that people don't use the CPython API by
34- mistake. How to achieve it, though? */
31+ /* ~~~~~~~~~~~~~~~~ HPy ABI version ~~~~~~~~~~~~~~~ */
32+ // NOTE: these must be kept on sync with the equivalent variables in hpy/devel/abitag.py
33+ /**
34+ * The ABI version.
35+ *
36+ * Minor version N+1 is binary compatible to minor version N. Major versions
37+ * are not binary compatible (note: HPy can run several binary incompatible
38+ * versions in one process).
39+ */
40+ #define HPY_ABI_VERSION 0
41+ #define HPY_ABI_VERSION_MINOR 0
42+ #define HPY_ABI_TAG "hpy0"
43+
44+
45+ /* ~~~~~~~~~~~~~~~~ HPy ABI macros ~~~~~~~~~~~~~~~~ */
46+
47+ /* The following macros are used to determine which kind of module we want to
48+ compile. The build system must set one of these (e.g. by using `gcc
49+ -D...`). This is the approach used by the setuptools support provided by
50+ hpy.devel:
51+
52+ - HPY_ABI_CPYTHON
53+ - HPY_ABI_UNIVERSAL
54+ - HPY_ABI_HYBRID
55+
56+ In addition we also define HPY_ABI which is a string literal containing a
57+ string representation of it.
58+ */
59+
60+ #if defined(HPY_ABI_CPYTHON )
61+ # if defined(HPY_ABI_HYBRID )
62+ # error "Conflicting macros are defined: HPY_ABI_CPYTHON and HPY_ABI_HYBRID"
63+ # endif
64+ # if defined(HPY_ABI_UNIVERSAL )
65+ # error "Conflicting macros are defined: HPY_ABI_CPYTHON and HPY_ABI_UNIVERSAL"
66+ # endif
67+ # define HPY_ABI "cpython"
68+
69+ #elif defined(HPY_ABI_HYBRID )
70+ # if defined(HPY_ABI_UNIVERSAL )
71+ # error "Conflicting macros are defined: HPY_ABI_HYBRID and HPY_ABI_UNIVERSAL"
72+ # endif
73+ # define HPY_ABI "hybrid"
74+
75+ #elif defined(HPY_ABI_UNIVERSAL )
76+ # define HPY_ABI "universal"
77+
78+ #else
79+ # error "Cannot determine the desired HPy ABI: you must set one of HPY_ABI_CPYTHON, HPY_ABI_UNIVERSAL or HPY_ABI_HYBRID"
80+ #endif
81+
82+
83+ #if defined(HPY_ABI_CPYTHON ) || defined(HPY_ABI_HYBRID )
3584# define PY_SSIZE_T_CLEAN
3685# include <Python.h>
3786#endif
@@ -49,6 +98,7 @@ extern "C" {
4998# define _HPy_HIDDEN
5099# define _HPy_UNUSED
51100#endif /* __GNUC__ */
101+ #define _HPy_UNUSED_ARG (x ) (__HPy_UNUSED_TAGGED ## x) _HPy_UNUSED
52102
53103#if defined(__clang__ ) || \
54104 (defined(__GNUC__ ) && \
@@ -61,6 +111,28 @@ extern "C" {
61111# define _HPy_NO_RETURN
62112#endif
63113
114+
115+ // clang and gcc supports __has_attribute, MSVC doesn't. This should be enough
116+ // to be able to use it portably
117+ #ifdef __has_attribute
118+ # define _HPY_compiler_has_attribute (x ) __has_attribute(x)
119+ #else
120+ # define _HPY_compiler_has_attribute (x ) 0
121+ #endif
122+
123+ #ifdef HPY_ABI_UNIVERSAL
124+ # if _HPY_compiler_has_attribute (error )
125+ // gcc, clang>=14
126+ # define _HPY_LEGACY __attribute__((error("Cannot use legacy functions when targeting the HPy Universal ABI")))
127+ # else
128+ // we don't have any diagnostic feature, too bad
129+ # define _HPY_LEGACY
130+ # endif
131+ #else
132+ // in non-universal modes, we don't attach any attribute
133+ # define _HPY_LEGACY
134+ #endif
135+
64136#if defined(_MSC_VER ) && defined(__cplusplus ) // MSVC C4576
65137# define _hconv (h ) {h}
66138# define _hfconv (h ) {h}
@@ -91,6 +163,9 @@ extern "C" {
91163 */
92164#define HPyAPI_FUNC _HPy_UNUSED static inline
93165
166+ /** An alias for ``HPyAPI_FUNC`` so we can handle it properly in the docs. */
167+ #define HPyAPI_INLINE_HELPER HPyAPI_FUNC
168+
94169/**
95170 * CPython implementations for ``HPyAPI_FUNC``
96171 * functions. Generally speaking, they are put in ctx_*.c files and they are
@@ -128,7 +203,8 @@ extern "C" {
128203
129204 - PyPy: ._i is an index into a list
130205
131- - GraalPython: ???
206+ - GraalPy: ._i is a tagged value, either an index into a list,
207+ or an immediate integer or double value
132208
133209 - Debug mode: _i is a pointer to a DebugHandle, which contains a
134210 another HPy among other stuff
@@ -165,15 +241,12 @@ typedef struct { void* _i; } HPyThreadState;
165241#define HPyListBuilder_IsNull (h ) ((h)._lst == 0)
166242#define HPyTupleBuilder_IsNull (h ) ((h)._tup == 0)
167243
168- #define HPyListBuilder_IsNull (h ) ((h)._lst == 0)
169- #define HPyTupleBuilder_IsNull (h ) ((h)._tup == 0)
170-
171244#define HPyField_NULL _hfconv(0)
172245#define HPyField_IsNull (f ) ((f)._i == 0)
173246
174247/* Convenience functions to cast between HPy and void*. We need to decide
175248 whether these are part of the official API or not, and maybe introduce a
176- better naming convetion . For now, they are needed for ujson. */
249+ better naming convention . For now, they are needed for ujson. */
177250#ifndef GRAALVM_PYTHON_LLVM
178251static inline HPy HPy_FromVoidP (void * p ) { return _hconv ((intptr_t )p ); }
179252static inline void * HPy_AsVoidP (HPy h ) { return (void * )h ._i ; }
@@ -187,51 +260,75 @@ static inline void* HPy_AsVoidP(HPy h) { return h._i; }
187260
188261typedef struct _HPyContext_s HPyContext ;
189262
190- #ifdef HPY_UNIVERSAL_ABI
263+ /** An enumeration of the different kinds of source code strings. */
264+ typedef enum {
265+ /** Parse isolated expressions (e.g. ``a + b``). */
266+ HPy_SourceKind_Expr = 0 ,
267+
268+ /**
269+ * Parse sequences of statements as read from a file or other source. This
270+ * is the symbol to use when compiling arbitrarily long Python source code.
271+ */
272+ HPy_SourceKind_File = 1 ,
273+
274+ /**
275+ * Parse a single statement. This is the mode used for the interactive
276+ * interpreter loop.
277+ */
278+ HPy_SourceKind_Single = 2 ,
279+ } HPy_SourceKind ;
280+
281+ #ifdef HPY_ABI_CPYTHON
282+ typedef Py_ssize_t HPy_ssize_t ;
283+ typedef Py_hash_t HPy_hash_t ;
284+ typedef Py_UCS4 HPy_UCS4 ;
285+
286+ # define HPY_SSIZE_T_MAX PY_SSIZE_T_MAX
287+ # define HPY_SSIZE_T_MIN PY_SSIZE_T_MIN
288+
289+ #else
191290 typedef intptr_t HPy_ssize_t ;
192291 typedef intptr_t HPy_hash_t ;
193292 typedef uint32_t HPy_UCS4 ;
194293
294+ # define HPY_SSIZE_T_MAX INTPTR_MAX
295+ # define HPY_SSIZE_T_MIN (-HPY_SSIZE_T_MAX-1)
296+
195297 /* HPyCapsule field keys */
196298 typedef enum {
197299 HPyCapsule_key_Pointer = 0 ,
198300 HPyCapsule_key_Name = 1 ,
199301 HPyCapsule_key_Context = 2 ,
200302 HPyCapsule_key_Destructor = 3 ,
201303 } _HPyCapsule_key ;
202-
203- #else
204- typedef Py_ssize_t HPy_ssize_t ;
205- typedef Py_hash_t HPy_hash_t ;
206- typedef Py_UCS4 HPy_UCS4 ;
207304#endif
208305
209- typedef void (* HPyCapsule_Destructor )(const char * name , void * pointer , void * context );
210-
211306
212307/* ~~~~~~~~~~~~~~~~ Additional #includes ~~~~~~~~~~~~~~~~ */
213308
214309#include "hpy/cpy_types.h"
310+ #include "hpy/hpyexports.h"
215311#include "hpy/macros.h"
216312#include "hpy/hpyfunc.h"
217313#include "hpy/hpydef.h"
218314#include "hpy/hpytype.h"
219315#include "hpy/hpymodule.h"
220316#include "hpy/runtime/argparse.h"
221317#include "hpy/runtime/buildvalue.h"
318+ #include "hpy/runtime/format.h"
222319#include "hpy/runtime/helpers.h"
223320#include "hpy/runtime/structseq.h"
224321
225- #ifdef HPY_UNIVERSAL_ABI
226- # include "hpy/universal/autogen_ctx.h"
227- # include "hpy/universal/autogen_trampolines.h"
228- # include "hpy/universal/misc_trampolines.h"
229- #else
230- // CPython-ABI
322+ #ifdef HPY_ABI_CPYTHON
323+ # include "hpy/cpython/autogen_ctx.h"
231324# include "hpy/runtime/ctx_funcs.h"
232325# include "hpy/runtime/ctx_type.h"
233326# include "hpy/cpython/misc.h"
234327# include "hpy/cpython/autogen_api_impl.h"
328+ #else
329+ # include "hpy/universal/autogen_ctx.h"
330+ # include "hpy/universal/autogen_trampolines.h"
331+ # include "hpy/universal/misc_trampolines.h"
235332#endif
236333
237334#include "hpy/inline_helpers.h"
0 commit comments