xref: /openbsd-src/gnu/llvm/compiler-rt/include/orc_rt/c_api.h (revision 810390e339a5425391477d5d41c78d7cab2424ac)
1*810390e3Srobert /*===- c_api.h - C API for the ORC runtime ------------------------*- C -*-===*\
2*810390e3Srobert |*                                                                            *|
3*810390e3Srobert |* Part of the LLVM Project, under the Apache License v2.0 with LLVM          *|
4*810390e3Srobert |* Exceptions.                                                                *|
5*810390e3Srobert |* See https://llvm.org/LICENSE.txt for license information.                  *|
6*810390e3Srobert |* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception                    *|
7*810390e3Srobert |*                                                                            *|
8*810390e3Srobert |*===----------------------------------------------------------------------===*|
9*810390e3Srobert |*                                                                            *|
10*810390e3Srobert |* This file defines the C API for the ORC runtime                            *|
11*810390e3Srobert |*                                                                            *|
12*810390e3Srobert \*===----------------------------------------------------------------------===*/
13*810390e3Srobert 
14*810390e3Srobert #ifndef ORC_RT_C_API_H
15*810390e3Srobert #define ORC_RT_C_API_H
16*810390e3Srobert 
17*810390e3Srobert #include <assert.h>
18*810390e3Srobert #include <stdio.h>
19*810390e3Srobert #include <stdlib.h>
20*810390e3Srobert #include <string.h>
21*810390e3Srobert 
22*810390e3Srobert /* Helper to suppress strict prototype warnings. */
23*810390e3Srobert #ifdef __clang__
24*810390e3Srobert #define ORC_RT_C_STRICT_PROTOTYPES_BEGIN                                       \
25*810390e3Srobert   _Pragma("clang diagnostic push")                                             \
26*810390e3Srobert       _Pragma("clang diagnostic error \"-Wstrict-prototypes\"")
27*810390e3Srobert #define ORC_RT_C_STRICT_PROTOTYPES_END _Pragma("clang diagnostic pop")
28*810390e3Srobert #else
29*810390e3Srobert #define ORC_RT_C_STRICT_PROTOTYPES_BEGIN
30*810390e3Srobert #define ORC_RT_C_STRICT_PROTOTYPES_END
31*810390e3Srobert #endif
32*810390e3Srobert 
33*810390e3Srobert /* Helper to wrap C code for C++ */
34*810390e3Srobert #ifdef __cplusplus
35*810390e3Srobert #define ORC_RT_C_EXTERN_C_BEGIN                                                \
36*810390e3Srobert   extern "C" {                                                                 \
37*810390e3Srobert   ORC_RT_C_STRICT_PROTOTYPES_BEGIN
38*810390e3Srobert #define ORC_RT_C_EXTERN_C_END                                                  \
39*810390e3Srobert   ORC_RT_C_STRICT_PROTOTYPES_END                                               \
40*810390e3Srobert   }
41*810390e3Srobert #else
42*810390e3Srobert #define ORC_RT_C_EXTERN_C_BEGIN ORC_RT_C_STRICT_PROTOTYPES_BEGIN
43*810390e3Srobert #define ORC_RT_C_EXTERN_C_END ORC_RT_C_STRICT_PROTOTYPES_END
44*810390e3Srobert #endif
45*810390e3Srobert 
46*810390e3Srobert ORC_RT_C_EXTERN_C_BEGIN
47*810390e3Srobert 
48*810390e3Srobert typedef union {
49*810390e3Srobert   char *ValuePtr;
50*810390e3Srobert   char Value[sizeof(char *)];
51*810390e3Srobert } __orc_rt_CWrapperFunctionResultDataUnion;
52*810390e3Srobert 
53*810390e3Srobert /**
54*810390e3Srobert  * __orc_rt_CWrapperFunctionResult is a kind of C-SmallVector with an
55*810390e3Srobert  * out-of-band error state.
56*810390e3Srobert  *
57*810390e3Srobert  * If Size == 0 and Data.ValuePtr is non-zero then the value is in the
58*810390e3Srobert  * 'out-of-band error' state, and Data.ValuePtr points at a malloc-allocated,
59*810390e3Srobert  * null-terminated string error message.
60*810390e3Srobert  *
61*810390e3Srobert  * If Size <= sizeof(__orc_rt_CWrapperFunctionResultData) then the value is in
62*810390e3Srobert  * the 'small' state and the content is held in the first Size bytes of
63*810390e3Srobert  * Data.Value.
64*810390e3Srobert  *
65*810390e3Srobert  * If Size > sizeof(OrtRTCWrapperFunctionResultData) then the value is in the
66*810390e3Srobert  * 'large' state and the content is held in the first Size bytes of the
67*810390e3Srobert  * memory pointed to by Data.ValuePtr. This memory must have been allocated by
68*810390e3Srobert  * malloc, and will be freed with free when this value is destroyed.
69*810390e3Srobert  */
70*810390e3Srobert typedef struct {
71*810390e3Srobert   __orc_rt_CWrapperFunctionResultDataUnion Data;
72*810390e3Srobert   size_t Size;
73*810390e3Srobert } __orc_rt_CWrapperFunctionResult;
74*810390e3Srobert 
75*810390e3Srobert typedef struct __orc_rt_CSharedOpaqueJITProcessControl
76*810390e3Srobert     *__orc_rt_SharedJITProcessControlRef;
77*810390e3Srobert 
78*810390e3Srobert /**
79*810390e3Srobert  * Zero-initialize an __orc_rt_CWrapperFunctionResult.
80*810390e3Srobert  */
81*810390e3Srobert static inline void
__orc_rt_CWrapperFunctionResultInit(__orc_rt_CWrapperFunctionResult * R)82*810390e3Srobert __orc_rt_CWrapperFunctionResultInit(__orc_rt_CWrapperFunctionResult *R) {
83*810390e3Srobert   R->Size = 0;
84*810390e3Srobert   R->Data.ValuePtr = 0;
85*810390e3Srobert }
86*810390e3Srobert 
87*810390e3Srobert /**
88*810390e3Srobert  * Create an __orc_rt_CWrapperFunctionResult with an uninitialized buffer of
89*810390e3Srobert  * size Size. The buffer is returned via the DataPtr argument.
90*810390e3Srobert  */
91*810390e3Srobert static inline __orc_rt_CWrapperFunctionResult
__orc_rt_CWrapperFunctionResultAllocate(size_t Size)92*810390e3Srobert __orc_rt_CWrapperFunctionResultAllocate(size_t Size) {
93*810390e3Srobert   __orc_rt_CWrapperFunctionResult R;
94*810390e3Srobert   R.Size = Size;
95*810390e3Srobert   // If Size is 0 ValuePtr must be 0 or it is considered an out-of-band error.
96*810390e3Srobert   R.Data.ValuePtr = 0;
97*810390e3Srobert   if (Size > sizeof(R.Data.Value))
98*810390e3Srobert     R.Data.ValuePtr = (char *)malloc(Size);
99*810390e3Srobert   return R;
100*810390e3Srobert }
101*810390e3Srobert 
102*810390e3Srobert /**
103*810390e3Srobert  * Create an __orc_rt_WrapperFunctionResult from the given data range.
104*810390e3Srobert  */
105*810390e3Srobert static inline __orc_rt_CWrapperFunctionResult
__orc_rt_CreateCWrapperFunctionResultFromRange(const char * Data,size_t Size)106*810390e3Srobert __orc_rt_CreateCWrapperFunctionResultFromRange(const char *Data, size_t Size) {
107*810390e3Srobert   __orc_rt_CWrapperFunctionResult R;
108*810390e3Srobert   R.Size = Size;
109*810390e3Srobert   if (R.Size > sizeof(R.Data.Value)) {
110*810390e3Srobert     char *Tmp = (char *)malloc(Size);
111*810390e3Srobert     memcpy(Tmp, Data, Size);
112*810390e3Srobert     R.Data.ValuePtr = Tmp;
113*810390e3Srobert   } else
114*810390e3Srobert     memcpy(R.Data.Value, Data, Size);
115*810390e3Srobert   return R;
116*810390e3Srobert }
117*810390e3Srobert 
118*810390e3Srobert /**
119*810390e3Srobert  * Create an __orc_rt_CWrapperFunctionResult by copying the given string,
120*810390e3Srobert  * including the null-terminator.
121*810390e3Srobert  *
122*810390e3Srobert  * This function copies the input string. The client is responsible for freeing
123*810390e3Srobert  * the ErrMsg arg.
124*810390e3Srobert  */
125*810390e3Srobert static inline __orc_rt_CWrapperFunctionResult
__orc_rt_CreateCWrapperFunctionResultFromString(const char * Source)126*810390e3Srobert __orc_rt_CreateCWrapperFunctionResultFromString(const char *Source) {
127*810390e3Srobert   return __orc_rt_CreateCWrapperFunctionResultFromRange(Source,
128*810390e3Srobert                                                         strlen(Source) + 1);
129*810390e3Srobert }
130*810390e3Srobert 
131*810390e3Srobert /**
132*810390e3Srobert  * Create an __orc_rt_CWrapperFunctionResult representing an out-of-band
133*810390e3Srobert  * error.
134*810390e3Srobert  *
135*810390e3Srobert  * This function copies the input string. The client is responsible for freeing
136*810390e3Srobert  * the ErrMsg arg.
137*810390e3Srobert  */
138*810390e3Srobert static inline __orc_rt_CWrapperFunctionResult
__orc_rt_CreateCWrapperFunctionResultFromOutOfBandError(const char * ErrMsg)139*810390e3Srobert __orc_rt_CreateCWrapperFunctionResultFromOutOfBandError(const char *ErrMsg) {
140*810390e3Srobert   __orc_rt_CWrapperFunctionResult R;
141*810390e3Srobert   R.Size = 0;
142*810390e3Srobert   char *Tmp = (char *)malloc(strlen(ErrMsg) + 1);
143*810390e3Srobert   strcpy(Tmp, ErrMsg);
144*810390e3Srobert   R.Data.ValuePtr = Tmp;
145*810390e3Srobert   return R;
146*810390e3Srobert }
147*810390e3Srobert 
148*810390e3Srobert /**
149*810390e3Srobert  * This should be called to destroy __orc_rt_CWrapperFunctionResult values
150*810390e3Srobert  * regardless of their state.
151*810390e3Srobert  */
152*810390e3Srobert static inline void
__orc_rt_DisposeCWrapperFunctionResult(__orc_rt_CWrapperFunctionResult * R)153*810390e3Srobert __orc_rt_DisposeCWrapperFunctionResult(__orc_rt_CWrapperFunctionResult *R) {
154*810390e3Srobert   if (R->Size > sizeof(R->Data.Value) ||
155*810390e3Srobert       (R->Size == 0 && R->Data.ValuePtr))
156*810390e3Srobert     free(R->Data.ValuePtr);
157*810390e3Srobert }
158*810390e3Srobert 
159*810390e3Srobert /**
160*810390e3Srobert  * Get a pointer to the data contained in the given
161*810390e3Srobert  * __orc_rt_CWrapperFunctionResult.
162*810390e3Srobert  */
163*810390e3Srobert static inline char *
__orc_rt_CWrapperFunctionResultData(__orc_rt_CWrapperFunctionResult * R)164*810390e3Srobert __orc_rt_CWrapperFunctionResultData(__orc_rt_CWrapperFunctionResult *R) {
165*810390e3Srobert   assert((R->Size != 0 || R->Data.ValuePtr == NULL) &&
166*810390e3Srobert          "Cannot get data for out-of-band error value");
167*810390e3Srobert   return R->Size > sizeof(R->Data.Value) ? R->Data.ValuePtr : R->Data.Value;
168*810390e3Srobert }
169*810390e3Srobert 
170*810390e3Srobert /**
171*810390e3Srobert  * Safely get the size of the given __orc_rt_CWrapperFunctionResult.
172*810390e3Srobert  *
173*810390e3Srobert  * Asserts that we're not trying to access the size of an error value.
174*810390e3Srobert  */
175*810390e3Srobert static inline size_t
__orc_rt_CWrapperFunctionResultSize(const __orc_rt_CWrapperFunctionResult * R)176*810390e3Srobert __orc_rt_CWrapperFunctionResultSize(const __orc_rt_CWrapperFunctionResult *R) {
177*810390e3Srobert   assert((R->Size != 0 || R->Data.ValuePtr == NULL) &&
178*810390e3Srobert          "Cannot get size for out-of-band error value");
179*810390e3Srobert   return R->Size;
180*810390e3Srobert }
181*810390e3Srobert 
182*810390e3Srobert /**
183*810390e3Srobert  * Returns 1 if this value is equivalent to a value just initialized by
184*810390e3Srobert  * __orc_rt_CWrapperFunctionResultInit, 0 otherwise.
185*810390e3Srobert  */
186*810390e3Srobert static inline size_t
__orc_rt_CWrapperFunctionResultEmpty(const __orc_rt_CWrapperFunctionResult * R)187*810390e3Srobert __orc_rt_CWrapperFunctionResultEmpty(const __orc_rt_CWrapperFunctionResult *R) {
188*810390e3Srobert   return R->Size == 0 && R->Data.ValuePtr == 0;
189*810390e3Srobert }
190*810390e3Srobert 
191*810390e3Srobert /**
192*810390e3Srobert  * Returns a pointer to the out-of-band error string for this
193*810390e3Srobert  * __orc_rt_CWrapperFunctionResult, or null if there is no error.
194*810390e3Srobert  *
195*810390e3Srobert  * The __orc_rt_CWrapperFunctionResult retains ownership of the error
196*810390e3Srobert  * string, so it should be copied if the caller wishes to preserve it.
197*810390e3Srobert  */
__orc_rt_CWrapperFunctionResultGetOutOfBandError(const __orc_rt_CWrapperFunctionResult * R)198*810390e3Srobert static inline const char *__orc_rt_CWrapperFunctionResultGetOutOfBandError(
199*810390e3Srobert     const __orc_rt_CWrapperFunctionResult *R) {
200*810390e3Srobert   return R->Size == 0 ? R->Data.ValuePtr : 0;
201*810390e3Srobert }
202*810390e3Srobert 
203*810390e3Srobert ORC_RT_C_EXTERN_C_END
204*810390e3Srobert 
205*810390e3Srobert #endif /* ORC_RT_C_API_H */
206