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