Mercurial > pub > dyncall > dyncall
comparison test/callf/main.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 | 7608e34098b0 |
children | d9558c1555df |
comparison
equal
deleted
inserted
replaced
532:d4bf63ab9164 | 533:71c884e610f0 |
---|---|
4 Library: test | 4 Library: test |
5 File: test/callf/main.c | 5 File: test/callf/main.c |
6 Description: | 6 Description: |
7 License: | 7 License: |
8 | 8 |
9 Copyright (c) 2007-2021 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. |
37 #endif | 37 #endif |
38 | 38 |
39 | 39 |
40 /* sample void function */ | 40 /* sample void function */ |
41 | 41 |
42 int vf_iii(int x,int y,int z) | 42 int i_iii(int x,int y,int z) |
43 { | 43 { |
44 int r = (x == 1 && y == 2 && z == 3); | 44 int r = (x == 1 && y == 2 && z == 3); |
45 printf("%d %d %d: %d", x, y, z, r); | 45 printf("%d %d %d: %d", x, y, z, r); |
46 return r; | 46 return r; |
47 } | 47 } |
48 | 48 |
49 int vf_ffiffiffi(float a, float b, int c, float d, float e, int f, float g, float h, int i) | 49 int i_ffiffiffi(float a, float b, int c, float d, float e, int f, float g, float h, int i) |
50 { | 50 { |
51 int r = (a == 1.f && b == 2.f && c == 3 && d == 4.f && e == 5.f && f == 6 && g == 7.f && h == 8.f && i == 9); | 51 int r = (a == 1.f && b == 2.f && c == 3 && d == 4.f && e == 5.f && f == 6 && g == 7.f && h == 8.f && i == 9); |
52 printf("%f %f %d %f %f %d %f %f %d: %d", a, b, c, d, e, f, g, h, i, r); | 52 printf("%f %f %d %f %f %d %f %f %d: %d", a, b, c, d, e, f, g, h, i, r); |
53 return r; | 53 return r; |
54 } | 54 } |
55 | 55 |
56 int vf_ffiV(float a, float b, int c, ...) | 56 int i_ffiV(float a, float b, int c, ...) |
57 { | 57 { |
58 va_list ap; | 58 va_list ap; |
59 double d, e, g, h; | 59 double d, e, g, h; |
60 int f, i; | 60 int f, i; |
61 int r; | 61 int r; |
72 r = (a == 1.f && b == 2.f && c == 3 && d == 4. && e == 5. && f == 6 && g == 7. && h == 8. && i == 9); | 72 r = (a == 1.f && b == 2.f && c == 3 && d == 4. && e == 5. && f == 6 && g == 7. && h == 8. && i == 9); |
73 printf("%f %f %d %f %f %d %f %f %d: %d", a, b, c, d, e, f, g, h, i, r); | 73 printf("%f %f %d %f %f %d %f %f %d: %d", a, b, c, d, e, f, g, h, i, r); |
74 return r; | 74 return r; |
75 } | 75 } |
76 | 76 |
77 | |
78 #if defined(DC__Feature_AggrByVal) | |
79 struct A { int i; char x[7]; long long dummy_too_big_for_regs[50]; }; /* returned via hidden ptr arg on x64/sysv */ | |
80 struct A A_cc(char a, char b) | |
81 { | |
82 int i; | |
83 struct A r = { (int)a-(int)b, { 3, a|b } }; | |
84 for(i=2; i<7; ++i) | |
85 r.x[i] = r.x[i-2]+r.x[i-1]; | |
86 printf("%d %d: ", a, b); | |
87 return r; | |
88 } | |
89 | |
90 struct B { int i; unsigned char x[7]; }; /* returned via regs on x64/sysv */ | |
91 struct B A_CC(unsigned char a, unsigned char b) | |
92 { | |
93 int i; | |
94 struct B r = { (int)a-(int)b, { 3, a|b } }; | |
95 for(i=2; i<7; ++i) | |
96 r.x[i] = r.x[i-2]+r.x[i-1]; | |
97 printf("%d %d: ", a, b); | |
98 return r; | |
99 } | |
100 #endif | |
101 | |
102 | |
77 /* main */ | 103 /* main */ |
78 | 104 |
79 int main(int argc, char* argv[]) | 105 int main(int argc, char* argv[]) |
80 { | 106 { |
81 DCCallVM* vm; | 107 DCCallVM* vm; |
89 | 115 |
90 | 116 |
91 /* calls using 'formatted' API */ | 117 /* calls using 'formatted' API */ |
92 dcReset(vm); | 118 dcReset(vm); |
93 printf("callf iii)i: "); | 119 printf("callf iii)i: "); |
94 dcCallF(vm, &ret, (void*)&vf_iii, "iii)i", 1, 2, 3); | 120 dcCallF(vm, &ret, (void*)&i_iii, "iii)i", 1, 2, 3); |
95 r = ret.i && r; | 121 r = ret.i && r; |
96 | 122 |
97 dcReset(vm); | 123 dcReset(vm); |
98 printf("\ncallf ffiffiffi)i: "); | 124 printf("\ncallf ffiffiffi)i: "); |
99 dcCallF(vm, &ret, (void*)&vf_ffiffiffi, "ffiffiffi)i", 1.f, 2.f, 3, 4.f, 5.f, 6, 7.f, 8.f, 9); | 125 dcCallF(vm, &ret, (void*)&i_ffiffiffi, "ffiffiffi)i", 1.f, 2.f, 3, 4.f, 5.f, 6, 7.f, 8.f, 9); |
100 r = ret.i && r; | 126 r = ret.i && r; |
101 | 127 |
102 /* same but with calling convention prefix */ | 128 /* same but with calling convention prefix */ |
103 dcReset(vm); | 129 dcReset(vm); |
104 printf("\ncallf _:ffiffiffi)i: "); | 130 printf("\ncallf _:ffiffiffi)i: "); |
105 dcCallF(vm, &ret, (void*)&vf_ffiffiffi, "_:ffiffiffi)i", 1.f, 2.f, 3, 4.f, 5.f, 6, 7.f, 8.f, 9); | 131 dcCallF(vm, &ret, (void*)&i_ffiffiffi, "_:ffiffiffi)i", 1.f, 2.f, 3, 4.f, 5.f, 6, 7.f, 8.f, 9); |
106 r = ret.i && r; | 132 r = ret.i && r; |
107 | 133 |
108 /* vararg call */ | 134 /* vararg call */ |
109 dcReset(vm); | 135 dcReset(vm); |
110 printf("\ncallf _effi_.ddiddi)i: "); | 136 printf("\ncallf _effi_.ddiddi)i: "); |
111 dcCallF(vm, &ret, (void*)&vf_ffiV, "_effi_.ddiddi)i", 1.f, 2.f, 3, 4., 5., 6, 7., 8., 9); | 137 dcCallF(vm, &ret, (void*)&i_ffiV, "_effi_.ddiddi)i", 1.f, 2.f, 3, 4., 5., 6, 7., 8., 9); |
112 r = ret.i && r; | 138 r = ret.i && r; |
113 | 139 |
114 /* arg binding then call using 'formatted' API */ | 140 /* arg binding then call using 'formatted' API */ |
115 dcReset(vm); | 141 dcReset(vm); |
116 /* reset calling convention too */ | 142 /* reset calling convention too */ |
117 dcMode(vm, DC_CALL_C_DEFAULT); | 143 dcMode(vm, DC_CALL_C_DEFAULT); |
118 printf("\nargf iii)i then call: "); | 144 printf("\nargf iii)i then call: "); |
119 dcArgF(vm, "iii)i", 1, 2, 3); | 145 dcArgF(vm, "iii)i", 1, 2, 3); |
120 r = r && dcCallInt(vm, (void*)&vf_iii); | 146 r = r && dcCallInt(vm, (void*)&i_iii); |
121 | 147 |
122 dcReset(vm); | 148 dcReset(vm); |
123 printf("\nargf iii then call: "); | 149 printf("\nargf iii then call: "); |
124 dcArgF(vm, "iii", 1, 2, 3); | 150 dcArgF(vm, "iii", 1, 2, 3); |
125 r = r && dcCallInt(vm, (void*)&vf_iii); | 151 r = r && dcCallInt(vm, (void*)&i_iii); |
126 | 152 |
127 dcReset(vm); | 153 dcReset(vm); |
128 printf("\nargf ffiffiffi)i then call: "); | 154 printf("\nargf ffiffiffi)i then call: "); |
129 dcArgF(vm, "ffiffiffi)i", 1.f, 2.f, 3, 4.f, 5.f, 6, 7.f, 8.f, 9); | 155 dcArgF(vm, "ffiffiffi)i", 1.f, 2.f, 3, 4.f, 5.f, 6, 7.f, 8.f, 9); |
130 r = r && dcCallInt(vm, (void*)&vf_ffiffiffi); | 156 r = r && dcCallInt(vm, (void*)&i_ffiffiffi); |
131 | 157 |
132 dcReset(vm); | 158 dcReset(vm); |
133 printf("\nargf ffiffiffi then call: "); | 159 printf("\nargf ffiffiffi then call: "); |
134 dcArgF(vm, "ffiffiffi", 1.f, 2.f, 3, 4.f, 5.f, 6, 7.f, 8.f, 9); | 160 dcArgF(vm, "ffiffiffi", 1.f, 2.f, 3, 4.f, 5.f, 6, 7.f, 8.f, 9); |
135 r = r && dcCallInt(vm, (void*)&vf_ffiffiffi); | 161 r = r && dcCallInt(vm, (void*)&i_ffiffiffi); |
136 | 162 |
137 #if defined(DC_UNIX) && !defined(DC__OS_MacOSX) && !defined(DC__OS_SunOS) && !defined(DC__OS_BeOS) | 163 #if defined(DC__Feature_Syscall) |
164 # if defined(DC_UNIX) | |
138 /* testing syscall using calling convention prefix - not available on all platforms */ | 165 /* testing syscall using calling convention prefix - not available on all platforms */ |
139 dcReset(vm); | 166 dcReset(vm); |
140 printf("\ncallf _$iZi)i"); | 167 printf("\ncallf _$iZi)i"); |
141 fflush(NULL); /* needed before syscall write as it's immediate, or order might be incorrect */ | 168 fflush(NULL); /* needed before syscall write as it's immediate, or order might be incorrect */ |
142 dcCallF(vm, &ret, (DCpointer)(ptrdiff_t)SYS_write, "_$iZi)i", 1/*stdout*/, " = syscall: 1", 13); | 169 dcCallF(vm, &ret, (DCpointer)(ptrdiff_t)SYS_write, "_$iZi)i", 1/*stdout*/, " = syscall: 1", 13); |
143 r = ret.i == 13 && r; | 170 r = ret.i == 13 && r; |
171 # else | |
172 /*@@@*/ | |
173 # endif | |
174 #endif | |
175 | |
176 #if defined(DC__Feature_AggrByVal) | |
177 /* aggregate return value test */ | |
178 { | |
179 int r_; | |
180 struct A a; | |
181 DCaggr *s = dcNewAggr(1, sizeof(struct A)); | |
182 dcAggrField(s, DC_SIGCHAR_INT, offsetof(struct A, i), 1); | |
183 dcAggrField(s, DC_SIGCHAR_CHAR, offsetof(struct A, x), 7); | |
184 dcCloseAggr(s); | |
185 | |
186 dcReset(vm); | |
187 printf("\ncallf _:cc)A (A={ic[7]l[50]}): "); | |
188 dcCallF(vm, &ret, (void*)&A_cc, "_:cc)A", 3, 16, s, &a); | |
189 r_ = ret.p == &a && a.i == -13 && a.x[0] == 3 && a.x[1] == 19 && a.x[2] == 22 && a.x[3] == 41 && a.x[4] == 63 && a.x[5] == 104 && a.x[6] == -89; | |
190 printf("%d %d %d %d %d %d %d %d: %d", a.i, a.x[0], a.x[1], a.x[2], a.x[3], a.x[4], a.x[5], a.x[6], r_); | |
191 | |
192 dcFreeAggr(s); | |
193 | |
194 r = r_ && r; | |
195 } | |
196 /* aggregate return value test */ | |
197 { | |
198 int r_; | |
199 struct B b; | |
200 DCaggr *s = dcNewAggr(1, sizeof(struct B)); | |
201 dcAggrField(s, DC_SIGCHAR_INT, offsetof(struct B, i), 1); | |
202 dcAggrField(s, DC_SIGCHAR_UCHAR, offsetof(struct B, x), 7); | |
203 dcCloseAggr(s); | |
204 | |
205 dcReset(vm); | |
206 printf("\ncallf _:cc)A (A={iC[7]}): "); | |
207 dcCallF(vm, &ret, (void*)&A_CC, "_:CC)A", 3, 16, s, &b); | |
208 r_ = ret.p == &b && b.i == -13 && b.x[0] == 3 && b.x[1] == 19 && b.x[2] == 22 && b.x[3] == 41 && b.x[4] == 63 && b.x[5] == 104 && b.x[6] == 167; | |
209 printf("%d %d %d %d %d %d %d %d: %d", b.i, b.x[0], b.x[1], b.x[2], b.x[3], b.x[4], b.x[5], b.x[6], r_); | |
210 | |
211 dcFreeAggr(s); | |
212 | |
213 r = r_ && r; | |
214 } | |
144 #endif | 215 #endif |
145 | 216 |
146 /* free vm */ | 217 /* free vm */ |
147 dcFree(vm); | 218 dcFree(vm); |
148 | 219 |