# HG changeset patch # User Tassilo Philipp # Date 1654014313 -7200 # Node ID 111236b31c75e32acde18db970f3640aac628198 # Parent 781b308aa32086837ddfd07c50d34dd973174021 - C++ non-trivial aggregate-by-value handling: * dyncallback support for dcbArgAggr() * better doc diff -r 781b308aa320 -r 111236b31c75 dyncallback/dyncall_args.h --- a/dyncallback/dyncall_args.h Tue May 31 16:47:57 2022 +0200 +++ b/dyncallback/dyncall_args.h Tue May 31 18:25:13 2022 +0200 @@ -61,10 +61,13 @@ DC_API DCfloat dcbArgFloat (DCArgs* p); DC_API DCdouble dcbArgDouble (DCArgs* p); DC_API DCpointer dcbArgPointer (DCArgs* p); -DC_API void dcbArgAggr (DCArgs* p, DCpointer target); +/* 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); -/* function helper to put a to be returned struct-by-value into the 'result' - param of the callback handler, in order to return it */ +/* 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 diff -r 781b308aa320 -r 111236b31c75 dyncallback/dyncall_args_arm64.c --- a/dyncallback/dyncall_args_arm64.c Tue May 31 16:47:57 2022 +0200 +++ b/dyncallback/dyncall_args_arm64.c Tue May 31 18:25:13 2022 +0200 @@ -6,7 +6,7 @@ Description: Callback's Arguments VM - Implementation for ARM64 / ARMv8 / AAPCS64 License: - Copyright (c) 2015-2018 Daniel Adler , + Copyright (c) 2015-2022 Daniel Adler , Tassilo Philipp Permission to use, copy, modify, and distribute this software for any @@ -75,6 +75,6 @@ DCulong dcbArgULong (DCArgs* p) { return (DCulong) dcbArgLong(p); } DCulonglong dcbArgULongLong(DCArgs* p) { return (DCulonglong) dcbArgLongLong(p); } -void dcbArgAggr (DCArgs* p, DCpointer target) { /* @@@AGGR not impl */ } +DCpointer dcbArgAggr (DCArgs* p, DCpointer target) { /* @@@AGGR not impl */ } void dcbReturnAggr (DCArgs *args, DCValue *result, DCpointer ret) { /* @@@AGGR not impl */ } diff -r 781b308aa320 -r 111236b31c75 dyncallback/dyncall_args_arm64_apple.c --- a/dyncallback/dyncall_args_arm64_apple.c Tue May 31 16:47:57 2022 +0200 +++ b/dyncallback/dyncall_args_arm64_apple.c Tue May 31 18:25:13 2022 +0200 @@ -6,7 +6,7 @@ Description: Callback's Arguments VM - Implementation for Apple's ARM64 / ARMv8 / AAPCS64 License: - Copyright (c) 2015-2018 Daniel Adler , + Copyright (c) 2015-2022 Daniel Adler , Tassilo Philipp Permission to use, copy, modify, and distribute this software for any @@ -158,6 +158,6 @@ DCulong dcbArgULong (DCArgs* p) { return (DCulong) dcbArgLong(p); } DCulonglong dcbArgULongLong(DCArgs* p) { return (DCulonglong) dcbArgLongLong(p); } -void dcbArgAggr (DCArgs* p, DCpointer target) { /* @@@AGGR not impl */ } +DCpointer dcbArgAggr (DCArgs* p, DCpointer target) { /* @@@AGGR not impl */ } void dcbReturnAggr (DCArgs *args, DCValue *result, DCpointer ret) { /* @@@AGGR not impl */ } diff -r 781b308aa320 -r 111236b31c75 dyncallback/dyncall_args_mips.c --- a/dyncallback/dyncall_args_mips.c Tue May 31 16:47:57 2022 +0200 +++ b/dyncallback/dyncall_args_mips.c Tue May 31 18:25:13 2022 +0200 @@ -85,6 +85,6 @@ return d.result; } -void dcbArgAggr (DCArgs* p, DCpointer target) { /* @@@AGGR not impl */ } +DCpointer dcbArgAggr (DCArgs* p, DCpointer target) { /* @@@AGGR not impl */ } void dcbReturnAggr (DCArgs *args, DCValue *result, DCpointer ret) { /* @@@AGGR not impl */ } diff -r 781b308aa320 -r 111236b31c75 dyncallback/dyncall_args_mips64.c --- a/dyncallback/dyncall_args_mips64.c Tue May 31 16:47:57 2022 +0200 +++ b/dyncallback/dyncall_args_mips64.c Tue May 31 18:25:13 2022 +0200 @@ -80,6 +80,6 @@ } -void dcbArgAggr (DCArgs* p, DCpointer target) { /* @@@AGGR not impl */ } +DCpointer dcbArgAggr (DCArgs* p, DCpointer target) { /* @@@AGGR not impl */ } void dcbReturnAggr (DCArgs *args, DCValue *result, DCpointer ret) { /* @@@AGGR not impl */ } diff -r 781b308aa320 -r 111236b31c75 dyncallback/dyncall_args_mips_o32.c --- a/dyncallback/dyncall_args_mips_o32.c Tue May 31 16:47:57 2022 +0200 +++ b/dyncallback/dyncall_args_mips_o32.c Tue May 31 18:25:13 2022 +0200 @@ -115,6 +115,6 @@ return d.result; } -void dcbArgAggr (DCArgs* p, DCpointer target) { /* @@@AGGR not impl */ } +DCpointer dcbArgAggr (DCArgs* p, DCpointer target) { /* @@@AGGR not impl */ } void dcbReturnAggr (DCArgs *args, DCValue *result, DCpointer ret) { /* @@@AGGR not impl */ } diff -r 781b308aa320 -r 111236b31c75 dyncallback/dyncall_args_ppc32.c --- a/dyncallback/dyncall_args_ppc32.c Tue May 31 16:47:57 2022 +0200 +++ b/dyncallback/dyncall_args_ppc32.c Tue May 31 18:25:13 2022 +0200 @@ -87,6 +87,6 @@ return result; } -void dcbArgAggr (DCArgs* p, DCpointer target) { /* @@@AGGR not impl */ } +DCpointer dcbArgAggr (DCArgs* p, DCpointer target) { /* @@@AGGR not impl */ } void dcbReturnAggr (DCArgs *args, DCValue *result, DCpointer ret) { /* @@@AGGR not impl */ } diff -r 781b308aa320 -r 111236b31c75 dyncallback/dyncall_args_ppc32_sysv.c --- a/dyncallback/dyncall_args_ppc32_sysv.c Tue May 31 16:47:57 2022 +0200 +++ b/dyncallback/dyncall_args_ppc32_sysv.c Tue May 31 18:25:13 2022 +0200 @@ -93,6 +93,6 @@ return result; } -void dcbArgAggr (DCArgs* p, DCpointer target) { /* @@@AGGR not impl */ } +DCpointer dcbArgAggr (DCArgs* p, DCpointer target) { /* @@@AGGR not impl */ } void dcbReturnAggr (DCArgs *args, DCValue *result, DCpointer ret) { /* @@@AGGR not impl */ } diff -r 781b308aa320 -r 111236b31c75 dyncallback/dyncall_args_ppc64.c --- a/dyncallback/dyncall_args_ppc64.c Tue May 31 16:47:57 2022 +0200 +++ b/dyncallback/dyncall_args_ppc64.c Tue May 31 18:25:13 2022 +0200 @@ -92,6 +92,6 @@ return result; } -void dcbArgAggr (DCArgs* p, DCpointer target) { /* @@@AGGR not impl */ } +DCpointer dcbArgAggr (DCArgs* p, DCpointer target) { /* @@@AGGR not impl */ } void dcbReturnAggr (DCArgs *args, DCValue *result, DCpointer ret) { /* @@@AGGR not impl */ } diff -r 781b308aa320 -r 111236b31c75 dyncallback/dyncall_args_sparc32.c --- a/dyncallback/dyncall_args_sparc32.c Tue May 31 16:47:57 2022 +0200 +++ b/dyncallback/dyncall_args_sparc32.c Tue May 31 18:25:13 2022 +0200 @@ -66,6 +66,6 @@ DCfloat dcbArgFloat (DCArgs* p) { return *(DCfloat*) sparc_word(p); } -void dcbArgAggr (DCArgs* p, DCpointer target) { /* @@@AGGR not impl */ } +DCpointer dcbArgAggr (DCArgs* p, DCpointer target) { /* @@@AGGR not impl */ } void dcbReturnAggr (DCArgs *args, DCValue *result, DCpointer ret) { /* @@@AGGR not impl */ } diff -r 781b308aa320 -r 111236b31c75 dyncallback/dyncall_args_sparc64.c --- a/dyncallback/dyncall_args_sparc64.c Tue May 31 16:47:57 2022 +0200 +++ b/dyncallback/dyncall_args_sparc64.c Tue May 31 18:25:13 2022 +0200 @@ -53,6 +53,6 @@ : *((DCfloat*)(p->arg_ptr + p->i++)+1); /* right aligned in 64bit slot */ } -void dcbArgAggr (DCArgs* p, DCpointer target) { /* @@@AGGR not impl */ } +DCpointer dcbArgAggr (DCArgs* p, DCpointer target) { /* @@@AGGR not impl */ } void dcbReturnAggr (DCArgs *args, DCValue *result, DCpointer ret) { /* @@@AGGR not impl */ } diff -r 781b308aa320 -r 111236b31c75 dyncallback/dyncall_args_x64.c --- a/dyncallback/dyncall_args_x64.c Tue May 31 16:47:57 2022 +0200 +++ b/dyncallback/dyncall_args_x64.c Tue May 31 18:25:13 2022 +0200 @@ -74,15 +74,14 @@ DCdouble dcbArgDouble (DCArgs* p) { return *arg_f64(p); } DCfloat dcbArgFloat (DCArgs* p) { return *(float*)arg_f64(p); } -void dcbArgAggr (DCArgs* p, DCpointer target) +DCpointer dcbArgAggr (DCArgs* p, DCpointer target) { int i; DCaggr *ag = *(p->aggrs++); if(!ag) { /* non-trivial aggr: retrieve as ptr, user is supposed to make copy */ - target = dcbArgPointer(p); - return; + return dcbArgPointer(p); } #if defined(DC_UNIX) @@ -102,21 +101,23 @@ { memcpy(target, p->stack_ptr, ag->size); p->stack_ptr = p->stack_ptr + ((ag->size + (sizeof(DClonglong)-1)) >> 3); // advance to next full stack slot - return; + } + else + { + for(i=0; ag->sysv_classes[i] && isysv_classes[i]) + { + case SYSVC_INTEGER: ((DClonglong*)target)[i] = dcbArgLongLong(p); break; + case SYSVC_SSE: ((DCdouble *)target)[i] = dcbArgDouble (p); break; + /* @@@AGGR implement when implementing x87 types */ + default: + assert(DC_FALSE && "Should never be reached because we check for unupported classes earlier"); + } + } } - - for(i=0; ag->sysv_classes[i] && isysv_classes[i]) - { - case SYSVC_INTEGER: ((DClonglong*)target)[i] = dcbArgLongLong(p); break; - case SYSVC_SSE: ((DCdouble *)target)[i] = dcbArgDouble (p); break; - /* @@@AGGR implement when implementing x87 types */ - default: - assert(DC_FALSE && "Should never be reached because we check for unupported classes earlier"); - } - } + return target; #else @@ -145,7 +146,7 @@ if(!ag) { /* non-trivial aggr: all we can do is to provide the ptr to the output space, user has to make copy */ - result->p = args->reg_data.i[0]; + result->p = (DCpointer) args->reg_data.i[0]; return; } diff -r 781b308aa320 -r 111236b31c75 dyncallback/dyncall_args_x86.c --- a/dyncallback/dyncall_args_x86.c Tue May 31 16:47:57 2022 +0200 +++ b/dyncallback/dyncall_args_x86.c Tue May 31 18:25:13 2022 +0200 @@ -49,7 +49,7 @@ DCulong dcbArgULong (DCArgs* p) { return (DCulong) dcbArgLong(p); } DCulonglong dcbArgULongLong(DCArgs* p) { return (DCulonglong) dcbArgLongLong(p); } -void dcbArgAggr (DCArgs* p, DCpointer target) { /* @@@AGGR not impl */ } +DCpointer dcbArgAggr (DCArgs* p, DCpointer target) { /* @@@AGGR not impl */ } void dcbReturnAggr (DCArgs *args, DCValue *result, DCpointer ret) { /* @@@AGGR not impl */ } diff -r 781b308aa320 -r 111236b31c75 dyncallback/dyncallback.3 --- a/dyncallback/dyncallback.3 Tue May 31 16:47:57 2022 +0200 +++ b/dyncallback/dyncallback.3 Tue May 31 18:25:13 2022 +0200 @@ -60,7 +60,7 @@ .Fn dcbArgDouble "DCArgs * p" .Ft DCpointer .Fn dcbArgPointer "DCArgs * p" -.Ft void +.Ft DCpointer .Fn dcbArgAggr "DCArgs * p" "DCpointer target" .Ft void .Fn dcbReturnAggr "DCArgs * args" "DCValue * result" "DCpointer ret" @@ -103,8 +103,8 @@ .Pp .Sy NOTE: C++ non-trivial aggregates (check with the std::is_trivial type trait) do not -use any aggregate descriptions, so the respective pointers in the provided -array must be NULL. See +use aggregate descriptions, so the respective pointers in the provided array +must be NULL. See .Xr dyncall 3 for more information on C++ non-trivial aggregates. .Pp @@ -115,7 +115,7 @@ .Fn dcbInitCallback and .Fn dcbInitCallback2 -(re)initializes the callback object. For a description of its parameters, see +(re)initialize the callback object. For a description of their parameters, see .Fn dcbNewCallback* . .Pp .Fn dcbFreeCallback @@ -144,27 +144,50 @@ is a pointer to an object used to store the callback's return value (output, to be set by the handler). Finally, .Ar userdata -is a pointer to some user defined data that can be set when creating or -(re)initializing the callback object. +is the user defined data pointer set when creating or (re)initializing the +callback object. The handler itself must return a signature character (see manual or dyncall_signature.h for format) specifying the data type of .Ar result . .Pp -Retrieving aggregates from the generic handler's +Retrieving aggregates by value from the generic handler's .Ar args argument can be done via .Fn dcbArgAggr , where .Ar target -must point to memory large enough for the aggregate to be copied to. +must point to memory large enough for the aggregate to be copied to, +.Sy iff +the aggregate is trivial (see below for non-trivial C++ aggregates), in which case +.Ar target +is returned. .Pp -To return an aggregate by value, a helper function +To return a trivial aggregate by value, a helper function .Fn dcbReturnAggr needs to be used in order to correctly place the aggregate pointed to by .Ar ret into .Ar result , then let the generic handler return DC_SIGCHAR_AGGREGATE. +.Pp +Retrieving or returning C++ non-trivial aggregates (check with the +std::is_trivial type trait) is done differently, as dyncall cannot know how to +do this copy and the C++ ABI handles those differently: +.Pp +When retrieving a C++ non-trivial aggregate via +.Fn dcbArgAggr , +.Ar target +is ignored, and a pointer to the non-trivial aggregate is returned (the user +should then do a local copy). +To return a C++ non-trivial aggregate by value via +.Fn dcbReturnAggr , +pass NULL for +.Ar ret , +which will make +.Ar result->p +point to (implicit, caller-provided) memory where the aggregate should be +copied to. + .Sh EXAMPLE Let's say, we want to create a callback object and call it. For simplicity, this example will omit passing it as a function pointer to a function (e.g. compar