changeset 544:111236b31c75

- C++ non-trivial aggregate-by-value handling: * dyncallback support for dcbArgAggr() * better doc
author Tassilo Philipp
date Tue, 31 May 2022 18:25:13 +0200
parents 781b308aa320
children ca28e9e3c644
files dyncallback/dyncall_args.h dyncallback/dyncall_args_arm64.c dyncallback/dyncall_args_arm64_apple.c dyncallback/dyncall_args_mips.c dyncallback/dyncall_args_mips64.c dyncallback/dyncall_args_mips_o32.c dyncallback/dyncall_args_ppc32.c dyncallback/dyncall_args_ppc32_sysv.c dyncallback/dyncall_args_ppc64.c dyncallback/dyncall_args_sparc32.c dyncallback/dyncall_args_sparc64.c dyncallback/dyncall_args_x64.c dyncallback/dyncall_args_x86.c dyncallback/dyncallback.3
diffstat 14 files changed, 69 insertions(+), 42 deletions(-) [+]
line wrap: on
line diff
--- 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
--- 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 <dadler@uni-goettingen.de>,
+   Copyright (c) 2015-2022 Daniel Adler <dadler@uni-goettingen.de>,
                            Tassilo Philipp <tphilipp@potion-studios.com>
 
    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 */ }
 
--- 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 <dadler@uni-goettingen.de>,
+   Copyright (c) 2015-2022 Daniel Adler <dadler@uni-goettingen.de>,
                            Tassilo Philipp <tphilipp@potion-studios.com>
 
    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 */ }
 
--- 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 */ }
 
--- 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 */ }
 
--- 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 */ }
 
--- 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 */ }
 
--- 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 */ }
 
--- 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 */ }
 
--- 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 */ }
 
--- 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 */ }
 
--- 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] && i<DC_SYSV_MAX_NUM_CLASSES; ++i)
+    {
+      switch (ag->sysv_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] && i<DC_SYSV_MAX_NUM_CLASSES; ++i)
-  {
-    switch (ag->sysv_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;
   }
 
--- 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 */ }
 
 
--- 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