added: wasm_runtime supports using `dyncall`
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 10 Mar 2023 17:36:34 +0000 (11:36 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 10 Mar 2023 17:36:34 +0000 (11:36 -0600)
compiler/build.sh
compiler/src/wasm_runtime.c
shared/include/dyncall/dyncall.h [new file with mode: 0644]
shared/include/dyncall/dyncall_config.h [new file with mode: 0644]
shared/include/dyncall/dyncall_macros.h [new file with mode: 0644]
shared/include/dyncall/dyncall_signature.h [new file with mode: 0644]
shared/include/dyncall/dyncall_types.h [new file with mode: 0644]
shared/lib/linux_x86_64/lib/libdyncall_s.a [new file with mode: 0644]

index 82af69d15d85582f6f7eb3ab5e3ce3e3064e5706..99fe9ff3cff5b4961ba3b227ecf3c0879e5999a0 100755 (executable)
@@ -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'
 
index 09797d4d8edbc63b67852ae2fff8c4fd785c4256..f36ad33d75485fd77909c778dd448d14c90e781b 100644 (file)
@@ -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 (file)
index 0000000..1f3191e
--- /dev/null
@@ -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 <dadler@uni-goettingen.de>,
+                           Tassilo Philipp <tphilipp@potion-studios.com>
+
+   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 (file)
index 0000000..db98c2a
--- /dev/null
@@ -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 <dadler@uni-goettingen.de>, 
+                           Tassilo Philipp <tphilipp@potion-studios.com>
+
+   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 (file)
index 0000000..041ba4a
--- /dev/null
@@ -0,0 +1,343 @@
+/*
+
+ Package: dyncall
+ Library: dyncall
+ File: dyncall/dyncall_macros.h
+ Description: Platform detection macros
+ License:
+
+   Copyright (c) 2007-2018 Daniel Adler <dadler@uni-goettingen.de>,
+                           Tassilo Philipp <tphilipp@potion-studios.com>
+
+   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 (file)
index 0000000..7c44836
--- /dev/null
@@ -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 <dadler@uni-goettingen.de>, 
+                           Tassilo Philipp <tphilipp@potion-studios.com>
+
+   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 (file)
index 0000000..ab46a7c
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+
+ Package: dyncall
+ Library: dyncall
+ File: dyncall/dyncall_types.h
+ Description: Typedefs
+ License:
+
+   Copyright (c) 2007-2018 Daniel Adler <dadler@uni-goettingen.de>, 
+                           Tassilo Philipp <tphilipp@potion-studios.com>
+
+   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 <stddef.h>
+
+#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 (file)
index 0000000..9e488ff
Binary files /dev/null and b/shared/lib/linux_x86_64/lib/libdyncall_s.a differ