1 /* 2 * Copyright (c) 2023, 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 * @enablePreview 27 * @library ../ /test/lib 28 * @requires jdk.foreign.linker != "UNSUPPORTED" 29 * @requires jdk.foreign.linker != "FALLBACK" 30 * @build NativeTestHelper 31 * @run testng/othervm --enable-native-access=ALL-UNNAMED TestNested 32 */ 33 34 import org.testng.annotations.DataProvider; 35 import org.testng.annotations.Test; 36 37 import java.lang.foreign.Arena; 38 import java.lang.foreign.FunctionDescriptor; 39 import java.lang.foreign.GroupLayout; 40 import java.lang.foreign.MemoryLayout; 41 import java.lang.foreign.MemorySegment; 42 import java.lang.foreign.SegmentAllocator; 43 import java.lang.foreign.StructLayout; 44 import java.lang.foreign.UnionLayout; 45 import java.lang.invoke.MethodHandle; 46 import java.util.List; 47 import java.util.Random; 48 import java.util.concurrent.atomic.AtomicReference; 49 50 public class TestNested extends NativeTestHelper { 51 52 static { 53 System.loadLibrary("Nested"); 54 } 55 56 @Test(dataProvider = "nestedLayouts") 57 public void testNested(GroupLayout layout) throws Throwable { 58 try (Arena arena = Arena.ofConfined()) { 59 Random random = new Random(0); 60 TestValue testValue = genTestValue(random, layout, arena); 61 62 String funcName = "test_" + layout.name().orElseThrow(); 63 FunctionDescriptor downcallDesc = FunctionDescriptor.of(layout, layout, C_POINTER); 64 FunctionDescriptor upcallDesc = FunctionDescriptor.of(layout, layout); 65 66 MethodHandle downcallHandle = downcallHandle(funcName, downcallDesc); 67 AtomicReference<Object[]> returnBox = new AtomicReference<>(); 68 MemorySegment stub = makeArgSaverCB(upcallDesc, arena, returnBox, 0); 69 70 MemorySegment returned = (MemorySegment) downcallHandle.invokeExact( 71 (SegmentAllocator) arena, (MemorySegment) testValue.value(), stub); 72 73 testValue.check().accept(returnBox.get()[0]); 74 testValue.check().accept(returned); 75 } 76 } 77 78 @DataProvider 79 public static Object[][] nestedLayouts() { 80 List<GroupLayout> layouts = List.of( 81 S1, U1, U17, S2, S3, S4, S5, S6, U2, S7, U3, U4, U5, U6, U7, S8, S9, U8, U9, U10, S10, 82 U11, S11, U12, S12, U13, U14, U15, S13, S14, U16, S15); 83 return layouts.stream().map(l -> new Object[]{l}).toArray(Object[][]::new); 84 } 85 86 static final StructLayout S1 = MemoryLayout.structLayout( 87 C_DOUBLE.withName("f0"), 88 C_LONG_LONG.withName("f1"), 89 C_DOUBLE.withName("f2"), 90 C_INT.withName("f3"), 91 MemoryLayout.paddingLayout(4) 92 ).withName("S1"); 93 static final UnionLayout U1 = MemoryLayout.unionLayout( 94 C_SHORT.withName("f0"), 95 C_LONG_LONG.withName("f1"), 96 C_SHORT.withName("f2"), 97 MemoryLayout.sequenceLayout(4, MemoryLayout.sequenceLayout(3, C_CHAR)).withName("f3"), 98 MemoryLayout.paddingLayout(16) 99 ).withName("U1"); 100 static final UnionLayout U17 = MemoryLayout.unionLayout( 101 C_CHAR.withName("f0"), 102 C_CHAR.withName("f1"), 103 C_LONG_LONG.withName("f2"), 104 C_DOUBLE.withName("f3") 105 ).withName("U17"); 106 static final StructLayout S2 = MemoryLayout.structLayout( 107 U17.withName("f0"), 108 MemoryLayout.sequenceLayout(4, C_LONG_LONG).withName("f1"), 109 C_SHORT.withName("f2"), 110 MemoryLayout.paddingLayout(6) 111 ).withName("S2"); 112 static final StructLayout S3 = MemoryLayout.structLayout( 113 C_FLOAT.withName("f0"), 114 C_INT.withName("f1"), 115 U1.withName("f2"), 116 S2.withName("f3") 117 ).withName("S3"); 118 static final StructLayout S4 = MemoryLayout.structLayout( 119 MemoryLayout.sequenceLayout(2, C_SHORT).withName("f0"), 120 MemoryLayout.paddingLayout(4), 121 S1.withName("f1") 122 ).withName("S4"); 123 static final StructLayout S5 = MemoryLayout.structLayout( 124 C_FLOAT.withName("f0"), 125 MemoryLayout.paddingLayout(4), 126 C_POINTER.withName("f1"), 127 S4.withName("f2") 128 ).withName("S5"); 129 static final StructLayout S6 = MemoryLayout.structLayout( 130 S5.withName("f0") 131 ).withName("S6"); 132 static final UnionLayout U2 = MemoryLayout.unionLayout( 133 C_FLOAT.withName("f0"), 134 C_SHORT.withName("f1"), 135 C_POINTER.withName("f2"), 136 C_FLOAT.withName("f3") 137 ).withName("U2"); 138 static final StructLayout S7 = MemoryLayout.structLayout( 139 C_DOUBLE.withName("f0"), 140 C_SHORT.withName("f1"), 141 C_SHORT.withName("f2"), 142 MemoryLayout.paddingLayout(4), 143 C_LONG_LONG.withName("f3") 144 ).withName("S7"); 145 static final UnionLayout U3 = MemoryLayout.unionLayout( 146 C_POINTER.withName("f0"), 147 U2.withName("f1"), 148 C_LONG_LONG.withName("f2"), 149 S7.withName("f3") 150 ).withName("U3"); 151 static final UnionLayout U4 = MemoryLayout.unionLayout( 152 C_FLOAT.withName("f0") 153 ).withName("U4"); 154 static final UnionLayout U5 = MemoryLayout.unionLayout( 155 U3.withName("f0"), 156 MemoryLayout.sequenceLayout(3, C_LONG_LONG).withName("f1"), 157 U4.withName("f2"), 158 C_FLOAT.withName("f3") 159 ).withName("U5"); 160 static final UnionLayout U6 = MemoryLayout.unionLayout( 161 C_SHORT.withName("f0"), 162 C_FLOAT.withName("f1"), 163 U5.withName("f2"), 164 C_SHORT.withName("f3") 165 ).withName("U6"); 166 static final UnionLayout U7 = MemoryLayout.unionLayout( 167 C_SHORT.withName("f0") 168 ).withName("U7"); 169 static final StructLayout S8 = MemoryLayout.structLayout( 170 MemoryLayout.sequenceLayout(3, C_DOUBLE).withName("f0"), 171 U7.withName("f1"), 172 MemoryLayout.paddingLayout(6), 173 C_POINTER.withName("f2"), 174 C_POINTER.withName("f3") 175 ).withName("S8"); 176 static final StructLayout S9 = MemoryLayout.structLayout( 177 C_CHAR.withName("f0"), 178 MemoryLayout.paddingLayout(7), 179 MemoryLayout.sequenceLayout(2, C_DOUBLE).withName("f1"), 180 C_CHAR.withName("f2"), 181 MemoryLayout.paddingLayout(7), 182 S8.withName("f3") 183 ).withName("S9"); 184 static final UnionLayout U8 = MemoryLayout.unionLayout( 185 C_LONG_LONG.withName("f0"), 186 C_POINTER.withName("f1"), 187 S9.withName("f2") 188 ).withName("U8"); 189 static final UnionLayout U9 = MemoryLayout.unionLayout( 190 C_INT.withName("f0"), 191 C_DOUBLE.withName("f1"), 192 MemoryLayout.sequenceLayout(2, C_SHORT).withName("f2"), 193 C_LONG_LONG.withName("f3") 194 ).withName("U9"); 195 static final UnionLayout U10 = MemoryLayout.unionLayout( 196 C_LONG_LONG.withName("f0"), 197 U9.withName("f1"), 198 C_CHAR.withName("f2"), 199 C_FLOAT.withName("f3") 200 ).withName("U10"); 201 static final StructLayout S10 = MemoryLayout.structLayout( 202 MemoryLayout.sequenceLayout(4, C_DOUBLE).withName("f0") 203 ).withName("S10"); 204 static final UnionLayout U11 = MemoryLayout.unionLayout( 205 MemoryLayout.sequenceLayout(3, S10).withName("f0") 206 ).withName("U11"); 207 static final StructLayout S11 = MemoryLayout.structLayout( 208 C_SHORT.withName("f0"), 209 C_CHAR.withName("f1"), 210 MemoryLayout.paddingLayout(1) 211 ).withName("S11"); 212 static final UnionLayout U12 = MemoryLayout.unionLayout( 213 C_FLOAT.withName("f0"), 214 S11.withName("f1"), 215 C_CHAR.withName("f2"), 216 C_CHAR.withName("f3") 217 ).withName("U12"); 218 static final StructLayout S12 = MemoryLayout.structLayout( 219 U12.withName("f0"), 220 C_FLOAT.withName("f1") 221 ).withName("S12"); 222 static final UnionLayout U13 = MemoryLayout.unionLayout( 223 C_FLOAT.withName("f0"), 224 S12.withName("f1") 225 ).withName("U13"); 226 static final UnionLayout U14 = MemoryLayout.unionLayout( 227 C_INT.withName("f0"), 228 MemoryLayout.sequenceLayout(2, C_POINTER).withName("f1"), 229 MemoryLayout.sequenceLayout(2, MemoryLayout.sequenceLayout(3, C_FLOAT)).withName("f2") 230 ).withName("U14"); 231 static final UnionLayout U15 = MemoryLayout.unionLayout( 232 C_POINTER.withName("f0"), 233 C_LONG_LONG.withName("f1"), 234 MemoryLayout.sequenceLayout(1, C_DOUBLE).withName("f2"), 235 C_LONG_LONG.withName("f3") 236 ).withName("U15"); 237 static final StructLayout S13 = MemoryLayout.structLayout( 238 C_INT.withName("f0"), 239 C_CHAR.withName("f1"), 240 MemoryLayout.paddingLayout(3), 241 C_POINTER.withName("f2"), 242 C_CHAR.withName("f3"), 243 MemoryLayout.paddingLayout(7) 244 ).withName("S13"); 245 static final StructLayout S14 = MemoryLayout.structLayout( 246 C_LONG_LONG.withName("f0") 247 ).withName("S14"); 248 static final UnionLayout U16 = MemoryLayout.unionLayout( 249 MemoryLayout.sequenceLayout(4, C_SHORT).withName("f0"), 250 C_INT.withName("f1"), 251 S13.withName("f2"), 252 S14.withName("f3") 253 ).withName("U16"); 254 static final StructLayout S15 = MemoryLayout.structLayout( 255 U16.withName("f0"), 256 C_FLOAT.withName("f1"), 257 C_INT.withName("f2"), 258 C_LONG_LONG.withName("f3") 259 ).withName("S15"); 260 }