< prev index next >

test/jdk/java/foreign/callarranger/TestSysVCallArranger.java

Print this page

 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);
< prev index next >