1 /*
   2  * Copyright (c) 2016, 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  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
  27  * @library /test/lib /testlibrary /
  28  * @modules jdk.vm.ci/jdk.vm.ci.hotspot
  29  *          jdk.vm.ci/jdk.vm.ci.code
  30  *          jdk.vm.ci/jdk.vm.ci.code.site
  31  *          jdk.vm.ci/jdk.vm.ci.meta
  32  *          jdk.vm.ci/jdk.vm.ci.runtime
  33  *          jdk.vm.ci/jdk.vm.ci.common
  34  *          jdk.vm.ci/jdk.vm.ci.amd64
  35  *          jdk.vm.ci/jdk.vm.ci.sparc
  36  * @compile CodeInstallationTest.java TestHotSpotVMConfig.java NativeCallTest.java TestAssembler.java sparc/SPARCTestAssembler.java amd64/AMD64TestAssembler.java
  37  * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI  -Xbootclasspath/a:. jdk.vm.ci.code.test.NativeCallTest
  38  */
  39 package jdk.vm.ci.code.test;
  40 
  41 import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.NativeCall;
  42 
  43 import org.junit.BeforeClass;
  44 import org.junit.Test;
  45 
  46 import jdk.vm.ci.code.CallingConvention;
  47 import jdk.vm.ci.code.RegisterValue;
  48 import jdk.vm.ci.meta.JavaType;
  49 
  50 public class NativeCallTest extends CodeInstallationTest {
  51 
  52     @BeforeClass
  53     public static void beforeClass() {
  54         System.loadLibrary("NativeCallTest");
  55     }
  56 
  57     @Test
  58     public void testFF() {
  59         float a = 1.2345678f;
  60         float b = 8.7654321f;
  61         test("FF", getFF(), float.class, new Class<?>[]{float.class, float.class}, new Object[]{a, b});
  62     }
  63 
  64     @Test
  65     public void testSDILDS() {
  66         float a = 1.2345678f;
  67         double b = 3.212434;
  68         int c = 43921652;
  69         long d = 412435326;
  70         double e = .31212333;
  71         float f = 8.7654321f;
  72         Class<?>[] argClazz = new Class[]{float.class, double.class, int.class, long.class, double.class,
  73                         float.class};
  74         test("SDILDS", getSDILDS(), float.class, argClazz, new Object[]{a, b, c, d, e, f});
  75     }
  76 
  77     @Test
  78     public void testS32SDILDS() {
  79         int sCount = 32;
  80         Object[] remainingArgs = new Object[]{ // Pairs of <Object>, <Class>
  81                         1.2345678F, float.class,
  82                         3.212434D, double.class,
  83                         43921652, int.class,
  84                         0xCAFEBABEDEADBEEFL, long.class,
  85                         .31212333D, double.class,
  86                         8.7654321F, float.class
  87         };
  88         Class<?>[] argClazz = new Class[sCount + remainingArgs.length / 2];
  89         Object[] argValues = new Object[sCount + remainingArgs.length / 2];
  90         for (int i = 0; i < sCount; i++) {
  91             argValues[i] = (float) i;
  92             argClazz[i] = float.class;
  93         }
  94         for (int i = 0; i < remainingArgs.length; i += 2) {
  95             argValues[sCount + i / 2] = remainingArgs[i + 0];
  96             argClazz[sCount + i / 2] = (Class<?>) remainingArgs[i + 1];
  97         }
  98         test("S32SDILDS", getS32SDILDS(), float.class, argClazz, argValues);
  99     }
 100 
 101     public void test(String name, long addr, Class<?> returnClazz, Class<?>[] types, Object[] values) {
 102         try {
 103             test(asm -> {
 104                 JavaType[] argTypes = new JavaType[types.length];
 105                 int i = 0;
 106                 for (Class<?> clazz : types) {
 107                     argTypes[i++] = metaAccess.lookupJavaType(clazz);
 108                 }
 109                 JavaType returnType = metaAccess.lookupJavaType(returnClazz);
 110                 CallingConvention cc = codeCache.getRegisterConfig().getCallingConvention(NativeCall, returnType, argTypes, asm.valueKindFactory);
 111                 asm.emitCallPrologue(cc, values);
 112                 asm.emitCall(addr);
 113                 asm.emitCallEpilogue(cc);
 114                 asm.emitFloatRet(((RegisterValue) cc.getReturn()).getRegister());
 115             }, getMethod(name, types), values);
 116         } catch (Throwable e) {
 117             e.printStackTrace();
 118             throw e;
 119         }
 120     }
 121 
 122     public static native long getFF();
 123 
 124     public static native float _FF(float a, float b);
 125 
 126     public static float FF(float a, float b) {
 127         return _FF(a, b);
 128     }
 129 
 130     public static native long getSDILDS();
 131 
 132     public static native float _SDILDS(float a, double b, int c, long d, double e, float f);
 133 
 134     public static float SDILDS(float a, double b, int c, long d, double e, float f) {
 135         return _SDILDS(a, b, c, d, e, f);
 136     }
 137 
 138     public static native long getS32SDILDS();
 139 
 140     public static native float _S32SDILDS(
 141                     float f00, float f01, float f02, float f03, float f04, float f05, float f06, float f07,
 142                     float f08, float f09, float f0a, float f0b, float f0c, float f0d, float f0e, float f0f,
 143                     float f10, float f11, float f12, float f13, float f14, float f15, float f16, float f17,
 144                     float f18, float f19, float f1a, float f1b, float f1c, float f1d, float f1e, float f1f,
 145                     float a, double b, int c, long d, double e, float f);
 146 
 147     public static float S32SDILDS(
 148                     float f00, float f01, float f02, float f03, float f04, float f05, float f06, float f07,
 149                     float f08, float f09, float f0a, float f0b, float f0c, float f0d, float f0e, float f0f,
 150                     float f10, float f11, float f12, float f13, float f14, float f15, float f16, float f17,
 151                     float f18, float f19, float f1a, float f1b, float f1c, float f1d, float f1e, float f1f,
 152                     float a, double b, int c, long d, double e, float f) {
 153         return _S32SDILDS(
 154                         f00, f01, f02, f03, f04, f05, f06, f07,
 155                         f08, f09, f0a, f0b, f0c, f0d, f0e, f0f,
 156                         f10, f11, f12, f13, f14, f15, f16, f17,
 157                         f18, f19, f1a, f1b, f1c, f1d, f1e, f1f,
 158                         a, b, c, d, e, f);
 159     }
 160 }