Mercurial > pub > dyncall > dyncall
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; -}