From: Brendan Hansen Date: Sat, 1 Apr 2023 19:51:41 +0000 (-0500) Subject: added: starting work on using `dyncallback` X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=9aae918fcc2b53df64874378f0305e27eca07892;p=onyx.git added: starting work on using `dyncallback` --- diff --git a/compiler/build.sh b/compiler/build.sh index ed80b613..7510b749 100755 --- a/compiler/build.sh +++ b/compiler/build.sh @@ -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" diff --git a/compiler/src/wasm_emit.c b/compiler/src/wasm_emit.c index 4841b8a2..2c377c02 100644 --- a/compiler/src/wasm_emit.c +++ b/compiler/src/wasm_emit.c @@ -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); diff --git a/compiler/src/wasm_runtime.c b/compiler/src/wasm_runtime.c index 78745a7e..75e9b69c 100644 --- a/compiler/src/wasm_runtime.c +++ b/compiler/src/wasm_runtime.c @@ -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 index 00000000..94a455d9 --- /dev/null +++ b/shared/include/dyncall/dyncall_args.h @@ -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 , + 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_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 index 00000000..73da3c1e --- /dev/null +++ b/shared/include/dyncall/dyncall_callback.h @@ -0,0 +1,58 @@ +/* + + Package: dyncall + Library: dyncallback + File: dyncallback/dyncall_callback.h + Description: Callback - Interface + 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_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 index 00000000..6a4cd863 --- /dev/null +++ b/shared/include/dyncall/dyncall_value.h @@ -0,0 +1,98 @@ +/* + + Package: dyncall + Library: dyncall + File: dyncall/dyncall_value.h + Description: Value variant type + 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 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 index 00000000..377a6f80 Binary files /dev/null and b/shared/lib/linux_x86_64/lib/libdyncallback_s.a differ