comparison test/plain/test_aggrs.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 test/plain/test_structs.c@5fe52b7c6e02
children c477ddd64718
comparison
equal deleted inserted replaced
532:d4bf63ab9164 533:71c884e610f0
1 /*
2
3 Package: dyncall
4 Library: test
5 File: test/plain/test_aggrs.c
6 Description:
7 License:
8
9 Copyright (c) 2022 Tassilo Philipp <tphilipp@potion-studios.com>
10
11 Permission to use, copy, modify, and distribute this software for any
12 purpose with or without fee is hereby granted, provided that the above
13 copyright notice and this permission notice appear in all copies.
14
15 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
16 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
17 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
18 ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
21 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23 */
24
25
26
27
28 #include "../../dyncall/dyncall.h"
29 #include "../../dyncall/dyncall_signature.h"
30 #include "../../dyncall/dyncall_aggregate.h"
31 #include <stdio.h>
32
33
34 #if defined(DC__Feature_AggrByVal)
35
36 #if !defined(DC__OS_Win32)
37 # define __cdecl
38 #endif
39
40 typedef struct {
41 unsigned char a;
42 } U8;
43
44 typedef struct {
45 unsigned char a;
46 double b;
47 } U8_Double;
48
49 typedef struct {
50 float a;
51 float b;
52 } Float_Float;
53
54 typedef struct {
55 double a;
56 unsigned char b;
57 } Double_U8;
58
59 typedef struct {
60 float f;
61 } NestedFloat;
62
63 typedef struct {
64 int a;
65 NestedFloat b;
66 } Int_NestedFloat;
67
68 typedef struct {
69 double f;
70 } NestedDouble;
71
72 typedef struct {
73 int a;
74 NestedDouble b;
75 } Int_NestedDouble;
76
77 typedef struct {
78 double a;
79 double b;
80 double c;
81 } Three_Double;
82
83 typedef struct {
84 int a;
85 long long b;
86 } Int_LongLong;
87
88 /* large struct: more than 8 int/ptr and 8 fp args, more than are passed by reg for both win and sysv for example */
89 typedef struct {
90 double a;
91 double b;
92 double c;
93 long long d;
94 char e;
95 char f;
96 double g;
97 double h;
98 double i;
99 float j;
100 int k;
101 float l;
102 double m;
103 short n;
104 long o;
105 int p;
106 unsigned int q;
107 long long r;
108 } More_Than_Regs;
109
110
111 static U8 __cdecl fun_return_u8(unsigned char a) { U8 r; r.a = a; return r; }
112 static U8_Double __cdecl fun_return_u8_double(unsigned char a, double b) { U8_Double r; r.a = a; r.b = b; return r; }
113 static Double_U8 __cdecl fun_return_double_u8(double a, unsigned char b) { Double_U8 r; r.a = a; r.b = b; return r; }
114 static Int_NestedFloat __cdecl fun_return_int_nested_float(int a, float b) { Int_NestedFloat r; r.a = a; r.b.f = b; return r; }
115 static Int_NestedDouble __cdecl fun_return_int_nested_double(int a, double b) { Int_NestedDouble r; r.a = a; r.b.f = b; return r; }
116 static Three_Double __cdecl fun_return_three_double(double a, double b, double c) { Three_Double r; r.a = a; r.b = b; r.c = c; return r; }
117
118
119 int testAggrReturns()
120 {
121 int ret = 1;
122
123 DCCallVM* vm = dcNewCallVM(4096);
124 dcMode(vm,DC_CALL_C_DEFAULT);
125 {
126 U8 expected = fun_return_u8(5), returned = { 124 };
127
128 DCaggr *s = dcNewAggr(1, sizeof(expected));
129
130 dcAggrField(s, DC_SIGCHAR_UCHAR, offsetof(U8, a), 1);
131 dcCloseAggr(s);
132
133 dcReset(vm);
134 dcBeginCallAggr(vm, s);
135 dcArgChar(vm, expected.a);
136
137 dcCallAggr(vm, (DCpointer) &fun_return_u8, s, &returned);
138
139 dcFreeAggr(s);
140
141 printf("r:{C} (cdecl): %d\n", (returned.a == expected.a));
142 ret = returned.a == expected.a && ret;
143 }
144 {
145 U8_Double expected = fun_return_u8_double(5, 5.5), returned = { 6, 7.8 };
146
147 DCaggr *s = dcNewAggr(2, sizeof(expected));
148
149 dcAggrField(s, DC_SIGCHAR_UCHAR, offsetof(U8_Double, a), 1);
150 dcAggrField(s, DC_SIGCHAR_DOUBLE, offsetof(U8_Double, b), 1);
151 dcCloseAggr(s);
152
153 dcReset(vm);
154 dcBeginCallAggr(vm, s);
155 dcArgChar(vm, expected.a);
156 dcArgDouble(vm, expected.b);
157
158 dcCallAggr(vm, (DCpointer) &fun_return_u8_double, s, &returned);
159
160 dcFreeAggr(s);
161
162 printf("r:{Cd} (cdecl): %d\n", (returned.a == expected.a && returned.b == expected.b));
163 ret = returned.a == expected.a && returned.b == expected.b && ret;
164 }
165 {
166 Double_U8 expected = fun_return_double_u8(5.5, 42), returned = { 6.7, 8 };
167
168 DCaggr *s = dcNewAggr(2, sizeof(expected));
169
170 dcAggrField(s, DC_SIGCHAR_DOUBLE, offsetof(Double_U8, a), 1);
171 dcAggrField(s, DC_SIGCHAR_UCHAR, offsetof(Double_U8, b), 1);
172 dcCloseAggr(s);
173
174 dcReset(vm);
175 dcBeginCallAggr(vm, s);
176 dcArgDouble(vm, expected.a);
177 dcArgChar(vm, expected.b);
178
179 dcCallAggr(vm, (DCpointer) &fun_return_double_u8, s, &returned);
180
181 dcFreeAggr(s);
182
183 printf("r:{dC} (cdecl): %d\n", (returned.a == expected.a && returned.b == expected.b));
184 ret = returned.a == expected.a && returned.b == expected.b && ret;
185 }
186 {
187 Int_NestedFloat expected = fun_return_int_nested_float(24, 2.5f), returned = { 25, { 3.5f } };
188 DCaggr *s, *s_;
189
190 s_ = dcNewAggr(1, sizeof(NestedFloat));
191 dcAggrField(s_, DC_SIGCHAR_FLOAT, offsetof(NestedFloat, f), 1);
192 dcCloseAggr(s_);
193
194 s = dcNewAggr(2, sizeof(expected));
195 dcAggrField(s, DC_SIGCHAR_INT, offsetof(Int_NestedFloat, a), 1);
196 dcAggrField(s, DC_SIGCHAR_AGGREGATE, offsetof(Int_NestedFloat, b), 1, s_);
197 dcCloseAggr(s);
198
199 dcReset(vm);
200 dcBeginCallAggr(vm, s);
201 dcArgInt(vm, expected.a);
202 dcArgFloat(vm, expected.b.f);
203
204 dcCallAggr(vm, (DCpointer) &fun_return_int_nested_float, s, &returned);
205
206 dcFreeAggr(s_);
207 dcFreeAggr(s);
208
209 printf("r:{i{f}} (cdecl): %d\n", (returned.a == expected.a && returned.b.f == expected.b.f));
210 ret = returned.a == expected.a && returned.b.f == expected.b.f && ret;
211 }
212 {
213 Int_NestedDouble expected = fun_return_int_nested_double(24, 2.5), returned = { 25, { 3.5f } };
214 DCaggr *s, *s_;
215
216 s_ = dcNewAggr(1, sizeof(NestedDouble));
217 dcAggrField(s_, DC_SIGCHAR_DOUBLE, offsetof(NestedDouble, f), 1);
218 dcCloseAggr(s_);
219
220 s = dcNewAggr(2, sizeof(expected));
221 dcAggrField(s, DC_SIGCHAR_INT, offsetof(Int_NestedDouble, a), 1);
222 dcAggrField(s, DC_SIGCHAR_AGGREGATE, offsetof(Int_NestedDouble, b), 1, s_);
223 dcCloseAggr(s);
224
225 dcReset(vm);
226 dcBeginCallAggr(vm, s);
227 dcArgInt(vm, expected.a);
228 dcArgDouble(vm, expected.b.f);
229
230 dcCallAggr(vm, (DCpointer) &fun_return_int_nested_double, s, &returned);
231
232 dcFreeAggr(s_);
233 dcFreeAggr(s);
234
235 printf("r:{i{d}} (cdecl): %d\n", (returned.a == expected.a && returned.b.f == expected.b.f));
236 ret = returned.a == expected.a && returned.b.f == expected.b.f && ret;
237 }
238 {
239 Three_Double expected = fun_return_three_double(1.5, 2.5, 3.5), returned = { 2.5, 3.5, 4.5 };
240
241 DCaggr *s = dcNewAggr(3, sizeof(expected));
242
243 dcAggrField(s, DC_SIGCHAR_DOUBLE, offsetof(Three_Double, a), 1);
244 dcAggrField(s, DC_SIGCHAR_DOUBLE, offsetof(Three_Double, b), 1);
245 dcAggrField(s, DC_SIGCHAR_DOUBLE, offsetof(Three_Double, c), 1);
246 dcCloseAggr(s);
247
248 dcReset(vm);
249 dcBeginCallAggr(vm, s);
250 dcArgDouble(vm, expected.a);
251 dcArgDouble(vm, expected.b);
252 dcArgDouble(vm, expected.c);
253
254 dcCallAggr(vm, (DCpointer) &fun_return_three_double, s, &returned);
255
256 dcFreeAggr(s);
257
258 printf("r:{ddd} (cdecl): %d\n", (returned.a == expected.a && returned.b == expected.b && returned.c == expected.c));
259 ret = returned.a == expected.a && returned.b == expected.b && returned.c == expected.c && ret;
260 }
261
262 dcFree(vm);
263
264 return ret;
265 }
266
267 static double __cdecl fun_take_u8(U8 s) { return s.a; }
268 static double __cdecl fun_take_u8_double(U8_Double s) { return s.a + s.b; }
269 static double __cdecl fun_take_float_float(Float_Float s) { return s.a + s.b; }
270 static double __cdecl fun_take_double_u8(Double_U8 s) { return s.a + s.b; }
271 static double __cdecl fun_take_int_nested_float(Int_NestedFloat s) { return s.a + s.b.f; }
272 static double __cdecl fun_take_int_nested_double(Int_NestedDouble s) { return s.a + s.b.f; }
273 static double __cdecl fun_take_three_double(Three_Double s) { return s.a + s.b + s.c; }
274 static double __cdecl fun_take_mixed_fp(double a, float b, float c, int d, float e, double f, float g, Three_Double s) { return a + 2.*b + 3.*c + 4.*d + 5.*e + 6.*f + 7.*g + 8.*s.a + 9.*s.b + 10.*s.c; }
275 static int __cdecl fun_take_iiiii_il(int a, int b, int c, int d, int e, Int_LongLong f) { return a + b + c + d + e + f.a + (int)f.b; }
276 static double __cdecl fun_take_more_than_regs(More_Than_Regs s) { return s.a + s.b + s.c + s.d + s.e + s.f + s.g + s.h + s.i + s.j + s.k + s.l + s.m + s.n + s.o + s.p + s.q + s.r; }
277
278
279 int testAggrParameters()
280 {
281 int ret = 1;
282
283 DCCallVM* vm = dcNewCallVM(4096);
284 dcMode(vm,DC_CALL_C_DEFAULT);
285 {
286 U8 t = { 5 };
287 double returned;
288
289 DCaggr *s = dcNewAggr(1, sizeof(t));
290 dcAggrField(s, DC_SIGCHAR_UCHAR, offsetof(U8, a), 1);
291 dcCloseAggr(s);
292
293 dcReset(vm);
294 dcArgAggr(vm, s, &t);
295 returned = dcCallDouble(vm, (DCpointer) &fun_take_u8);
296
297 dcFreeAggr(s);
298
299 printf("{C} (cdecl): %d\n", returned == t.a);
300 ret = returned == t.a && ret;
301 }
302 {
303 U8_Double t = { 5, 5.5 };
304 double returned;
305
306 DCaggr *s = dcNewAggr(2, sizeof(t));
307 dcAggrField(s, DC_SIGCHAR_UCHAR, offsetof(U8_Double, a), 1);
308 dcAggrField(s, DC_SIGCHAR_DOUBLE, offsetof(U8_Double, b), 1);
309 dcCloseAggr(s);
310
311 dcReset(vm);
312 dcArgAggr(vm, s, &t);
313 returned = dcCallDouble(vm, (DCpointer) &fun_take_u8_double);
314
315 dcFreeAggr(s);
316
317 printf("{Cd} (cdecl): %d\n", returned == t.a + t.b);
318 ret = returned == t.a + t.b && ret;
319 }
320 {
321 Float_Float t = { 1.5, 5.5 };
322 double returned;
323
324 DCaggr *s = dcNewAggr(2, sizeof(t));
325 dcAggrField(s, DC_SIGCHAR_FLOAT, offsetof(Float_Float, a), 1);
326 dcAggrField(s, DC_SIGCHAR_FLOAT, offsetof(Float_Float, b), 1);
327 dcCloseAggr(s);
328
329 dcReset(vm);
330 dcArgAggr(vm, s, &t);
331 returned = dcCallDouble(vm, (DCpointer) &fun_take_float_float);
332
333 dcFreeAggr(s);
334
335 printf("{ff} (cdecl): %d\n", returned == t.a + t.b);
336 ret = returned == t.a + t.b && ret;
337 }
338 {
339 Double_U8 t = { 5.5, 42 };
340 double returned;
341
342 DCaggr *s = dcNewAggr(2, sizeof(t));
343 dcAggrField(s, DC_SIGCHAR_DOUBLE, offsetof(Double_U8, a), 1);
344 dcAggrField(s, DC_SIGCHAR_UCHAR, offsetof(Double_U8, b), 1);
345 dcCloseAggr(s);
346
347 dcReset(vm);
348 dcArgAggr(vm, s, &t);
349 returned = dcCallDouble(vm, (DCpointer) &fun_take_double_u8);
350
351 dcFreeAggr(s);
352
353 printf("{dC} (cdecl): %d\n", returned == t.a + t.b);
354 ret = returned == t.a + t.b && ret;
355 }
356 {
357 Int_NestedFloat t = { 24, { 2.5f } };
358 double returned;
359 DCaggr *s, *s_;
360
361 s_ = dcNewAggr(1, sizeof(NestedFloat));
362 dcAggrField(s_, DC_SIGCHAR_FLOAT, offsetof(NestedFloat, f), 1);
363 dcCloseAggr(s_);
364
365 s = dcNewAggr(2, sizeof(t));
366 dcAggrField(s, DC_SIGCHAR_INT, offsetof(Int_NestedFloat, a), 1);
367 dcAggrField(s, DC_SIGCHAR_AGGREGATE, offsetof(Int_NestedFloat, b), 1, s_);
368 dcCloseAggr(s);
369
370 dcReset(vm);
371 dcArgAggr(vm, s, &t);
372 returned = dcCallDouble(vm, (DCpointer) &fun_take_int_nested_float);
373
374 dcFreeAggr(s_);
375 dcFreeAggr(s);
376
377 printf("{i{f}} (cdecl): %d\n", returned == t.a + t.b.f);
378 ret = returned == t.a + t.b.f && ret;
379 }
380 {
381 Int_NestedDouble t = { 24, { 2.5} };
382 double returned;
383 DCaggr *s, *s_;
384
385 s_ = dcNewAggr(1, sizeof(NestedDouble));
386 dcAggrField(s_, DC_SIGCHAR_DOUBLE, offsetof(NestedDouble, f), 1);
387 dcCloseAggr(s_);
388
389 s = dcNewAggr(2, sizeof(t));
390 dcAggrField(s, DC_SIGCHAR_INT, offsetof(Int_NestedDouble, a), 1);
391 dcAggrField(s, DC_SIGCHAR_AGGREGATE, offsetof(Int_NestedDouble, b), 1, s_);
392 dcCloseAggr(s);
393
394 dcReset(vm);
395 dcArgAggr(vm, s, &t);
396 returned = dcCallDouble(vm, (DCpointer) &fun_take_int_nested_double);
397
398 dcFreeAggr(s_);
399 dcFreeAggr(s);
400
401 printf("{i{d}} (cdecl): %d\n", returned == t.a + t.b.f);
402 ret = returned == t.a + t.b.f && ret;
403 }
404 {
405 Three_Double t = { 1.5, 2.5, 3.5 };
406 double returned;
407
408 DCaggr *s = dcNewAggr(3, sizeof(t));
409 dcAggrField(s, DC_SIGCHAR_DOUBLE, offsetof(Three_Double, a), 1);
410 dcAggrField(s, DC_SIGCHAR_DOUBLE, offsetof(Three_Double, b), 1);
411 dcAggrField(s, DC_SIGCHAR_DOUBLE, offsetof(Three_Double, c), 1);
412 dcCloseAggr(s);
413
414 dcReset(vm);
415 dcArgAggr(vm, s, &t);
416 returned = dcCallDouble(vm, (DCpointer) &fun_take_three_double);
417
418 dcFreeAggr(s);
419
420 printf("{fff} (cdecl): %d\n", returned == t.a + t.b + t.c);
421 ret = returned == t.a + t.b + t.c && ret;
422 }
423 {
424 /* w/ some prev params, so not fitting into float regs anymore (on win and sysv) */
425 Three_Double t = { 1.5, 2.5, 3.5 };
426 double returned;
427
428 DCaggr *s = dcNewAggr(3, sizeof(t));
429 dcAggrField(s, DC_SIGCHAR_DOUBLE, offsetof(Three_Double, a), 1);
430 dcAggrField(s, DC_SIGCHAR_DOUBLE, offsetof(Three_Double, b), 1);
431 dcAggrField(s, DC_SIGCHAR_DOUBLE, offsetof(Three_Double, c), 1);
432 dcCloseAggr(s);
433
434 dcReset(vm);
435 dcArgDouble(vm, 234.4);
436 dcArgFloat(vm, 34.4f);
437 dcArgFloat(vm, 4.0f);
438 dcArgInt(vm, -12);
439 dcArgFloat(vm, -83.9f);
440 dcArgDouble(vm, -.9);
441 dcArgFloat(vm, .6f);
442 dcArgAggr(vm, s, &t);
443 returned = dcCallDouble(vm, (DCpointer) &fun_take_mixed_fp) + 84.;
444 if(returned < 0.)
445 returned = -returned;
446
447 dcFreeAggr(s);
448
449 printf("dffifdf{fff} (cdecl): %d\n", returned < .00001);
450 ret = returned < .00001 && ret;
451 }
452 {
453 Int_LongLong t = { -17, 822LL };
454 int returned;
455
456 DCaggr *s = dcNewAggr(2, sizeof(t));
457 dcAggrField(s, DC_SIGCHAR_INT, offsetof(Int_LongLong, a), 1);
458 dcAggrField(s, DC_SIGCHAR_LONGLONG, offsetof(Int_LongLong, b), 1);
459 dcCloseAggr(s);
460
461 dcReset(vm);
462 dcArgInt(vm, 23);
463 dcArgInt(vm, -211);
464 dcArgInt(vm, 111);
465 dcArgInt(vm, 34);
466 dcArgInt(vm, -19290);
467 dcArgAggr(vm, s, &t);
468 returned = dcCallInt(vm, (DCpointer) &fun_take_iiiii_il);
469
470 dcFreeAggr(s);
471
472 printf("iiiii{il} (cdecl): %d\n", returned == -18528);
473 ret = returned == -18528 && ret;
474 }
475 {
476 More_Than_Regs t = { 1., 2., 3., 4, 5, 6, 7., 8., 9., 10.f, 11, 12.f, 13., 14, 15, 16, 17, 18 };
477 double returned;
478
479 DCaggr *s = dcNewAggr(18, sizeof(t));
480 dcAggrField(s, DC_SIGCHAR_DOUBLE, offsetof(More_Than_Regs, a), 1);
481 dcAggrField(s, DC_SIGCHAR_DOUBLE, offsetof(More_Than_Regs, b), 1);
482 dcAggrField(s, DC_SIGCHAR_DOUBLE, offsetof(More_Than_Regs, c), 1);
483 dcAggrField(s, DC_SIGCHAR_LONGLONG, offsetof(More_Than_Regs, d), 1);
484 dcAggrField(s, DC_SIGCHAR_CHAR, offsetof(More_Than_Regs, e), 1);
485 dcAggrField(s, DC_SIGCHAR_CHAR, offsetof(More_Than_Regs, f), 1);
486 dcAggrField(s, DC_SIGCHAR_DOUBLE, offsetof(More_Than_Regs, g), 1);
487 dcAggrField(s, DC_SIGCHAR_DOUBLE, offsetof(More_Than_Regs, h), 1);
488 dcAggrField(s, DC_SIGCHAR_DOUBLE, offsetof(More_Than_Regs, i), 1);
489 dcAggrField(s, DC_SIGCHAR_FLOAT, offsetof(More_Than_Regs, j), 1);
490 dcAggrField(s, DC_SIGCHAR_INT, offsetof(More_Than_Regs, k), 1);
491 dcAggrField(s, DC_SIGCHAR_FLOAT, offsetof(More_Than_Regs, l), 1);
492 dcAggrField(s, DC_SIGCHAR_DOUBLE, offsetof(More_Than_Regs, m), 1);
493 dcAggrField(s, DC_SIGCHAR_SHORT, offsetof(More_Than_Regs, n), 1);
494 dcAggrField(s, DC_SIGCHAR_LONG, offsetof(More_Than_Regs, o), 1);
495 dcAggrField(s, DC_SIGCHAR_INT, offsetof(More_Than_Regs, p), 1);
496 dcAggrField(s, DC_SIGCHAR_UINT, offsetof(More_Than_Regs, q), 1);
497 dcAggrField(s, DC_SIGCHAR_LONGLONG, offsetof(More_Than_Regs, r), 1);
498 dcCloseAggr(s);
499
500 dcReset(vm);
501 dcArgAggr(vm, s, &t);
502 returned = dcCallDouble(vm, (DCpointer) &fun_take_more_than_regs);
503
504 dcFreeAggr(s);
505
506 printf("{dddlccdddfifdsjiIl} (cdecl): %d\n", returned == 171.);
507 ret = returned == 171. && ret;
508 }
509
510 dcFree(vm);
511
512 return ret;
513 }
514
515 #endif
516