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
orc_rt_CWrapperFunctionResultInit(orc_rt_CWrapperFunctionResult * R)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
orc_rt_CWrapperFunctionResultAllocate(size_t Size)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
orc_rt_CreateCWrapperFunctionResultFromRange(const char * Data,size_t Size)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
orc_rt_CreateCWrapperFunctionResultFromString(const char * Source)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
orc_rt_CreateCWrapperFunctionResultFromOutOfBandError(const char * ErrMsg)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
orc_rt_DisposeCWrapperFunctionResult(orc_rt_CWrapperFunctionResult * R)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 *
orc_rt_CWrapperFunctionResultData(orc_rt_CWrapperFunctionResult * R)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
orc_rt_CWrapperFunctionResultSize(const orc_rt_CWrapperFunctionResult * R)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
orc_rt_CWrapperFunctionResultEmpty(const orc_rt_CWrapperFunctionResult * R)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 */
orc_rt_CWrapperFunctionResultGetOutOfBandError(const orc_rt_CWrapperFunctionResult * R)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