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.sysv
31 * @build CallArrangerTestBase
32 * @run testng TestSysVCallArranger
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.sysv.CallArranger;
42 import org.testng.annotations.DataProvider;
43 import org.testng.annotations.Test;
44
45 import java.lang.invoke.MethodType;
46
47 import static jdk.internal.foreign.PlatformLayouts.SysV.*;
48 import static jdk.internal.foreign.abi.Binding.*;
49 import static jdk.internal.foreign.abi.x64.X86_64Architecture.*;
50 import static org.testng.Assert.assertEquals;
51 import static org.testng.Assert.assertFalse;
52 import static org.testng.Assert.assertTrue;
53
54 public class TestSysVCallArranger 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.appendParameterTypes(long.class));
65 assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG));
66
67 checkArgumentBindings(callingSequence, new Binding[][]{
68 { vmStore(rax, long.class) }
69 });
70
71 checkReturnBindings(callingSequence, new Binding[]{});
72
73 assertEquals(bindings.nVectorArgs, 0);
74 }
75
76 @Test
77 public void testNestedStructs() {
78 MemoryLayout POINT = MemoryLayout.structLayout(
79 C_INT,
80 MemoryLayout.structLayout(
81 C_INT,
82 C_INT
83 )
84 );
85 MethodType mt = MethodType.methodType(void.class, MemorySegment.class);
86 FunctionDescriptor fd = FunctionDescriptor.ofVoid(POINT);
87 CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false);
88
89 assertFalse(bindings.isInMemoryReturn);
90 CallingSequence callingSequence = bindings.callingSequence;
91 assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class));
92 assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG));
93
94 checkArgumentBindings(callingSequence, new Binding[][]{
95 { dup(), bufferLoad(0, long.class), vmStore(rdi, long.class),
96 bufferLoad(8, int.class), vmStore(rsi, int.class)},
97 { vmStore(rax, long.class) },
98 });
99
100 checkReturnBindings(callingSequence, new Binding[]{});
101
102 assertEquals(bindings.nVectorArgs, 0);
103 }
104
105 @Test
106 public void testNestedUnion() {
107 MemoryLayout POINT = MemoryLayout.structLayout(
108 C_INT,
109 MemoryLayout.paddingLayout(32),
110 MemoryLayout.unionLayout(
111 MemoryLayout.structLayout(C_INT, C_INT),
112 C_LONG
113 )
114 );
115 MethodType mt = MethodType.methodType(void.class, MemorySegment.class);
116 FunctionDescriptor fd = FunctionDescriptor.ofVoid(POINT);
117 CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false);
118
119 assertFalse(bindings.isInMemoryReturn);
120 CallingSequence callingSequence = bindings.callingSequence;
121 assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class));
122 assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG));
123
124 checkArgumentBindings(callingSequence, new Binding[][]{
125 { dup(), bufferLoad(0, long.class), vmStore(rdi, long.class),
126 bufferLoad(8, long.class), vmStore(rsi, long.class)},
127 { vmStore(rax, long.class) },
128 });
129
130 checkReturnBindings(callingSequence, new Binding[]{});
131
132 assertEquals(bindings.nVectorArgs, 0);
133 }
134
135 @Test
136 public void testNestedStructsUnaligned() {
137 MemoryLayout POINT = MemoryLayout.structLayout(
138 C_INT,
139 MemoryLayout.structLayout(
140 C_LONG,
141 C_INT
142 )
143 );
144 MethodType mt = MethodType.methodType(void.class, MemorySegment.class);
145 FunctionDescriptor fd = FunctionDescriptor.ofVoid(POINT);
146 CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false);
147
148 assertFalse(bindings.isInMemoryReturn);
149 CallingSequence callingSequence = bindings.callingSequence;
150 assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class));
151 assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG));
152
153 checkArgumentBindings(callingSequence, new Binding[][]{
154 { dup(), bufferLoad(0, long.class), vmStore(stackStorage(0), long.class),
155 bufferLoad(8, long.class), vmStore(stackStorage(1), long.class)},
156 { vmStore(rax, long.class) },
157 });
158
159 checkReturnBindings(callingSequence, new Binding[]{});
160
161 assertEquals(bindings.nVectorArgs, 0);
162 }
163
164 @Test
165 public void testNestedUnionUnaligned() {
166 MemoryLayout POINT = MemoryLayout.structLayout(
167 C_INT,
168 MemoryLayout.unionLayout(
169 MemoryLayout.structLayout(C_INT, C_INT),
170 C_LONG
171 )
172 );
173 MethodType mt = MethodType.methodType(void.class, MemorySegment.class);
174 FunctionDescriptor fd = FunctionDescriptor.ofVoid(POINT);
175 CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false);
176
177 assertFalse(bindings.isInMemoryReturn);
178 CallingSequence callingSequence = bindings.callingSequence;
179 assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class));
180 assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG));
181
182 checkArgumentBindings(callingSequence, new Binding[][]{
183 { dup(), bufferLoad(0, long.class), vmStore(stackStorage(0), long.class),
184 bufferLoad(8, int.class), vmStore(stackStorage(1), int.class)},
185 { vmStore(rax, long.class) },
186 });
187
188 checkReturnBindings(callingSequence, new Binding[]{});
189
190 assertEquals(bindings.nVectorArgs, 0);
191 }
192
193 @Test
194 public void testIntegerRegs() {
195 MethodType mt = MethodType.methodType(void.class,
196 int.class, int.class, int.class, int.class, int.class, int.class);
197 FunctionDescriptor fd = FunctionDescriptor.ofVoid(
198 C_INT, C_INT, C_INT, C_INT, C_INT, C_INT);
199 CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false);
200
201 assertFalse(bindings.isInMemoryReturn);
202 CallingSequence callingSequence = bindings.callingSequence;
203 assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class));
204 assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG));
205
206 checkArgumentBindings(callingSequence, new Binding[][]{
207 { vmStore(rdi, int.class) },
208 { vmStore(rsi, int.class) },
209 { vmStore(rdx, int.class) },
210 { vmStore(rcx, int.class) },
211 { vmStore(r8, int.class) },
212 { vmStore(r9, int.class) },
213 { vmStore(rax, long.class) },
214 });
215
216 checkReturnBindings(callingSequence, new Binding[]{});
217
218 assertEquals(bindings.nVectorArgs, 0);
219 }
220
221 @Test
222 public void testDoubleRegs() {
223 MethodType mt = MethodType.methodType(void.class,
224 double.class, double.class, double.class, double.class,
225 double.class, double.class, double.class, double.class);
226 FunctionDescriptor fd = FunctionDescriptor.ofVoid(
227 C_DOUBLE, C_DOUBLE, C_DOUBLE, C_DOUBLE,
228 C_DOUBLE, C_DOUBLE, C_DOUBLE, C_DOUBLE);
229 CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false);
230
231 assertFalse(bindings.isInMemoryReturn);
232 CallingSequence callingSequence = bindings.callingSequence;
233 assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class));
234 assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG));
235
236 checkArgumentBindings(callingSequence, new Binding[][]{
237 { vmStore(xmm0, double.class) },
238 { vmStore(xmm1, double.class) },
239 { vmStore(xmm2, double.class) },
240 { vmStore(xmm3, double.class) },
241 { vmStore(xmm4, double.class) },
242 { vmStore(xmm5, double.class) },
243 { vmStore(xmm6, double.class) },
244 { vmStore(xmm7, double.class) },
245 { vmStore(rax, long.class) },
246 });
247
248 checkReturnBindings(callingSequence, new Binding[]{});
249
250 assertEquals(bindings.nVectorArgs, 8);
251 }
252
253 @Test
254 public void testMixed() {
255 MethodType mt = MethodType.methodType(void.class,
256 long.class, long.class, long.class, long.class, long.class, long.class, long.class, long.class,
257 float.class, float.class, float.class, float.class,
258 float.class, float.class, float.class, float.class, float.class, float.class);
259 FunctionDescriptor fd = FunctionDescriptor.ofVoid(
260 C_LONG, C_LONG, C_LONG, C_LONG, C_LONG, C_LONG, C_LONG, C_LONG,
261 C_FLOAT, C_FLOAT, C_FLOAT, C_FLOAT,
262 C_FLOAT, C_FLOAT, C_FLOAT, C_FLOAT, C_FLOAT, C_FLOAT);
263 CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false);
264
265 assertFalse(bindings.isInMemoryReturn);
266 CallingSequence callingSequence = bindings.callingSequence;
267 assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class));
268 assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG));
269
270 checkArgumentBindings(callingSequence, new Binding[][]{
271 { vmStore(rdi, long.class) },
272 { vmStore(rsi, long.class) },
273 { vmStore(rdx, long.class) },
274 { vmStore(rcx, long.class) },
275 { vmStore(r8, long.class) },
276 { vmStore(r9, long.class) },
277 { vmStore(stackStorage(0), long.class) },
278 { vmStore(stackStorage(1), long.class) },
279 { vmStore(xmm0, float.class) },
280 { vmStore(xmm1, float.class) },
281 { vmStore(xmm2, float.class) },
282 { vmStore(xmm3, float.class) },
283 { vmStore(xmm4, float.class) },
284 { vmStore(xmm5, float.class) },
285 { vmStore(xmm6, float.class) },
286 { vmStore(xmm7, float.class) },
287 { vmStore(stackStorage(2), float.class) },
288 { vmStore(stackStorage(3), float.class) },
289 { vmStore(rax, long.class) },
290 });
303 * int32_t e, f, g, h, i, j, k;
304 * double m, n;
305 *
306 * void m(e, f, s, g, h, m, n, i, j, k);
307 *
308 * m(s);
309 */
310 @Test
311 public void testAbiExample() {
312 MemoryLayout struct = MemoryLayout.structLayout(C_INT, C_INT, C_DOUBLE);
313
314 MethodType mt = MethodType.methodType(void.class,
315 int.class, int.class, MemorySegment.class, int.class, int.class,
316 double.class, double.class, int.class, int.class, int.class);
317 FunctionDescriptor fd = FunctionDescriptor.ofVoid(
318 C_INT, C_INT, struct, C_INT, C_INT, C_DOUBLE, C_DOUBLE, C_INT, C_INT, C_INT);
319 CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false);
320
321 assertFalse(bindings.isInMemoryReturn);
322 CallingSequence callingSequence = bindings.callingSequence;
323 assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class));
324 assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG));
325
326 checkArgumentBindings(callingSequence, new Binding[][]{
327 { vmStore(rdi, int.class) },
328 { vmStore(rsi, int.class) },
329 {
330 dup(),
331 bufferLoad(0, long.class), vmStore(rdx, long.class),
332 bufferLoad(8, double.class), vmStore(xmm0, double.class)
333 },
334 { vmStore(rcx, int.class) },
335 { vmStore(r8, int.class) },
336 { vmStore(xmm1, double.class) },
337 { vmStore(xmm2, double.class) },
338 { vmStore(r9, int.class) },
339 { vmStore(stackStorage(0), int.class) },
340 { vmStore(stackStorage(1), int.class) },
341 { vmStore(rax, long.class) },
342 });
343
344 checkReturnBindings(callingSequence, new Binding[]{});
345
346 assertEquals(bindings.nVectorArgs, 3);
347 }
348
349 /**
350 * typedef void (*f)(void);
351 *
352 * void m(f f);
353 * void f_impl(void);
354 *
355 * m(f_impl);
356 */
357 @Test
358 public void testMemoryAddress() {
359 MethodType mt = MethodType.methodType(void.class, MemoryAddress.class);
360 FunctionDescriptor fd = FunctionDescriptor.ofVoid( C_POINTER);
361 CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false);
362
363 assertFalse(bindings.isInMemoryReturn);
364 CallingSequence callingSequence = bindings.callingSequence;
365 assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class));
366 assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG));
367
368 checkArgumentBindings(callingSequence, new Binding[][]{
369 { unboxAddress(), vmStore(rdi, long.class) },
370 { vmStore(rax, long.class) },
371 });
372
373 checkReturnBindings(callingSequence, new Binding[]{});
374
375 assertEquals(bindings.nVectorArgs, 0);
376 }
377
378 @Test(dataProvider = "structs")
379 public void testStruct(MemoryLayout struct, Binding[] expectedBindings) {
380 MethodType mt = MethodType.methodType(void.class, MemorySegment.class);
381 FunctionDescriptor fd = FunctionDescriptor.ofVoid(struct);
382 CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false);
383
384 assertFalse(bindings.isInMemoryReturn);
385 CallingSequence callingSequence = bindings.callingSequence;
386 assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class));
387 assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG));
388
389 checkArgumentBindings(callingSequence, new Binding[][]{
390 expectedBindings,
391 { vmStore(rax, long.class) },
392 });
393
394 checkReturnBindings(callingSequence, new Binding[]{});
395
396 assertEquals(bindings.nVectorArgs, 0);
397 }
398
399
400 @DataProvider
401 public static Object[][] structs() {
402 return new Object[][]{
403 { MemoryLayout.structLayout(C_LONG), new Binding[]{
404 bufferLoad(0, long.class), vmStore(rdi, long.class)
405 }
406 },
407 { MemoryLayout.structLayout(C_LONG, C_LONG), new Binding[]{
408 dup(),
409 bufferLoad(0, long.class), vmStore(rdi, long.class),
424 dup(),
425 bufferLoad(8, long.class), vmStore(stackStorage(1), long.class),
426 dup(),
427 bufferLoad(16, long.class), vmStore(stackStorage(2), long.class),
428 bufferLoad(24, long.class), vmStore(stackStorage(3), long.class)
429 }
430 },
431 };
432 }
433
434 @Test
435 public void testReturnRegisterStruct() {
436 MemoryLayout struct = MemoryLayout.structLayout(C_LONG, C_LONG);
437
438 MethodType mt = MethodType.methodType(MemorySegment.class);
439 FunctionDescriptor fd = FunctionDescriptor.of(struct);
440 CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false);
441
442 assertFalse(bindings.isInMemoryReturn);
443 CallingSequence callingSequence = bindings.callingSequence;
444 assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class));
445 assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG));
446
447 checkArgumentBindings(callingSequence, new Binding[][]{
448 { vmStore(rax, long.class) }
449 });
450
451 checkReturnBindings(callingSequence, new Binding[] {
452 allocate(struct),
453 dup(),
454 vmLoad(rax, long.class),
455 bufferStore(0, long.class),
456 dup(),
457 vmLoad(rdx, long.class),
458 bufferStore(8, long.class)
459 });
460
461 assertEquals(bindings.nVectorArgs, 0);
462 }
463
464 @Test
465 public void testIMR() {
466 MemoryLayout struct = MemoryLayout.structLayout(C_LONG, C_LONG, C_LONG);
467
468 MethodType mt = MethodType.methodType(MemorySegment.class);
469 FunctionDescriptor fd = FunctionDescriptor.of(struct);
470 CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false);
471
472 assertTrue(bindings.isInMemoryReturn);
473 CallingSequence callingSequence = bindings.callingSequence;
474 assertEquals(callingSequence.methodType(), MethodType.methodType(void.class, MemoryAddress.class, long.class));
475 assertEquals(callingSequence.functionDesc(), FunctionDescriptor.ofVoid(C_POINTER, C_LONG));
476
477 checkArgumentBindings(callingSequence, new Binding[][]{
478 { unboxAddress(), vmStore(rdi, long.class) },
479 { vmStore(rax, long.class) }
480 });
481
482 checkReturnBindings(callingSequence, new Binding[] {});
483
484 assertEquals(bindings.nVectorArgs, 0);
485 }
486
487 @Test
488 public void testFloatStructsUpcall() {
489 MemoryLayout struct = MemoryLayout.structLayout(C_FLOAT); // should be passed in float regs
490
491 MethodType mt = MethodType.methodType(MemorySegment.class, MemorySegment.class);
492 FunctionDescriptor fd = FunctionDescriptor.of(struct, struct);
493 CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, true);
494
495 assertFalse(bindings.isInMemoryReturn);
496 CallingSequence callingSequence = bindings.callingSequence;
497 assertEquals(callingSequence.methodType(), mt);
|
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.sysv
31 * @build CallArrangerTestBase
32 * @run testng TestSysVCallArranger
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.sysv.CallArranger;
43 import org.testng.annotations.DataProvider;
44 import org.testng.annotations.Test;
45
46 import java.lang.invoke.MethodType;
47
48 import static jdk.incubator.foreign.ValueLayout.ADDRESS;
49 import static jdk.internal.foreign.PlatformLayouts.SysV.*;
50 import static jdk.internal.foreign.abi.Binding.*;
51 import static jdk.internal.foreign.abi.x64.X86_64Architecture.*;
52 import static org.testng.Assert.assertEquals;
53 import static org.testng.Assert.assertFalse;
54 import static org.testng.Assert.assertTrue;
55
56 public class TestSysVCallArranger extends CallArrangerTestBase {
57
58 @Test
59 public void testEmpty() {
60 MethodType mt = MethodType.methodType(void.class);
61 FunctionDescriptor fd = FunctionDescriptor.ofVoid();
62 CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false);
63
64 assertFalse(bindings.isInMemoryReturn);
65 CallingSequence callingSequence = bindings.callingSequence;
66 assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, NativeSymbol.class));
67 assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG).insertArgumentLayouts(0, ADDRESS));
68
69 checkArgumentBindings(callingSequence, new Binding[][]{
70 { unboxAddress(NativeSymbol.class), vmStore(r10, long.class) },
71 { vmStore(rax, long.class) }
72 });
73
74 checkReturnBindings(callingSequence, new Binding[]{});
75
76 assertEquals(bindings.nVectorArgs, 0);
77 }
78
79 @Test
80 public void testNestedStructs() {
81 MemoryLayout POINT = MemoryLayout.structLayout(
82 C_INT,
83 MemoryLayout.structLayout(
84 C_INT,
85 C_INT
86 )
87 );
88 MethodType mt = MethodType.methodType(void.class, MemorySegment.class);
89 FunctionDescriptor fd = FunctionDescriptor.ofVoid(POINT);
90 CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false);
91
92 assertFalse(bindings.isInMemoryReturn);
93 CallingSequence callingSequence = bindings.callingSequence;
94 assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, NativeSymbol.class));
95 assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG).insertArgumentLayouts(0, ADDRESS));
96
97 checkArgumentBindings(callingSequence, new Binding[][]{
98 { unboxAddress(NativeSymbol.class), vmStore(r10, long.class) },
99 { dup(), bufferLoad(0, long.class), vmStore(rdi, long.class),
100 bufferLoad(8, int.class), vmStore(rsi, int.class)},
101 { vmStore(rax, long.class) },
102 });
103
104 checkReturnBindings(callingSequence, new Binding[]{});
105
106 assertEquals(bindings.nVectorArgs, 0);
107 }
108
109 @Test
110 public void testNestedUnion() {
111 MemoryLayout POINT = MemoryLayout.structLayout(
112 C_INT,
113 MemoryLayout.paddingLayout(32),
114 MemoryLayout.unionLayout(
115 MemoryLayout.structLayout(C_INT, C_INT),
116 C_LONG
117 )
118 );
119 MethodType mt = MethodType.methodType(void.class, MemorySegment.class);
120 FunctionDescriptor fd = FunctionDescriptor.ofVoid(POINT);
121 CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false);
122
123 assertFalse(bindings.isInMemoryReturn);
124 CallingSequence callingSequence = bindings.callingSequence;
125 assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, NativeSymbol.class));
126 assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG).insertArgumentLayouts(0, ADDRESS));
127
128 checkArgumentBindings(callingSequence, new Binding[][]{
129 { unboxAddress(NativeSymbol.class), vmStore(r10, long.class) },
130 { dup(), bufferLoad(0, long.class), vmStore(rdi, long.class),
131 bufferLoad(8, long.class), vmStore(rsi, long.class)},
132 { vmStore(rax, long.class) },
133 });
134
135 checkReturnBindings(callingSequence, new Binding[]{});
136
137 assertEquals(bindings.nVectorArgs, 0);
138 }
139
140 @Test
141 public void testNestedStructsUnaligned() {
142 MemoryLayout POINT = MemoryLayout.structLayout(
143 C_INT,
144 MemoryLayout.structLayout(
145 C_LONG,
146 C_INT
147 )
148 );
149 MethodType mt = MethodType.methodType(void.class, MemorySegment.class);
150 FunctionDescriptor fd = FunctionDescriptor.ofVoid(POINT);
151 CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false);
152
153 assertFalse(bindings.isInMemoryReturn);
154 CallingSequence callingSequence = bindings.callingSequence;
155 assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, NativeSymbol.class));
156 assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG).insertArgumentLayouts(0, ADDRESS));
157
158 checkArgumentBindings(callingSequence, new Binding[][]{
159 { unboxAddress(NativeSymbol.class), vmStore(r10, long.class) },
160 { dup(), bufferLoad(0, long.class), vmStore(stackStorage(0), long.class),
161 bufferLoad(8, long.class), vmStore(stackStorage(1), long.class)},
162 { vmStore(rax, long.class) },
163 });
164
165 checkReturnBindings(callingSequence, new Binding[]{});
166
167 assertEquals(bindings.nVectorArgs, 0);
168 }
169
170 @Test
171 public void testNestedUnionUnaligned() {
172 MemoryLayout POINT = MemoryLayout.structLayout(
173 C_INT,
174 MemoryLayout.unionLayout(
175 MemoryLayout.structLayout(C_INT, C_INT),
176 C_LONG
177 )
178 );
179 MethodType mt = MethodType.methodType(void.class, MemorySegment.class);
180 FunctionDescriptor fd = FunctionDescriptor.ofVoid(POINT);
181 CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false);
182
183 assertFalse(bindings.isInMemoryReturn);
184 CallingSequence callingSequence = bindings.callingSequence;
185 assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, NativeSymbol.class));
186 assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG).insertArgumentLayouts(0, ADDRESS));
187
188 checkArgumentBindings(callingSequence, new Binding[][]{
189 { unboxAddress(NativeSymbol.class), vmStore(r10, long.class) },
190 { dup(), bufferLoad(0, long.class), vmStore(stackStorage(0), long.class),
191 bufferLoad(8, int.class), vmStore(stackStorage(1), int.class)},
192 { vmStore(rax, long.class) },
193 });
194
195 checkReturnBindings(callingSequence, new Binding[]{});
196
197 assertEquals(bindings.nVectorArgs, 0);
198 }
199
200 @Test
201 public void testIntegerRegs() {
202 MethodType mt = MethodType.methodType(void.class,
203 int.class, int.class, int.class, int.class, int.class, int.class);
204 FunctionDescriptor fd = FunctionDescriptor.ofVoid(
205 C_INT, C_INT, C_INT, C_INT, C_INT, C_INT);
206 CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false);
207
208 assertFalse(bindings.isInMemoryReturn);
209 CallingSequence callingSequence = bindings.callingSequence;
210 assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, NativeSymbol.class));
211 assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG).insertArgumentLayouts(0, ADDRESS));
212
213 checkArgumentBindings(callingSequence, new Binding[][]{
214 { unboxAddress(NativeSymbol.class), vmStore(r10, long.class) },
215 { vmStore(rdi, int.class) },
216 { vmStore(rsi, int.class) },
217 { vmStore(rdx, int.class) },
218 { vmStore(rcx, int.class) },
219 { vmStore(r8, int.class) },
220 { vmStore(r9, int.class) },
221 { vmStore(rax, long.class) },
222 });
223
224 checkReturnBindings(callingSequence, new Binding[]{});
225
226 assertEquals(bindings.nVectorArgs, 0);
227 }
228
229 @Test
230 public void testDoubleRegs() {
231 MethodType mt = MethodType.methodType(void.class,
232 double.class, double.class, double.class, double.class,
233 double.class, double.class, double.class, double.class);
234 FunctionDescriptor fd = FunctionDescriptor.ofVoid(
235 C_DOUBLE, C_DOUBLE, C_DOUBLE, C_DOUBLE,
236 C_DOUBLE, C_DOUBLE, C_DOUBLE, C_DOUBLE);
237 CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false);
238
239 assertFalse(bindings.isInMemoryReturn);
240 CallingSequence callingSequence = bindings.callingSequence;
241 assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, NativeSymbol.class));
242 assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG).insertArgumentLayouts(0, ADDRESS));
243
244 checkArgumentBindings(callingSequence, new Binding[][]{
245 { unboxAddress(NativeSymbol.class), vmStore(r10, long.class) },
246 { vmStore(xmm0, double.class) },
247 { vmStore(xmm1, double.class) },
248 { vmStore(xmm2, double.class) },
249 { vmStore(xmm3, double.class) },
250 { vmStore(xmm4, double.class) },
251 { vmStore(xmm5, double.class) },
252 { vmStore(xmm6, double.class) },
253 { vmStore(xmm7, double.class) },
254 { vmStore(rax, long.class) },
255 });
256
257 checkReturnBindings(callingSequence, new Binding[]{});
258
259 assertEquals(bindings.nVectorArgs, 8);
260 }
261
262 @Test
263 public void testMixed() {
264 MethodType mt = MethodType.methodType(void.class,
265 long.class, long.class, long.class, long.class, long.class, long.class, long.class, long.class,
266 float.class, float.class, float.class, float.class,
267 float.class, float.class, float.class, float.class, float.class, float.class);
268 FunctionDescriptor fd = FunctionDescriptor.ofVoid(
269 C_LONG, C_LONG, C_LONG, C_LONG, C_LONG, C_LONG, C_LONG, C_LONG,
270 C_FLOAT, C_FLOAT, C_FLOAT, C_FLOAT,
271 C_FLOAT, C_FLOAT, C_FLOAT, C_FLOAT, C_FLOAT, C_FLOAT);
272 CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false);
273
274 assertFalse(bindings.isInMemoryReturn);
275 CallingSequence callingSequence = bindings.callingSequence;
276 assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, NativeSymbol.class));
277 assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG).insertArgumentLayouts(0, ADDRESS));
278
279 checkArgumentBindings(callingSequence, new Binding[][]{
280 { unboxAddress(NativeSymbol.class), vmStore(r10, long.class) },
281 { vmStore(rdi, long.class) },
282 { vmStore(rsi, long.class) },
283 { vmStore(rdx, long.class) },
284 { vmStore(rcx, long.class) },
285 { vmStore(r8, long.class) },
286 { vmStore(r9, long.class) },
287 { vmStore(stackStorage(0), long.class) },
288 { vmStore(stackStorage(1), long.class) },
289 { vmStore(xmm0, float.class) },
290 { vmStore(xmm1, float.class) },
291 { vmStore(xmm2, float.class) },
292 { vmStore(xmm3, float.class) },
293 { vmStore(xmm4, float.class) },
294 { vmStore(xmm5, float.class) },
295 { vmStore(xmm6, float.class) },
296 { vmStore(xmm7, float.class) },
297 { vmStore(stackStorage(2), float.class) },
298 { vmStore(stackStorage(3), float.class) },
299 { vmStore(rax, long.class) },
300 });
313 * int32_t e, f, g, h, i, j, k;
314 * double m, n;
315 *
316 * void m(e, f, s, g, h, m, n, i, j, k);
317 *
318 * m(s);
319 */
320 @Test
321 public void testAbiExample() {
322 MemoryLayout struct = MemoryLayout.structLayout(C_INT, C_INT, C_DOUBLE);
323
324 MethodType mt = MethodType.methodType(void.class,
325 int.class, int.class, MemorySegment.class, int.class, int.class,
326 double.class, double.class, int.class, int.class, int.class);
327 FunctionDescriptor fd = FunctionDescriptor.ofVoid(
328 C_INT, C_INT, struct, C_INT, C_INT, C_DOUBLE, C_DOUBLE, C_INT, C_INT, C_INT);
329 CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false);
330
331 assertFalse(bindings.isInMemoryReturn);
332 CallingSequence callingSequence = bindings.callingSequence;
333 assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, NativeSymbol.class));
334 assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG).insertArgumentLayouts(0, ADDRESS));
335
336 checkArgumentBindings(callingSequence, new Binding[][]{
337 { unboxAddress(NativeSymbol.class), vmStore(r10, long.class) },
338 { vmStore(rdi, int.class) },
339 { vmStore(rsi, int.class) },
340 {
341 dup(),
342 bufferLoad(0, long.class), vmStore(rdx, long.class),
343 bufferLoad(8, double.class), vmStore(xmm0, double.class)
344 },
345 { vmStore(rcx, int.class) },
346 { vmStore(r8, int.class) },
347 { vmStore(xmm1, double.class) },
348 { vmStore(xmm2, double.class) },
349 { vmStore(r9, int.class) },
350 { vmStore(stackStorage(0), int.class) },
351 { vmStore(stackStorage(1), int.class) },
352 { vmStore(rax, long.class) },
353 });
354
355 checkReturnBindings(callingSequence, new Binding[]{});
356
357 assertEquals(bindings.nVectorArgs, 3);
358 }
359
360 /**
361 * typedef void (*f)(void);
362 *
363 * void m(f f);
364 * void f_impl(void);
365 *
366 * m(f_impl);
367 */
368 @Test
369 public void testMemoryAddress() {
370 MethodType mt = MethodType.methodType(void.class, MemoryAddress.class);
371 FunctionDescriptor fd = FunctionDescriptor.ofVoid( C_POINTER);
372 CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false);
373
374 assertFalse(bindings.isInMemoryReturn);
375 CallingSequence callingSequence = bindings.callingSequence;
376 assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, NativeSymbol.class));
377 assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG).insertArgumentLayouts(0, ADDRESS));
378
379 checkArgumentBindings(callingSequence, new Binding[][]{
380 { unboxAddress(NativeSymbol.class), vmStore(r10, long.class) },
381 { unboxAddress(), vmStore(rdi, long.class) },
382 { vmStore(rax, long.class) },
383 });
384
385 checkReturnBindings(callingSequence, new Binding[]{});
386
387 assertEquals(bindings.nVectorArgs, 0);
388 }
389
390 @Test(dataProvider = "structs")
391 public void testStruct(MemoryLayout struct, Binding[] expectedBindings) {
392 MethodType mt = MethodType.methodType(void.class, MemorySegment.class);
393 FunctionDescriptor fd = FunctionDescriptor.ofVoid(struct);
394 CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false);
395
396 assertFalse(bindings.isInMemoryReturn);
397 CallingSequence callingSequence = bindings.callingSequence;
398 assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, NativeSymbol.class));
399 assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG).insertArgumentLayouts(0, ADDRESS));
400
401 checkArgumentBindings(callingSequence, new Binding[][]{
402 { unboxAddress(NativeSymbol.class), vmStore(r10, long.class) },
403 expectedBindings,
404 { vmStore(rax, long.class) },
405 });
406
407 checkReturnBindings(callingSequence, new Binding[]{});
408
409 assertEquals(bindings.nVectorArgs, 0);
410 }
411
412
413 @DataProvider
414 public static Object[][] structs() {
415 return new Object[][]{
416 { MemoryLayout.structLayout(C_LONG), new Binding[]{
417 bufferLoad(0, long.class), vmStore(rdi, long.class)
418 }
419 },
420 { MemoryLayout.structLayout(C_LONG, C_LONG), new Binding[]{
421 dup(),
422 bufferLoad(0, long.class), vmStore(rdi, long.class),
437 dup(),
438 bufferLoad(8, long.class), vmStore(stackStorage(1), long.class),
439 dup(),
440 bufferLoad(16, long.class), vmStore(stackStorage(2), long.class),
441 bufferLoad(24, long.class), vmStore(stackStorage(3), long.class)
442 }
443 },
444 };
445 }
446
447 @Test
448 public void testReturnRegisterStruct() {
449 MemoryLayout struct = MemoryLayout.structLayout(C_LONG, C_LONG);
450
451 MethodType mt = MethodType.methodType(MemorySegment.class);
452 FunctionDescriptor fd = FunctionDescriptor.of(struct);
453 CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false);
454
455 assertFalse(bindings.isInMemoryReturn);
456 CallingSequence callingSequence = bindings.callingSequence;
457 assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, MemorySegment.class, NativeSymbol.class));
458 assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG).insertArgumentLayouts(0, ADDRESS, ADDRESS));
459
460 checkArgumentBindings(callingSequence, new Binding[][]{
461 { unboxAddress(MemorySegment.class), vmStore(r11, long.class) },
462 { unboxAddress(NativeSymbol.class), vmStore(r10, long.class) },
463 { vmStore(rax, long.class) }
464 });
465
466 checkReturnBindings(callingSequence, new Binding[] {
467 allocate(struct),
468 dup(),
469 vmLoad(rax, long.class),
470 bufferStore(0, long.class),
471 dup(),
472 vmLoad(rdx, long.class),
473 bufferStore(8, long.class)
474 });
475
476 assertEquals(bindings.nVectorArgs, 0);
477 }
478
479 @Test
480 public void testIMR() {
481 MemoryLayout struct = MemoryLayout.structLayout(C_LONG, C_LONG, C_LONG);
482
483 MethodType mt = MethodType.methodType(MemorySegment.class);
484 FunctionDescriptor fd = FunctionDescriptor.of(struct);
485 CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false);
486
487 assertTrue(bindings.isInMemoryReturn);
488 CallingSequence callingSequence = bindings.callingSequence;
489 assertEquals(callingSequence.methodType(), MethodType.methodType(void.class, NativeSymbol.class, MemoryAddress.class, long.class));
490 assertEquals(callingSequence.functionDesc(), FunctionDescriptor.ofVoid(ADDRESS, C_POINTER, C_LONG));
491
492 checkArgumentBindings(callingSequence, new Binding[][]{
493 { unboxAddress(NativeSymbol.class), vmStore(r10, long.class) },
494 { unboxAddress(), vmStore(rdi, long.class) },
495 { vmStore(rax, long.class) }
496 });
497
498 checkReturnBindings(callingSequence, new Binding[] {});
499
500 assertEquals(bindings.nVectorArgs, 0);
501 }
502
503 @Test
504 public void testFloatStructsUpcall() {
505 MemoryLayout struct = MemoryLayout.structLayout(C_FLOAT); // should be passed in float regs
506
507 MethodType mt = MethodType.methodType(MemorySegment.class, MemorySegment.class);
508 FunctionDescriptor fd = FunctionDescriptor.of(struct, struct);
509 CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, true);
510
511 assertFalse(bindings.isInMemoryReturn);
512 CallingSequence callingSequence = bindings.callingSequence;
513 assertEquals(callingSequence.methodType(), mt);
|