comparison dyncall/dyncall_callvm_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 ddfb9577a00e
children ba70fb631bea
comparison
equal deleted inserted replaced
532:d4bf63ab9164 533:71c884e610f0
4 Library: dyncall 4 Library: dyncall
5 File: dyncall/dyncall_callvm_x64.c 5 File: dyncall/dyncall_callvm_x64.c
6 Description: 6 Description:
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.
29 /* MS Windows x64 calling convention, AMD64 SystemV ABI. */ 29 /* MS Windows x64 calling convention, AMD64 SystemV ABI. */
30 30
31 31
32 #include "dyncall_callvm_x64.h" 32 #include "dyncall_callvm_x64.h"
33 #include "dyncall_alloc.h" 33 #include "dyncall_alloc.h"
34 #include "dyncall_struct.h" 34 #include "dyncall_aggregate.h"
35
36 #include <stdint.h>
37 #include <string.h>
38 #include <assert.h>
35 39
36 40
37 /* 41 /*
38 ** x64 SystemV calling convention 42 ** x64 SystemV calling convention
39 ** 43 **
40 ** - hybrid return-type call (bool ... pointer) 44 ** - hybrid return-type call (bool ... pointer)
41 ** 45 **
42 */ 46 */
43 47
44 void dcCall_x64_sysv(DCsize stacksize, DCpointer stackdata, DCpointer regdata_i, DCpointer regdata_f, DCpointer target); 48 #if defined(DC_UNIX)
45 void dcCall_x64_win64(DCsize stacksize, DCpointer stackdata, DCpointer regdata, DCpointer target); 49 extern void dcCall_x64_sysv(DCsize stacksize, DCpointer stackdata, DCpointer regdata_i, DCpointer regdata_f, DCpointer target);
46 void dcCall_x64_syscall_sysv(DCpointer argdata, DCpointer target); 50 extern void dcCall_x64_sysv_aggr(DCsize stacksize, DCpointer stackdata, DCpointer regdata_i, DCpointer regdata_f, DCpointer target, DCpointer ret_regs);
51 #else
52 extern void dcCall_x64_win64(DCsize stacksize, DCpointer stackdata, DCpointer regdata, DCpointer target);
53 extern void dcCall_x64_win64_aggr(DCsize stacksize, DCpointer stackdata, DCpointer regdata, DCpointer target, DCpointer aggr_mem);
54 #endif
55 extern void dcCall_x64_syscall_sysv(DCpointer argdata, DCpointer target);
56
57
47 58
48 59
49 static void dc_callvm_free_x64(DCCallVM* in_self) 60 static void dc_callvm_free_x64(DCCallVM* in_self)
50 { 61 {
51 dcFreeMem(in_self); 62 dcFreeMem(in_self);
55 static void dc_callvm_reset_x64(DCCallVM* in_self) 66 static void dc_callvm_reset_x64(DCCallVM* in_self)
56 { 67 {
57 DCCallVM_x64* self = (DCCallVM_x64*)in_self; 68 DCCallVM_x64* self = (DCCallVM_x64*)in_self;
58 dcVecReset(&self->mVecHead); 69 dcVecReset(&self->mVecHead);
59 self->mRegCount.i = self->mRegCount.f = 0; 70 self->mRegCount.i = self->mRegCount.f = 0;
60 } 71 self->mAggrReturnReg = -1;
72 #if defined(DC_WINDOWS)
73 self->mpAggrVecCopies = ((DCchar*)dcVecData(&self->mVecHead)) + self->mVecHead.mTotal;
74 #endif
75 }
76
77
61 78
62 79
63 static void dc_callvm_argLongLong_x64(DCCallVM* in_self, DClonglong x) 80 static void dc_callvm_argLongLong_x64(DCCallVM* in_self, DClonglong x)
64 { 81 {
65 /* A long long always has 64 bits on the supported x64 platforms (lp64 on unix and llp64 on windows). */ 82 /* A long long always has 64 bits on the supported x64 platforms (lp64 on unix and llp64 on windows). */
66 DCCallVM_x64* self = (DCCallVM_x64*)in_self; 83 DCCallVM_x64* self = (DCCallVM_x64*)in_self;
84
85 self->mRegCount.i += (self->mRegCount.i == self->mAggrReturnReg);
86
67 if(self->mRegCount.i < numIntRegs) 87 if(self->mRegCount.i < numIntRegs)
68 self->mRegData.i[self->mRegCount.i++] = x; 88 self->mRegData.i[self->mRegCount.i++] = x;
69 else 89 else
70 dcVecAppend(&self->mVecHead, &x, sizeof(DClonglong)); 90 dcVecAppend(&self->mVecHead, &x, sizeof(DClonglong));
71 } 91 }
99 { 119 {
100 dc_callvm_argLongLong_x64(in_self, x); 120 dc_callvm_argLongLong_x64(in_self, x);
101 } 121 }
102 122
103 123
124 static void dc_callvm_argDouble_x64(DCCallVM* in_self, DCdouble x)
125 {
126 DCCallVM_x64* self = (DCCallVM_x64*)in_self;
127
128 #if defined(DC_WINDOWS)
129 self->mRegCount.f += (self->mRegCount.f == self->mAggrReturnReg);
130 #endif
131
132 if(self->mRegCount.f < numFloatRegs)
133 self->mRegData.f[self->mRegCount.f++] = x;
134 else
135 dcVecAppend(&self->mVecHead, &x, sizeof(DCdouble));
136 }
137
138
104 static void dc_callvm_argFloat_x64(DCCallVM* in_self, DCfloat x) 139 static void dc_callvm_argFloat_x64(DCCallVM* in_self, DCfloat x)
105 { 140 {
106 DCCallVM_x64* self = (DCCallVM_x64*)in_self;
107
108 /* Although not promoted to doubles, floats are stored with 64bits in this API.*/ 141 /* Although not promoted to doubles, floats are stored with 64bits in this API.*/
109 union { 142 union {
110 DCdouble d; 143 DCdouble d;
111 DCfloat f; 144 DCfloat f;
112 } f; 145 } f;
113 f.f = x; 146 f.f = x;
114 147
115 if(self->mRegCount.f < numFloatRegs) 148 dc_callvm_argDouble_x64(in_self, f.d);
116 *(DCfloat*)&self->mRegData.f[self->mRegCount.f++] = x;
117 else
118 dcVecAppend(&self->mVecHead, &f.f, sizeof(DCdouble));
119 }
120
121
122 static void dc_callvm_argDouble_x64(DCCallVM* in_self, DCdouble x)
123 {
124 DCCallVM_x64* self = (DCCallVM_x64*)in_self;
125 if(self->mRegCount.f < numFloatRegs)
126 self->mRegData.f[self->mRegCount.f++] = x;
127 else
128 dcVecAppend(&self->mVecHead, &x, sizeof(DCdouble));
129 } 149 }
130 150
131 151
132 static void dc_callvm_argPointer_x64(DCCallVM* in_self, DCpointer x) 152 static void dc_callvm_argPointer_x64(DCCallVM* in_self, DCpointer x)
133 { 153 {
134 DCCallVM_x64* self = (DCCallVM_x64*)in_self; 154 DCCallVM_x64* self = (DCCallVM_x64*)in_self;
155
156 self->mRegCount.i += (self->mRegCount.i == self->mAggrReturnReg);
157
135 if(self->mRegCount.i < numIntRegs) 158 if(self->mRegCount.i < numIntRegs)
136 *(DCpointer*)&self->mRegData.i[self->mRegCount.i++] = x; 159 *(DCpointer*)&self->mRegData.i[self->mRegCount.i++] = x;
137 else 160 else
138 dcVecAppend(&self->mVecHead, &x, sizeof(DCpointer)); 161 dcVecAppend(&self->mVecHead, &x, sizeof(DCpointer));
139 } 162 }
140 163
141 static void dc_callvm_argStruct_x64(DCCallVM* in_self, DCstruct* s, DCpointer x) 164
142 { 165 static void dc_callvm_argAggr_x64(DCCallVM* in_self, const DCaggr* ag, const void* x)
143 DCCallVM_x64* self = (DCCallVM_x64*)in_self; 166 {
144 dcVecAppend(&self->mVecHead, x, s->size); 167 int i;
145 /*printf("dc_callvm_argStruct_x64 size = %d\n", (int)s->size);@@@*/ 168 DCCallVM_x64* self = (DCCallVM_x64*)in_self;
146 if (s->size <= 64) 169
147 dcArgStructUnroll(in_self, s, x); 170 if (!ag) {
148 /*else@@@*/ 171 /* non-trivial aggrs (C++) are passed via pointer (win and sysv callconv),
149 /* dcVecAppend(&self->mVecHead, &x, sizeof(DCpointer));@@@*/ 172 * copy has to be provided by user, as dyncall cannot do such copies*/
173 dc_callvm_argPointer_x64(in_self, (DCpointer)x);
174 return;
175 }
176
177 #if defined(DC_UNIX)
178 DCRegCount_x64 n_regs = { self->mRegCount.i, self->mRegCount.f };
179
180 if(ag->sysv_classes[0] != SYSVC_MEMORY) {
181 /* reclassify aggr w/ respect to remaining regs, might need to pass it all via the stack */
182 for(i=0; ag->sysv_classes[i] && i<DC_SYSV_MAX_NUM_CLASSES; ++i) {
183 DCuchar clz = ag->sysv_classes[i];
184 n_regs.i += (clz == SYSVC_INTEGER);
185 n_regs.f += (clz == SYSVC_SSE);
186 /* @@@AGGR implement when implementing x87 types */
187 }
188 }
189
190 if(ag->sysv_classes[0] == SYSVC_MEMORY || (n_regs.i > numIntRegs) || (n_regs.f > numFloatRegs))
191 {
192 dcVecAppend(&self->mVecHead, x, ag->size);
193 dcVecSkip(&self->mVecHead, (ag->size + (sizeof(DClonglong)-1) & -sizeof(DClonglong)) - ag->size); /* realign to qword */
194 return;
195 }
196
197 for(i=0; ag->sysv_classes[i] && i<DC_SYSV_MAX_NUM_CLASSES; ++i)
198 {
199 switch (ag->sysv_classes[i]) {
200 case SYSVC_INTEGER: dc_callvm_argLongLong_x64(in_self, ((DClonglong*)x)[i]); break;
201 case SYSVC_SSE: dc_callvm_argDouble_x64 (in_self, ((DCdouble *)x)[i]); break;
202 /* @@@AGGR implement when implementing x87 types */
203 }
204 }
205
206 #else
207
208 switch (ag->size) {
209 case 1: dc_callvm_argChar_x64 (in_self, *(DCchar *)x); break;
210 case 2: dc_callvm_argShort_x64 (in_self, *(DCshort *)x); break;
211 case 4: dc_callvm_argLong_x64 (in_self, *(DClong *)x); break;
212 case 8: dc_callvm_argLongLong_x64(in_self, *(DClonglong*)x); break;
213 default:
214 /* pass the aggr indirectly via hidden pointer; requires caller-made copy
215 * to mimic pass-by-value semantics (or a call that modifies the param
216 * would corrupt the source aggr)
217 * place those copies at the end of the param vector (aligned to 16b for
218 * this calling convention); it's a bit of a hack, but should be safe: in
219 * any case the vector has to be big enough to hold all params */
220 self->mpAggrVecCopies = (void*)((intptr_t)((DCchar*)self->mpAggrVecCopies - ag->size) & -16);
221 x = memcpy(self->mpAggrVecCopies, x, ag->size);
222 dc_callvm_argPointer_x64(in_self, (DCpointer)x);
223 break;
224 }
225 #endif
150 } 226 }
151 227
152 228
153 /* Call. */ 229 /* Call. */
154 void dc_callvm_call_x64(DCCallVM* in_self, DCpointer target) 230 static void dc_callvm_call_x64(DCCallVM* in_self, DCpointer target)
155 { 231 {
156 DCCallVM_x64* self = (DCCallVM_x64*)in_self; 232 DCCallVM_x64* self = (DCCallVM_x64*)in_self;
157 #if defined(DC_UNIX) 233 #if defined(DC_UNIX)
158 dcCall_x64_sysv( 234 dcCall_x64_sysv(
159 #else 235 #else
165 #if defined(DC_UNIX) 241 #if defined(DC_UNIX)
166 self->mRegData.f, /* Pointer to floating point register arguments. */ 242 self->mRegData.f, /* Pointer to floating point register arguments. */
167 #endif 243 #endif
168 target 244 target
169 ); 245 );
246 }
247
248
249 static void dc_callvm_begin_aggr_x64(DCCallVM* in_self, const DCaggr *ag)
250 {
251 DCCallVM_x64* self = (DCCallVM_x64*)in_self;
252
253 assert(self->mRegCount.i == 0 && self->mRegCount.f == 0 && "dc_callvm_begin_aggr_x64 should be called before any function arguments are declared");
254 #if defined(DC_UNIX)
255 if (!ag || (ag->sysv_classes[0] == SYSVC_MEMORY)) {
256 #else
257 if (!ag || ag->size > 8) {
258 #endif
259 /* pass pointer to aggregate as hidden first argument */
260 self->mAggrReturnReg = 0;
261 }
262 }
263
264
265 #if defined(DC_WINDOWS)
266 static void dc_callvm_begin_aggr_x64_win64_this(DCCallVM* in_self, const DCaggr *ag)
267 {
268 DCCallVM_x64* self = (DCCallVM_x64*)in_self;
269
270 assert(self->mRegCount.i == 0 && self->mRegCount.f == 0 && "dc_callvm_begin_aggr_x64_win64_this should be called before any function arguments are declared");
271
272 if (!ag || ag->size > 8) {
273 /* thiscall: this-ptr comes first, then pointer to aggregate as hidden (second) argument */
274 self->mAggrReturnReg = 1;
275 }
276 }
277 #endif
278
279
280 static void dc_callvm_call_x64_aggr(DCCallVM* in_self, DCpointer target, const DCaggr *ag, DCpointer ret)
281 {
282 DCCallVM_x64* self = (DCCallVM_x64*)in_self;
283
284 #if defined(DC_UNIX)
285
286 if (self->mAggrReturnReg != -1) {
287 /* call regular dcCall_x64_sysv here, w/ pointer to the aggr in first arg */
288 self->mRegData.i[self->mAggrReturnReg] = (int64)ret;
289
290 dcCall_x64_sysv(
291 dcVecSize(&self->mVecHead), /* rdi: Size of stack data. */
292 dcVecData(&self->mVecHead), /* rsi: Pointer to stack arguments. */
293 self->mRegData.i, /* rdx: Pointer to register arguments (ints on SysV). */
294 self->mRegData.f, /* rcx: Pointer to floating point register arguments. */
295 target /* r8 */
296 );
297 } else {
298 int i;
299 DCchar ret_regs[32]; /* 4 qwords: 2 for ints, 2 for floats */
300 DCchar *ret_regs_i = ret_regs+0;
301 DCchar *ret_regs_f = ret_regs+16;
302 DCsize st_size = ag->size;
303 DCchar* dst = (char*)ret;
304 dcCall_x64_sysv_aggr(
305 dcVecSize(&self->mVecHead), /* rdi: Size of stack data. */
306 dcVecData(&self->mVecHead), /* rsi: Pointer to stack arguments. */
307 self->mRegData.i, /* rdx: Pointer to register arguments (ints on SysV). */
308 self->mRegData.f, /* rcx: Pointer to floating point register arguments. */
309 target, /* r8 */
310 ret_regs /* r9 */
311 );
312 /* reassemble aggr to be returned from reg data */
313 for(i=0; ag->sysv_classes[i] && i<DC_SYSV_MAX_NUM_CLASSES; ++i) {
314 DCchar** src;
315 int ll = 8;
316 switch(ag->sysv_classes[i]) {
317 case SYSVC_INTEGER: src = &ret_regs_i; break;
318 case SYSVC_SSE: src = &ret_regs_f; break;
319 /* @@@AGGR implement when implementing x87 types */
320 }
321 while(ll-- && st_size--)
322 *dst++ = *(*src)++;
323 }
324 }
325
326 #else
327
328 if (self->mAggrReturnReg != -1) {
329 /* call regular dcCall_x64_sysv here, w/ pointer to the aggr in first arg */
330 self->mRegData.i[self->mAggrReturnReg] = (int64)ret;
331
332 dcCall_x64_win64(
333 dcVecSize(&self->mVecHead), /* rcx: Size of stack data. */
334 dcVecData(&self->mVecHead), /* rdx: Pointer to stack arguments. */
335 self->mRegData.i, /* r8: Pointer to register arguments */
336 target /* r9 */
337 );
338 } else {
339 DCchar ret_reg[8]; /* 1 qword */
340 DCsize st_size = ag->size; /* guaranteed to be <= 8 */
341 DCchar* dst = (char*)ret;
342 DCchar* src = ret_reg;
343 dcCall_x64_win64_aggr(
344 dcVecSize(&self->mVecHead), /* rcx: Size of stack data. */
345 dcVecData(&self->mVecHead), /* rdx: Pointer to stack arguments. */
346 self->mRegData.i, /* r8: Pointer to register arguments */
347 target, /* r9 */
348 ret_reg /* stack */
349 );
350 while(st_size--)
351 *dst++ = *src++;
352 }
353
354 #endif
170 } 355 }
171 356
172 357
173 static void dc_callvm_mode_x64(DCCallVM* in_self, DCint mode); 358 static void dc_callvm_mode_x64(DCCallVM* in_self, DCint mode);
174 359
184 , &dc_callvm_argLong_x64 369 , &dc_callvm_argLong_x64
185 , &dc_callvm_argLongLong_x64 370 , &dc_callvm_argLongLong_x64
186 , &dc_callvm_argFloat_x64 371 , &dc_callvm_argFloat_x64
187 , &dc_callvm_argDouble_x64 372 , &dc_callvm_argDouble_x64
188 , &dc_callvm_argPointer_x64 373 , &dc_callvm_argPointer_x64
189 , &dc_callvm_argStruct_x64 374 , &dc_callvm_argAggr_x64
190 , (DCvoidvmfunc*) &dc_callvm_call_x64 375 , (DCvoidvmfunc*) &dc_callvm_call_x64
191 , (DCboolvmfunc*) &dc_callvm_call_x64 376 , (DCboolvmfunc*) &dc_callvm_call_x64
192 , (DCcharvmfunc*) &dc_callvm_call_x64 377 , (DCcharvmfunc*) &dc_callvm_call_x64
193 , (DCshortvmfunc*) &dc_callvm_call_x64 378 , (DCshortvmfunc*) &dc_callvm_call_x64
194 , (DCintvmfunc*) &dc_callvm_call_x64 379 , (DCintvmfunc*) &dc_callvm_call_x64
195 , (DClongvmfunc*) &dc_callvm_call_x64 380 , (DClongvmfunc*) &dc_callvm_call_x64
196 , (DClonglongvmfunc*) &dc_callvm_call_x64 381 , (DClonglongvmfunc*) &dc_callvm_call_x64
197 , (DCfloatvmfunc*) &dc_callvm_call_x64 382 , (DCfloatvmfunc*) &dc_callvm_call_x64
198 , (DCdoublevmfunc*) &dc_callvm_call_x64 383 , (DCdoublevmfunc*) &dc_callvm_call_x64
199 , (DCpointervmfunc*) &dc_callvm_call_x64 384 , (DCpointervmfunc*) &dc_callvm_call_x64
200 , NULL /* callStruct */ 385 , (DCaggrvmfunc*) &dc_callvm_call_x64_aggr
386 , (DCbeginaggrvmfunc*)&dc_callvm_begin_aggr_x64
201 }; 387 };
202 388
203 389
204 /* --- syscall ------------------------------------------------------------- */ 390 #if defined(DC_WINDOWS)
205 391 /* --- win64 thiscalls ------------------------------------------------------------- */
206 #include <assert.h> 392
207 void dc_callvm_call_x64_syscall_sysv(DCCallVM* in_self, DCpointer target) 393 DCCallVM_vt gVT_x64_win64_this =
208 {
209 DCCallVM_x64* self;
210
211 /* syscalls can have up to 6 args, required to be "Only values of class INTEGER or class MEMORY" (from */
212 /* SysV manual), so we can use self->mRegData.i directly; verify this has space for at least 6 values, though. */
213 assert(numIntRegs >= 6);
214
215 self = (DCCallVM_x64*)in_self;
216 dcCall_x64_syscall_sysv(self->mRegData.i, target);
217 }
218
219 DCCallVM_vt gVT_x64_syscall_sysv =
220 { 394 {
221 &dc_callvm_free_x64 395 &dc_callvm_free_x64
222 , &dc_callvm_reset_x64 396 , &dc_callvm_reset_x64
223 , &dc_callvm_mode_x64 397 , &dc_callvm_mode_x64
224 , &dc_callvm_argBool_x64 398 , &dc_callvm_argBool_x64
228 , &dc_callvm_argLong_x64 402 , &dc_callvm_argLong_x64
229 , &dc_callvm_argLongLong_x64 403 , &dc_callvm_argLongLong_x64
230 , &dc_callvm_argFloat_x64 404 , &dc_callvm_argFloat_x64
231 , &dc_callvm_argDouble_x64 405 , &dc_callvm_argDouble_x64
232 , &dc_callvm_argPointer_x64 406 , &dc_callvm_argPointer_x64
233 , NULL /* argStruct */ 407 , &dc_callvm_argAggr_x64
408 , (DCvoidvmfunc*) &dc_callvm_call_x64
409 , (DCboolvmfunc*) &dc_callvm_call_x64
410 , (DCcharvmfunc*) &dc_callvm_call_x64
411 , (DCshortvmfunc*) &dc_callvm_call_x64
412 , (DCintvmfunc*) &dc_callvm_call_x64
413 , (DClongvmfunc*) &dc_callvm_call_x64
414 , (DClonglongvmfunc*) &dc_callvm_call_x64
415 , (DCfloatvmfunc*) &dc_callvm_call_x64
416 , (DCdoublevmfunc*) &dc_callvm_call_x64
417 , (DCpointervmfunc*) &dc_callvm_call_x64
418 , (DCaggrvmfunc*) &dc_callvm_call_x64_aggr
419 , (DCbeginaggrvmfunc*)&dc_callvm_begin_aggr_x64_win64_this
420 };
421
422 #endif
423
424 /* --- syscall ------------------------------------------------------------- */
425
426 #if defined(DC_UNIX)
427 void dc_callvm_call_x64_syscall_sysv(DCCallVM* in_self, DCpointer target)
428 {
429 DCCallVM_x64* self;
430
431 /* syscalls can have up to 6 args, required to be "Only values of class INTEGER or class MEMORY" (from */
432 /* SysV manual), so we can use self->mRegData.i directly; verify this has space for at least 6 values, though. */
433 assert(numIntRegs >= 6);
434
435 self = (DCCallVM_x64*)in_self;
436 dcCall_x64_syscall_sysv(self->mRegData.i, target);
437 }
438
439 DCCallVM_vt gVT_x64_syscall_sysv =
440 {
441 &dc_callvm_free_x64
442 , &dc_callvm_reset_x64
443 , &dc_callvm_mode_x64
444 , &dc_callvm_argBool_x64
445 , &dc_callvm_argChar_x64
446 , &dc_callvm_argShort_x64
447 , &dc_callvm_argInt_x64
448 , &dc_callvm_argLong_x64
449 , &dc_callvm_argLongLong_x64
450 , &dc_callvm_argFloat_x64
451 , &dc_callvm_argDouble_x64
452 , &dc_callvm_argPointer_x64
453 , NULL /* argAggr */
234 , (DCvoidvmfunc*) &dc_callvm_call_x64_syscall_sysv 454 , (DCvoidvmfunc*) &dc_callvm_call_x64_syscall_sysv
235 , (DCboolvmfunc*) &dc_callvm_call_x64_syscall_sysv 455 , (DCboolvmfunc*) &dc_callvm_call_x64_syscall_sysv
236 , (DCcharvmfunc*) &dc_callvm_call_x64_syscall_sysv 456 , (DCcharvmfunc*) &dc_callvm_call_x64_syscall_sysv
237 , (DCshortvmfunc*) &dc_callvm_call_x64_syscall_sysv 457 , (DCshortvmfunc*) &dc_callvm_call_x64_syscall_sysv
238 , (DCintvmfunc*) &dc_callvm_call_x64_syscall_sysv 458 , (DCintvmfunc*) &dc_callvm_call_x64_syscall_sysv
239 , (DClongvmfunc*) &dc_callvm_call_x64_syscall_sysv 459 , (DClongvmfunc*) &dc_callvm_call_x64_syscall_sysv
240 , (DClonglongvmfunc*) &dc_callvm_call_x64_syscall_sysv 460 , (DClonglongvmfunc*) &dc_callvm_call_x64_syscall_sysv
241 , (DCfloatvmfunc*) &dc_callvm_call_x64_syscall_sysv 461 , (DCfloatvmfunc*) &dc_callvm_call_x64_syscall_sysv
242 , (DCdoublevmfunc*) &dc_callvm_call_x64_syscall_sysv 462 , (DCdoublevmfunc*) &dc_callvm_call_x64_syscall_sysv
243 , (DCpointervmfunc*) &dc_callvm_call_x64_syscall_sysv 463 , (DCpointervmfunc*) &dc_callvm_call_x64_syscall_sysv
244 , NULL /* callStruct */ 464 , NULL /* callAggr */
465 , NULL /* beginAggr */
245 }; 466 };
467 #endif
246 468
247 469
248 470
249 /* mode */ 471 /* mode */
250 472
253 DCCallVM_x64* self = (DCCallVM_x64*)in_self; 475 DCCallVM_x64* self = (DCCallVM_x64*)in_self;
254 DCCallVM_vt* vt; 476 DCCallVM_vt* vt;
255 477
256 switch(mode) { 478 switch(mode) {
257 case DC_CALL_C_DEFAULT: 479 case DC_CALL_C_DEFAULT:
258 case DC_CALL_C_DEFAULT_THIS: 480 #if defined(DC_UNIX)
259 #if defined(DC_UNIX) 481 case DC_CALL_C_DEFAULT_THIS:
260 case DC_CALL_C_X64_SYSV: 482 case DC_CALL_C_X64_SYSV: /* = DC_CALL_C_X64_SYSV_THIS */
261 #else 483 #else
262 case DC_CALL_C_X64_WIN64: 484 case DC_CALL_C_X64_WIN64:
263 #endif 485 #endif
264 case DC_CALL_C_ELLIPSIS: 486 case DC_CALL_C_ELLIPSIS:
265 case DC_CALL_C_ELLIPSIS_VARARGS: 487 case DC_CALL_C_ELLIPSIS_VARARGS:
266 vt = &gVT_x64; 488 vt = &gVT_x64;
267 break; 489 break;
490 #if defined(DC_WINDOWS)
491 case DC_CALL_C_DEFAULT_THIS:
492 case DC_CALL_C_X64_WIN64_THIS:
493 vt = &gVT_x64_win64_this;
494 break;
495 #endif
268 case DC_CALL_SYS_DEFAULT: 496 case DC_CALL_SYS_DEFAULT:
269 #if defined(DC_UNIX) 497 #if defined(DC_UNIX)
270 case DC_CALL_SYS_X64_SYSCALL_SYSV: 498 case DC_CALL_SYS_X64_SYSCALL_SYSV:
271 vt = &gVT_x64_syscall_sysv; break; 499 vt = &gVT_x64_syscall_sysv; break;
272 #else 500 #else