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 46ORC_RT_C_EXTERN_C_BEGIN 47 48typedef 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 */ 70typedef struct { 71 __orc_rt_CWrapperFunctionResultDataUnion Data; 72 size_t Size; 73} __orc_rt_CWrapperFunctionResult; 74 75typedef struct __orc_rt_CSharedOpaqueJITProcessControl 76 *__orc_rt_SharedJITProcessControlRef; 77 78/** 79 * Zero-initialize an __orc_rt_CWrapperFunctionResult. 80 */ 81static inline void 82__orc_rt_CWrapperFunctionResultInit(__orc_rt_CWrapperFunctionResult *R) { 83 R->Size = 0; 84 R->Data.ValuePtr = 0; 85} 86 87/** 88 * Create an __orc_rt_CWrapperFunctionResult with an uninitialized buffer of 89 * size Size. The buffer is returned via the DataPtr argument. 90 */ 91static inline __orc_rt_CWrapperFunctionResult 92__orc_rt_CWrapperFunctionResultAllocate(size_t Size) { 93 __orc_rt_CWrapperFunctionResult R; 94 R.Size = Size; 95 // If Size is 0 ValuePtr must be 0 or it is considered an out-of-band error. 96 R.Data.ValuePtr = 0; 97 if (Size > sizeof(R.Data.Value)) 98 R.Data.ValuePtr = (char *)malloc(Size); 99 return R; 100} 101 102/** 103 * Create an __orc_rt_WrapperFunctionResult from the given data range. 104 */ 105static inline __orc_rt_CWrapperFunctionResult 106__orc_rt_CreateCWrapperFunctionResultFromRange(const char *Data, size_t Size) { 107 __orc_rt_CWrapperFunctionResult R; 108 R.Size = Size; 109 if (R.Size > sizeof(R.Data.Value)) { 110 char *Tmp = (char *)malloc(Size); 111 memcpy(Tmp, Data, Size); 112 R.Data.ValuePtr = Tmp; 113 } else 114 memcpy(R.Data.Value, Data, Size); 115 return R; 116} 117 118/** 119 * Create an __orc_rt_CWrapperFunctionResult by copying the given string, 120 * including the null-terminator. 121 * 122 * This function copies the input string. The client is responsible for freeing 123 * the ErrMsg arg. 124 */ 125static inline __orc_rt_CWrapperFunctionResult 126__orc_rt_CreateCWrapperFunctionResultFromString(const char *Source) { 127 return __orc_rt_CreateCWrapperFunctionResultFromRange(Source, 128 strlen(Source) + 1); 129} 130 131/** 132 * Create an __orc_rt_CWrapperFunctionResult representing an out-of-band 133 * error. 134 * 135 * This function copies the input string. The client is responsible for freeing 136 * the ErrMsg arg. 137 */ 138static inline __orc_rt_CWrapperFunctionResult 139__orc_rt_CreateCWrapperFunctionResultFromOutOfBandError(const char *ErrMsg) { 140 __orc_rt_CWrapperFunctionResult R; 141 R.Size = 0; 142 char *Tmp = (char *)malloc(strlen(ErrMsg) + 1); 143 strcpy(Tmp, ErrMsg); 144 R.Data.ValuePtr = Tmp; 145 return R; 146} 147 148/** 149 * This should be called to destroy __orc_rt_CWrapperFunctionResult values 150 * regardless of their state. 151 */ 152static inline void 153__orc_rt_DisposeCWrapperFunctionResult(__orc_rt_CWrapperFunctionResult *R) { 154 if (R->Size > sizeof(R->Data.Value) || 155 (R->Size == 0 && R->Data.ValuePtr)) 156 free(R->Data.ValuePtr); 157} 158 159/** 160 * Get a pointer to the data contained in the given 161 * __orc_rt_CWrapperFunctionResult. 162 */ 163static inline char * 164__orc_rt_CWrapperFunctionResultData(__orc_rt_CWrapperFunctionResult *R) { 165 assert((R->Size != 0 || R->Data.ValuePtr == NULL) && 166 "Cannot get data for out-of-band error value"); 167 return R->Size > sizeof(R->Data.Value) ? R->Data.ValuePtr : R->Data.Value; 168} 169 170/** 171 * Safely get the size of the given __orc_rt_CWrapperFunctionResult. 172 * 173 * Asserts that we're not trying to access the size of an error value. 174 */ 175static inline size_t 176__orc_rt_CWrapperFunctionResultSize(const __orc_rt_CWrapperFunctionResult *R) { 177 assert((R->Size != 0 || R->Data.ValuePtr == NULL) && 178 "Cannot get size for out-of-band error value"); 179 return R->Size; 180} 181 182/** 183 * Returns 1 if this value is equivalent to a value just initialized by 184 * __orc_rt_CWrapperFunctionResultInit, 0 otherwise. 185 */ 186static inline size_t 187__orc_rt_CWrapperFunctionResultEmpty(const __orc_rt_CWrapperFunctionResult *R) { 188 return R->Size == 0 && R->Data.ValuePtr == 0; 189} 190 191/** 192 * Returns a pointer to the out-of-band error string for this 193 * __orc_rt_CWrapperFunctionResult, or null if there is no error. 194 * 195 * The __orc_rt_CWrapperFunctionResult retains ownership of the error 196 * string, so it should be copied if the caller wishes to preserve it. 197 */ 198static inline const char *__orc_rt_CWrapperFunctionResultGetOutOfBandError( 199 const __orc_rt_CWrapperFunctionResult *R) { 200 return R->Size == 0 ? R->Data.ValuePtr : 0; 201} 202 203ORC_RT_C_EXTERN_C_END 204 205#endif /* ORC_RT_C_API_H */ 206