1 /* 2 * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. 3 * Copyright (c) 2023 SAP SE. All rights reserved. 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 */ 24 25 /* 26 * @test 27 * @summary Test passing of Homogeneous Float Aggregates. 28 * 29 * @run testng/othervm --enable-native-access=ALL-UNNAMED TestHFA 30 */ 31 32 import java.lang.foreign.*; 33 import java.lang.invoke.MethodHandle; 34 import java.lang.invoke.MethodHandles; 35 import java.lang.invoke.MethodType; 36 import org.testng.annotations.Test; 37 38 import static java.lang.foreign.ValueLayout.*; 39 40 public class TestHFA { 41 42 static { 43 System.loadLibrary("TestHFA"); 44 } 45 46 final static Linker abi = Linker.nativeLinker(); 47 final static SymbolLookup lookup = SymbolLookup.loaderLookup(); 48 49 static final OfFloat FLOAT = JAVA_FLOAT.withByteAlignment(4); 50 51 final static GroupLayout S_FFLayout = MemoryLayout.structLayout( 52 FLOAT.withName("p0"), 53 FLOAT.withName("p1") 54 ).withName("S_FF"); 55 56 final static GroupLayout S_FFFFFFFLayout = MemoryLayout.structLayout( 57 FLOAT.withName("p0"), 58 FLOAT.withName("p1"), 59 FLOAT.withName("p2"), 60 FLOAT.withName("p3"), 61 FLOAT.withName("p4"), 62 FLOAT.withName("p5"), 63 FLOAT.withName("p6") 64 ).withName("S_FFFF"); 65 66 static final FunctionDescriptor fdadd_float_structs = FunctionDescriptor.of(S_FFFFFFFLayout, S_FFFFFFFLayout, S_FFFFFFFLayout); 67 static final FunctionDescriptor fdadd_float_to_struct_after_floats = FunctionDescriptor.of(S_FFLayout, 68 JAVA_FLOAT, JAVA_FLOAT, JAVA_FLOAT, JAVA_FLOAT, JAVA_FLOAT, 69 JAVA_FLOAT, JAVA_FLOAT, JAVA_FLOAT, JAVA_FLOAT, JAVA_FLOAT, 70 JAVA_FLOAT, JAVA_FLOAT, S_FFLayout, JAVA_FLOAT); 71 static final FunctionDescriptor fdadd_float_to_struct_after_structs = FunctionDescriptor.of(S_FFLayout, 72 S_FFLayout, S_FFLayout, S_FFLayout, S_FFLayout, S_FFLayout, S_FFLayout, 73 S_FFLayout, JAVA_FLOAT); 74 static final FunctionDescriptor fdadd_double_to_struct_after_structs = FunctionDescriptor.of(S_FFLayout, 75 S_FFLayout, S_FFLayout, S_FFLayout, S_FFLayout, S_FFLayout, S_FFLayout, 76 S_FFLayout, JAVA_DOUBLE); 77 static final FunctionDescriptor fdadd_float_to_large_struct_after_structs = FunctionDescriptor.of(S_FFFFFFFLayout, 78 S_FFLayout, S_FFLayout, S_FFLayout, S_FFLayout, S_FFLayout, S_FFLayout, 79 S_FFFFFFFLayout, JAVA_FLOAT); 80 81 static final FunctionDescriptor fdpass_two_large_structs = FunctionDescriptor.of(S_FFFFFFFLayout, ADDRESS, S_FFFFFFFLayout, S_FFFFFFFLayout); 82 static final FunctionDescriptor fdpass_struct_after_floats = FunctionDescriptor.of(S_FFLayout, ADDRESS, S_FFLayout, JAVA_FLOAT); 83 static final FunctionDescriptor fdpass_struct_after_structs = FunctionDescriptor.of(S_FFLayout, ADDRESS, S_FFLayout, JAVA_FLOAT); 84 static final FunctionDescriptor fdpass_struct_after_structs_plus_double = FunctionDescriptor.of(S_FFLayout, ADDRESS, S_FFLayout, JAVA_DOUBLE); 85 static final FunctionDescriptor fdpass_large_struct_after_structs = FunctionDescriptor.of(S_FFFFFFFLayout, ADDRESS, S_FFFFFFFLayout, JAVA_FLOAT); 86 87 final static MethodHandle mhadd_float_structs = abi.downcallHandle(lookup.find("add_float_structs").orElseThrow(), 88 fdadd_float_structs); 89 final static MethodHandle mhadd_float_to_struct_after_floats = abi.downcallHandle(lookup.find("add_float_to_struct_after_floats").orElseThrow(), 90 fdadd_float_to_struct_after_floats); 91 final static MethodHandle mhadd_float_to_struct_after_structs = abi.downcallHandle(lookup.find("add_float_to_struct_after_structs").orElseThrow(), 92 fdadd_float_to_struct_after_structs); 93 final static MethodHandle mhadd_double_to_struct_after_structs = abi.downcallHandle(lookup.find("add_double_to_struct_after_structs").orElseThrow(), 94 fdadd_double_to_struct_after_structs); 95 final static MethodHandle mhadd_float_to_large_struct_after_structs = abi.downcallHandle(lookup.find("add_float_to_large_struct_after_structs").orElseThrow(), 96 fdadd_float_to_large_struct_after_structs); 97 98 final static MethodHandle mhpass_two_large_structs = abi.downcallHandle(lookup.find("pass_two_large_structs").orElseThrow(), 99 fdpass_two_large_structs); 100 final static MethodHandle mhpass_struct_after_floats = abi.downcallHandle(lookup.find("pass_struct_after_floats").orElseThrow(), 101 fdpass_struct_after_floats); 102 final static MethodHandle mhpass_struct_after_structs = abi.downcallHandle(lookup.find("pass_struct_after_structs").orElseThrow(), 103 fdpass_struct_after_structs); 104 final static MethodHandle mhpass_struct_after_structs_plus_double = abi.downcallHandle(lookup.find("pass_struct_after_structs_plus_double").orElseThrow(), 105 fdpass_struct_after_structs_plus_double); 106 final static MethodHandle mhpass_large_struct_after_structs = abi.downcallHandle(lookup.find("pass_large_struct_after_structs").orElseThrow(), 107 fdpass_large_struct_after_structs); 108 109 @Test 110 public static void testAddFloatStructs() { 111 float p0 = 0.0f, p1 = 0.0f, p2 = 0.0f, p3 = 0.0f, p4 = 0.0f, p5 = 0.0f, p6 = 0.0f; 112 try { 113 Arena arena = Arena.ofConfined(); 114 MemorySegment s = arena.allocate(S_FFFFFFFLayout); 115 s.set(FLOAT, 0, 1.0f); 116 s.set(FLOAT, 4, 2.0f); 117 s.set(FLOAT, 8, 3.0f); 118 s.set(FLOAT, 12, 4.0f); 119 s.set(FLOAT, 16, 5.0f); 120 s.set(FLOAT, 20, 6.0f); 121 s.set(FLOAT, 24, 7.0f); 122 s = (MemorySegment)mhadd_float_structs.invokeExact((SegmentAllocator)arena, s, s); 123 p0 = s.get(FLOAT, 0); 124 p1 = s.get(FLOAT, 4); 125 p2 = s.get(FLOAT, 8); 126 p3 = s.get(FLOAT, 12); 127 p4 = s.get(FLOAT, 16); 128 p5 = s.get(FLOAT, 20); 129 p6 = s.get(FLOAT, 24); 130 System.out.println("S_FFFFFFF(" + p0 + ";" + p1 + ";" + p2 + ";" + p3 + ";" + p4 + ";" + p5 + ";" + p6 + ")"); 131 } catch (Throwable t) { 132 t.printStackTrace(); 133 } 134 if (p0 != 2.0f || p1 != 4.0f || p2 != 6.0f || p3 != 8.0f || p4 != 10.0f || p5 != 12.0f || p6 != 14.0f) 135 throw new RuntimeException("add_float_structs error"); 136 } 137 138 @Test 139 public static void testAddFloatToStructAfterFloats() { 140 float p0 = 0.0f, p1 = 0.0f; 141 try { 142 Arena arena = Arena.ofConfined(); 143 MemorySegment s = arena.allocate(S_FFLayout); 144 s.set(FLOAT, 0, 1.0f); 145 s.set(FLOAT, 4, 1.0f); 146 s = (MemorySegment)mhadd_float_to_struct_after_floats.invokeExact((SegmentAllocator)arena, 147 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 148 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 149 11.0f, 12.0f, s, 1.0f); 150 p0 = s.get(FLOAT, 0); 151 p1 = s.get(FLOAT, 4); 152 System.out.println("S_FF(" + p0 + ";" + p1 + ")"); 153 } catch (Throwable t) { 154 t.printStackTrace(); 155 } 156 if (p0 != 2.0f || p1 != 1.0f) throw new RuntimeException("add_float_to_struct_after_floats error"); 157 } 158 159 @Test 160 public static void testAddFloatToStructAfterStructs() { 161 float p0 = 0.0f, p1 = 0.0f; 162 try { 163 Arena arena = Arena.ofConfined(); 164 MemorySegment s = arena.allocate(S_FFLayout); 165 s.set(FLOAT, 0, 1.0f); 166 s.set(FLOAT, 4, 1.0f); 167 s = (MemorySegment)mhadd_float_to_struct_after_structs.invokeExact((SegmentAllocator)arena, 168 s, s, s, s, s, s, 169 s, 1.0f); 170 p0 = s.get(FLOAT, 0); 171 p1 = s.get(FLOAT, 4); 172 System.out.println("S_FF(" + p0 + ";" + p1 + ")"); 173 } catch (Throwable t) { 174 t.printStackTrace(); 175 } 176 if (p0 != 2.0f || p1 != 1.0f) throw new RuntimeException("add_float_to_struct_after_structs error"); 177 } 178 179 @Test 180 public static void testAddDoubleToStructAfterStructs() { 181 float p0 = 0.0f, p1 = 0.0f; 182 try { 183 Arena arena = Arena.ofConfined(); 184 MemorySegment s = arena.allocate(S_FFLayout); 185 s.set(FLOAT, 0, 1.0f); 186 s.set(FLOAT, 4, 1.0f); 187 s = (MemorySegment)mhadd_double_to_struct_after_structs.invokeExact((SegmentAllocator)arena, 188 s, s, s, s, s, s, 189 s, 1.0d); 190 p0 = s.get(FLOAT, 0); 191 p1 = s.get(FLOAT, 4); 192 System.out.println("S_FF(" + p0 + ";" + p1 + ")"); 193 } catch (Throwable t) { 194 t.printStackTrace(); 195 } 196 if (p0 != 2.0f || p1 != 1.0f) throw new RuntimeException("add_double_to_struct_after_structs error"); 197 } 198 199 @Test 200 public static void testAddFloatToLargeStructAfterStructs() { 201 float p0 = 0.0f, p1 = 0.0f, p2 = 0.0f, p3 = 0.0f, p4 = 0.0f, p5 = 0.0f, p6 = 0.0f; 202 try { 203 Arena arena = Arena.ofConfined(); 204 MemorySegment s = arena.allocate(S_FFFFFFFLayout); 205 s.set(FLOAT, 0, 1.0f); 206 s.set(FLOAT, 4, 2.0f); 207 s.set(FLOAT, 8, 3.0f); 208 s.set(FLOAT, 12, 4.0f); 209 s.set(FLOAT, 16, 5.0f); 210 s.set(FLOAT, 20, 6.0f); 211 s.set(FLOAT, 24, 7.0f); 212 s = (MemorySegment)mhadd_float_to_large_struct_after_structs.invokeExact((SegmentAllocator)arena, 213 s, s, s, s, s, s, 214 s, 1.0f); 215 p0 = s.get(FLOAT, 0); 216 p1 = s.get(FLOAT, 4); 217 p2 = s.get(FLOAT, 8); 218 p3 = s.get(FLOAT, 12); 219 p4 = s.get(FLOAT, 16); 220 p5 = s.get(FLOAT, 20); 221 p6 = s.get(FLOAT, 24); 222 System.out.println("S_FFFFFFF(" + p0 + ";" + p1 + ";" + p2 + ";" + p3 + ";" + p4 + ";" + p5 + ";" + p6 + ")"); 223 } catch (Throwable t) { 224 t.printStackTrace(); 225 } 226 if (p0 != 2.0f || p1 != 2.0f || p2 != 3.0f || p3 != 4.0f || p4 != 5.0f || p5 != 6.0f || p6 != 7.0f) 227 throw new RuntimeException("add_float_to_large_struct_after_structs error"); 228 } 229 230 // Java versions for Upcall tests. 231 public static MemorySegment addFloatStructs(MemorySegment p0, MemorySegment p1) { 232 float val0 = p0.get(FLOAT, 0) + p1.get(FLOAT, 0); 233 float val1 = p0.get(FLOAT, 4) + p1.get(FLOAT, 4); 234 float val2 = p0.get(FLOAT, 8) + p1.get(FLOAT, 8); 235 float val3 = p0.get(FLOAT, 12) + p1.get(FLOAT, 12); 236 float val4 = p0.get(FLOAT, 16) + p1.get(FLOAT, 16); 237 float val5 = p0.get(FLOAT, 20) + p1.get(FLOAT, 20); 238 float val6 = p0.get(FLOAT, 24) + p1.get(FLOAT, 24); 239 p0.set(FLOAT, 0, val0); 240 p0.set(FLOAT, 4, val1); 241 p0.set(FLOAT, 8, val2); 242 p0.set(FLOAT, 12, val3); 243 p0.set(FLOAT, 16, val4); 244 p0.set(FLOAT, 20, val5); 245 p0.set(FLOAT, 24, val6); 246 return p0; 247 } 248 249 public static MemorySegment addFloatToStructAfterFloats( 250 float f1, float f2, float f3, float f4, float f5, 251 float f6, float f7, float f8, float f9, float f10, 252 float f11, float f12, MemorySegment s, float f) { 253 float val = s.get(FLOAT, 0); 254 s.set(FLOAT, 0, val + f); 255 return s; 256 } 257 258 public static MemorySegment addFloatToStructAfterStructs( 259 MemorySegment s1, MemorySegment s2, MemorySegment s3, 260 MemorySegment s4, MemorySegment s5, MemorySegment s6, 261 MemorySegment s, float f) { 262 float val = s.get(FLOAT, 0); 263 s.set(FLOAT, 0, val + f); 264 return s; 265 } 266 267 public static MemorySegment addDoubleToStructAfterStructs( 268 MemorySegment s1, MemorySegment s2, MemorySegment s3, 269 MemorySegment s4, MemorySegment s5, MemorySegment s6, 270 MemorySegment s, double f) { 271 float val = s.get(FLOAT, 0); 272 s.set(FLOAT, 0, val + (float) f); 273 return s; 274 } 275 276 @Test 277 public static void testAddFloatStructsUpcall() { 278 float p0 = 0.0f, p1 = 0.0f, p2 = 0.0f, p3 = 0.0f, p4 = 0.0f, p5 = 0.0f, p6 = 0.0f; 279 try { 280 Arena arena = Arena.ofConfined(); 281 MemorySegment s = arena.allocate(S_FFFFFFFLayout); 282 s.set(FLOAT, 0, 1.0f); 283 s.set(FLOAT, 4, 2.0f); 284 s.set(FLOAT, 8, 3.0f); 285 s.set(FLOAT, 12, 4.0f); 286 s.set(FLOAT, 16, 5.0f); 287 s.set(FLOAT, 20, 6.0f); 288 s.set(FLOAT, 24, 7.0f); 289 MethodType mt = MethodType.methodType(MemorySegment.class, 290 MemorySegment.class, MemorySegment.class); 291 MemorySegment stub = abi.upcallStub(MethodHandles.lookup().findStatic(TestHFA.class, "addFloatStructs", mt), 292 fdadd_float_structs, arena); 293 s = (MemorySegment)mhpass_two_large_structs.invokeExact((SegmentAllocator)arena, stub, s, s); 294 p0 = s.get(FLOAT, 0); 295 p1 = s.get(FLOAT, 4); 296 p2 = s.get(FLOAT, 8); 297 p3 = s.get(FLOAT, 12); 298 p4 = s.get(FLOAT, 16); 299 p5 = s.get(FLOAT, 20); 300 p6 = s.get(FLOAT, 24); 301 System.out.println("S_FFFFFFF(" + p0 + ";" + p1 + ";" + p2 + ";" + p3 + ";" + p4 + ";" + p5 + ";" + p6 + ")"); 302 } catch (Throwable t) { 303 t.printStackTrace(); 304 } 305 if (p0 != 2.0f || p1 != 4.0f || p2 != 6.0f || p3 != 8.0f || p4 != 10.0f || p5 != 12.0f || p6 != 14.0f) 306 throw new RuntimeException("add_float_structs (Upcall)"); 307 } 308 309 @Test 310 public static void testAddFloatToStructAfterFloatsUpcall() { 311 float p0 = 0.0f, p1 = 0.0f; 312 try { 313 Arena arena = Arena.ofConfined(); 314 MemorySegment s = arena.allocate(S_FFLayout); 315 s.set(FLOAT, 0, 1.0f); 316 s.set(FLOAT, 4, 1.0f); 317 MethodType mt = MethodType.methodType(MemorySegment.class, 318 float.class, float.class, float.class, float.class, 319 float.class, float.class, float.class, float.class, 320 float.class, float.class, float.class, float.class, 321 MemorySegment.class, float.class); 322 MemorySegment stub = abi.upcallStub(MethodHandles.lookup().findStatic(TestHFA.class, "addFloatToStructAfterFloats", mt), 323 fdadd_float_to_struct_after_floats, arena); 324 s = (MemorySegment)mhpass_struct_after_floats.invokeExact((SegmentAllocator)arena, stub, s, 1.0f); 325 p0 = s.get(FLOAT, 0); 326 p1 = s.get(FLOAT, 4); 327 System.out.println("S_FF(" + p0 + ";" + p1 + ")"); 328 } catch (Throwable t) { 329 t.printStackTrace(); 330 } 331 if (p0 != 2.0f || p1 != 1.0f) throw new RuntimeException("add_float_to_struct_after_floats (Upcall)"); 332 } 333 334 @Test 335 public static void testAddFloatToStructAfterStructsUpcall() { 336 float p0 = 0.0f, p1 = 0.0f; 337 try { 338 Arena arena = Arena.ofConfined(); 339 MemorySegment s = arena.allocate(S_FFLayout); 340 s.set(FLOAT, 0, 1.0f); 341 s.set(FLOAT, 4, 1.0f); 342 MethodType mt = MethodType.methodType(MemorySegment.class, 343 MemorySegment.class, MemorySegment.class, MemorySegment.class, 344 MemorySegment.class, MemorySegment.class, MemorySegment.class, 345 MemorySegment.class, float.class); 346 MemorySegment stub = abi.upcallStub(MethodHandles.lookup().findStatic(TestHFA.class, "addFloatToStructAfterStructs", mt), 347 fdadd_float_to_struct_after_structs, arena); 348 s = (MemorySegment)mhpass_struct_after_structs.invokeExact((SegmentAllocator)arena, stub, s, 1.0f); 349 p0 = s.get(FLOAT, 0); 350 p1 = s.get(FLOAT, 4); 351 System.out.println("S_FF(" + p0 + ";" + p1 + ")"); 352 } catch (Throwable t) { 353 t.printStackTrace(); 354 } 355 if (p0 != 2.0f || p1 != 1.0f) throw new RuntimeException("add_float_to_struct_after_structs (Upcall)"); 356 } 357 358 @Test 359 public static void testAddDoubleToStructAfterStructsUpcall() { 360 float p0 = 0.0f, p1 = 0.0f; 361 try { 362 Arena arena = Arena.ofConfined(); 363 MemorySegment s = arena.allocate(S_FFLayout); 364 s.set(FLOAT, 0, 1.0f); 365 s.set(FLOAT, 4, 1.0f); 366 MethodType mt = MethodType.methodType(MemorySegment.class, 367 MemorySegment.class, MemorySegment.class, MemorySegment.class, 368 MemorySegment.class, MemorySegment.class, MemorySegment.class, 369 MemorySegment.class, double.class); 370 MemorySegment stub = abi.upcallStub(MethodHandles.lookup().findStatic(TestHFA.class, "addDoubleToStructAfterStructs", mt), 371 fdadd_double_to_struct_after_structs, arena); 372 s = (MemorySegment)mhpass_struct_after_structs_plus_double.invokeExact((SegmentAllocator)arena, stub, s, 1.0d); 373 p0 = s.get(FLOAT, 0); 374 p1 = s.get(FLOAT, 4); 375 System.out.println("S_FF(" + p0 + ";" + p1 + ")"); 376 } catch (Throwable t) { 377 t.printStackTrace(); 378 } 379 if (p0 != 2.0f || p1 != 1.0f) throw new RuntimeException("add_double_to_struct_after_structs (Upcall)"); 380 } 381 382 @Test 383 public static void testAddFloatToLargeStructAfterStructsUpcall() { 384 float p0 = 0.0f, p1 = 0.0f, p2 = 0.0f, p3 = 0.0f, p4 = 0.0f, p5 = 0.0f, p6 = 0.0f; 385 try { 386 Arena arena = Arena.ofConfined(); 387 MemorySegment s = arena.allocate(S_FFFFFFFLayout); 388 s.set(FLOAT, 0, 1.0f); 389 s.set(FLOAT, 4, 2.0f); 390 s.set(FLOAT, 8, 3.0f); 391 s.set(FLOAT, 12, 4.0f); 392 s.set(FLOAT, 16, 5.0f); 393 s.set(FLOAT, 20, 6.0f); 394 s.set(FLOAT, 24, 7.0f); 395 MethodType mt = MethodType.methodType(MemorySegment.class, 396 MemorySegment.class, MemorySegment.class, MemorySegment.class, 397 MemorySegment.class, MemorySegment.class, MemorySegment.class, 398 MemorySegment.class, float.class); 399 MemorySegment stub = abi.upcallStub(MethodHandles.lookup().findStatic(TestHFA.class, "addFloatToStructAfterStructs", mt), 400 fdadd_float_to_large_struct_after_structs, arena); 401 s = (MemorySegment)mhpass_large_struct_after_structs.invokeExact((SegmentAllocator)arena, stub, s, 1.0f); 402 p0 = s.get(FLOAT, 0); 403 p1 = s.get(FLOAT, 4); 404 p2 = s.get(FLOAT, 8); 405 p3 = s.get(FLOAT, 12); 406 p4 = s.get(FLOAT, 16); 407 p5 = s.get(FLOAT, 20); 408 p6 = s.get(FLOAT, 24); 409 System.out.println("S_FFFFFFF(" + p0 + ";" + p1 + ";" + p2 + ";" + p3 + ";" + p4 + ";" + p5 + ";" + p6 + ")"); 410 } catch (Throwable t) { 411 t.printStackTrace(); 412 } 413 if (p0 != 2.0f || p1 != 2.0f || p2 != 3.0f || p3 != 4.0f || p4 != 5.0f || p5 != 6.0f || p6 != 7.0f) 414 throw new RuntimeException("add_float_to_large_struct_after_structs (Upcall)"); 415 } 416 }