Mercurial > pub > dyncall > dyncall
comparison dyncallback/dyncall_callback_x86.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 | ddfb9577a00e |
children |
comparison
equal
deleted
inserted
replaced
532:d4bf63ab9164 | 533:71c884e610f0 |
---|---|
4 Library: dyncallback | 4 Library: dyncallback |
5 File: dyncallback/dyncall_callback_x86.c | 5 File: dyncallback/dyncall_callback_x86.c |
6 Description: Callback - Implementation for x86 | 6 Description: Callback - Implementation for x86 |
7 License: | 7 License: |
8 | 8 |
9 Copyright (c) 2007-2020 Daniel Adler <dadler@uni-goettingen.de>, | 9 Copyright (c) 2007-2022 Daniel Adler <dadler@uni-goettingen.de>, |
10 Tassilo Philipp <tphilipp@potion-studios.com> | 10 Tassilo Philipp <tphilipp@potion-studios.com> |
11 | 11 |
12 Permission to use, copy, modify, and distribute this software for any | 12 Permission to use, copy, modify, and distribute this software for any |
13 purpose with or without fee is hereby granted, provided that the above | 13 purpose with or without fee is hereby granted, provided that the above |
14 copyright notice and this permission notice appear in all copies. | 14 copyright notice and this permission notice appear in all copies. |
27 #include "dyncall_callback.h" | 27 #include "dyncall_callback.h" |
28 #include "dyncall_alloc_wx.h" | 28 #include "dyncall_alloc_wx.h" |
29 #include "dyncall_thunk.h" | 29 #include "dyncall_thunk.h" |
30 #include "dyncall_args_x86.h" | 30 #include "dyncall_args_x86.h" |
31 | 31 |
32 | |
32 /* Callback symbol. */ | 33 /* Callback symbol. */ |
33 extern void dcCallbackThunkEntry(); | 34 extern void dcCallbackThunkEntry(); |
34 | 35 |
35 struct DCCallback | 36 struct DCCallback |
36 { | 37 { |
45 /* compute stacksize for callee cleanup calling conventions: | 46 /* compute stacksize for callee cleanup calling conventions: |
46 * | 47 * |
47 * cdecl,stdcall,thiscall_ms,fastcall_ms,fastcall_gnu | 48 * cdecl,stdcall,thiscall_ms,fastcall_ms,fastcall_gnu |
48 */ | 49 */ |
49 | 50 |
50 static int dcbCleanupSize_x86_cdecl(const char* signature) | 51 static int dcbCleanupSize_x86_cdecl(const DCsigchar* signature) |
51 { | 52 { |
52 return 0; | 53 return 0; |
53 } | 54 } |
54 | 55 |
55 static int dcbCleanupSize_x86_std(const char* signature) | 56 static int dcbCleanupSize_x86_std(const DCsigchar* signature) |
56 { | 57 { |
57 const char* ptr = signature; | 58 const DCsigchar* ptr = signature; |
58 int size = 0; | 59 int size = 0; |
59 char ch; | 60 DCsigchar ch; |
60 while( (ch = *ptr++) != DC_SIGCHAR_ENDARG ) { | 61 while( (ch = *ptr++) != DC_SIGCHAR_ENDARG ) { |
61 switch(ch) { | 62 switch(ch) { |
62 case DC_SIGCHAR_BOOL: | 63 case DC_SIGCHAR_BOOL: |
63 case DC_SIGCHAR_CHAR: | 64 case DC_SIGCHAR_CHAR: |
64 case DC_SIGCHAR_SHORT: | 65 case DC_SIGCHAR_SHORT: |
81 } | 82 } |
82 } | 83 } |
83 return size; | 84 return size; |
84 } | 85 } |
85 | 86 |
86 static int dcbCleanupSize_x86_this_ms(const char* signature) | 87 static int dcbCleanupSize_x86_this_ms(const DCsigchar* signature) |
87 { | 88 { |
88 const char* ptr = signature; | 89 const DCsigchar* ptr = signature; |
89 int size = 0; | 90 int size = 0; |
90 char ch; | 91 DCsigchar ch; |
91 while( (ch = *ptr++) != DC_SIGCHAR_ENDARG ) | 92 while( (ch = *ptr++) != DC_SIGCHAR_ENDARG ) |
92 { | 93 { |
93 switch(ch) | 94 switch(ch) |
94 { | 95 { |
95 case DC_SIGCHAR_BOOL: | 96 case DC_SIGCHAR_BOOL: |
114 } | 115 } |
115 } | 116 } |
116 return size; | 117 return size; |
117 } | 118 } |
118 | 119 |
119 static int dcbCleanupSize_x86_fast_ms(const char* signature) | 120 static int dcbCleanupSize_x86_fast_ms(const DCsigchar* signature) |
120 { | 121 { |
121 const char* ptr = signature; | 122 const DCsigchar* ptr = signature; |
122 int size = 0; | 123 int size = 0; |
123 int regs = 0; | 124 int regs = 0; |
124 char ch; | 125 DCsigchar ch; |
125 while( (ch = *ptr++) != DC_SIGCHAR_ENDARG ) | 126 while( (ch = *ptr++) != DC_SIGCHAR_ENDARG ) |
126 { | 127 { |
127 switch(ch) | 128 switch(ch) |
128 { | 129 { |
129 case DC_SIGCHAR_BOOL: | 130 case DC_SIGCHAR_BOOL: |
153 } | 154 } |
154 } | 155 } |
155 return size; | 156 return size; |
156 } | 157 } |
157 | 158 |
158 static int dcbCleanupSize_x86_fast_gnu(const char* signature) | 159 static int dcbCleanupSize_x86_fast_gnu(const DCsigchar* signature) |
159 { | 160 { |
160 const char* ptr = signature; | 161 const DCsigchar* ptr = signature; |
161 char ch; | 162 DCsigchar ch; |
162 int size = 0; | 163 int size = 0; |
163 int regs = 0; | 164 int regs = 0; |
164 while( (ch = *ptr++) != DC_SIGCHAR_ENDARG ) { | 165 while( (ch = *ptr++) != DC_SIGCHAR_ENDARG ) { |
165 switch(ch) { | 166 switch(ch) { |
166 case DC_SIGCHAR_FLOAT: | 167 case DC_SIGCHAR_FLOAT: |
181 } | 182 } |
182 } | 183 } |
183 return size; | 184 return size; |
184 } | 185 } |
185 | 186 |
186 void dcbInitCallback(DCCallback* pcb, const char* signature, DCCallbackHandler* handler, void* userdata) | 187 |
187 { | 188 void dcbInitCallback2(DCCallback* pcb, const DCsigchar* signature, DCCallbackHandler* handler, void* userdata, DCaggr *const * aggrs) |
188 const char* ptr; | 189 { |
190 const DCsigchar* ptr; | |
189 int mode; | 191 int mode; |
190 pcb->handler = handler; | 192 pcb->handler = handler; |
191 pcb->userdata = userdata; | 193 pcb->userdata = userdata; |
192 | 194 |
193 ptr = signature; | 195 ptr = signature; |
219 break; | 221 break; |
220 case DC_CALL_C_X86_WIN32_FAST_GNU: | 222 case DC_CALL_C_X86_WIN32_FAST_GNU: |
221 pcb->args_vt = &dcArgsVT_fast_gnu; | 223 pcb->args_vt = &dcArgsVT_fast_gnu; |
222 pcb->stack_cleanup = dcbCleanupSize_x86_fast_gnu(ptr); | 224 pcb->stack_cleanup = dcbCleanupSize_x86_fast_gnu(ptr); |
223 break; | 225 break; |
226 #if defined(DC_WINDOWS) && defined(DC__C_MSVC) | |
227 case DC_CALL_C_DEFAULT_THIS: | |
228 #endif | |
224 case DC_CALL_C_X86_WIN32_THIS_MS: | 229 case DC_CALL_C_X86_WIN32_THIS_MS: |
225 pcb->args_vt = &dcArgsVT_this_ms; | 230 pcb->args_vt = &dcArgsVT_this_ms; |
226 pcb->stack_cleanup = dcbCleanupSize_x86_this_ms(ptr); | 231 pcb->stack_cleanup = dcbCleanupSize_x86_this_ms(ptr); |
227 break; | 232 break; |
228 } | 233 } |
246 } | 251 } |
247 } | 252 } |
248 #endif | 253 #endif |
249 } | 254 } |
250 | 255 |
251 /* | 256 |
252 * callback constructor | 257 DCCallback* dcbNewCallback2(const DCsigchar* signature, DCCallbackHandler* handler, void* userdata, DCaggr *const * aggrs) |
253 */ | 258 { |
254 DCCallback* dcbNewCallback(const char* signature, DCCallbackHandler* handler, void* userdata) | |
255 { | |
256 int err; | |
257 DCCallback* pcb; | 259 DCCallback* pcb; |
258 err = dcAllocWX(sizeof(DCCallback), (void**) &pcb); | 260 int err = dcAllocWX(sizeof(DCCallback), (void**) &pcb); |
259 if(err) | 261 if(err) |
260 return NULL; | 262 return NULL; |
261 | 263 |
264 dcbInitCallback2(pcb, signature, handler, userdata, aggrs); | |
262 dcbInitThunk(&pcb->thunk, dcCallbackThunkEntry); | 265 dcbInitThunk(&pcb->thunk, dcCallbackThunkEntry); |
263 dcbInitCallback(pcb, signature, handler, userdata); | |
264 | 266 |
265 err = dcInitExecWX(pcb, sizeof(DCCallback)); | 267 err = dcInitExecWX(pcb, sizeof(DCCallback)); |
266 if(err) { | 268 if(err) { |
267 dcFreeWX(pcb, sizeof(DCCallback)); | 269 dcFreeWX(pcb, sizeof(DCCallback)); |
268 return NULL; | 270 return NULL; |
269 } | 271 } |
270 | 272 |
271 return pcb; | 273 return pcb; |
272 } | 274 } |
273 | 275 |
274 /* | |
275 * free | |
276 */ | |
277 | |
278 void dcbFreeCallback(DCCallback* pcb) | |
279 { | |
280 dcFreeWX(pcb, sizeof(DCCallback)); | |
281 } | |
282 | |
283 void* dcbGetUserData(DCCallback* pcb) | |
284 { | |
285 return pcb->userdata; | |
286 } |