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