1 /*
   2  * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  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  * @test
  26  * @modules java.base/jdk.internal.foreign.abi java.base/jdk.internal.foreign.memory java.base/jdk.internal.foreign.abi.x64.sysv
  27  */
  28 
  29 import java.foreign.NativeTypes;
  30 import java.foreign.layout.Group;
  31 import java.foreign.layout.Layout;
  32 import java.foreign.memory.LayoutType;
  33 import java.util.ArrayList;
  34 import java.util.List;
  35 import java.util.stream.Stream;
  36 
  37 import jdk.internal.foreign.abi.CallingSequence;
  38 import jdk.internal.foreign.abi.StorageClass;
  39 import jdk.internal.foreign.abi.x64.sysv.Constants;
  40 import jdk.internal.foreign.abi.x64.sysv.StandardCall;
  41 import jdk.internal.foreign.memory.Types;
  42 
  43 public class StandardCallTest {
  44     public StandardCallTest() {
  45     }
  46 
  47     public void testInteger() {
  48         StandardCall sc = new StandardCall();
  49 
  50         // Fill registers and spill over with 2 args on stack
  51         LayoutType<?> args[] = new LayoutType<?>[Constants.MAX_INTEGER_ARGUMENT_REGISTERS + 2];
  52         for (int i = 0; i < Constants.MAX_INTEGER_ARGUMENT_REGISTERS + 2; i++) {
  53             args[i] = NativeTypes.INT64;
  54         }
  55 
  56         CallingSequence recipe = sc.arrangeCall(null,
  57                 Stream.of(args).map(LayoutType::layout).toArray(Layout[]::new));
  58 
  59         assertEquals(false, recipe.returnsInMemory());
  60         assertEquals(Constants.MAX_INTEGER_ARGUMENT_REGISTERS, recipe.getBindings(StorageClass.INTEGER_ARGUMENT_REGISTER).size());
  61         assertEquals(0, recipe.getBindings(StorageClass.VECTOR_ARGUMENT_REGISTER).size());
  62         assertEquals(2, recipe.getBindings(StorageClass.STACK_ARGUMENT_SLOT).size());
  63 
  64         for (int i = 0; i < Constants.MAX_INTEGER_ARGUMENT_REGISTERS; i++) {
  65             assertEquals(args[i].layout(), recipe.getBindings(StorageClass.INTEGER_ARGUMENT_REGISTER).get(i).getMember().getType());
  66             assertEquals(0, recipe.getBindings(StorageClass.INTEGER_ARGUMENT_REGISTER).get(i).getOffset());
  67         }
  68 
  69         for (int i = 0; i < 2; i++) {
  70             assertEquals(args[Constants.MAX_INTEGER_ARGUMENT_REGISTERS + i].layout(),
  71                     recipe.getBindings(StorageClass.STACK_ARGUMENT_SLOT).get(i).getMember().getType());
  72             assertEquals(0, recipe.getBindings(StorageClass.STACK_ARGUMENT_SLOT).get(i).getOffset());
  73         }
  74     }
  75 
  76     public void testSse() {
  77         StandardCall sc = new StandardCall();
  78 
  79         // Fill registers and spill over with 2 args on stack
  80         LayoutType<?> args[] = new LayoutType<?>[Constants.MAX_VECTOR_ARGUMENT_REGISTERS + 2];
  81         for (int i = 0; i < Constants.MAX_VECTOR_ARGUMENT_REGISTERS + 2; i++) {
  82             args[i] = NativeTypes.IEEE_FLOAT32;
  83         }
  84 
  85         CallingSequence recipe = sc.arrangeCall(null,
  86                 Stream.of(args).map(LayoutType::layout).toArray(Layout[]::new));
  87 
  88         assertEquals(false, recipe.returnsInMemory());
  89         assertEquals(0, recipe.getBindings(StorageClass.INTEGER_ARGUMENT_REGISTER).size());
  90         assertEquals(Constants.MAX_VECTOR_ARGUMENT_REGISTERS, recipe.getBindings(StorageClass.VECTOR_ARGUMENT_REGISTER).size());
  91         assertEquals(2, recipe.getBindings(StorageClass.STACK_ARGUMENT_SLOT).size());
  92 
  93         for (int i = 0; i < Constants.MAX_VECTOR_ARGUMENT_REGISTERS; i++) {
  94             assertEquals(args[i].layout(), recipe.getBindings(StorageClass.VECTOR_ARGUMENT_REGISTER).get(i).getMember().getType());
  95             assertEquals(0, recipe.getBindings(StorageClass.VECTOR_ARGUMENT_REGISTER).get(i).getOffset());
  96         }
  97 
  98         for (int i = 0; i < 2; i++) {
  99             assertEquals(args[Constants.MAX_VECTOR_ARGUMENT_REGISTERS + i].layout(),
 100                     recipe.getBindings(StorageClass.STACK_ARGUMENT_SLOT).get(i).getMember().getType());
 101             assertEquals(0, recipe.getBindings(StorageClass.STACK_ARGUMENT_SLOT).get(i).getOffset());
 102         }
 103     }
 104 
 105      public void testMixed() {
 106         StandardCall sc = new StandardCall();
 107 
 108         // Fill GP registers + 2 on stack
 109         List<LayoutType<?>> args = new ArrayList<>();
 110         for (int i = 0; i < Constants.MAX_INTEGER_ARGUMENT_REGISTERS + 2; i++) {
 111             args.add(NativeTypes.INT64);
 112         }
 113 
 114         // Fill SSE registers + 2 on stack
 115         for (int i = 0; i < Constants.MAX_VECTOR_ARGUMENT_REGISTERS + 2; i++) {
 116             args.add(NativeTypes.IEEE_FLOAT32);
 117         }
 118 
 119         CallingSequence recipe = sc.arrangeCall(null,
 120                 args.stream().map(LayoutType::layout).toArray(Layout[]::new));
 121 
 122         assertEquals(false, recipe.returnsInMemory());
 123         assertEquals(Constants.MAX_INTEGER_ARGUMENT_REGISTERS, recipe.getBindings(StorageClass.INTEGER_ARGUMENT_REGISTER).size());
 124         assertEquals(Constants.MAX_VECTOR_ARGUMENT_REGISTERS, recipe.getBindings(StorageClass.VECTOR_ARGUMENT_REGISTER).size());
 125         assertEquals(4, recipe.getBindings(StorageClass.STACK_ARGUMENT_SLOT).size());
 126 
 127         int arg = 0;
 128         for (int i = 0; i < Constants.MAX_INTEGER_ARGUMENT_REGISTERS; i++, arg++) {
 129             assertEquals(args.get(arg).layout(), recipe.getBindings(StorageClass.INTEGER_ARGUMENT_REGISTER).get(i).getMember().getType());
 130             assertEquals(0, recipe.getBindings(StorageClass.INTEGER_ARGUMENT_REGISTER).get(i).getOffset());
 131         }
 132 
 133         for (int i = 0; i < 2; i++, arg++) {
 134             assertEquals(args.get(arg).layout(), recipe.getBindings(StorageClass.STACK_ARGUMENT_SLOT).get(i).getMember().getType());
 135             assertEquals(0, recipe.getBindings(StorageClass.STACK_ARGUMENT_SLOT).get(i).getOffset());
 136         }
 137 
 138         for (int i = 0; i < Constants.MAX_VECTOR_ARGUMENT_REGISTERS; i++, arg++) {
 139             assertEquals(args.get(arg).layout(), recipe.getBindings(StorageClass.VECTOR_ARGUMENT_REGISTER).get(i).getMember().getType());
 140             assertEquals(0, recipe.getBindings(StorageClass.VECTOR_ARGUMENT_REGISTER).get(i).getOffset());
 141         }
 142 
 143         for (int i = 2; i < 4; i++, arg++) {
 144             assertEquals(args.get(arg).layout(), recipe.getBindings(StorageClass.STACK_ARGUMENT_SLOT).get(i).getMember().getType());
 145             assertEquals(0, recipe.getBindings(StorageClass.STACK_ARGUMENT_SLOT).get(i).getOffset());
 146         }
 147     }
 148 
 149     /**
 150      * This is the example from the System V ABI AMD64 document
 151      *
 152      * struct structparm {
 153      *   int32_t a, int32_t b, double d;
 154      * } s;
 155      * int32_t e, f, g, h, i, j, k;
 156      * long double ld;
 157      * double m, n;
 158      * __m256 y;
 159      *
 160      * void m(e, f, s, g, h, ld, m, y, n, i, j, k);
 161      *
 162      * m(s);
 163      */
 164     public void testAbiExample() {
 165         Layout[] args = { Types.INT32, Types.INT32, Group.struct(Types.INT32, Types.INT32, Types.DOUBLE),
 166                 Types.INT32, Types.INT32, Types.LONG_DOUBLE, Types.DOUBLE,
 167                 Types.DOUBLE, Types.INT32, Types.INT32, Types.INT32 };
 168 
 169         StandardCall sc = new StandardCall();
 170         CallingSequence recipe = sc.arrangeCall(null, args);
 171 
 172         assertEquals(false, recipe.returnsInMemory());
 173         assertEquals(6, recipe.getBindings(StorageClass.INTEGER_ARGUMENT_REGISTER).size());
 174         assertEquals(3, recipe.getBindings(StorageClass.VECTOR_ARGUMENT_REGISTER).size());
 175         assertEquals(4, recipe.getBindings(StorageClass.STACK_ARGUMENT_SLOT).size());
 176 
 177         // e
 178         assertEquals(args[0], recipe.getBindings(StorageClass.INTEGER_ARGUMENT_REGISTER).get(0).getMember().getType());
 179         assertEquals(0, recipe.getBindings(StorageClass.INTEGER_ARGUMENT_REGISTER).get(0).getOffset());
 180 
 181         // f
 182         assertEquals(args[1], recipe.getBindings(StorageClass.INTEGER_ARGUMENT_REGISTER).get(1).getMember().getType());
 183         assertEquals(0, recipe.getBindings(StorageClass.INTEGER_ARGUMENT_REGISTER).get(1).getOffset());
 184 
 185         // s.a & s.b
 186         assertEquals(args[2], recipe.getBindings(StorageClass.INTEGER_ARGUMENT_REGISTER).get(2).getMember().getType());
 187         assertEquals(0, recipe.getBindings(StorageClass.INTEGER_ARGUMENT_REGISTER).get(2).getOffset());
 188 
 189         // s.d
 190         assertEquals(args[2], recipe.getBindings(StorageClass.VECTOR_ARGUMENT_REGISTER).get(0).getMember().getType());
 191         assertEquals(8, recipe.getBindings(StorageClass.VECTOR_ARGUMENT_REGISTER).get(0).getOffset());
 192 
 193         // g
 194         assertEquals(args[3], recipe.getBindings(StorageClass.INTEGER_ARGUMENT_REGISTER).get(3).getMember().getType());
 195         assertEquals(0, recipe.getBindings(StorageClass.INTEGER_ARGUMENT_REGISTER).get(3).getOffset());
 196 
 197         // h
 198         assertEquals(args[4], recipe.getBindings(StorageClass.INTEGER_ARGUMENT_REGISTER).get(4).getMember().getType());
 199         assertEquals(0, recipe.getBindings(StorageClass.INTEGER_ARGUMENT_REGISTER).get(4).getOffset());
 200 
 201         // ld
 202         assertEquals(args[5], recipe.getBindings(StorageClass.STACK_ARGUMENT_SLOT).get(0).getMember().getType());
 203         assertEquals(0, recipe.getBindings(StorageClass.STACK_ARGUMENT_SLOT).get(0).getOffset());
 204         assertEquals(args[5], recipe.getBindings(StorageClass.STACK_ARGUMENT_SLOT).get(1).getMember().getType());
 205         assertEquals(8, recipe.getBindings(StorageClass.STACK_ARGUMENT_SLOT).get(1).getOffset());
 206 
 207         // m
 208         assertEquals(args[6], recipe.getBindings(StorageClass.VECTOR_ARGUMENT_REGISTER).get(1).getMember().getType());
 209         assertEquals(0, recipe.getBindings(StorageClass.VECTOR_ARGUMENT_REGISTER).get(1).getOffset());
 210 
 211         // n
 212         assertEquals(args[7], recipe.getBindings(StorageClass.VECTOR_ARGUMENT_REGISTER).get(2).getMember().getType());
 213         assertEquals(0, recipe.getBindings(StorageClass.VECTOR_ARGUMENT_REGISTER).get(2).getOffset());
 214 
 215         // i
 216         assertEquals(args[8], recipe.getBindings(StorageClass.INTEGER_ARGUMENT_REGISTER).get(5).getMember().getType());
 217         assertEquals(0, recipe.getBindings(StorageClass.INTEGER_ARGUMENT_REGISTER).get(5).getOffset());
 218 
 219         // j
 220         assertEquals(args[9], recipe.getBindings(StorageClass.STACK_ARGUMENT_SLOT).get(2).getMember().getType());
 221         assertEquals(0, recipe.getBindings(StorageClass.STACK_ARGUMENT_SLOT).get(2).getOffset());
 222 
 223         // k
 224         assertEquals(args[10], recipe.getBindings(StorageClass.STACK_ARGUMENT_SLOT).get(3).getMember().getType());
 225         assertEquals(0, recipe.getBindings(StorageClass.STACK_ARGUMENT_SLOT).get(3).getOffset());
 226     }
 227 
 228     /**
 229      * This is a varargs example from the System V ABI AMD64 document
 230      *
 231      * int a, b;
 232      * long double ld;
 233      * double m, n;
 234      * __m256 u, y;
 235      *
 236      * extern void func (int a, double m, __m256 u, ...);
 237      *
 238      * func(a, m, u, b, ld, y, n);
 239      */
 240     public void testAbiExampleVarargs() {
 241         Layout[] args = {
 242                 Types.INT,
 243                 Types.DOUBLE,
 244                 Types.INT,
 245                 Types.LONG_DOUBLE,
 246                 Types.DOUBLE };
 247         StandardCall sc = new StandardCall();
 248         CallingSequence recipe = sc.arrangeCall(null, args);
 249 
 250         assertEquals(false, recipe.returnsInMemory());
 251         assertEquals(2, recipe.getBindings(StorageClass.INTEGER_ARGUMENT_REGISTER).size());
 252         assertEquals(2, recipe.getBindings(StorageClass.VECTOR_ARGUMENT_REGISTER).size());
 253         assertEquals(2, recipe.getBindings(StorageClass.STACK_ARGUMENT_SLOT).size());
 254 
 255 
 256         // a
 257         assertEquals(args[0], recipe.getBindings(StorageClass.INTEGER_ARGUMENT_REGISTER).get(0).getMember().getType());
 258         assertEquals(0, recipe.getBindings(StorageClass.INTEGER_ARGUMENT_REGISTER).get(0).getOffset());
 259 
 260         // m
 261         assertEquals(args[1], recipe.getBindings(StorageClass.VECTOR_ARGUMENT_REGISTER).get(0).getMember().getType());
 262         assertEquals(0, recipe.getBindings(StorageClass.VECTOR_ARGUMENT_REGISTER).get(0).getOffset());
 263 
 264         // b
 265         assertEquals(args[2], recipe.getBindings(StorageClass.INTEGER_ARGUMENT_REGISTER).get(1).getMember().getType());
 266         assertEquals(0, recipe.getBindings(StorageClass.INTEGER_ARGUMENT_REGISTER).get(1).getOffset());
 267 
 268         // ld
 269         assertEquals(args[3], recipe.getBindings(StorageClass.STACK_ARGUMENT_SLOT).get(0).getMember().getType());
 270         assertEquals(0, recipe.getBindings(StorageClass.STACK_ARGUMENT_SLOT).get(0).getOffset());
 271         assertEquals(args[3], recipe.getBindings(StorageClass.STACK_ARGUMENT_SLOT).get(1).getMember().getType());
 272         assertEquals(8, recipe.getBindings(StorageClass.STACK_ARGUMENT_SLOT).get(1).getOffset());
 273 
 274         // n
 275         assertEquals(args[4], recipe.getBindings(StorageClass.VECTOR_ARGUMENT_REGISTER).get(1).getMember().getType());
 276         assertEquals(0, recipe.getBindings(StorageClass.VECTOR_ARGUMENT_REGISTER).get(1).getOffset());
 277     }
 278 
 279 
 280     /**
 281      * struct s {
 282      *   uint64_t u0;
 283      * } s;
 284      *
 285      * void m(struct s s);
 286      *
 287      * m(s);
 288      */
 289     public void testStruct8() {
 290         Group structparm = Group.struct(Types.UNSIGNED.INT64);
 291 
 292         StandardCall sc = new StandardCall();
 293         CallingSequence recipe = sc.arrangeCall(null, structparm);
 294 
 295         assertEquals(false, recipe.returnsInMemory());
 296         assertEquals(1, recipe.getBindings(StorageClass.INTEGER_ARGUMENT_REGISTER).size());
 297         assertEquals(0, recipe.getBindings(StorageClass.VECTOR_ARGUMENT_REGISTER).size());
 298         assertEquals(0, recipe.getBindings(StorageClass.STACK_ARGUMENT_SLOT).size());
 299 
 300         // s.u0
 301         assertEquals(structparm, recipe.getBindings(StorageClass.INTEGER_ARGUMENT_REGISTER).get(0).getMember().getType());
 302         assertEquals(0, recipe.getBindings(StorageClass.INTEGER_ARGUMENT_REGISTER).get(0).getOffset());
 303     }
 304 
 305     /**
 306      * struct s {
 307      *   uint64_t u0, u1;
 308      * } s;
 309      *
 310      * void m(struct s s);
 311      *
 312      * m(s);
 313      */
 314     public void testStruct16() {
 315         Group structparm = Group.struct(Types.UNSIGNED.INT64, Types.UNSIGNED.INT64);
 316 
 317         StandardCall sc = new StandardCall();
 318         CallingSequence recipe = sc.arrangeCall(null, structparm);
 319 
 320         assertEquals(false, recipe.returnsInMemory());
 321         assertEquals(2, recipe.getBindings(StorageClass.INTEGER_ARGUMENT_REGISTER).size());
 322         assertEquals(0, recipe.getBindings(StorageClass.VECTOR_ARGUMENT_REGISTER).size());
 323         assertEquals(0, recipe.getBindings(StorageClass.STACK_ARGUMENT_SLOT).size());
 324 
 325         // s.u0
 326         assertEquals(structparm, recipe.getBindings(StorageClass.INTEGER_ARGUMENT_REGISTER).get(0).getMember().getType());
 327         assertEquals(0, recipe.getBindings(StorageClass.INTEGER_ARGUMENT_REGISTER).get(0).getOffset());
 328 
 329         // s.u1
 330         assertEquals(structparm, recipe.getBindings(StorageClass.INTEGER_ARGUMENT_REGISTER).get(1).getMember().getType());
 331         assertEquals(8, recipe.getBindings(StorageClass.INTEGER_ARGUMENT_REGISTER).get(1).getOffset());
 332     }
 333 
 334     /**
 335      * struct s {
 336      *   uint64_t u0, u1, u2;
 337      * } s;
 338      *
 339      * void m(struct s s);
 340      *
 341      * m(s);
 342      */
 343     public void testStruct24() {
 344         Group structparm = Group.struct(Types.UNSIGNED.INT64, Types.UNSIGNED.INT64, Types.UNSIGNED.INT64);
 345 
 346         StandardCall sc = new StandardCall();
 347         CallingSequence recipe = sc.arrangeCall(null, structparm);
 348 
 349         assertEquals(false, recipe.returnsInMemory());
 350         assertEquals(0, recipe.getBindings(StorageClass.INTEGER_ARGUMENT_REGISTER).size());
 351         assertEquals(0, recipe.getBindings(StorageClass.VECTOR_ARGUMENT_REGISTER).size());
 352         assertEquals(3, recipe.getBindings(StorageClass.STACK_ARGUMENT_SLOT).size());
 353 
 354         // s.u0
 355         assertEquals(structparm, recipe.getBindings(StorageClass.STACK_ARGUMENT_SLOT).get(0).getMember().getType());
 356         assertEquals(0, recipe.getBindings(StorageClass.STACK_ARGUMENT_SLOT).get(0).getOffset());
 357 
 358         // s.u1
 359         assertEquals(structparm, recipe.getBindings(StorageClass.STACK_ARGUMENT_SLOT).get(1).getMember().getType());
 360         assertEquals(8, recipe.getBindings(StorageClass.STACK_ARGUMENT_SLOT).get(1).getOffset());
 361 
 362         // s.u2
 363         assertEquals(structparm, recipe.getBindings(StorageClass.STACK_ARGUMENT_SLOT).get(2).getMember().getType());
 364         assertEquals(16, recipe.getBindings(StorageClass.STACK_ARGUMENT_SLOT).get(2).getOffset());
 365     }
 366 
 367     /**
 368      * struct s {
 369      *   uint64_t u0, u1, u2, u3;
 370      * } s;
 371      *
 372      * void m(struct s s);
 373      *
 374      * m(s);
 375      */
 376     public void testStruct32() {
 377         Layout structparm = Layout.of("[u64u64u64u64]");
 378 
 379         StandardCall sc = new StandardCall();
 380         CallingSequence recipe = sc.arrangeCall(null, structparm);
 381 
 382         assertEquals(false, recipe.returnsInMemory());
 383         assertEquals(0, recipe.getBindings(StorageClass.INTEGER_ARGUMENT_REGISTER).size());
 384         assertEquals(0, recipe.getBindings(StorageClass.VECTOR_ARGUMENT_REGISTER).size());
 385         assertEquals(4, recipe.getBindings(StorageClass.STACK_ARGUMENT_SLOT).size());
 386 
 387         // s.u0
 388         assertEquals(structparm, recipe.getBindings(StorageClass.STACK_ARGUMENT_SLOT).get(0).getMember().getType());
 389         assertEquals(0, recipe.getBindings(StorageClass.STACK_ARGUMENT_SLOT).get(0).getOffset());
 390 
 391         // s.u1
 392         assertEquals(structparm, recipe.getBindings(StorageClass.STACK_ARGUMENT_SLOT).get(1).getMember().getType());
 393         assertEquals(8, recipe.getBindings(StorageClass.STACK_ARGUMENT_SLOT).get(1).getOffset());
 394 
 395         // s.u2
 396         assertEquals(structparm, recipe.getBindings(StorageClass.STACK_ARGUMENT_SLOT).get(2).getMember().getType());
 397         assertEquals(16, recipe.getBindings(StorageClass.STACK_ARGUMENT_SLOT).get(2).getOffset());
 398 
 399         // s.u3
 400         assertEquals(structparm, recipe.getBindings(StorageClass.STACK_ARGUMENT_SLOT).get(3).getMember().getType());
 401         assertEquals(24, recipe.getBindings(StorageClass.STACK_ARGUMENT_SLOT).get(3).getOffset());
 402     }
 403 
 404     /**
 405      * typedef void (*f)(void);
 406      *
 407      * void m(f f);
 408      * void f_impl(void);
 409      *
 410      * m(f_impl);
 411      */
 412     public void testFunctionType() {
 413         Layout arg = Layout.of("u64:()v");
 414         CallingSequence recipe = new StandardCall().arrangeCall(null, arg);
 415 
 416         assertEquals(false, recipe.returnsInMemory());
 417         assertEquals(1, recipe.getBindings(StorageClass.INTEGER_ARGUMENT_REGISTER).size());
 418         assertEquals(0, recipe.getBindings(StorageClass.VECTOR_ARGUMENT_REGISTER).size());
 419         assertEquals(0, recipe.getBindings(StorageClass.STACK_ARGUMENT_SLOT).size());
 420 
 421         // s.u0
 422         assertEquals(arg, recipe.getBindings(StorageClass.INTEGER_ARGUMENT_REGISTER).get(0).getMember().getType());
 423         assertEquals(0, recipe.getBindings(StorageClass.INTEGER_ARGUMENT_REGISTER).get(0).getOffset());
 424     }
 425 
 426     /**
 427      * void f(int64_t l0, float f0, __m256 m0);
 428      */
 429     public void testMixedArgs() {
 430         CallingSequence recipe = new StandardCall().arrangeCall(null,
 431                 Types.INT64, Types.FLOAT);
 432 
 433         assertEquals(false, recipe.returnsInMemory());
 434         assertEquals(1, recipe.getBindings(StorageClass.INTEGER_ARGUMENT_REGISTER).size());
 435         assertEquals(1, recipe.getBindings(StorageClass.VECTOR_ARGUMENT_REGISTER).size());
 436         assertEquals(0, recipe.getBindings(StorageClass.STACK_ARGUMENT_SLOT).size());
 437 
 438         // l0
 439         assertEquals(Types.INT64, recipe.getBindings(StorageClass.INTEGER_ARGUMENT_REGISTER).get(0).getMember().getType());
 440         assertEquals(0, recipe.getBindings(StorageClass.INTEGER_ARGUMENT_REGISTER).get(0).getOffset());
 441 
 442         // f0
 443         assertEquals(Types.FLOAT, recipe.getBindings(StorageClass.VECTOR_ARGUMENT_REGISTER).get(0).getMember().getType());
 444         assertEquals(0, recipe.getBindings(StorageClass.VECTOR_ARGUMENT_REGISTER).get(0).getOffset());
 445     }
 446 
 447     /**
 448      * struct s {
 449      *    int64_t l0;
 450      *    int64_t l1;
 451      * };
 452      *
 453      * void f(struct s s1);
 454      */
 455     public void testIntegerStruct() {
 456         Layout arg = Layout.of("[i64i64]");
 457 
 458         CallingSequence recipe = new StandardCall().arrangeCall(null, arg);
 459 
 460         assertEquals(false, recipe.returnsInMemory());
 461         assertEquals(2, recipe.getBindings(StorageClass.INTEGER_ARGUMENT_REGISTER).size());
 462         assertEquals(0, recipe.getBindings(StorageClass.VECTOR_ARGUMENT_REGISTER).size());
 463         assertEquals(0, recipe.getBindings(StorageClass.STACK_ARGUMENT_SLOT).size());
 464 
 465         // s.l0
 466         assertEquals(arg, recipe.getBindings(StorageClass.INTEGER_ARGUMENT_REGISTER).get(0).getMember().getType());
 467         assertEquals(0, recipe.getBindings(StorageClass.INTEGER_ARGUMENT_REGISTER).get(0).getOffset());
 468 
 469         // s.l1
 470         assertEquals(arg, recipe.getBindings(StorageClass.INTEGER_ARGUMENT_REGISTER).get(1).getMember().getType());
 471         assertEquals(8, recipe.getBindings(StorageClass.INTEGER_ARGUMENT_REGISTER).get(1).getOffset());
 472     }
 473 
 474     static void assertEquals(long expected, long actual) {
 475         if (expected != actual) {
 476             throw new RuntimeException("expected: " + expected + " does not match actual: " + actual);
 477         }
 478     }
 479 
 480     static void assertEquals(boolean expected, boolean actual) {
 481         if (expected != actual) {
 482             throw new RuntimeException("expected: " + expected + " does not match actual: " + actual);
 483         }
 484     }
 485 
 486     static void assertEquals(Object expected, Object actual) {
 487         if (expected != actual) {
 488             throw new RuntimeException("expected: " + expected + " does not match actual: " + actual);
 489         }
 490     }
 491 
 492     public static void main(String[] args) {
 493         StandardCallTest t = new StandardCallTest();
 494 
 495         t.testInteger();
 496         t.testSse();
 497         t.testMixed();
 498         t.testAbiExample();
 499         t.testAbiExampleVarargs();
 500         t.testStruct8();
 501         t.testStruct16();
 502         t.testStruct24();
 503         t.testStruct32();
 504         t.testFunctionType();
 505         t.testMixedArgs();
 506         t.testIntegerStruct();
 507     }
 508 }