28
28
extern "C" {
29
29
#endif
30
30
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 )
35
84
# define PY_SSIZE_T_CLEAN
36
85
# include <Python.h>
37
86
#endif
@@ -49,6 +98,7 @@ extern "C" {
49
98
# define _HPy_HIDDEN
50
99
# define _HPy_UNUSED
51
100
#endif /* __GNUC__ */
101
+ #define _HPy_UNUSED_ARG (x ) (__HPy_UNUSED_TAGGED ## x) _HPy_UNUSED
52
102
53
103
#if defined(__clang__ ) || \
54
104
(defined(__GNUC__ ) && \
@@ -61,6 +111,28 @@ extern "C" {
61
111
# define _HPy_NO_RETURN
62
112
#endif
63
113
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
+
64
136
#if defined(_MSC_VER ) && defined(__cplusplus ) // MSVC C4576
65
137
# define _hconv (h ) {h}
66
138
# define _hfconv (h ) {h}
@@ -91,6 +163,9 @@ extern "C" {
91
163
*/
92
164
#define HPyAPI_FUNC _HPy_UNUSED static inline
93
165
166
+ /** An alias for ``HPyAPI_FUNC`` so we can handle it properly in the docs. */
167
+ #define HPyAPI_INLINE_HELPER HPyAPI_FUNC
168
+
94
169
/**
95
170
* CPython implementations for ``HPyAPI_FUNC``
96
171
* functions. Generally speaking, they are put in ctx_*.c files and they are
@@ -128,7 +203,8 @@ extern "C" {
128
203
129
204
- PyPy: ._i is an index into a list
130
205
131
- - GraalPython: ???
206
+ - GraalPy: ._i is a tagged value, either an index into a list,
207
+ or an immediate integer or double value
132
208
133
209
- Debug mode: _i is a pointer to a DebugHandle, which contains a
134
210
another HPy among other stuff
@@ -165,15 +241,12 @@ typedef struct { void* _i; } HPyThreadState;
165
241
#define HPyListBuilder_IsNull (h ) ((h)._lst == 0)
166
242
#define HPyTupleBuilder_IsNull (h ) ((h)._tup == 0)
167
243
168
- #define HPyListBuilder_IsNull (h ) ((h)._lst == 0)
169
- #define HPyTupleBuilder_IsNull (h ) ((h)._tup == 0)
170
-
171
244
#define HPyField_NULL _hfconv(0)
172
245
#define HPyField_IsNull (f ) ((f)._i == 0)
173
246
174
247
/* Convenience functions to cast between HPy and void*. We need to decide
175
248
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. */
177
250
#ifndef GRAALVM_PYTHON_LLVM
178
251
static inline HPy HPy_FromVoidP (void * p ) { return _hconv ((intptr_t )p ); }
179
252
static inline void * HPy_AsVoidP (HPy h ) { return (void * )h ._i ; }
@@ -187,51 +260,75 @@ static inline void* HPy_AsVoidP(HPy h) { return h._i; }
187
260
188
261
typedef struct _HPyContext_s HPyContext ;
189
262
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
191
290
typedef intptr_t HPy_ssize_t ;
192
291
typedef intptr_t HPy_hash_t ;
193
292
typedef uint32_t HPy_UCS4 ;
194
293
294
+ # define HPY_SSIZE_T_MAX INTPTR_MAX
295
+ # define HPY_SSIZE_T_MIN (-HPY_SSIZE_T_MAX-1)
296
+
195
297
/* HPyCapsule field keys */
196
298
typedef enum {
197
299
HPyCapsule_key_Pointer = 0 ,
198
300
HPyCapsule_key_Name = 1 ,
199
301
HPyCapsule_key_Context = 2 ,
200
302
HPyCapsule_key_Destructor = 3 ,
201
303
} _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 ;
207
304
#endif
208
305
209
- typedef void (* HPyCapsule_Destructor )(const char * name , void * pointer , void * context );
210
-
211
306
212
307
/* ~~~~~~~~~~~~~~~~ Additional #includes ~~~~~~~~~~~~~~~~ */
213
308
214
309
#include "hpy/cpy_types.h"
310
+ #include "hpy/hpyexports.h"
215
311
#include "hpy/macros.h"
216
312
#include "hpy/hpyfunc.h"
217
313
#include "hpy/hpydef.h"
218
314
#include "hpy/hpytype.h"
219
315
#include "hpy/hpymodule.h"
220
316
#include "hpy/runtime/argparse.h"
221
317
#include "hpy/runtime/buildvalue.h"
318
+ #include "hpy/runtime/format.h"
222
319
#include "hpy/runtime/helpers.h"
223
320
#include "hpy/runtime/structseq.h"
224
321
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"
231
324
# include "hpy/runtime/ctx_funcs.h"
232
325
# include "hpy/runtime/ctx_type.h"
233
326
# include "hpy/cpython/misc.h"
234
327
# 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"
235
332
#endif
236
333
237
334
#include "hpy/inline_helpers.h"
0 commit comments