| /*===- c_api.h - C API for the ORC runtime ------------------------*- C -*-===*\ |
| |* *| |
| |* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| |
| |* Exceptions. *| |
| |* See https://llvm.org/LICENSE.txt for license information. *| |
| |* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| |
| |* *| |
| |*===----------------------------------------------------------------------===*| |
| |* *| |
| |* This file defines the C API for the ORC runtime *| |
| |* *| |
| \*===----------------------------------------------------------------------===*/ |
| |
| #ifndef ORC_RT_C_API_H |
| #define ORC_RT_C_API_H |
| |
| #include <assert.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| |
| /* Helper to suppress strict prototype warnings. */ |
| #ifdef __clang__ |
| #define ORC_RT_C_STRICT_PROTOTYPES_BEGIN \ |
| _Pragma("clang diagnostic push") \ |
| _Pragma("clang diagnostic error \"-Wstrict-prototypes\"") |
| #define ORC_RT_C_STRICT_PROTOTYPES_END _Pragma("clang diagnostic pop") |
| #else |
| #define ORC_RT_C_STRICT_PROTOTYPES_BEGIN |
| #define ORC_RT_C_STRICT_PROTOTYPES_END |
| #endif |
| |
| /* Helper to wrap C code for C++ */ |
| #ifdef __cplusplus |
| #define ORC_RT_C_EXTERN_C_BEGIN \ |
| extern "C" { \ |
| ORC_RT_C_STRICT_PROTOTYPES_BEGIN |
| #define ORC_RT_C_EXTERN_C_END \ |
| ORC_RT_C_STRICT_PROTOTYPES_END \ |
| } |
| #else |
| #define ORC_RT_C_EXTERN_C_BEGIN ORC_RT_C_STRICT_PROTOTYPES_BEGIN |
| #define ORC_RT_C_EXTERN_C_END ORC_RT_C_STRICT_PROTOTYPES_END |
| #endif |
| |
| ORC_RT_C_EXTERN_C_BEGIN |
| |
| typedef union { |
| char *ValuePtr; |
| char Value[sizeof(char *)]; |
| } __orc_rt_CWrapperFunctionResultDataUnion; |
| |
| /** |
| * __orc_rt_CWrapperFunctionResult is a kind of C-SmallVector with an |
| * out-of-band error state. |
| * |
| * If Size == 0 and Data.ValuePtr is non-zero then the value is in the |
| * 'out-of-band error' state, and Data.ValuePtr points at a malloc-allocated, |
| * null-terminated string error message. |
| * |
| * If Size <= sizeof(__orc_rt_CWrapperFunctionResultData) then the value is in |
| * the 'small' state and the content is held in the first Size bytes of |
| * Data.Value. |
| * |
| * If Size > sizeof(OrtRTCWrapperFunctionResultData) then the value is in the |
| * 'large' state and the content is held in the first Size bytes of the |
| * memory pointed to by Data.ValuePtr. This memory must have been allocated by |
| * malloc, and will be freed with free when this value is destroyed. |
| */ |
| typedef struct { |
| __orc_rt_CWrapperFunctionResultDataUnion Data; |
| size_t Size; |
| } __orc_rt_CWrapperFunctionResult; |
| |
| typedef struct __orc_rt_CSharedOpaqueJITProcessControl |
| *__orc_rt_SharedJITProcessControlRef; |
| |
| /** |
| * Zero-initialize an __orc_rt_CWrapperFunctionResult. |
| */ |
| static inline void |
| __orc_rt_CWrapperFunctionResultInit(__orc_rt_CWrapperFunctionResult *R) { |
| R->Size = 0; |
| R->Data.ValuePtr = 0; |
| } |
| |
| /** |
| * Create an __orc_rt_CWrapperFunctionResult with an uninitialized buffer of |
| * size Size. The buffer is returned via the DataPtr argument. |
| */ |
| static inline __orc_rt_CWrapperFunctionResult |
| __orc_rt_CWrapperFunctionResultAllocate(size_t Size) { |
| __orc_rt_CWrapperFunctionResult R; |
| R.Size = Size; |
| // If Size is 0 ValuePtr must be 0 or it is considered an out-of-band error. |
| R.Data.ValuePtr = 0; |
| if (Size > sizeof(R.Data.Value)) |
| R.Data.ValuePtr = (char *)malloc(Size); |
| return R; |
| } |
| |
| /** |
| * Create an __orc_rt_WrapperFunctionResult from the given data range. |
| */ |
| static inline __orc_rt_CWrapperFunctionResult |
| __orc_rt_CreateCWrapperFunctionResultFromRange(const char *Data, size_t Size) { |
| __orc_rt_CWrapperFunctionResult R; |
| R.Size = Size; |
| if (R.Size > sizeof(R.Data.Value)) { |
| char *Tmp = (char *)malloc(Size); |
| memcpy(Tmp, Data, Size); |
| R.Data.ValuePtr = Tmp; |
| } else |
| memcpy(R.Data.Value, Data, Size); |
| return R; |
| } |
| |
| /** |
| * Create an __orc_rt_CWrapperFunctionResult by copying the given string, |
| * including the null-terminator. |
| * |
| * This function copies the input string. The client is responsible for freeing |
| * the ErrMsg arg. |
| */ |
| static inline __orc_rt_CWrapperFunctionResult |
| __orc_rt_CreateCWrapperFunctionResultFromString(const char *Source) { |
| return __orc_rt_CreateCWrapperFunctionResultFromRange(Source, |
| strlen(Source) + 1); |
| } |
| |
| /** |
| * Create an __orc_rt_CWrapperFunctionResult representing an out-of-band |
| * error. |
| * |
| * This function copies the input string. The client is responsible for freeing |
| * the ErrMsg arg. |
| */ |
| static inline __orc_rt_CWrapperFunctionResult |
| __orc_rt_CreateCWrapperFunctionResultFromOutOfBandError(const char *ErrMsg) { |
| __orc_rt_CWrapperFunctionResult R; |
| R.Size = 0; |
| char *Tmp = (char *)malloc(strlen(ErrMsg) + 1); |
| strcpy(Tmp, ErrMsg); |
| R.Data.ValuePtr = Tmp; |
| return R; |
| } |
| |
| /** |
| * This should be called to destroy __orc_rt_CWrapperFunctionResult values |
| * regardless of their state. |
| */ |
| static inline void |
| __orc_rt_DisposeCWrapperFunctionResult(__orc_rt_CWrapperFunctionResult *R) { |
| if (R->Size > sizeof(R->Data.Value) || |
| (R->Size == 0 && R->Data.ValuePtr)) |
| free(R->Data.ValuePtr); |
| } |
| |
| /** |
| * Get a pointer to the data contained in the given |
| * __orc_rt_CWrapperFunctionResult. |
| */ |
| static inline char * |
| __orc_rt_CWrapperFunctionResultData(__orc_rt_CWrapperFunctionResult *R) { |
| assert((R->Size != 0 || R->Data.ValuePtr == NULL) && |
| "Cannot get data for out-of-band error value"); |
| return R->Size > sizeof(R->Data.Value) ? R->Data.ValuePtr : R->Data.Value; |
| } |
| |
| /** |
| * Safely get the size of the given __orc_rt_CWrapperFunctionResult. |
| * |
| * Asserts that we're not trying to access the size of an error value. |
| */ |
| static inline size_t |
| __orc_rt_CWrapperFunctionResultSize(const __orc_rt_CWrapperFunctionResult *R) { |
| assert((R->Size != 0 || R->Data.ValuePtr == NULL) && |
| "Cannot get size for out-of-band error value"); |
| return R->Size; |
| } |
| |
| /** |
| * Returns 1 if this value is equivalent to a value just initialized by |
| * __orc_rt_CWrapperFunctionResultInit, 0 otherwise. |
| */ |
| static inline size_t |
| __orc_rt_CWrapperFunctionResultEmpty(const __orc_rt_CWrapperFunctionResult *R) { |
| return R->Size == 0 && R->Data.ValuePtr == 0; |
| } |
| |
| /** |
| * Returns a pointer to the out-of-band error string for this |
| * __orc_rt_CWrapperFunctionResult, or null if there is no error. |
| * |
| * The __orc_rt_CWrapperFunctionResult retains ownership of the error |
| * string, so it should be copied if the caller wishes to preserve it. |
| */ |
| static inline const char *__orc_rt_CWrapperFunctionResultGetOutOfBandError( |
| const __orc_rt_CWrapperFunctionResult *R) { |
| return R->Size == 0 ? R->Data.ValuePtr : 0; |
| } |
| |
| ORC_RT_C_EXTERN_C_END |
| |
| #endif /* ORC_RT_C_API_H */ |