added: starting work on using `dyncallback`
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Sat, 1 Apr 2023 19:51:41 +0000 (14:51 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Sat, 1 Apr 2023 19:51:41 +0000 (14:51 -0500)
compiler/build.sh
compiler/src/wasm_emit.c
compiler/src/wasm_runtime.c
shared/include/dyncall/dyncall_args.h [new file with mode: 0644]
shared/include/dyncall/dyncall_callback.h [new file with mode: 0644]
shared/include/dyncall/dyncall_value.h [new file with mode: 0644]
shared/lib/linux_x86_64/lib/libdyncallback_s.a [new file with mode: 0644]

index ed80b613b36b562eb766e247d4f88d5aafb3c007..7510b749a7ac9635e9264c32b630fbbb1d40f2fb 100755 (executable)
@@ -2,11 +2,14 @@
 
 . ../settings.sh
 
+# Enable Dynamic call
+USE_DYNCALL=1
+
 # Temporary flag
 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 ../shared/lib/linux_$ARCH/lib/libdyncall_s.a"
+LIBS="-L$CORE_DIR/lib -l$RUNTIME_LIBRARY -Wl,-rpath=$CORE_DIR/lib:./ -lpthread -ldl -lm"
 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'
@@ -25,7 +28,12 @@ if [ "$ENABLE_DEBUG_INFO" = "1" ]; then
     FLAGS="$FLAGS -DENABLE_DEBUG_INFO"
 fi
 
-FLAGS="$FLAGS -DENABLE_RUN_WITH_WASMER -DUSE_DYNCALL"
+FLAGS="$FLAGS -DENABLE_RUN_WITH_WASMER"
+
+if [ "$USE_DYNCALL" = "1" ]; then
+    LIBS="$LIBS ../shared/lib/linux_$ARCH/lib/libdyncall_s.a ../shared/lib/linux_$ARCH/lib/libdyncallback_s.a"
+    FLAGS="$FLAGS -DUSE_DYNCALL"
+fi
 
 sudo mkdir -p "$BIN_DIR"
 
index 4841b8a28ea80c20ae8cfd0e681605375f8ab9fc..2c377c02d1e7e8bffe3f1d1723014479732f7007 100644 (file)
@@ -4121,38 +4121,37 @@ static void emit_function(OnyxWasmModule* mod, AstFunction* fd) {
     debug_end_function(mod);
 }
 
-static char encode_type_as_dyncall_symbol(Type *t) {
+static void encode_type_as_dyncall_symbol(char *out, Type *t) {
     if (type_struct_is_just_one_basic_value(t)) {
         Type *inner = type_struct_is_just_one_basic_value(t);
-        return encode_type_as_dyncall_symbol(inner);
+        encode_type_as_dyncall_symbol(out, inner);
     }
 
-    if (t->kind == Type_Kind_Slice)   return 's';
-    if (t->kind == Type_Kind_Pointer) return 'p';
-    if (t->kind == Type_Kind_MultiPointer) return 'p';
-    if (t->kind == Type_Kind_Enum)    return encode_type_as_dyncall_symbol(t->Enum.backing);
-    if (t->kind == Type_Kind_Basic) {
+    else if (t->kind == Type_Kind_Slice) strncat(out, "s", 64);
+    else if (t->kind == Type_Kind_Pointer) strncat(out, "p", 64);
+    else if (t->kind == Type_Kind_MultiPointer) strncat(out, "p", 64);
+    else if (t->kind == Type_Kind_Enum) encode_type_as_dyncall_symbol(out, t->Enum.backing);
+    else if (t->kind == Type_Kind_Basic) {
         TypeBasic* basic = &t->Basic;
-        if (basic->flags & Basic_Flag_Boolean) return 'i';
-        if (basic->flags & Basic_Flag_Integer) {
-            if (basic->size <= 4) return 'i';
-            if (basic->size == 8) return 'l';
+        if (basic->flags & Basic_Flag_Boolean) strncat(out, "i", 64);
+        else if (basic->flags & Basic_Flag_Integer) {
+            if (basic->size <= 4) strncat(out, "i", 64);
+            if (basic->size == 8) strncat(out, "l", 64);
         }
-        if (basic->flags & Basic_Flag_Pointer) return 'p';
-        if (basic->flags & Basic_Flag_Float) {
-            if (basic->size <= 4) return 'f';
-            if (basic->size == 8) return 'd';
+        else if (basic->flags & Basic_Flag_Pointer) strncat(out, "p", 64);
+        else if (basic->flags & Basic_Flag_Float) {
+            if (basic->size <= 4) strncat(out, "f", 64);
+            if (basic->size == 8) strncat(out, "d", 64);
         }
-        if (basic->flags & Basic_Flag_SIMD) return 'v';
-        if (basic->flags & Basic_Flag_Type_Index) return 'i';
-        if (basic->size == 0) return 'v';
+        else if (basic->flags & Basic_Flag_SIMD) strncat(out, "v", 64);
+        else if (basic->flags & Basic_Flag_Type_Index) strncat(out, "i", 64);
+        else strncat(out, "v", 64);
     }
-
-    if (t->kind == Type_Kind_Distinct) {
-        return encode_type_as_dyncall_symbol(t->Distinct.base_type);
+    else if (t->kind == Type_Kind_Distinct) {
+        encode_type_as_dyncall_symbol(out, t->Distinct.base_type);
     }
 
-    return 'v';
+    else strncat(out, "v", 64);
 }
 
 static void emit_foreign_function(OnyxWasmModule* mod, AstFunction* fd) {
@@ -4165,12 +4164,11 @@ static void emit_foreign_function(OnyxWasmModule* mod, AstFunction* fd) {
     if (fd->is_foreign_dyncall) {
         module = bh_aprintf(global_heap_allocator, "dyncall:%b", fd->foreign_module->text, fd->foreign_module->length);
 
-        char type_encoding[64] = {0};
-        type_encoding[0] = encode_type_as_dyncall_symbol(fd->type->Function.return_type);
+        char type_encoding[65] = {0};
+        encode_type_as_dyncall_symbol(type_encoding, fd->type->Function.return_type);
 
-        int index = 1;
         bh_arr_each(AstParam, param, fd->params) {
-            type_encoding[index++] = encode_type_as_dyncall_symbol(param->local->type);
+            encode_type_as_dyncall_symbol(type_encoding, param->local->type);
         }
 
         name = bh_aprintf(global_heap_allocator, "%b:%s", fd->foreign_name->text, fd->foreign_name->length, type_encoding);
index 78745a7e5c6dd31c81a4d642a9575c90d6f962d9..75e9b69cf9bb2f0b4f1e502cd8914a1be43d593c 100644 (file)
@@ -6,6 +6,7 @@
 
 #ifdef USE_DYNCALL
     #include "dyncall.h"
+    #include "dyncall_callback.h"
     static DCCallVM *dcCallVM;
 #endif
 
@@ -225,6 +226,7 @@ static wasm_trap_t *__wasm_dyncall(void *env, const wasm_val_vec_t *args, wasm_v
                 arg_idx++;
                 dcArgInt(dcCallVM, args->data[arg_idx++].of.i32);
                 break;
+
             default: assert(("bad dynamic call type", 0));
         }
     }
diff --git a/shared/include/dyncall/dyncall_args.h b/shared/include/dyncall/dyncall_args.h
new file mode 100644 (file)
index 0000000..94a455d
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+
+ Package: dyncall
+ Library: dyncallback
+ File: dyncallback/dyncall_args.h
+ Description: Callback's Arguments VM - Interface
+ 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_ARGS_H
+#define DYNCALL_ARGS_H
+
+/*
+ * dyncall args C API
+ *
+ * dyncall args provides serialized access to arguments of a function call.
+ * related concepts: callback
+ *
+ */
+
+#include "dyncall.h"
+
+#include "dyncall_value.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct DCArgs DCArgs;
+
+/* functions to retrieve callback's params in callback handler */
+DC_API DCbool      dcbArgBool     (DCArgs* p);
+DC_API DCchar      dcbArgChar     (DCArgs* p);
+DC_API DCshort     dcbArgShort    (DCArgs* p);
+DC_API DCint       dcbArgInt      (DCArgs* p);
+DC_API DClong      dcbArgLong     (DCArgs* p);
+DC_API DClonglong  dcbArgLongLong (DCArgs* p);
+DC_API DCuchar     dcbArgUChar    (DCArgs* p);
+DC_API DCushort    dcbArgUShort   (DCArgs* p);
+DC_API DCuint      dcbArgUInt     (DCArgs* p);
+DC_API DCulong     dcbArgULong    (DCArgs* p);
+DC_API DCulonglong dcbArgULongLong(DCArgs* p);
+DC_API DCfloat     dcbArgFloat    (DCArgs* p);
+DC_API DCdouble    dcbArgDouble   (DCArgs* p);
+DC_API DCpointer   dcbArgPointer  (DCArgs* p);
+/* for trivial aggrs: 'target' points to space to copy aggr to, returns 'target'
+   for C++ non-trivial aggrs: target is ignored, returns ptr to aggr arg */
+DC_API DCpointer   dcbArgAggr     (DCArgs* p, DCpointer target);
+
+/* helper func to put a to be returned struct-by-value into the 'result'
+   param of the callback handler; for C++ non-trivial aggrs, pass NULL in
+   'ret', then copy aggr into result->p */
+DC_API void dcbReturnAggr(DCArgs *args, DCValue *result, DCpointer ret);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* DYNCALL_ARGS_H */
+
diff --git a/shared/include/dyncall/dyncall_callback.h b/shared/include/dyncall/dyncall_callback.h
new file mode 100644 (file)
index 0000000..73da3c1
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+
+ Package: dyncall
+ Library: dyncallback
+ File: dyncallback/dyncall_callback.h
+ Description: Callback - Interface
+ 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_CALLBACK_H
+#define DYNCALL_CALLBACK_H
+
+#include "dyncall_args.h"
+#include "dyncall_signature.h"
+#include "dyncall_value.h"
+
+typedef struct DCCallback DCCallback;
+
+/* callback handler:
+   - handlers return value signature char (see dyncall_signature.h) of callback's return value type
+   - callback return value is written to the corresponding type's field of result
+   - if callback return value is an aggregate (by value), use dcbReturnAggr() as a helper to write to result
+*/
+typedef DCsigchar (DCCallbackHandler)(DCCallback* pcb, DCArgs* args, DCValue* result, void* userdata);
+
+#ifdef __cplusplus
+extern "C" {
+#endif 
+
+DCCallback* dcbNewCallback  (const DCsigchar* signature, DCCallbackHandler* funcptr, void* userdata);
+DCCallback* dcbNewCallback2 (const DCsigchar* signature, DCCallbackHandler* funcptr, void* userdata, DCaggr *const * aggrs);
+void        dcbInitCallback (DCCallback* pcb, const DCsigchar* signature, DCCallbackHandler* handler, void* userdata);
+void        dcbInitCallback2(DCCallback* pcb, const DCsigchar* signature, DCCallbackHandler* handler, void* userdata, DCaggr *const * aggrs);
+void        dcbFreeCallback (DCCallback* pcb);
+void*       dcbGetUserData  (DCCallback* pcb);
+
+#ifdef __cplusplus
+}
+#endif 
+
+#endif /* DYNCALL_CALLBACK_H */
+
diff --git a/shared/include/dyncall/dyncall_value.h b/shared/include/dyncall/dyncall_value.h
new file mode 100644 (file)
index 0000000..6a4cd86
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+
+ Package: dyncall
+ Library: dyncall
+ File: dyncall/dyncall_value.h
+ Description: Value variant type
+ 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 value variant
+
+  a value variant union-type that carries all supported dyncall types.
+
+  REVISION
+  2007/12/11 initial
+
+*/
+
+#ifndef DYNCALL_VALUE_H
+#define DYNCALL_VALUE_H
+
+#include "dyncall_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif 
+
+typedef union DCValue_ DCValue;
+
+union DCValue_
+{
+/* dyncallback assembly pulls value directly from DCValue structs, without   */
+/* knowledge about types used, so lay it out as needed at compile time, here */
+#if defined(DC__Endian_BIG) && (defined(DC__Arch_PPC32) || defined(DC__Arch_MIPS) || defined(DC__Arch_Sparc))
+  DCbool      B;
+  struct { DCchar  c_pad[3]; DCchar  c; };
+  struct { DCuchar C_pad[3]; DCuchar C; };
+  struct { DCshort s_pad;    DCshort s; };
+  struct { DCshort S_pad;    DCshort S; };
+  DCint       i;
+  DCuint      I;
+#elif defined(DC__Endian_BIG) && (defined(DC__Arch_PPC64) || defined(DC__Arch_MIPS64) || defined(DC__Arch_Sparc64))
+  struct { DCbool  B_pad;    DCbool  B; };
+  struct { DCchar  c_pad[7]; DCchar  c; };
+  struct { DCuchar C_pad[7]; DCuchar C; };
+  struct { DCshort s_pad[3]; DCshort s; };
+  struct { DCshort S_pad[3]; DCshort S; };
+  struct { DCint   i_pad;    DCint   i; };
+  struct { DCint   I_pad;    DCuint  I; };
+#else
+  DCbool      B;
+  DCchar      c;
+  DCuchar     C;
+  DCshort     s;
+  DCushort    S;
+  DCint       i;
+  DCuint      I;
+#endif
+  DClong      j;
+  DCulong     J;
+  DClonglong  l;
+  DCulonglong L;
+/* floats on mips are right justified in fp-registers on big endian targets, as they aren't promoted */
+#if defined(DC__Endian_BIG) && (defined(DC__Arch_MIPS) || defined(DC__Arch_MIPS64))
+  struct { DCfloat f_pad; DCfloat f; };
+#else
+  DCfloat     f;
+#endif
+  DCdouble    d;
+  DCpointer   p;
+  DCstring    Z;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* DYNCALL_VALUE_H */
+
diff --git a/shared/lib/linux_x86_64/lib/libdyncallback_s.a b/shared/lib/linux_x86_64/lib/libdyncallback_s.a
new file mode 100644 (file)
index 0000000..377a6f8
Binary files /dev/null and b/shared/lib/linux_x86_64/lib/libdyncallback_s.a differ