From: Brendan Hansen Date: Fri, 10 Mar 2023 17:36:34 +0000 (-0600) Subject: added: wasm_runtime supports using `dyncall` X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=de7b1ae8f9cb760e330acd5d7f8c9bee6332da5a;p=onyx.git added: wasm_runtime supports using `dyncall` --- 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 00000000..9e488ff9 Binary files /dev/null and b/shared/lib/linux_x86_64/lib/libdyncall_s.a differ