< prev index next >

test/jdk/java/foreign/callarranger/TestWindowsCallArranger.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.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     }
< prev index next >