< prev index next >

test/jdk/java/foreign/abi/x64/sysv/StandardCallTest.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  * @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 


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