19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 /*
26 * @test
27 * @modules jdk.incubator.foreign/jdk.internal.foreign
28 * jdk.incubator.foreign/jdk.internal.foreign.abi
29 * jdk.incubator.foreign/jdk.internal.foreign.abi.x64
30 * jdk.incubator.foreign/jdk.internal.foreign.abi.x64.windows
31 * @build CallArrangerTestBase
32 * @run testng TestWindowsCallArranger
33 */
34
35 import jdk.incubator.foreign.FunctionDescriptor;
36 import jdk.incubator.foreign.MemoryAddress;
37 import jdk.incubator.foreign.MemoryLayout;
38 import jdk.incubator.foreign.MemorySegment;
39 import jdk.internal.foreign.abi.Binding;
40 import jdk.internal.foreign.abi.CallingSequence;
41 import jdk.internal.foreign.abi.x64.windows.CallArranger;
42 import org.testng.annotations.Test;
43
44 import java.lang.invoke.MethodType;
45
46 import static jdk.internal.foreign.PlatformLayouts.Win64.*;
47 import static jdk.internal.foreign.abi.Binding.*;
48 import static jdk.internal.foreign.abi.Binding.copy;
49 import static jdk.internal.foreign.abi.x64.X86_64Architecture.*;
50 import static org.testng.Assert.*;
51
52 public class TestWindowsCallArranger extends CallArrangerTestBase {
53
54 @Test
55 public void testEmpty() {
56 MethodType mt = MethodType.methodType(void.class);
57 FunctionDescriptor fd = FunctionDescriptor.ofVoid();
58 CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false);
59
60 assertFalse(bindings.isInMemoryReturn);
61 CallingSequence callingSequence = bindings.callingSequence;
62 assertEquals(callingSequence.methodType(), mt);
63 assertEquals(callingSequence.functionDesc(), fd);
64
65 checkArgumentBindings(callingSequence, new Binding[][]{});
66 checkReturnBindings(callingSequence, new Binding[]{});
67 }
68
69 @Test
70 public void testIntegerRegs() {
71 MethodType mt = MethodType.methodType(void.class, int.class, int.class, int.class, int.class);
72 FunctionDescriptor fd = FunctionDescriptor.ofVoid(C_INT, C_INT, C_INT, C_INT);
73 CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false);
74
75 assertFalse(bindings.isInMemoryReturn);
76 CallingSequence callingSequence = bindings.callingSequence;
77 assertEquals(callingSequence.methodType(), mt);
78 assertEquals(callingSequence.functionDesc(), fd);
79
80 checkArgumentBindings(callingSequence, new Binding[][]{
81 { vmStore(rcx, int.class) },
82 { vmStore(rdx, int.class) },
83 { vmStore(r8, int.class) },
84 { vmStore(r9, int.class) }
85 });
86
87 checkReturnBindings(callingSequence, new Binding[]{});
88 }
89
90 @Test
91 public void testDoubleRegs() {
92 MethodType mt = MethodType.methodType(void.class, double.class, double.class, double.class, double.class);
93 FunctionDescriptor fd = FunctionDescriptor.ofVoid(C_DOUBLE, C_DOUBLE, C_DOUBLE, C_DOUBLE);
94 CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false);
95
96 assertFalse(bindings.isInMemoryReturn);
97 CallingSequence callingSequence = bindings.callingSequence;
98 assertEquals(callingSequence.methodType(), mt);
99 assertEquals(callingSequence.functionDesc(), fd);
100
101 checkArgumentBindings(callingSequence, new Binding[][]{
102 { vmStore(xmm0, double.class) },
103 { vmStore(xmm1, double.class) },
104 { vmStore(xmm2, double.class) },
105 { vmStore(xmm3, double.class) }
106 });
107
108 checkReturnBindings(callingSequence, new Binding[]{});
109 }
110
111 @Test
112 public void testMixed() {
113 MethodType mt = MethodType.methodType(void.class,
114 long.class, long.class, float.class, float.class, long.class, long.class, float.class, float.class);
115 FunctionDescriptor fd = FunctionDescriptor.ofVoid(
116 C_LONG_LONG, C_LONG_LONG, C_FLOAT, C_FLOAT, C_LONG_LONG, C_LONG_LONG, C_FLOAT, C_FLOAT);
117 CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false);
118
119 assertFalse(bindings.isInMemoryReturn);
120 CallingSequence callingSequence = bindings.callingSequence;
121 assertEquals(callingSequence.methodType(), mt);
122 assertEquals(callingSequence.functionDesc(), fd);
123
124 checkArgumentBindings(callingSequence, new Binding[][]{
125 { vmStore(rcx, long.class) },
126 { vmStore(rdx, long.class) },
127 { vmStore(xmm2, float.class) },
128 { vmStore(xmm3, float.class) },
129 { vmStore(stackStorage(0), long.class) },
130 { vmStore(stackStorage(1), long.class) },
131 { vmStore(stackStorage(2), float.class) },
132 { vmStore(stackStorage(3), float.class) }
133 });
134
135 checkReturnBindings(callingSequence, new Binding[]{});
136 }
137
138 @Test
139 public void testAbiExample() {
140 MemoryLayout structLayout = MemoryLayout.structLayout(C_INT, C_INT, C_DOUBLE);
141 MethodType mt = MethodType.methodType(void.class,
142 int.class, int.class, MemorySegment.class, int.class, int.class,
143 double.class, double.class, double.class, int.class, int.class, int.class);
144 FunctionDescriptor fd = FunctionDescriptor.ofVoid(
145 C_INT, C_INT, structLayout, C_INT, C_INT,
146 C_DOUBLE, C_DOUBLE, C_DOUBLE, C_INT, C_INT, C_INT);
147 CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false);
148
149 assertFalse(bindings.isInMemoryReturn);
150 CallingSequence callingSequence = bindings.callingSequence;
151 assertEquals(callingSequence.methodType(), mt);
152 assertEquals(callingSequence.functionDesc(), fd);
153
154 checkArgumentBindings(callingSequence, new Binding[][]{
155 { vmStore(rcx, int.class) },
156 { vmStore(rdx, int.class) },
157 {
158 copy(structLayout),
159 unboxAddress(MemorySegment.class),
160 vmStore(r8, long.class)
161 },
162 { vmStore(r9, int.class) },
163 { vmStore(stackStorage(0), int.class) },
164 { vmStore(stackStorage(1), double.class) },
165 { vmStore(stackStorage(2), double.class) },
166 { vmStore(stackStorage(3), double.class) },
167 { vmStore(stackStorage(4), int.class) },
168 { vmStore(stackStorage(5), int.class) },
169 { vmStore(stackStorage(6), int.class) }
170 });
171
172 checkReturnBindings(callingSequence, new Binding[]{});
173 }
174
175 @Test
176 public void testAbiExampleVarargs() {
177 MethodType mt = MethodType.methodType(void.class,
178 int.class, double.class, int.class, double.class, double.class);
179 FunctionDescriptor fd = FunctionDescriptor.ofVoid(
180 C_INT, C_DOUBLE).asVariadic(C_INT, C_DOUBLE, C_DOUBLE);
181 CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false);
182
183 assertFalse(bindings.isInMemoryReturn);
184 CallingSequence callingSequence = bindings.callingSequence;
185 assertEquals(callingSequence.methodType(), mt);
186 assertEquals(callingSequence.functionDesc(), fd);
187
188 checkArgumentBindings(callingSequence, new Binding[][]{
189 { vmStore(rcx, int.class) },
190 { vmStore(xmm1, double.class) },
191 { vmStore(r8, int.class) },
192 { dup(), vmStore(r9, double.class), vmStore(xmm3, double.class) },
193 { vmStore(stackStorage(0), double.class) },
194 });
195
196 checkReturnBindings(callingSequence, new Binding[]{});
197 }
198
199 /**
200 * struct s {
201 * uint64_t u0;
202 * } s;
203 *
204 * void m(struct s s);
205 *
206 * m(s);
207 */
208 @Test
209 public void testStructRegister() {
210 MemoryLayout struct = MemoryLayout.structLayout(C_LONG_LONG);
211
212 MethodType mt = MethodType.methodType(void.class, MemorySegment.class);
213 FunctionDescriptor fd = FunctionDescriptor.ofVoid(struct);
214 CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false);
215
216 assertFalse(bindings.isInMemoryReturn);
217 CallingSequence callingSequence = bindings.callingSequence;
218 assertEquals(callingSequence.methodType(), mt);
219 assertEquals(callingSequence.functionDesc(), fd);
220
221 checkArgumentBindings(callingSequence, new Binding[][]{
222 { bufferLoad(0, long.class), vmStore(rcx, long.class) }
223 });
224
225 checkReturnBindings(callingSequence, new Binding[]{});
226 }
227
228 /**
229 * struct s {
230 * uint64_t u0, u1;
231 * } s;
232 *
233 * void m(struct s s);
234 *
235 * m(s);
236 */
237 @Test
238 public void testStructReference() {
239 MemoryLayout struct = MemoryLayout.structLayout(C_LONG_LONG, C_LONG_LONG);
240
241 MethodType mt = MethodType.methodType(void.class, MemorySegment.class);
242 FunctionDescriptor fd = FunctionDescriptor.ofVoid(struct);
243 CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false);
244
245 assertFalse(bindings.isInMemoryReturn);
246 CallingSequence callingSequence = bindings.callingSequence;
247 assertEquals(callingSequence.methodType(), mt);
248 assertEquals(callingSequence.functionDesc(), fd);
249
250 checkArgumentBindings(callingSequence, new Binding[][]{
251 {
252 copy(struct),
253 unboxAddress(MemorySegment.class),
254 vmStore(rcx, long.class)
255 }
256 });
257
258 checkReturnBindings(callingSequence, new Binding[]{});
259 }
260
261 /**
262 * typedef void (*f)(void);
263 *
264 * void m(f f);
265 * void f_impl(void);
266 *
267 * m(f_impl);
268 */
269 @Test
270 public void testMemoryAddress() {
271 MethodType mt = MethodType.methodType(void.class, MemoryAddress.class);
272 FunctionDescriptor fd = FunctionDescriptor.ofVoid(C_POINTER);
273 CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false);
274
275 assertFalse(bindings.isInMemoryReturn);
276 CallingSequence callingSequence = bindings.callingSequence;
277 assertEquals(callingSequence.methodType(), mt);
278 assertEquals(callingSequence.functionDesc(), fd);
279
280 checkArgumentBindings(callingSequence, new Binding[][]{
281 { unboxAddress(), vmStore(rcx, long.class) }
282 });
283
284 checkReturnBindings(callingSequence, new Binding[]{});
285 }
286
287 @Test
288 public void testReturnRegisterStruct() {
289 MemoryLayout struct = MemoryLayout.structLayout(C_LONG_LONG);
290
291 MethodType mt = MethodType.methodType(MemorySegment.class);
292 FunctionDescriptor fd = FunctionDescriptor.of(struct);
293 CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false);
294
295 assertFalse(bindings.isInMemoryReturn);
296 CallingSequence callingSequence = bindings.callingSequence;
297 assertEquals(callingSequence.methodType(), mt);
298 assertEquals(callingSequence.functionDesc(), fd);
299
300 checkArgumentBindings(callingSequence, new Binding[][]{});
301
302 checkReturnBindings(callingSequence,
303 new Binding[]{ allocate(struct),
304 dup(),
305 vmLoad(rax, long.class),
306 bufferStore(0, long.class) });
307 }
308
309 @Test
310 public void testIMR() {
311 MemoryLayout struct = MemoryLayout.structLayout(C_LONG_LONG, C_LONG_LONG);
312
313 MethodType mt = MethodType.methodType(MemorySegment.class);
314 FunctionDescriptor fd = FunctionDescriptor.of(struct);
315 CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false);
316
317 assertTrue(bindings.isInMemoryReturn);
318 CallingSequence callingSequence = bindings.callingSequence;
319 assertEquals(callingSequence.methodType(), MethodType.methodType(void.class, MemoryAddress.class));
320 assertEquals(callingSequence.functionDesc(), FunctionDescriptor.ofVoid(C_POINTER));
321
322 checkArgumentBindings(callingSequence, new Binding[][]{
323 { unboxAddress(), vmStore(rcx, long.class) }
324 });
325
326 checkReturnBindings(callingSequence, new Binding[]{});
327 }
328
329 @Test
330 public void testStackStruct() {
331 MemoryLayout struct = MemoryLayout.structLayout(C_POINTER, C_DOUBLE, C_INT);
332
333 MethodType mt = MethodType.methodType(void.class,
334 MemorySegment.class, int.class, double.class, MemoryAddress.class,
335 MemorySegment.class, int.class, double.class, MemoryAddress.class,
336 MemorySegment.class, int.class, double.class, MemoryAddress.class,
337 MemorySegment.class, int.class, double.class, MemoryAddress.class);
338 FunctionDescriptor fd = FunctionDescriptor.ofVoid(
339 struct, C_INT, C_DOUBLE, C_POINTER,
340 struct, C_INT, C_DOUBLE, C_POINTER,
341 struct, C_INT, C_DOUBLE, C_POINTER,
342 struct, C_INT, C_DOUBLE, C_POINTER);
343 CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false);
344
345 assertFalse(bindings.isInMemoryReturn);
346 CallingSequence callingSequence = bindings.callingSequence;
347 assertEquals(callingSequence.methodType(), mt);
348 assertEquals(callingSequence.functionDesc(), fd);
349
350 checkArgumentBindings(callingSequence, new Binding[][]{
351 { copy(struct), unboxAddress(MemorySegment.class), vmStore(rcx, long.class) },
352 { vmStore(rdx, int.class) },
353 { vmStore(xmm2, double.class) },
354 { unboxAddress(), vmStore(r9, long.class) },
355 { copy(struct), unboxAddress(MemorySegment.class), vmStore(stackStorage(0), long.class) },
356 { vmStore(stackStorage(1), int.class) },
357 { vmStore(stackStorage(2), double.class) },
358 { unboxAddress(), vmStore(stackStorage(3), long.class) },
359 { copy(struct), unboxAddress(MemorySegment.class), vmStore(stackStorage(4), long.class) },
360 { vmStore(stackStorage(5), int.class) },
361 { vmStore(stackStorage(6), double.class) },
362 { unboxAddress(), vmStore(stackStorage(7), long.class) },
363 { copy(struct), unboxAddress(MemorySegment.class), vmStore(stackStorage(8), long.class) },
364 { vmStore(stackStorage(9), int.class) },
365 { vmStore(stackStorage(10), double.class) },
366 { unboxAddress(), vmStore(stackStorage(11), long.class) },
367 });
368
369 checkReturnBindings(callingSequence, new Binding[]{});
370 }
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 /*
26 * @test
27 * @modules jdk.incubator.foreign/jdk.internal.foreign
28 * jdk.incubator.foreign/jdk.internal.foreign.abi
29 * jdk.incubator.foreign/jdk.internal.foreign.abi.x64
30 * jdk.incubator.foreign/jdk.internal.foreign.abi.x64.windows
31 * @build CallArrangerTestBase
32 * @run testng TestWindowsCallArranger
33 */
34
35 import jdk.incubator.foreign.FunctionDescriptor;
36 import jdk.incubator.foreign.MemoryAddress;
37 import jdk.incubator.foreign.MemoryLayout;
38 import jdk.incubator.foreign.MemorySegment;
39 import jdk.incubator.foreign.NativeSymbol;
40 import jdk.internal.foreign.abi.Binding;
41 import jdk.internal.foreign.abi.CallingSequence;
42 import jdk.internal.foreign.abi.x64.windows.CallArranger;
43 import org.testng.annotations.Test;
44
45 import java.lang.invoke.MethodType;
46
47 import static jdk.incubator.foreign.ValueLayout.ADDRESS;
48 import static jdk.internal.foreign.PlatformLayouts.Win64.*;
49 import static jdk.internal.foreign.abi.Binding.*;
50 import static jdk.internal.foreign.abi.Binding.copy;
51 import static jdk.internal.foreign.abi.x64.X86_64Architecture.*;
52 import static org.testng.Assert.*;
53
54 public class TestWindowsCallArranger extends CallArrangerTestBase {
55
56 @Test
57 public void testEmpty() {
58 MethodType mt = MethodType.methodType(void.class);
59 FunctionDescriptor fd = FunctionDescriptor.ofVoid();
60 CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false);
61
62 assertFalse(bindings.isInMemoryReturn);
63 CallingSequence callingSequence = bindings.callingSequence;
64 assertEquals(callingSequence.methodType(), mt.insertParameterTypes(0, NativeSymbol.class));
65 assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS));
66
67 checkArgumentBindings(callingSequence, new Binding[][]{
68 { unboxAddress(NativeSymbol.class), vmStore(r10, long.class) }
69 });
70 checkReturnBindings(callingSequence, new Binding[]{});
71 }
72
73 @Test
74 public void testIntegerRegs() {
75 MethodType mt = MethodType.methodType(void.class, int.class, int.class, int.class, int.class);
76 FunctionDescriptor fd = FunctionDescriptor.ofVoid(C_INT, C_INT, C_INT, C_INT);
77 CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false);
78
79 assertFalse(bindings.isInMemoryReturn);
80 CallingSequence callingSequence = bindings.callingSequence;
81 assertEquals(callingSequence.methodType(), mt.insertParameterTypes(0, NativeSymbol.class));
82 assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS));
83
84 checkArgumentBindings(callingSequence, new Binding[][]{
85 { unboxAddress(NativeSymbol.class), vmStore(r10, long.class) },
86 { vmStore(rcx, int.class) },
87 { vmStore(rdx, int.class) },
88 { vmStore(r8, int.class) },
89 { vmStore(r9, int.class) }
90 });
91
92 checkReturnBindings(callingSequence, new Binding[]{});
93 }
94
95 @Test
96 public void testDoubleRegs() {
97 MethodType mt = MethodType.methodType(void.class, double.class, double.class, double.class, double.class);
98 FunctionDescriptor fd = FunctionDescriptor.ofVoid(C_DOUBLE, C_DOUBLE, C_DOUBLE, C_DOUBLE);
99 CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false);
100
101 assertFalse(bindings.isInMemoryReturn);
102 CallingSequence callingSequence = bindings.callingSequence;
103 assertEquals(callingSequence.methodType(), mt.insertParameterTypes(0, NativeSymbol.class));
104 assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS));
105
106 checkArgumentBindings(callingSequence, new Binding[][]{
107 { unboxAddress(NativeSymbol.class), vmStore(r10, long.class) },
108 { vmStore(xmm0, double.class) },
109 { vmStore(xmm1, double.class) },
110 { vmStore(xmm2, double.class) },
111 { vmStore(xmm3, double.class) }
112 });
113
114 checkReturnBindings(callingSequence, new Binding[]{});
115 }
116
117 @Test
118 public void testMixed() {
119 MethodType mt = MethodType.methodType(void.class,
120 long.class, long.class, float.class, float.class, long.class, long.class, float.class, float.class);
121 FunctionDescriptor fd = FunctionDescriptor.ofVoid(
122 C_LONG_LONG, C_LONG_LONG, C_FLOAT, C_FLOAT, C_LONG_LONG, C_LONG_LONG, C_FLOAT, C_FLOAT);
123 CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false);
124
125 assertFalse(bindings.isInMemoryReturn);
126 CallingSequence callingSequence = bindings.callingSequence;
127 assertEquals(callingSequence.methodType(), mt.insertParameterTypes(0, NativeSymbol.class));
128 assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS));
129
130 checkArgumentBindings(callingSequence, new Binding[][]{
131 { unboxAddress(NativeSymbol.class), vmStore(r10, long.class) },
132 { vmStore(rcx, long.class) },
133 { vmStore(rdx, long.class) },
134 { vmStore(xmm2, float.class) },
135 { vmStore(xmm3, float.class) },
136 { vmStore(stackStorage(0), long.class) },
137 { vmStore(stackStorage(1), long.class) },
138 { vmStore(stackStorage(2), float.class) },
139 { vmStore(stackStorage(3), float.class) }
140 });
141
142 checkReturnBindings(callingSequence, new Binding[]{});
143 }
144
145 @Test
146 public void testAbiExample() {
147 MemoryLayout structLayout = MemoryLayout.structLayout(C_INT, C_INT, C_DOUBLE);
148 MethodType mt = MethodType.methodType(void.class,
149 int.class, int.class, MemorySegment.class, int.class, int.class,
150 double.class, double.class, double.class, int.class, int.class, int.class);
151 FunctionDescriptor fd = FunctionDescriptor.ofVoid(
152 C_INT, C_INT, structLayout, C_INT, C_INT,
153 C_DOUBLE, C_DOUBLE, C_DOUBLE, C_INT, C_INT, C_INT);
154 CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false);
155
156 assertFalse(bindings.isInMemoryReturn);
157 CallingSequence callingSequence = bindings.callingSequence;
158 assertEquals(callingSequence.methodType(), mt.insertParameterTypes(0, NativeSymbol.class));
159 assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS));
160
161 checkArgumentBindings(callingSequence, new Binding[][]{
162 { unboxAddress(NativeSymbol.class), vmStore(r10, long.class) },
163 { vmStore(rcx, int.class) },
164 { vmStore(rdx, int.class) },
165 {
166 copy(structLayout),
167 unboxAddress(MemorySegment.class),
168 vmStore(r8, long.class)
169 },
170 { vmStore(r9, int.class) },
171 { vmStore(stackStorage(0), int.class) },
172 { vmStore(stackStorage(1), double.class) },
173 { vmStore(stackStorage(2), double.class) },
174 { vmStore(stackStorage(3), double.class) },
175 { vmStore(stackStorage(4), int.class) },
176 { vmStore(stackStorage(5), int.class) },
177 { vmStore(stackStorage(6), int.class) }
178 });
179
180 checkReturnBindings(callingSequence, new Binding[]{});
181 }
182
183 @Test
184 public void testAbiExampleVarargs() {
185 MethodType mt = MethodType.methodType(void.class,
186 int.class, double.class, int.class, double.class, double.class);
187 FunctionDescriptor fd = FunctionDescriptor.ofVoid(
188 C_INT, C_DOUBLE).asVariadic(C_INT, C_DOUBLE, C_DOUBLE);
189 FunctionDescriptor fdExpected = FunctionDescriptor.ofVoid(
190 ADDRESS, C_INT, C_DOUBLE).asVariadic(C_INT, C_DOUBLE, C_DOUBLE);
191 CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false);
192
193 assertFalse(bindings.isInMemoryReturn);
194 CallingSequence callingSequence = bindings.callingSequence;
195 assertEquals(callingSequence.methodType(), mt.insertParameterTypes(0, NativeSymbol.class));
196 assertEquals(callingSequence.functionDesc(), fdExpected);
197
198 checkArgumentBindings(callingSequence, new Binding[][]{
199 { unboxAddress(NativeSymbol.class), vmStore(r10, long.class) },
200 { vmStore(rcx, int.class) },
201 { vmStore(xmm1, double.class) },
202 { vmStore(r8, int.class) },
203 { dup(), vmStore(r9, double.class), vmStore(xmm3, double.class) },
204 { vmStore(stackStorage(0), double.class) },
205 });
206
207 checkReturnBindings(callingSequence, new Binding[]{});
208 }
209
210 /**
211 * struct s {
212 * uint64_t u0;
213 * } s;
214 *
215 * void m(struct s s);
216 *
217 * m(s);
218 */
219 @Test
220 public void testStructRegister() {
221 MemoryLayout struct = MemoryLayout.structLayout(C_LONG_LONG);
222
223 MethodType mt = MethodType.methodType(void.class, MemorySegment.class);
224 FunctionDescriptor fd = FunctionDescriptor.ofVoid(struct);
225 CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false);
226
227 assertFalse(bindings.isInMemoryReturn);
228 CallingSequence callingSequence = bindings.callingSequence;
229 assertEquals(callingSequence.methodType(), mt.insertParameterTypes(0, NativeSymbol.class));
230 assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS));
231
232 checkArgumentBindings(callingSequence, new Binding[][]{
233 { unboxAddress(NativeSymbol.class), vmStore(r10, long.class) },
234 { bufferLoad(0, long.class), vmStore(rcx, long.class) }
235 });
236
237 checkReturnBindings(callingSequence, new Binding[]{});
238 }
239
240 /**
241 * struct s {
242 * uint64_t u0, u1;
243 * } s;
244 *
245 * void m(struct s s);
246 *
247 * m(s);
248 */
249 @Test
250 public void testStructReference() {
251 MemoryLayout struct = MemoryLayout.structLayout(C_LONG_LONG, C_LONG_LONG);
252
253 MethodType mt = MethodType.methodType(void.class, MemorySegment.class);
254 FunctionDescriptor fd = FunctionDescriptor.ofVoid(struct);
255 CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false);
256
257 assertFalse(bindings.isInMemoryReturn);
258 CallingSequence callingSequence = bindings.callingSequence;
259 assertEquals(callingSequence.methodType(), mt.insertParameterTypes(0, NativeSymbol.class));
260 assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS));
261
262 checkArgumentBindings(callingSequence, new Binding[][]{
263 { unboxAddress(NativeSymbol.class), vmStore(r10, long.class) },
264 {
265 copy(struct),
266 unboxAddress(MemorySegment.class),
267 vmStore(rcx, long.class)
268 }
269 });
270
271 checkReturnBindings(callingSequence, new Binding[]{});
272 }
273
274 /**
275 * typedef void (*f)(void);
276 *
277 * void m(f f);
278 * void f_impl(void);
279 *
280 * m(f_impl);
281 */
282 @Test
283 public void testMemoryAddress() {
284 MethodType mt = MethodType.methodType(void.class, MemoryAddress.class);
285 FunctionDescriptor fd = FunctionDescriptor.ofVoid(C_POINTER);
286 CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false);
287
288 assertFalse(bindings.isInMemoryReturn);
289 CallingSequence callingSequence = bindings.callingSequence;
290 assertEquals(callingSequence.methodType(), mt.insertParameterTypes(0, NativeSymbol.class));
291 assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS));
292
293 checkArgumentBindings(callingSequence, new Binding[][]{
294 { unboxAddress(NativeSymbol.class), vmStore(r10, long.class) },
295 { unboxAddress(), vmStore(rcx, long.class) }
296 });
297
298 checkReturnBindings(callingSequence, new Binding[]{});
299 }
300
301 @Test
302 public void testReturnRegisterStruct() {
303 MemoryLayout struct = MemoryLayout.structLayout(C_LONG_LONG);
304
305 MethodType mt = MethodType.methodType(MemorySegment.class);
306 FunctionDescriptor fd = FunctionDescriptor.of(struct);
307 CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false);
308
309 assertFalse(bindings.isInMemoryReturn);
310 CallingSequence callingSequence = bindings.callingSequence;
311 assertEquals(callingSequence.methodType(), mt.insertParameterTypes(0, NativeSymbol.class));
312 assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS));
313
314 checkArgumentBindings(callingSequence, new Binding[][]{
315 { unboxAddress(NativeSymbol.class), vmStore(r10, long.class) },
316 });
317
318 checkReturnBindings(callingSequence,
319 new Binding[]{ allocate(struct),
320 dup(),
321 vmLoad(rax, long.class),
322 bufferStore(0, long.class) });
323 }
324
325 @Test
326 public void testIMR() {
327 MemoryLayout struct = MemoryLayout.structLayout(C_LONG_LONG, C_LONG_LONG);
328
329 MethodType mt = MethodType.methodType(MemorySegment.class);
330 FunctionDescriptor fd = FunctionDescriptor.of(struct);
331 CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false);
332
333 assertTrue(bindings.isInMemoryReturn);
334 CallingSequence callingSequence = bindings.callingSequence;
335 assertEquals(callingSequence.methodType(), MethodType.methodType(void.class, NativeSymbol.class, MemoryAddress.class));
336 assertEquals(callingSequence.functionDesc(), FunctionDescriptor.ofVoid(ADDRESS, C_POINTER));
337
338 checkArgumentBindings(callingSequence, new Binding[][]{
339 { unboxAddress(NativeSymbol.class), vmStore(r10, long.class) },
340 { unboxAddress(), vmStore(rcx, long.class) }
341 });
342
343 checkReturnBindings(callingSequence, new Binding[]{});
344 }
345
346 @Test
347 public void testStackStruct() {
348 MemoryLayout struct = MemoryLayout.structLayout(C_POINTER, C_DOUBLE, C_INT);
349
350 MethodType mt = MethodType.methodType(void.class,
351 MemorySegment.class, int.class, double.class, MemoryAddress.class,
352 MemorySegment.class, int.class, double.class, MemoryAddress.class,
353 MemorySegment.class, int.class, double.class, MemoryAddress.class,
354 MemorySegment.class, int.class, double.class, MemoryAddress.class);
355 FunctionDescriptor fd = FunctionDescriptor.ofVoid(
356 struct, C_INT, C_DOUBLE, C_POINTER,
357 struct, C_INT, C_DOUBLE, C_POINTER,
358 struct, C_INT, C_DOUBLE, C_POINTER,
359 struct, C_INT, C_DOUBLE, C_POINTER);
360 CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false);
361
362 assertFalse(bindings.isInMemoryReturn);
363 CallingSequence callingSequence = bindings.callingSequence;
364 assertEquals(callingSequence.methodType(), mt.insertParameterTypes(0, NativeSymbol.class));
365 assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS));
366
367 checkArgumentBindings(callingSequence, new Binding[][]{
368 { unboxAddress(NativeSymbol.class), vmStore(r10, long.class) },
369 { copy(struct), unboxAddress(MemorySegment.class), vmStore(rcx, long.class) },
370 { vmStore(rdx, int.class) },
371 { vmStore(xmm2, double.class) },
372 { unboxAddress(), vmStore(r9, long.class) },
373 { copy(struct), unboxAddress(MemorySegment.class), vmStore(stackStorage(0), long.class) },
374 { vmStore(stackStorage(1), int.class) },
375 { vmStore(stackStorage(2), double.class) },
376 { unboxAddress(), vmStore(stackStorage(3), long.class) },
377 { copy(struct), unboxAddress(MemorySegment.class), vmStore(stackStorage(4), long.class) },
378 { vmStore(stackStorage(5), int.class) },
379 { vmStore(stackStorage(6), double.class) },
380 { unboxAddress(), vmStore(stackStorage(7), long.class) },
381 { copy(struct), unboxAddress(MemorySegment.class), vmStore(stackStorage(8), long.class) },
382 { vmStore(stackStorage(9), int.class) },
383 { vmStore(stackStorage(10), double.class) },
384 { unboxAddress(), vmStore(stackStorage(11), long.class) },
385 });
386
387 checkReturnBindings(callingSequence, new Binding[]{});
388 }
|