Mercurial > pub > dyncall > dyncall
annotate dyncallback/dyncall_callback_x86.c @ 642:575760fc57b7
Added tag r1.4 for changeset 2147d1c9dc8a
author | Tassilo Philipp |
---|---|
date | Tue, 06 Dec 2022 21:11:43 +0100 |
parents | 71c884e610f0 |
children |
rev | line source |
---|---|
0 | 1 /* |
2 | |
3 Package: dyncall | |
4 Library: dyncallback | |
5 File: dyncallback/dyncall_callback_x86.c | |
6 Description: Callback - Implementation for x86 | |
7 License: | |
8 | |
533
71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
Tassilo Philipp
parents:
466
diff
changeset
|
9 Copyright (c) 2007-2022 Daniel Adler <dadler@uni-goettingen.de>, |
0 | 10 Tassilo Philipp <tphilipp@potion-studios.com> |
11 | |
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 | |
14 copyright notice and this permission notice appear in all copies. | |
15 | |
16 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
17 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
18 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
19 ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
20 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
21 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
22 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
23 | |
24 */ | |
25 | |
26 | |
152
d48a8b8d2ef9
- integrated all headers containing DCCallback definition into the translation units used (arm64 already avoided this pointless header, so following that style)
cslag
parents:
0
diff
changeset
|
27 #include "dyncall_callback.h" |
d48a8b8d2ef9
- integrated all headers containing DCCallback definition into the translation units used (arm64 already avoided this pointless header, so following that style)
cslag
parents:
0
diff
changeset
|
28 #include "dyncall_alloc_wx.h" |
d48a8b8d2ef9
- integrated all headers containing DCCallback definition into the translation units used (arm64 already avoided this pointless header, so following that style)
cslag
parents:
0
diff
changeset
|
29 #include "dyncall_thunk.h" |
0 | 30 #include "dyncall_args_x86.h" |
31 | |
533
71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
Tassilo Philipp
parents:
466
diff
changeset
|
32 |
152
d48a8b8d2ef9
- integrated all headers containing DCCallback definition into the translation units used (arm64 already avoided this pointless header, so following that style)
cslag
parents:
0
diff
changeset
|
33 /* Callback symbol. */ |
d48a8b8d2ef9
- integrated all headers containing DCCallback definition into the translation units used (arm64 already avoided this pointless header, so following that style)
cslag
parents:
0
diff
changeset
|
34 extern void dcCallbackThunkEntry(); |
0 | 35 |
152
d48a8b8d2ef9
- integrated all headers containing DCCallback definition into the translation units used (arm64 already avoided this pointless header, so following that style)
cslag
parents:
0
diff
changeset
|
36 struct DCCallback |
d48a8b8d2ef9
- integrated all headers containing DCCallback definition into the translation units used (arm64 already avoided this pointless header, so following that style)
cslag
parents:
0
diff
changeset
|
37 { |
d48a8b8d2ef9
- integrated all headers containing DCCallback definition into the translation units used (arm64 already avoided this pointless header, so following that style)
cslag
parents:
0
diff
changeset
|
38 DCThunk thunk; /* offset 0, size 16 */ |
d48a8b8d2ef9
- integrated all headers containing DCCallback definition into the translation units used (arm64 already avoided this pointless header, so following that style)
cslag
parents:
0
diff
changeset
|
39 DCCallbackHandler* handler; /* offset 16 */ |
d48a8b8d2ef9
- integrated all headers containing DCCallback definition into the translation units used (arm64 already avoided this pointless header, so following that style)
cslag
parents:
0
diff
changeset
|
40 DCArgsVT* args_vt; /* offset 20 */ |
d48a8b8d2ef9
- integrated all headers containing DCCallback definition into the translation units used (arm64 already avoided this pointless header, so following that style)
cslag
parents:
0
diff
changeset
|
41 size_t stack_cleanup; /* offset 24 */ |
d48a8b8d2ef9
- integrated all headers containing DCCallback definition into the translation units used (arm64 already avoided this pointless header, so following that style)
cslag
parents:
0
diff
changeset
|
42 void* userdata; /* offset 28 */ |
d48a8b8d2ef9
- integrated all headers containing DCCallback definition into the translation units used (arm64 already avoided this pointless header, so following that style)
cslag
parents:
0
diff
changeset
|
43 }; |
0 | 44 |
45 | |
46 /* compute stacksize for callee cleanup calling conventions: | |
47 * | |
152
d48a8b8d2ef9
- integrated all headers containing DCCallback definition into the translation units used (arm64 already avoided this pointless header, so following that style)
cslag
parents:
0
diff
changeset
|
48 * cdecl,stdcall,thiscall_ms,fastcall_ms,fastcall_gnu |
0 | 49 */ |
50 | |
533
71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
Tassilo Philipp
parents:
466
diff
changeset
|
51 static int dcbCleanupSize_x86_cdecl(const DCsigchar* signature) |
0 | 52 { |
53 return 0; | |
54 } | |
55 | |
533
71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
Tassilo Philipp
parents:
466
diff
changeset
|
56 static int dcbCleanupSize_x86_std(const DCsigchar* signature) |
0 | 57 { |
533
71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
Tassilo Philipp
parents:
466
diff
changeset
|
58 const DCsigchar* ptr = signature; |
0 | 59 int size = 0; |
533
71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
Tassilo Philipp
parents:
466
diff
changeset
|
60 DCsigchar ch; |
0 | 61 while( (ch = *ptr++) != DC_SIGCHAR_ENDARG ) { |
62 switch(ch) { | |
63 case DC_SIGCHAR_BOOL: | |
64 case DC_SIGCHAR_CHAR: | |
65 case DC_SIGCHAR_SHORT: | |
66 case DC_SIGCHAR_INT: | |
67 case DC_SIGCHAR_LONG: | |
68 case DC_SIGCHAR_POINTER: | |
69 case DC_SIGCHAR_UCHAR: | |
70 case DC_SIGCHAR_USHORT: | |
71 case DC_SIGCHAR_UINT: | |
72 case DC_SIGCHAR_ULONG: | |
73 case DC_SIGCHAR_STRING: | |
74 case DC_SIGCHAR_FLOAT: | |
75 size += 4; | |
76 break; | |
77 case DC_SIGCHAR_DOUBLE: | |
78 case DC_SIGCHAR_LONGLONG: | |
79 case DC_SIGCHAR_ULONGLONG: | |
80 size += 8; | |
81 break; | |
82 } | |
83 } | |
84 return size; | |
85 } | |
86 | |
533
71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
Tassilo Philipp
parents:
466
diff
changeset
|
87 static int dcbCleanupSize_x86_this_ms(const DCsigchar* signature) |
0 | 88 { |
533
71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
Tassilo Philipp
parents:
466
diff
changeset
|
89 const DCsigchar* ptr = signature; |
0 | 90 int size = 0; |
533
71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
Tassilo Philipp
parents:
466
diff
changeset
|
91 DCsigchar ch; |
0 | 92 while( (ch = *ptr++) != DC_SIGCHAR_ENDARG ) |
93 { | |
94 switch(ch) | |
95 { | |
96 case DC_SIGCHAR_BOOL: | |
97 case DC_SIGCHAR_CHAR: | |
98 case DC_SIGCHAR_SHORT: | |
99 case DC_SIGCHAR_INT: | |
100 case DC_SIGCHAR_LONG: | |
101 case DC_SIGCHAR_POINTER: | |
102 case DC_SIGCHAR_UCHAR: | |
103 case DC_SIGCHAR_USHORT: | |
104 case DC_SIGCHAR_UINT: | |
105 case DC_SIGCHAR_ULONG: | |
106 case DC_SIGCHAR_STRING: | |
107 case DC_SIGCHAR_FLOAT: | |
108 size += 4; | |
109 break; | |
110 case DC_SIGCHAR_DOUBLE: | |
111 case DC_SIGCHAR_LONGLONG: | |
112 case DC_SIGCHAR_ULONGLONG: | |
113 size += 8; | |
114 break; | |
115 } | |
116 } | |
117 return size; | |
118 } | |
119 | |
533
71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
Tassilo Philipp
parents:
466
diff
changeset
|
120 static int dcbCleanupSize_x86_fast_ms(const DCsigchar* signature) |
0 | 121 { |
533
71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
Tassilo Philipp
parents:
466
diff
changeset
|
122 const DCsigchar* ptr = signature; |
0 | 123 int size = 0; |
124 int regs = 0; | |
533
71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
Tassilo Philipp
parents:
466
diff
changeset
|
125 DCsigchar ch; |
0 | 126 while( (ch = *ptr++) != DC_SIGCHAR_ENDARG ) |
127 { | |
128 switch(ch) | |
129 { | |
130 case DC_SIGCHAR_BOOL: | |
131 case DC_SIGCHAR_CHAR: | |
132 case DC_SIGCHAR_SHORT: | |
133 case DC_SIGCHAR_INT: | |
134 case DC_SIGCHAR_LONG: | |
135 case DC_SIGCHAR_POINTER: | |
136 case DC_SIGCHAR_UCHAR: | |
137 case DC_SIGCHAR_USHORT: | |
138 case DC_SIGCHAR_UINT: | |
139 case DC_SIGCHAR_ULONG: | |
140 case DC_SIGCHAR_STRING: | |
141 if (regs < 2) regs++; | |
142 else size += 4; | |
143 break; | |
144 case DC_SIGCHAR_FLOAT: | |
145 size += 4; | |
146 break; | |
147 case DC_SIGCHAR_DOUBLE: | |
148 size += 8; | |
149 break; | |
150 case DC_SIGCHAR_LONGLONG: | |
151 case DC_SIGCHAR_ULONGLONG: | |
152 size += 8; | |
153 break; | |
154 } | |
155 } | |
156 return size; | |
157 } | |
158 | |
533
71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
Tassilo Philipp
parents:
466
diff
changeset
|
159 static int dcbCleanupSize_x86_fast_gnu(const DCsigchar* signature) |
0 | 160 { |
533
71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
Tassilo Philipp
parents:
466
diff
changeset
|
161 const DCsigchar* ptr = signature; |
71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
Tassilo Philipp
parents:
466
diff
changeset
|
162 DCsigchar ch; |
0 | 163 int size = 0; |
164 int regs = 0; | |
165 while( (ch = *ptr++) != DC_SIGCHAR_ENDARG ) { | |
166 switch(ch) { | |
167 case DC_SIGCHAR_FLOAT: | |
168 size += 4; | |
169 break; | |
170 case DC_SIGCHAR_DOUBLE: | |
171 size += 8; | |
172 break; | |
173 case DC_SIGCHAR_LONGLONG: | |
174 case DC_SIGCHAR_ULONGLONG: | |
175 regs = 2; | |
176 size += 8; | |
177 break; | |
178 default: | |
179 if (regs < 2) regs++; | |
180 else size += 4; | |
181 break; | |
182 } | |
183 } | |
184 return size; | |
185 } | |
186 | |
533
71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
Tassilo Philipp
parents:
466
diff
changeset
|
187 |
71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
Tassilo Philipp
parents:
466
diff
changeset
|
188 void dcbInitCallback2(DCCallback* pcb, const DCsigchar* signature, DCCallbackHandler* handler, void* userdata, DCaggr *const * aggrs) |
0 | 189 { |
533
71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
Tassilo Philipp
parents:
466
diff
changeset
|
190 const DCsigchar* ptr; |
0 | 191 int mode; |
192 pcb->handler = handler; | |
193 pcb->userdata = userdata; | |
194 | |
195 ptr = signature; | |
196 | |
197 /* x86 hints: */ | |
198 | |
199 mode = DC_CALL_C_X86_CDECL; | |
200 | |
466
ddfb9577a00e
introduced platform-native thiscall mode (DC_CALL_C_DEFAULT_THIS), as needed
Tassilo Philipp
parents:
364
diff
changeset
|
201 if(*ptr == DC_SIGCHAR_CC_PREFIX) |
0 | 202 { |
466
ddfb9577a00e
introduced platform-native thiscall mode (DC_CALL_C_DEFAULT_THIS), as needed
Tassilo Philipp
parents:
364
diff
changeset
|
203 mode = dcGetModeFromCCSigChar(ptr[1]); |
ddfb9577a00e
introduced platform-native thiscall mode (DC_CALL_C_DEFAULT_THIS), as needed
Tassilo Philipp
parents:
364
diff
changeset
|
204 ptr += 2; |
0 | 205 } |
206 | |
207 /* x86 configuration: */ | |
208 | |
209 switch(mode) { | |
210 case DC_CALL_C_X86_CDECL: | |
211 pcb->args_vt = &dcArgsVT_default; | |
212 pcb->stack_cleanup = dcbCleanupSize_x86_cdecl(ptr); | |
213 break; | |
214 case DC_CALL_C_X86_WIN32_STD: | |
215 pcb->args_vt = &dcArgsVT_default; | |
216 pcb->stack_cleanup = dcbCleanupSize_x86_std(ptr); | |
217 break; | |
218 case DC_CALL_C_X86_WIN32_FAST_MS: | |
219 pcb->args_vt = &dcArgsVT_fast_ms; | |
220 pcb->stack_cleanup = dcbCleanupSize_x86_fast_ms(ptr); | |
221 break; | |
222 case DC_CALL_C_X86_WIN32_FAST_GNU: | |
223 pcb->args_vt = &dcArgsVT_fast_gnu; | |
224 pcb->stack_cleanup = dcbCleanupSize_x86_fast_gnu(ptr); | |
225 break; | |
533
71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
Tassilo Philipp
parents:
466
diff
changeset
|
226 #if defined(DC_WINDOWS) && defined(DC__C_MSVC) |
71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
Tassilo Philipp
parents:
466
diff
changeset
|
227 case DC_CALL_C_DEFAULT_THIS: |
71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
Tassilo Philipp
parents:
466
diff
changeset
|
228 #endif |
364 | 229 case DC_CALL_C_X86_WIN32_THIS_MS: |
230 pcb->args_vt = &dcArgsVT_this_ms; | |
231 pcb->stack_cleanup = dcbCleanupSize_x86_this_ms(ptr); | |
232 break; | |
0 | 233 } |
234 | |
235 #if defined(DC_PLAN9) | |
236 /* HACK for Plan9 - 'reuse' pcb->stack_cleanup as a flag | |
237 to indicate if return value is 64bit. The field is not | |
238 used anyways as the caller is responsible to clean up | |
239 the stack in Plan9. If set to '1' the callback kernel | |
240 takes into account an extra stack-parameter (pointer | |
241 to 64bit return value). | |
242 I thought of introducing a new field, but for one single | |
243 x86 calling convention out of many, it seemed overkill | |
244 to change the struct for everybody else. Maybe renaming | |
245 would be a good idea, though. ~ Tassilo | |
246 */ | |
247 while(*ptr) { | |
248 if(*ptr++ == DC_SIGCHAR_ENDARG) { | |
249 pcb->stack_cleanup = (*ptr == DC_SIGCHAR_LONGLONG) || (*ptr == DC_SIGCHAR_ULONGLONG); | |
250 break; | |
251 } | |
252 } | |
253 #endif | |
254 } | |
255 | |
533
71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
Tassilo Philipp
parents:
466
diff
changeset
|
256 |
71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
Tassilo Philipp
parents:
466
diff
changeset
|
257 DCCallback* dcbNewCallback2(const DCsigchar* signature, DCCallbackHandler* handler, void* userdata, DCaggr *const * aggrs) |
0 | 258 { |
259 DCCallback* pcb; | |
533
71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
Tassilo Philipp
parents:
466
diff
changeset
|
260 int err = dcAllocWX(sizeof(DCCallback), (void**) &pcb); |
202 | 261 if(err) |
262 return NULL; | |
0 | 263 |
533
71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
Tassilo Philipp
parents:
466
diff
changeset
|
264 dcbInitCallback2(pcb, signature, handler, userdata, aggrs); |
0 | 265 dcbInitThunk(&pcb->thunk, dcCallbackThunkEntry); |
202 | 266 |
267 err = dcInitExecWX(pcb, sizeof(DCCallback)); | |
268 if(err) { | |
269 dcFreeWX(pcb, sizeof(DCCallback)); | |
270 return NULL; | |
271 } | |
272 | |
0 | 273 return pcb; |
274 } | |
275 |