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 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 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 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 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 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 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 * 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 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 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 */ 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