From de7b1ae8f9cb760e330acd5d7f8c9bee6332da5a Mon Sep 17 00:00:00 2001 From: Brendan Hansen Date: Fri, 10 Mar 2023 11:36:34 -0600 Subject: [PATCH] added: wasm_runtime supports using `dyncall` --- compiler/build.sh | 4 +- compiler/src/wasm_runtime.c | 202 +++++++++--- shared/include/dyncall/dyncall.h | 143 +++++++++ shared/include/dyncall/dyncall_config.h | 47 +++ shared/include/dyncall/dyncall_macros.h | 343 +++++++++++++++++++++ shared/include/dyncall/dyncall_signature.h | 69 +++++ shared/include/dyncall/dyncall_types.h | 74 +++++ shared/lib/linux_x86_64/lib/libdyncall_s.a | Bin 0 -> 39613 bytes 8 files changed, 837 insertions(+), 45 deletions(-) create mode 100644 shared/include/dyncall/dyncall.h create mode 100644 shared/include/dyncall/dyncall_config.h create mode 100644 shared/include/dyncall/dyncall_macros.h create mode 100644 shared/include/dyncall/dyncall_signature.h create mode 100644 shared/include/dyncall/dyncall_types.h create mode 100644 shared/lib/linux_x86_64/lib/libdyncall_s.a diff --git a/compiler/build.sh b/compiler/build.sh index 82af69d1..99fe9ff3 100755 --- a/compiler/build.sh +++ b/compiler/build.sh @@ -6,8 +6,8 @@ ENABLE_DEBUG_INFO=1 C_FILES="onyx astnodes builtins checker clone doc entities errors lex parser symres types utils wasm_emit wasm_runtime " -LIBS="-L$CORE_DIR/lib -l$RUNTIME_LIBRARY -Wl,-rpath=$CORE_DIR/lib:./ -lpthread -ldl -lm" -INCLUDES="-I./include -I../shared/include" +LIBS="-L$CORE_DIR/lib -l$RUNTIME_LIBRARY -Wl,-rpath=$CORE_DIR/lib:./ -lpthread -ldl -lm -ldyncall_s" +INCLUDES="-I./include -I../shared/include -I../shared/include/dyncall" WARNINGS='-Wimplicit -Wmisleading-indentation -Wparentheses -Wsequence-point -Wreturn-type -Wshift-negative-value -Wunused-but-set-parameter -Wunused-but-set-variable -Wunused-function -Wunused-label -Wmaybe-uninitialized -Wsign-compare -Wstrict-overflow -Wduplicated-branches -Wduplicated-cond -Wtrigraphs -Waddress -Wlogical-op' diff --git a/compiler/src/wasm_runtime.c b/compiler/src/wasm_runtime.c index 09797d4d..f36ad33d 100644 --- a/compiler/src/wasm_runtime.c +++ b/compiler/src/wasm_runtime.c @@ -3,6 +3,7 @@ #include "astnodes.h" #include "wasm.h" #include "onyx_library.h" +#include "dyncall.h" #ifndef USE_OVM_DEBUGGER #include "wasmer.h" @@ -24,6 +25,9 @@ wasm_instance_t* wasm_instance; wasm_module_t* wasm_module; wasm_memory_t* wasm_memory; +// @Temporary +static DCCallVM *dcCallVM; + OnyxRuntime wasm_runtime; b32 wasm_name_equals(const wasm_name_t* name1, const wasm_name_t* name2) { @@ -37,6 +41,12 @@ b32 wasm_name_equals_string(const wasm_name_t* name1, const char* name2) { return !strncmp(name1->data, name2, name1->size); } +b32 wasm_name_starts_with(const wasm_name_t* name, const char *prefix) { + u32 prefix_size = strlen(prefix); + if (name->size < prefix_size) return 0; + return !strncmp(name->data, prefix, prefix_size); +} + wasm_extern_t* wasm_extern_lookup_by_name(wasm_module_t* module, wasm_instance_t* instance, const char* name) { i32 name_len = strlen(name); @@ -61,16 +71,39 @@ wasm_extern_t* wasm_extern_lookup_by_name(wasm_module_t* module, wasm_instance_t return exports.data[idx]; } +typedef struct LinkLibraryContext { + bh_buffer wasm_bytes; + bh_arr(char *) library_paths; +} LinkLibraryContext; -typedef void *(*LibraryLinker)(OnyxRuntime *runtime); +static void *locate_symbol_in_dynamic_library(LinkLibraryContext *ctx, char *libname, char *sym) { + #ifdef _BH_LINUX + char *library_name = bh_lookup_file(libname, ".", ".so", 1, (const char **) ctx->library_paths, 1); + void* handle = dlopen(library_name, RTLD_LAZY); + if (handle == NULL) { + return NULL; + } -typedef struct LibraryLinkContext { - bh_buffer wasm_bytes; - bh_arr(char *) library_paths; -} LibraryLinkContext; + return dlsym(handle, sym); + #endif + + #ifdef _BH_WINDOWS + char *library_name = bh_lookup_file(libname, ".", ".dll", 1, (const char **) ctx->library_paths, 1); + HMODULE handle = LoadLibraryA(library_name); + if (handle == NULL) { + return NULL; + } -static WasmFuncDefinition** onyx_load_library(LibraryLinkContext *ctx, char *name) { + return GetProcAddress(handle, sym); + #endif + + return NULL; +} + +typedef void *(*LinkLibraryer)(OnyxRuntime *runtime); + +static WasmFuncDefinition** onyx_load_library(LinkLibraryContext *ctx, char *name) { #ifdef _BH_LINUX #define DIR_SEPARATOR '/' #endif @@ -86,42 +119,17 @@ static WasmFuncDefinition** onyx_load_library(LibraryLinkContext *ctx, char *nam char *library_load_name_tmp = bh_bprintf("onyx_library_%s", library); char *library_load_name = alloca(strlen(library_load_name_tmp) + 1); strcpy(library_load_name, library_load_name_tmp); - LibraryLinker library_load; - - #ifdef _BH_LINUX - char *library_name = bh_lookup_file(name, ".", ".so", 1, (const char **) ctx->library_paths, 1); - void* handle = dlopen(library_name, RTLD_LAZY); - if (handle == NULL) { - printf("ERROR LOADING LIBRARY %s: %s\n", name, dlerror()); - return NULL; - } - library_load = (LibraryLinker) dlsym(handle, library_load_name); + LinkLibraryer library_load = locate_symbol_in_dynamic_library(ctx, name, library_load_name); if (library_load == NULL) { printf("ERROR RESOLVING '%s': %s\n", library_load_name, dlerror()); return NULL; } - #endif - - #ifdef _BH_WINDOWS - char *library_name = bh_lookup_file(name, ".", ".dll", 1, (const char **) ctx->library_paths, 1); - HMODULE handle = LoadLibraryA(library_name); - if (handle == NULL) { - printf("ERROR LOADING LIBRARY %s: %d\n", name, GetLastError()); - return NULL; - } - - library_load = (LibraryLinker) GetProcAddress(handle, library_load_name); - if (library_load == NULL) { - printf("ERROR RESOLVING '%s': %d\n", library_load_name, GetLastError()); - return NULL; - } - #endif return library_load(runtime); } -static void lookup_and_load_custom_libraries(LibraryLinkContext *ctx, bh_arr(WasmFuncDefinition **)* p_out) { +static void lookup_and_load_custom_libraries(LinkLibraryContext *ctx, bh_arr(WasmFuncDefinition **)* p_out) { bh_arr(WasmFuncDefinition **) out = *p_out; bh_buffer wasm_bytes = ctx->wasm_bytes; @@ -177,6 +185,90 @@ static void lookup_and_load_custom_libraries(LibraryLinkContext *ctx, bh_arr(Was *p_out = out; } + +typedef struct DynCallContext { + void (*func)(); + char types[64]; +} DynCallContext; + +static wasm_trap_t *__wasm_dyncall(void *env, const wasm_val_vec_t *args, wasm_val_vec_t *res) { + DynCallContext *ctx = env; + dcReset(dcCallVM); + + int arg_idx = 0; + for (int i = 1; i < 64; i++) { + switch (ctx->types[i]) { + case '\0': goto arguments_placed; + case 'i': dcArgInt(dcCallVM, args->data[arg_idx++].of.i32); break; + case 'l': dcArgLongLong(dcCallVM, args->data[arg_idx++].of.i64); break; + case 'f': dcArgFloat(dcCallVM, args->data[arg_idx++].of.f32); break; + case 'd': dcArgFloat(dcCallVM, args->data[arg_idx++].of.f64); break; + case 'p': dcArgPointer(dcCallVM, ONYX_PTR(args->data[arg_idx++].of.i32)); break; + case 'v': break; + case 's': + dcArgPointer(dcCallVM, ONYX_PTR(args->data[arg_idx++].of.i32)); + dcArgInt(dcCallVM, args->data[arg_idx++].of.i32); + break; + default: assert(("bad dynamic call type", 0)); + } + } + + arguments_placed: + switch (ctx->types[0]) { + case 'i': res->data[0] = WASM_I32_VAL(dcCallInt(dcCallVM, ctx->func)); break; + case 'l': res->data[0] = WASM_I64_VAL(dcCallLongLong(dcCallVM, ctx->func)); break; + case 'f': res->data[0] = WASM_F32_VAL(dcCallFloat(dcCallVM, ctx->func)); break; + case 'd': res->data[0] = WASM_F64_VAL(dcCallDouble(dcCallVM, ctx->func)); break; + case 'p': res->data[0] = WASM_I64_VAL((u64) dcCallPointer(dcCallVM, ctx->func)); break; + case 'v': dcCallVoid(dcCallVM, ctx->func); + } + + return NULL; +} + +static wasm_func_t *link_and_prepare_dyncall_function( + wasm_externtype_t* type, + LinkLibraryContext *lib_ctx, + wasm_name_t library_name, + wasm_name_t function_name) +{ + // + // When using any dynamic functions, a DCCallVM has to be created. + if (!dcCallVM) { + dcCallVM = dcNewCallVM(4096); + dcMode(dcCallVM, DC_CALL_C_DEFAULT); + } + + char lib_name[256]; + strncpy(lib_name, library_name.data, bh_min(256, library_name.size)); + + u32 index; + char func_name[256]; + for (index = 0; index < function_name.size; index++) { + if (function_name.data[index] == ':') break; + func_name[index] = function_name.data[index]; + } + func_name[index++] = '\0'; + + char dynamic_types[64]; + for (; index < function_name.size; index++) { + dynamic_types[index] = function_name.data[index]; + } + dynamic_types[index] = '\0'; + + void (*func)() = locate_symbol_in_dynamic_library(lib_ctx, lib_name, func_name); + if (!func) return NULL; + + wasm_functype_t *functype = wasm_externtype_as_functype(type); + + DynCallContext* dcc = bh_alloc_item(bh_heap_allocator(), DynCallContext); + dcc->func = func; + memcpy(&dcc->types, dynamic_types, 64); + + wasm_func_t *wasm_func = wasm_func_new_with_env(wasm_store, functype, &__wasm_dyncall, dcc, NULL); + return wasm_func; +} + static void onyx_print_trap(wasm_trap_t* trap) { wasm_message_t msg; wasm_trap_message(trap, &msg); @@ -229,7 +321,11 @@ static void cleanup_wasm_objects() { // // This could be cleaned up a bit, as this function directly modifies various global variables. // Those being wasm_memory and wasm_imports. -static b32 link_wasm_imports(bh_arr(WasmFuncDefinition **) linkable_functions, wasm_module_t *wasm_module) { +static b32 link_wasm_imports( + bh_arr(WasmFuncDefinition **) linkable_functions, + LinkLibraryContext *lib_ctx, + wasm_module_t *wasm_module) +{ wasm_importtype_vec_t module_imports; wasm_module_imports(wasm_module, &module_imports); @@ -254,6 +350,28 @@ static b32 link_wasm_imports(bh_arr(WasmFuncDefinition **) linkable_functions, w } } + if (wasm_name_starts_with(module_name, "dyncall:")) { + wasm_name_t library_name = *module_name; + library_name.data += 8; + library_name.size -= 8; + + wasm_name_t function_name = *import_name; + + wasm_func_t *wasm_func = link_and_prepare_dyncall_function( + (wasm_externtype_t *) wasm_importtype_type(module_imports.data[i]), + lib_ctx, + library_name, + function_name + ); + + if (!wasm_func) { + goto bad_import; + } + + import = wasm_func_as_extern(wasm_func); + goto import_found; + } + bh_arr_each(WasmFuncDefinition **, library_funcs, linkable_functions) { WasmFuncDefinition **pcurrent_function = *library_funcs; while (*pcurrent_function != NULL) { @@ -362,14 +480,10 @@ b32 onyx_run_wasm(bh_buffer wasm_bytes, int argc, char *argv[]) { bh_arr(WasmFuncDefinition **) linkable_functions = NULL; bh_arr_new(bh_heap_allocator(), linkable_functions, 4); - { - LibraryLinkContext lib_ctx; - lib_ctx.wasm_bytes = wasm_bytes; - lib_ctx.library_paths = NULL; - lookup_and_load_custom_libraries(&lib_ctx, &linkable_functions); - - bh_arr_free(lib_ctx.library_paths); - } + LinkLibraryContext lib_ctx; + lib_ctx.wasm_bytes = wasm_bytes; + lib_ctx.library_paths = NULL; + lookup_and_load_custom_libraries(&lib_ctx, &linkable_functions); wasm_byte_vec_t wasm_data; wasm_data.size = wasm_bytes.length; @@ -382,10 +496,12 @@ b32 onyx_run_wasm(bh_buffer wasm_bytes, int argc, char *argv[]) { } wasm_imports = (wasm_extern_vec_t) WASM_EMPTY_VEC; - if (!link_wasm_imports(linkable_functions, wasm_module)) { + if (!link_wasm_imports(linkable_functions, &lib_ctx, wasm_module)) { return 0; } + bh_arr_free(lib_ctx.library_paths); + wasm_trap_t* traps = NULL; wasm_instance = wasm_instance_new(wasm_store, wasm_module, &wasm_imports, &traps); diff --git a/shared/include/dyncall/dyncall.h b/shared/include/dyncall/dyncall.h new file mode 100644 index 00000000..1f3191e3 --- /dev/null +++ b/shared/include/dyncall/dyncall.h @@ -0,0 +1,143 @@ +/* + + Package: dyncall + Library: dyncall + File: dyncall/dyncall.h + Description: public header for library dyncall + License: + + Copyright (c) 2007-2022 Daniel Adler , + Tassilo Philipp + + Permission to use, copy, modify, and distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +*/ + + +#ifndef DYNCALL_H +#define DYNCALL_H + +#include "dyncall_types.h" +#include "dyncall_signature.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct DCCallVM_ DCCallVM; +typedef struct DCaggr_ DCaggr; + +/* Supported Calling Convention Modes */ + +/* default */ +#define DC_CALL_C_DEFAULT 0 /* C default (platform native) */ +#define DC_CALL_C_DEFAULT_THIS 99 /* for C++ calls where first param is hidden this ptr (platform native) */ +#define DC_CALL_C_ELLIPSIS 100 /* to be set for vararg calls' non-hidden (e.g. C++ this ptr), named arguments */ +#define DC_CALL_C_ELLIPSIS_VARARGS 101 /* to be set for vararg calls' non-hidden (e.g. C++ this ptr), variable arguments (in ... part) */ +/* platform specific */ +#define DC_CALL_C_X86_CDECL 1 +#define DC_CALL_C_X86_WIN32_STD 2 +#define DC_CALL_C_X86_WIN32_FAST_MS 3 +#define DC_CALL_C_X86_WIN32_FAST_GNU 4 +#define DC_CALL_C_X86_WIN32_THIS_MS 5 +#define DC_CALL_C_X86_WIN32_THIS_GNU DC_CALL_C_X86_CDECL /* alias - identical to cdecl (w/ this-ptr as 1st arg) */ +#define DC_CALL_C_X64_WIN64 7 +#define DC_CALL_C_X64_WIN64_THIS 70 /* only needed when using aggregate by value as return type */ +#define DC_CALL_C_X64_SYSV 8 +#define DC_CALL_C_X64_SYSV_THIS DC_CALL_C_X64_SYSV /* alias */ +#define DC_CALL_C_PPC32_DARWIN 9 +#define DC_CALL_C_PPC32_OSX DC_CALL_C_PPC32_DARWIN /* alias */ +#define DC_CALL_C_ARM_ARM_EABI 10 +#define DC_CALL_C_ARM_THUMB_EABI 11 +#define DC_CALL_C_ARM_ARMHF 30 +#define DC_CALL_C_MIPS32_EABI 12 +#define DC_CALL_C_MIPS32_PSPSDK DC_CALL_C_MIPS32_EABI /* alias - deprecated. */ +#define DC_CALL_C_PPC32_SYSV 13 +#define DC_CALL_C_PPC32_LINUX DC_CALL_C_PPC32_SYSV /* alias */ +#define DC_CALL_C_ARM_ARM 14 +#define DC_CALL_C_ARM_THUMB 15 +#define DC_CALL_C_MIPS32_O32 16 +#define DC_CALL_C_MIPS64_N32 17 +#define DC_CALL_C_MIPS64_N64 18 +#define DC_CALL_C_X86_PLAN9 19 +#define DC_CALL_C_SPARC32 20 +#define DC_CALL_C_SPARC64 21 +#define DC_CALL_C_ARM64 22 +#define DC_CALL_C_PPC64 23 +#define DC_CALL_C_PPC64_LINUX DC_CALL_C_PPC64 /* alias */ +/* syscalls, default */ +#define DC_CALL_SYS_DEFAULT 200 +/* syscalls, platform specific */ +#define DC_CALL_SYS_X86_INT80H_LINUX 201 +#define DC_CALL_SYS_X86_INT80H_BSD 202 +#define DC_CALL_SYS_X64_SYSCALL_SYSV 204 +#define DC_CALL_SYS_PPC32 210 +#define DC_CALL_SYS_PPC64 211 + +/* Error codes. */ + +#define DC_ERROR_NONE 0 +#define DC_ERROR_UNSUPPORTED_MODE -1 + +DC_API DCCallVM* dcNewCallVM (DCsize size); +DC_API void dcFree (DCCallVM* vm); +DC_API void dcReset (DCCallVM* vm); + +DC_API void dcMode (DCCallVM* vm, DCint mode); + +DC_API void dcBeginCallAggr (DCCallVM* vm, const DCaggr* ag); + +DC_API void dcArgBool (DCCallVM* vm, DCbool value); +DC_API void dcArgChar (DCCallVM* vm, DCchar value); +DC_API void dcArgShort (DCCallVM* vm, DCshort value); +DC_API void dcArgInt (DCCallVM* vm, DCint value); +DC_API void dcArgLong (DCCallVM* vm, DClong value); +DC_API void dcArgLongLong (DCCallVM* vm, DClonglong value); +DC_API void dcArgFloat (DCCallVM* vm, DCfloat value); +DC_API void dcArgDouble (DCCallVM* vm, DCdouble value); +DC_API void dcArgPointer (DCCallVM* vm, DCpointer value); +DC_API void dcArgAggr (DCCallVM* vm, const DCaggr* ag, const void* value); + +DC_API void dcCallVoid (DCCallVM* vm, DCpointer funcptr); +DC_API DCbool dcCallBool (DCCallVM* vm, DCpointer funcptr); +DC_API DCchar dcCallChar (DCCallVM* vm, DCpointer funcptr); +DC_API DCshort dcCallShort (DCCallVM* vm, DCpointer funcptr); +DC_API DCint dcCallInt (DCCallVM* vm, DCpointer funcptr); +DC_API DClong dcCallLong (DCCallVM* vm, DCpointer funcptr); +DC_API DClonglong dcCallLongLong (DCCallVM* vm, DCpointer funcptr); +DC_API DCfloat dcCallFloat (DCCallVM* vm, DCpointer funcptr); +DC_API DCdouble dcCallDouble (DCCallVM* vm, DCpointer funcptr); +DC_API DCpointer dcCallPointer (DCCallVM* vm, DCpointer funcptr); +DC_API DCpointer dcCallAggr (DCCallVM* vm, DCpointer funcptr, const DCaggr* ag, DCpointer ret); /* retval is written to *ret, returns ret */ + +DC_API DCint dcGetError (DCCallVM* vm); + +DC_API DCaggr* dcNewAggr (DCsize maxFieldCount, DCsize size); +DC_API void dcFreeAggr (DCaggr* ag); +/* if type == DC_SIGCHAR_AGGREGATE, pass DCaggr* of nested struct/union in ... */ +DC_API void dcAggrField (DCaggr* ag, DCsigchar type, DCint offset, DCsize array_len, ...); +DC_API void dcCloseAggr (DCaggr* ag); /* to indicate end of struct definition, required */ + + +/* helpers */ + +/* returns respective mode for callconv sig char (w/o checking if mode exists */ +/* on current platform), or DC_ERROR_UNSUPPORTED_MODE if char isn't a sigchar */ +DC_API DCint dcGetModeFromCCSigChar(DCsigchar sig_char); + +#ifdef __cplusplus +} +#endif + +#endif /* DYNCALL_H */ + diff --git a/shared/include/dyncall/dyncall_config.h b/shared/include/dyncall/dyncall_config.h new file mode 100644 index 00000000..db98c2ad --- /dev/null +++ b/shared/include/dyncall/dyncall_config.h @@ -0,0 +1,47 @@ +/* + + Package: dyncall + Library: dyncall + File: dyncall/dyncall_config.h + Description: Macro configuration file for non-standard C types + License: + + Copyright (c) 2007-2018 Daniel Adler , + Tassilo Philipp + + Permission to use, copy, modify, and distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +*/ + + + +/* + + dyncall type configuration + + REVISION + 2007/12/11 initial + +*/ + +#ifndef DYNCALL_CONFIG_H +#define DYNCALL_CONFIG_H + +#include "dyncall_macros.h" + +#define DC_BOOL int +#define DC_LONG_LONG long long +#define DC_POINTER void* + +#endif /* DYNCALL_CONFIG_H */ + diff --git a/shared/include/dyncall/dyncall_macros.h b/shared/include/dyncall/dyncall_macros.h new file mode 100644 index 00000000..041ba4ac --- /dev/null +++ b/shared/include/dyncall/dyncall_macros.h @@ -0,0 +1,343 @@ +/* + + Package: dyncall + Library: dyncall + File: dyncall/dyncall_macros.h + Description: Platform detection macros + License: + + Copyright (c) 2007-2018 Daniel Adler , + Tassilo Philipp + + Permission to use, copy, modify, and distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +*/ + + + +/* + + dyncall macros + + Platform detection, specific defines and configuration. + The purpose of this file is to provide coherent platform and compiler + specific defines. So instead of defines like WIN32, _OpenBSD_ or + __GNUC__, one should use DC__OS_Win32, DC__OS_OpenBSD or DC__C_GNU, + respectively. + + REVISION + 2007/12/11 initial + +*/ + + +#ifndef DYNCALL_MACROS_H +#define DYNCALL_MACROS_H + + + +/* -- Platform specific #defines ------------------------------------ */ + +/* MS Windows XP x64/Vista64 or later. */ +#if defined(WIN64) || defined(_WIN64) || defined(__WIN64__) +# define DC__OS_Win64 + +/* MS Windows NT/95/98/ME/2000/XP/Vista32. */ +#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__) || defined(__WINDOWS__) || defined(_WINDOWS) +# define DC__OS_Win32 + +/* All the OS' based on Darwin OS (MacOS X, OpenDarwin). Note that '__APPLE__' may be defined for classic MacOS, too. */ +/* __MACOSX__ is not defined in gcc assembler mode (switch: -S) */ +#elif defined(__APPLE__) || defined(__Darwin__) +# define DC__OS_Darwin +# if defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) +# define DC__OS_IPhone +# else /* defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) */ +# define DC__OS_MacOSX +# endif + +/* The most popular open source Unix-like OS - Linux. */ +#elif defined(__linux__) || defined(__linux) || defined(__gnu_linux__) +# define DC__OS_Linux + +/* The most powerful open source Unix-like OS - FreeBSD. */ +#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) /* latter is (also) used by systems using FreeBSD kernel, e.g. Debian/kFreeBSD, which could be detected specifically by also checking for __GLIBC__ */ +# define DC__OS_FreeBSD + +/* The most secure open source Unix-like OS - OpenBSD. */ +#elif defined(__OpenBSD__) +# define DC__OS_OpenBSD + +/* The most portable open source Unix-like OS - NetBSD. */ +#elif defined(__NetBSD__) +# define DC__OS_NetBSD + +/* The FreeBSD fork having heavy clusterization in mind - DragonFlyBSD. */ +#elif defined(__DragonFly__) +# define DC__OS_DragonFlyBSD + +/* Sun's Unix-like OS - SunOS / Solaris. */ +#elif defined(__sun__) || defined(__sun) || defined(sun) +# define DC__OS_SunOS + +/* The Nintendo DS (homebrew) using devkitpro. */ +#elif defined(__nds__) +# define DC__OS_NDS + +/* The PlayStation Portable (homebrew) SDK. */ +#elif defined(__psp__) || defined(PSP) +# define DC__OS_PSP + +/* Haiku (BeOS alike). */ +#elif defined(__HAIKU__) +# define DC__OS_BeOS + +/* The Unix successor - Plan9 from Bell Labs */ +#elif defined(Plan9) || defined(__Plan9__) +# define DC__OS_Plan9 + +/* Digital's Unix-like OS - VMS */ +#elif defined(__vms) +# define DC__OS_VMS + +/* Tanenbaum's Microkernel OS - Minix */ +#elif defined(__minix) +# define DC__OS_Minix + +/* Unable to determine OS, which is probably ok (e.g. baremetal stuff, etc.). */ +#else +# define DC__OS_UNKNOWN + +#endif + + +/* windows sub envs */ +#if defined(DC__OS_Win32) || defined(DC__OS_Win64) + +/* The "Linux-like environment for Windows" - Cygwin. */ +# if defined(__CYGWIN__) +# define DC__OS_Cygwin + +/* The "Minimalist GNU for Windows" - MinGW. */ +# elif defined(__MINGW32__) || defined(__MINGW64__) +# define DC__OS_MinGW +# endif + +#endif + + + +/* -- Compiler specific #defines ------------------------------------ */ + +/* Don't change the order, b/c some compilers use same #defines compatibility */ + +/* Intel's C/C++ compiler. */ +#if defined(__INTEL_COMPILER) +# define DC__C_Intel + +/* MS C/C++ compiler. */ +#elif defined(_MSC_VER) +# define DC__C_MSVC + +/* LLVM clang. */ +#elif defined(__clang__) || defined(__llvm__) +# define DC__C_CLANG + +/* The GNU Compiler Collection - GCC. */ +#elif defined(__GNUC__) +# define DC__C_GNU + +/* Watcom compiler. */ +#elif defined(__WATCOMC__) +# define DC__C_WATCOM + +/* Portable C Compiler. */ +#elif defined(__PCC__) +# define DC__C_PCC + +/* Sun Pro C. */ +#elif defined(__SUNPRO_C) +# define DC__C_SUNPRO + +/* Undetected C Compiler. */ +#else +# define DC__C_UNKNOWN +#endif + + + +/* -- Architecture -------------------------------------------------- */ + +/* Check architecture. */ +#if defined(_M_X64_) || defined(_M_AMD64) || defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) +# define DC__Arch_AMD64 +#elif defined(_M_IX86) || defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) || defined(__386__) || defined(__i386) +# define DC__Arch_Intel_x86 +#elif defined(_M_IA64) || defined(__ia64__) +# define DC__Arch_Itanium +#elif defined(_M_PPC) || defined(__powerpc__) || defined(__powerpc) || defined(__POWERPC__) || defined(__ppc__) || defined(__power__) +# if defined(__ppc64__) || defined(_ARCH_PPC64) || defined(__power64__) || defined(__powerpc64__) +# define DC__Arch_PPC64 +# else +# define DC__Arch_PPC32 +# endif +#elif defined(__mips64__) || defined(__mips64) +# define DC__Arch_MIPS64 +#elif defined(_M_MRX000) || defined(__mips__) || defined(__mips) || defined(_mips) +# define DC__Arch_MIPS +#elif defined(__arm__) +# define DC__Arch_ARM +#elif defined(_M_ARM64) || defined(__aarch64__) || defined(__arm64) || defined(__arm64__) +# define DC__Arch_ARM64 +#elif defined(__sh__) +# define DC__Arch_SuperH +#elif defined(__sparc) || defined(__sparc__) +# if defined(__sparcv9) || defined(__sparc_v9__) || defined(__sparc64__) || defined(__arch64__) +# define DC__Arch_Sparc64 +# else +# define DC__Arch_Sparc +# endif +#endif + + + +/* -- Runtime ------------------------------------------------------- */ + +#if defined(__MSVCRT__) +# define DC__RT_MSVCRT +#endif + + +/* -- Rough OS classification --------------------------------------- */ + +#if defined(DC__OS_Win32) || defined(DC__OS_Win64) +# define DC_WINDOWS +#elif defined(DC__OS_Plan9) +# define DC_PLAN9 +#elif defined(DC__OS_NDS) || defined(DC__OS_PSP) +# define DC_OTHER +#else +# define DC_UNIX +#endif + + + +/* -- Misc machine-dependent modes, ABIs, etc. ---------------------- */ + +#if defined(__arm__) && !defined(__thumb__) +# define DC__Arch_ARM_ARM +#elif defined(__arm__) && defined(__thumb__) +# define DC__Arch_ARM_THUMB +#endif + +#if defined(DC__Arch_ARM_ARM) || defined(DC__Arch_ARM_THUMB) +# if defined(__ARM_EABI__) || defined(DC__OS_NDS) +# if defined (__ARM_PCS_VFP) && (__ARM_PCS_VFP == 1) +# define DC__ABI_ARM_HF +# else +# define DC__ABI_ARM_EABI +# endif +# elif defined(__APCS_32__) +# define DC__ABI_ARM_OABI +# endif +#endif /* ARM */ + +#if defined(DC__Arch_MIPS) || defined(DC__Arch_MIPS64) +# if defined(_ABIO32) || defined(__mips_o32) || defined(_MIPS_ARCH_MIPS1) || defined(_MIPS_ARCH_MIPS2) +# define DC__ABI_MIPS_O32 +# elif defined(_ABI64) || defined(__mips_n64) +# define DC__ABI_MIPS_N64 +# elif defined(_ABIN32) +# define DC__ABI_MIPS_N32 +# else +# define DC__ABI_MIPS_EABI +# endif +/* Set extra flag to know if FP hardware ABI, default to yes, if unsure */ +# if (defined(__mips_hard_float) && (__mips_hard_float == 1)) || !defined(__mips_soft_float) || (__mips_soft_float != 1) +# define DC__ABI_HARDFLOAT /* @@@ make this general for all archs? */ +# else +# define DC__ABI_SOFTFLOAT +# endif +#endif /* MIPS */ + +#if defined(DC__Arch_PPC64) +# if defined(_CALL_ELF) +# define DC__ABI_PPC64_ELF_V _CALL_ELF +# else +# define DC__ABI_PPC64_ELF_V 0 /* 0 means not explicitly set, otherwise this is 1 (big endian) and 2 (little endian) */ +# endif +#endif /* PPC64 */ + + + +/* -- Endianness detection ------------------------------------------ */ + +#if defined(DC__Arch_Intel_x86) || defined(DC__Arch_AMD64) /* always little */ +# define DC__Endian_LITTLE +#elif defined(DC__Arch_Sparc) /* always purely big until v9 */ +# define DC__Endian_BIG +#else /* all others are bi-endian */ +/* @@@check flags used on following bi-endianness archs: +DC__Arch_Itanium +DC__Arch_PPC32 +DC__Arch_PPC64 +DC__Arch_SuperH +*/ +# if (defined(DC__Arch_PPC64) && (DC__ABI_PPC64_ELF_V == 1)) || defined(MIPSEB) || defined(_MIPSEB) || defined(__MIPSEB) || defined(__MIPSEB__) || defined(__ARMEB__) || defined(__AARCH64EB__) +# define DC__Endian_BIG +# elif (defined(DC__Arch_PPC64) && (DC__ABI_PPC64_ELF_V == 2)) || defined(MIPSEL) || defined(_MIPSEL) || defined(__MIPSEL) || defined(__MIPSEL__) || defined(__ARMEL__) || defined(__AARCH64EL__) +# define DC__Endian_LITTLE +# elif defined(DC__Arch_Sparc64) && !defined(__BYTE_ORDER__) /* Sparc64 default is big-endian, except if explicitly defined */ +# define DC__Endian_BIG +# elif defined(BYTE_ORDER) || defined(_BYTE_ORDER) || defined(__BYTE_ORDER__) /* explicitly set byte order, either through compiler or platform specific endian.h */ +# if (defined(BIG_ENDIAN) && (BYTE_ORDER == BIG_ENDIAN)) || (defined(_BIG_ENDIAN) && (_BYTE_ORDER == _BIG_ENDIAN)) || (defined(__ORDER_BIG_ENDIAN__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) +# define DC__Endian_BIG +# elif (defined(LITTLE_ENDIAN) && (BYTE_ORDER == LITTLE_ENDIAN)) || (defined(_LITTLE_ENDIAN) && (_BYTE_ORDER == _LITTLE_ENDIAN)) || (defined(__ORDER_LITTLE_ENDIAN__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) +# define DC__Endian_LITTLE +# endif +# elif (defined(_BIG_ENDIAN) && (_BIG_ENDIAN == 1)) || (defined(__BIG_ENDIAN__) && (__BIG_ENDIAN__ == 1)) /* explicitly set as on/off */ +# define DC__Endian_BIG +# elif (defined(_LITTLE_ENDIAN) && (_LITTLE_ENDIAN == 1)) || (defined(__LITTLE_ENDIAN__) && (__LITTLE_ENDIAN__ == 1)) /* explicitly set as on/off */ +# define DC__Endian_LITTLE +# endif /* no else, leave unset if not sure */ +#endif + + + +/* -- Internal macro/tag -------------------------------------------- */ + +#if !defined(DC_API) +# define DC_API +#endif + + + +/* -- Library feature support macors -------------------------------- */ + +/* macros for specifying lesser used feature support (main features like basic + call and callback support are required for a platform implementation */ + +/* syscalls */ +#if (defined(DC__Arch_Intel_x86) || (defined(DC__Arch_AMD64) && defined(DC_UNIX)) || defined(DC__Arch_PPC32) || defined(DC__Arch_PPC64)) && \ + !defined(DC__OS_MacOSX) && !defined(DC__OS_Plan9) && !defined(DC__OS_NDS) && !defined(DC__OS_PSP) && !defined(DC__OS_Minix) && !defined(DC__OS_SunOS) && !defined(DC__OS_BeOS) +# define DC__Feature_Syscall +#endif + +/* aggregate (struct, union) by value */ +#if defined(DC__Arch_AMD64) +# define DC__Feature_AggrByVal +#endif + + +#endif /* DYNCALL_MACROS_H */ + diff --git a/shared/include/dyncall/dyncall_signature.h b/shared/include/dyncall/dyncall_signature.h new file mode 100644 index 00000000..7c44836a --- /dev/null +++ b/shared/include/dyncall/dyncall_signature.h @@ -0,0 +1,69 @@ +/* + + Package: dyncall + Library: dyncall + File: dyncall/dyncall_signature.h + Description: Type and calling-convention signature character defines + License: + + Copyright (c) 2007-2022 Daniel Adler , + Tassilo Philipp + + Permission to use, copy, modify, and distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +*/ + + +#ifndef DYNCALL_SIGNATURE_H +#define DYNCALL_SIGNATURE_H + +typedef char DCsigchar; + +#define DC_SIGCHAR_VOID 'v' +#define DC_SIGCHAR_BOOL 'B' +#define DC_SIGCHAR_CHAR 'c' +#define DC_SIGCHAR_UCHAR 'C' +#define DC_SIGCHAR_SHORT 's' +#define DC_SIGCHAR_USHORT 'S' +#define DC_SIGCHAR_INT 'i' +#define DC_SIGCHAR_UINT 'I' +#define DC_SIGCHAR_LONG 'j' +#define DC_SIGCHAR_ULONG 'J' +#define DC_SIGCHAR_LONGLONG 'l' +#define DC_SIGCHAR_ULONGLONG 'L' +#define DC_SIGCHAR_FLOAT 'f' +#define DC_SIGCHAR_DOUBLE 'd' +#define DC_SIGCHAR_POINTER 'p' /* also used for arrays, as such args decay to ptrs */ +#define DC_SIGCHAR_STRING 'Z' /* in theory same as 'p', but convenient to disambiguate */ +#define DC_SIGCHAR_AGGREGATE 'A' /* aggregate (struct/union described out-of-band via DCaggr) */ +#define DC_SIGCHAR_ENDARG ')' + +/* calling convention / mode signatures */ + +#define DC_SIGCHAR_CC_PREFIX '_' /* announces next char to be one of the below calling convention mode chars */ +#define DC_SIGCHAR_CC_DEFAULT ':' /* default calling conv (platform native) */ +#define DC_SIGCHAR_CC_THISCALL '*' /* C++ this calls (platform native) */ +#define DC_SIGCHAR_CC_ELLIPSIS 'e' +#define DC_SIGCHAR_CC_ELLIPSIS_VARARGS '.' +#define DC_SIGCHAR_CC_CDECL 'c' /* x86 specific */ +#define DC_SIGCHAR_CC_STDCALL 's' /* x86 specific */ +#define DC_SIGCHAR_CC_FASTCALL_MS 'F' /* x86 specific */ +#define DC_SIGCHAR_CC_FASTCALL_GNU 'f' /* x86 specific */ +#define DC_SIGCHAR_CC_THISCALL_MS '+' /* x86 specific, MS C++ this calls */ +#define DC_SIGCHAR_CC_THISCALL_GNU '#' /* x86 specific, GNU C++ this calls are cdecl, but keep specific sig char for clarity */ +#define DC_SIGCHAR_CC_ARM_ARM 'A' +#define DC_SIGCHAR_CC_ARM_THUMB 'a' +#define DC_SIGCHAR_CC_SYSCALL '$' + +#endif /* DYNCALL_SIGNATURE_H */ + diff --git a/shared/include/dyncall/dyncall_types.h b/shared/include/dyncall/dyncall_types.h new file mode 100644 index 00000000..ab46a7c4 --- /dev/null +++ b/shared/include/dyncall/dyncall_types.h @@ -0,0 +1,74 @@ +/* + + Package: dyncall + Library: dyncall + File: dyncall/dyncall_types.h + Description: Typedefs + License: + + Copyright (c) 2007-2018 Daniel Adler , + Tassilo Philipp + + Permission to use, copy, modify, and distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +*/ + + + +/* + + dyncall argument- and return-types + + REVISION + 2007/12/11 initial + +*/ + +#ifndef DYNCALL_TYPES_H +#define DYNCALL_TYPES_H + +#include + +#include "dyncall_config.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void DCvoid; +typedef DC_BOOL DCbool; +typedef char DCchar; +typedef unsigned char DCuchar; +typedef short DCshort; +typedef unsigned short DCushort; +typedef int DCint; +typedef unsigned int DCuint; +typedef long DClong; +typedef unsigned long DCulong; +typedef DC_LONG_LONG DClonglong; +typedef unsigned DC_LONG_LONG DCulonglong; +typedef float DCfloat; +typedef double DCdouble; +typedef DC_POINTER DCpointer; +typedef const char* DCstring; +typedef size_t DCsize; + +#define DC_TRUE 1 +#define DC_FALSE 0 + +#ifdef __cplusplus +} +#endif + +#endif /* DYNCALL_TYPES_H */ + diff --git a/shared/lib/linux_x86_64/lib/libdyncall_s.a b/shared/lib/linux_x86_64/lib/libdyncall_s.a new file mode 100644 index 0000000000000000000000000000000000000000..9e488ff9a3625a66fad71f125b2764c139e3e16f GIT binary patch literal 39613 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