1 /*
   2  * Copyright (c) 2016, 2019, 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 vm.jvmci
  27  * @requires vm.simpleArch == "x64"
  28  * @library /test/lib /
  29  * @modules jdk.internal.vm.ci/jdk.vm.ci.hotspot
  30  *          jdk.internal.vm.ci/jdk.vm.ci.code
  31  *          jdk.internal.vm.ci/jdk.vm.ci.code.site
  32  *          jdk.internal.vm.ci/jdk.vm.ci.meta
  33  *          jdk.internal.vm.ci/jdk.vm.ci.runtime
  34  *          jdk.internal.vm.ci/jdk.vm.ci.common
  35  *          jdk.internal.vm.ci/jdk.vm.ci.amd64
  36  * @compile CodeInstallationTest.java TestHotSpotVMConfig.java NativeCallTest.java TestAssembler.java amd64/AMD64TestAssembler.java
  37  * @run junit/othervm/native -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 testF32SDILDS() {
  79         int sCount = 32;
  80         // Pairs of <Object>, <Class>
  81         Object[] remainingArgs = new Object[]{
  82                         1.2345678F, float.class,
  83                         3.212434D, double.class,
  84                         43921652, int.class,
  85                         0xCAFEBABEDEADBEEFL, long.class,
  86                         .31212333D, double.class,
  87                         8.7654321F, float.class
  88         };
  89         Class<?>[] argClazz = new Class[sCount + remainingArgs.length / 2];
  90         Object[] argValues = new Object[sCount + remainingArgs.length / 2];
  91         for (int i = 0; i < sCount; i++) {
  92             argValues[i] = (float) i;
  93             argClazz[i] = float.class;
  94         }
  95         for (int i = 0; i < remainingArgs.length; i += 2) {
  96             argValues[sCount + i / 2] = remainingArgs[i + 0];
  97             argClazz[sCount + i / 2] = (Class<?>) remainingArgs[i + 1];
  98         }
  99         test("F32SDILDS", getF32SDILDS(), float.class, argClazz, argValues);
 100     }
 101 
 102     @Test
 103     public void testI32SDILDS() {
 104         int sCount = 32;
 105         // Pairs of <Object>, <Class>
 106         Object[] remainingArgs = new Object[]{
 107                         1.2345678F, float.class,
 108                         3.212434D, double.class,
 109                         43921652, int.class,
 110                         0xCAFEBABEDEADBEEFL, long.class,
 111                         .31212333D, double.class,
 112                         8.7654321F, float.class
 113         };
 114         Class<?>[] argClazz = new Class[sCount + remainingArgs.length / 2];
 115         Object[] argValues = new Object[sCount + remainingArgs.length / 2];
 116         for (int i = 0; i < sCount; i++) {
 117             argValues[i] = i;
 118             argClazz[i] = int.class;
 119         }
 120         for (int i = 0; i < remainingArgs.length; i += 2) {
 121             argValues[sCount + i / 2] = remainingArgs[i + 0];
 122             argClazz[sCount + i / 2] = (Class<?>) remainingArgs[i + 1];
 123         }
 124         test("I32SDILDS", getI32SDILDS(), float.class, argClazz, argValues);
 125     }
 126 
 127     public void test(String name, long addr, Class<?> returnClazz, Class<?>[] types, Object[] values) {
 128         try {
 129             test(asm -> {
 130                 JavaType[] argTypes = new JavaType[types.length];
 131                 int i = 0;
 132                 for (Class<?> clazz : types) {
 133                     argTypes[i++] = metaAccess.lookupJavaType(clazz);
 134                 }
 135                 JavaType returnType = metaAccess.lookupJavaType(returnClazz);
 136                 CallingConvention cc = codeCache.getRegisterConfig().getCallingConvention(NativeCall, returnType, argTypes, asm.valueKindFactory);
 137                 asm.emitCallPrologue(cc, values);
 138                 asm.emitCall(addr);
 139                 asm.emitCallEpilogue(cc);
 140                 asm.emitFloatRet(((RegisterValue) cc.getReturn()).getRegister());
 141             }, getMethod(name, types), values);
 142         } catch (Throwable e) {
 143             e.printStackTrace();
 144             throw e;
 145         }
 146     }
 147 
 148     // Checkstyle: stop
 149 
 150     public static native long getFF();
 151 
 152     public static native float _FF(float a, float b);
 153 
 154     public static float FF(float a, float b) {
 155         return _FF(a, b);
 156     }
 157 
 158     public static native long getSDILDS();
 159 
 160     public static native float _SDILDS(float a, double b, int c, long d, double e, float f);
 161 
 162     public static float SDILDS(float a, double b, int c, long d, double e, float f) {
 163         return _SDILDS(a, b, c, d, e, f);
 164     }
 165 
 166     public static native long getF32SDILDS();
 167 
 168     public static native float _F32SDILDS(float f00, float f01, float f02, float f03, float f04, float f05, float f06, float f07,
 169                     float f08, float f09, float f0a, float f0b, float f0c, float f0d, float f0e, float f0f,
 170                     float f10, float f11, float f12, float f13, float f14, float f15, float f16, float f17,
 171                     float f18, float f19, float f1a, float f1b, float f1c, float f1d, float f1e, float f1f,
 172                     float a, double b, int c, long d, double e, float f);
 173 
 174     public static float F32SDILDS(float f00, float f01, float f02, float f03, float f04, float f05, float f06, float f07,
 175                     float f08, float f09, float f0a, float f0b, float f0c, float f0d, float f0e, float f0f,
 176                     float f10, float f11, float f12, float f13, float f14, float f15, float f16, float f17,
 177                     float f18, float f19, float f1a, float f1b, float f1c, float f1d, float f1e, float f1f,
 178                     float a, double b, int c, long d, double e, float f) {
 179         return _F32SDILDS(f00, f01, f02, f03, f04, f05, f06, f07,
 180                         f08, f09, f0a, f0b, f0c, f0d, f0e, f0f,
 181                         f10, f11, f12, f13, f14, f15, f16, f17,
 182                         f18, f19, f1a, f1b, f1c, f1d, f1e, f1f,
 183                         a, b, c, d, e, f);
 184     }
 185 
 186     public static native long getD32SDILDS();
 187 
 188     public static native float _D32SDILDS(double d00, double d01, double d02, double d03, double d04, double d05, double d06, double d07,
 189                     double d08, double d09, double d0a, double d0b, double d0c, double d0d, double d0e, double d0f,
 190                     double d10, double d11, double d12, double d13, double d14, double d15, double d16, double d17,
 191                     double d18, double d19, double d1a, double d1b, double d1c, double d1d, double d1e, double d1f,
 192                     float a, double b, int c, long d, double e, float f);
 193 
 194     @SuppressWarnings("unused")
 195     public static float D32SDILDS(double d00, double d01, double d02, double d03, double d04, double d05, double d06, double d07,
 196                     double d08, double d09, double d0a, double d0b, double d0c, double d0d, double d0e, double d0f,
 197                     double d10, double d11, double d12, double d13, double d14, double d15, double d16, double d17,
 198                     double d18, double d19, double d1a, double d1b, double d1c, double d1d, double d1e, double d1f,
 199                     float a, double b, int c, long d, double e, float f) {
 200         return _D32SDILDS(d00, d01, d02, d03, d04, d05, d06, d07,
 201                         d08, d09, d0a, d0b, d0c, d0d, d0e, d0d,
 202                         d10, d11, d12, d13, d14, d15, d16, d17,
 203                         d18, d19, d1a, d1b, d1c, d1d, d1e, d1f,
 204                         a, b, c, d, e, f);
 205     }
 206 
 207     public static native long getI32SDILDS();
 208 
 209     public static native float _I32SDILDS(int i00, int i01, int i02, int i03, int i04, int i05, int i06, int i07,
 210                     int i08, int i09, int i0a, int i0b, int i0c, int i0d, int i0e, int i0f,
 211                     int i10, int i11, int i12, int i13, int i14, int i15, int i16, int i17,
 212                     int i18, int i19, int i1a, int i1b, int i1c, int i1d, int i1e, int i1f,
 213                     float a, double b, int c, long d, double e, float f);
 214 
 215     public static float I32SDILDS(int i00, int i01, int i02, int i03, int i04, int i05, int i06, int i07,
 216                     int i08, int i09, int i0a, int i0b, int i0c, int i0d, int i0e, int i0f,
 217                     int i10, int i11, int i12, int i13, int i14, int i15, int i16, int i17,
 218                     int i18, int i19, int i1a, int i1b, int i1c, int i1d, int i1e, int i1f,
 219                     float a, double b, int c, long d, double e, float f) {
 220         return _I32SDILDS(i00, i01, i02, i03, i04, i05, i06, i07,
 221                         i08, i09, i0a, i0b, i0c, i0d, i0e, i0f,
 222                         i10, i11, i12, i13, i14, i15, i16, i17,
 223                         i18, i19, i1a, i1b, i1c, i1d, i1e, i1f,
 224                         a, b, c, d, e, f);
 225     }
 226 
 227     public static native long getL32SDILDS();
 228 
 229     public static native float _L32SDILDS(long l00, long l01, long l02, long l03, long l04, long l05, long l06, long l07,
 230                     long l08, long l09, long l0a, long l0b, long l0c, long l0d, long l0e, long l0f,
 231                     long l10, long l11, long l12, long l13, long l14, long l15, long l16, long l17,
 232                     long l18, long l19, long l1a, long l1b, long l1c, long l1d, long l1e, long l1f,
 233                     float a, double b, int c, long d, double e, float f);
 234 
 235     public static float L32SDILDS(long l00, long l01, long l02, long l03, long l04, long l05, long l06, long l07,
 236                     long l08, long l09, long l0a, long l0b, long l0c, long l0d, long l0e, long l0f,
 237                     long l10, long l11, long l12, long l13, long l14, long l15, long l16, long l17,
 238                     long l18, long l19, long l1a, long l1b, long l1c, long l1d, long l1e, long l1f,
 239                     float a, double b, int c, long d, double e, float f) {
 240         return _L32SDILDS(l00, l01, l02, l03, l04, l05, l06, l07,
 241                         l08, l09, l0a, l0b, l0c, l0d, l0e, l0f,
 242                         l10, l11, l12, l13, l14, l15, l16, l17,
 243                         l18, l19, l1a, l1b, l1c, l1d, l1e, l1f,
 244                         a, b, c, d, e, f);
 245     }
 246 }