diff dyncallback/dyncall_callback_x64.c @ 533:71c884e610f0

- integration of patches from Raphael Luba, Thekla, Inc.: * integration of aggregate-by-value (struct, union) support patch for x64 (win and sysv) * windows/x64 asm additions to specify how stack unwinds (help for debuggers, exception handling, etc.) * see Changelog for details - new calling convention modes for thiscalls (platform agnostic, was specific before) * new signature character for platform agnostic thiscalls ('*' / DC_SIGCHAR_CC_THISCALL) - dcCallF(), dcVCallF(), dcArgF() and dcVArgF(): * added support for aggregates-by-value (wasn't part of patch) * change that those functions don't implicitly call dcReset() anymore, which was unflexible (breaking change) - added macros to feature test implementation for aggregate-by-value and syscall support - changed libdyncall_s.lib and libdyncallback_s.lib order in callback test makefiles, as some toolchains are picky about order - doc: * man page updates to describe aggregate interface * manual overview changes to highlight platforms with aggregate-by-value support - test/plain: replaced tests w/ old/stale sctruct interface with new aggregate one
author Tassilo Philipp
date Thu, 21 Apr 2022 13:35:47 +0200
parents f5577f6bf97a
children ba70fb631bea
line wrap: on
line diff
--- a/dyncallback/dyncall_callback_x64.c	Sat Apr 16 15:00:58 2022 +0200
+++ b/dyncallback/dyncall_callback_x64.c	Thu Apr 21 13:35:47 2022 +0200
@@ -6,7 +6,7 @@
  Description: Callback - Implementation for x64
  License:
 
-   Copyright (c) 2007-2018 Daniel Adler <dadler@uni-goettingen.de>,
+   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
@@ -26,28 +26,61 @@
 
 #include "dyncall_callback.h"
 #include "dyncall_alloc_wx.h"
+#include "dyncall_aggregate.h"
 #include "dyncall_thunk.h"
 
+
 /* Callback symbol. */
 extern void dcCallback_x64_sysv();
 extern void dcCallback_x64_win64();
 
 struct DCCallback
 {
-  DCThunk  	         thunk;    // offset 0,  size 24
-  DCCallbackHandler* handler;  // offset 24
-  void*              userdata; // offset 32
+  DCThunk            thunk;                /* offset 0,  size 24 */
+  DCCallbackHandler* handler;              /* offset 24 */
+  void*              userdata;             /* offset 32 */
+  DCint              aggr_return_register; /* offset 40 */
+  DCint              pad;                  /* offset 44 */
+  DCaggr *const *    aggrs;                /* offset 48 */
 };
 
 
-void dcbInitCallback(DCCallback* pcb, const char* signature, DCCallbackHandler* handler, void* userdata)
+void dcbInitCallback2(DCCallback* pcb, const DCsigchar* signature, DCCallbackHandler* handler, void* userdata, DCaggr *const * aggrs)
 {
-  pcb->handler  = handler;
-  pcb->userdata = userdata;
+  const DCsigchar *ch = signature;
+  DCint num_aggrs = 0;
+
+  pcb->handler              = handler;
+  pcb->userdata             = userdata;
+  pcb->aggrs                = NULL;
+  pcb->aggr_return_register = -2; /* default, = no aggr as ret value */
+
+  while(*ch)
+    num_aggrs += (*(ch++) == DC_SIGCHAR_AGGREGATE);
+
+  if(num_aggrs)
+  {
+    pcb->aggrs = aggrs;
+  
+    if (ch != signature && *(ch - 1) == DC_SIGCHAR_AGGREGATE) {
+      const DCaggr *ag = pcb->aggrs[num_aggrs - 1];
+  
+#if defined(DC_UNIX)
+      if (!ag || (ag->sysv_classes[0] == SYSVC_MEMORY)) {
+#else
+      if (!ag || ag->size > 8) {
+#endif 
+        /* we need to "return" this aggr as a hidden pointer (first arg) */
+        pcb->aggr_return_register = 0;
+      } else {
+        pcb->aggr_return_register = -1; /* small aggr, returned in register */
+      }
+    }
+  }
 }
 
 
-DCCallback* dcbNewCallback(const char* signature, DCCallbackHandler* handler, void* userdata)
+DCCallback* dcbNewCallback2(const DCsigchar* signature, DCCallbackHandler* handler, void* userdata, DCaggr *const * aggrs)
 {
   int err;
   DCCallback* pcb;
@@ -55,12 +88,13 @@
   if(err)
     return NULL;
 
+  dcbInitCallback2(pcb, signature, handler, userdata, aggrs);
+
 #if defined (DC__OS_Win64)
   dcbInitThunk(&pcb->thunk, dcCallback_x64_win64); 
 #else
   dcbInitThunk(&pcb->thunk, dcCallback_x64_sysv); 
 #endif
-  dcbInitCallback(pcb, signature, handler, userdata);
 
   err = dcInitExecWX(pcb, sizeof(DCCallback));
   if(err) {
@@ -71,13 +105,3 @@
   return pcb;
 }
 
-
-void dcbFreeCallback(DCCallback* pcb)
-{
-  dcFreeWX(pcb, sizeof(DCCallback));
-}
-
-void* dcbGetUserData(DCCallback* pcb)
-{
-  return pcb->userdata;
-}