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