Skip to content

Commit 61dc07c

Browse files
committed
8346869: [AIX] Add regression test for handling 4 Byte aligned doubles in structures
Reviewed-by: mbaesken, jkern
1 parent 13e1ea5 commit 61dc07c

File tree

2 files changed

+178
-0
lines changed

2 files changed

+178
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
/*
2+
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
3+
* Copyright (c) 2024 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 a structure which contains a double with 4 Byte alignment on AIX.
28+
*
29+
* @run testng/othervm --enable-native-access=ALL-UNNAMED Test4BAlignedDouble
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 Test4BAlignedDouble {
41+
42+
static {
43+
System.loadLibrary("Test4BAlignedDouble");
44+
}
45+
46+
static final Linker abi = Linker.nativeLinker();
47+
static final SymbolLookup lookup = SymbolLookup.loaderLookup();
48+
static final boolean isAix = System.getProperty("os.name").equals("AIX");
49+
50+
static final OfInt C_INT = JAVA_INT;
51+
static final OfFloat C_FLOAT = JAVA_FLOAT;
52+
static final OfDouble C_DOUBLE = JAVA_DOUBLE;
53+
// Double with platform specific alignment rule. Can be used on AIX with #pragma align (power).
54+
static final OfDouble C_DOUBLE4B = JAVA_DOUBLE.withByteAlignment(4);
55+
static final OfDouble platform_C_DOUBLE = isAix ? C_DOUBLE4B : C_DOUBLE;
56+
57+
static final StructLayout S_IDFLayout_with_padding = MemoryLayout.structLayout(
58+
C_INT.withName("p0"),
59+
MemoryLayout.paddingLayout(4), // AIX: only with #pragma align (natural)
60+
C_DOUBLE.withName("p1"),
61+
C_FLOAT.withName("p2"),
62+
MemoryLayout.paddingLayout(4)
63+
).withName("S_IDF");
64+
65+
static final StructLayout S_IDFLayout_without_padding = MemoryLayout.structLayout(
66+
C_INT.withName("p0"),
67+
// AIX uses #pragma align (power) by default. This means no padding, here.
68+
C_DOUBLE4B.withName("p1"),
69+
C_FLOAT.withName("p2")
70+
).withName("S_IDF");
71+
72+
static final StructLayout platform_S_IDFLayout = isAix ? S_IDFLayout_without_padding : S_IDFLayout_with_padding;
73+
74+
static final long p0_offs = platform_S_IDFLayout.byteOffset(PathElement.groupElement("p0")),
75+
p1_offs = platform_S_IDFLayout.byteOffset(PathElement.groupElement("p1")),
76+
p2_offs = platform_S_IDFLayout.byteOffset(PathElement.groupElement("p2"));
77+
78+
static final FunctionDescriptor fdpass_S_IDF = FunctionDescriptor.of(platform_S_IDFLayout, platform_S_IDFLayout);
79+
80+
static final MethodHandle mhpass_S_IDF = abi.downcallHandle(lookup.find("pass_S_IDF").orElseThrow(), fdpass_S_IDF);
81+
static final MethodHandle mhpass_S_IDF_fun = abi.downcallHandle(lookup.find("call_S_IDF_fun").orElseThrow(),
82+
FunctionDescriptor.of(platform_S_IDFLayout, ADDRESS, platform_S_IDFLayout));
83+
84+
@Test
85+
public static void testDowncall() {
86+
int p0 = 0;
87+
double p1 = 0.0d;
88+
float p2 = 0.0f;
89+
try (Arena arena = Arena.ofConfined()) {
90+
MemorySegment s = arena.allocate(platform_S_IDFLayout);
91+
s.set(C_INT, p0_offs, 1);
92+
s.set(platform_C_DOUBLE, p1_offs, 2.0d);
93+
s.set(C_FLOAT, p2_offs, 3.0f);
94+
s = (MemorySegment) mhpass_S_IDF.invokeExact((SegmentAllocator) arena, s);
95+
p0 = s.get(C_INT, p0_offs);
96+
p1 = s.get(platform_C_DOUBLE, p1_offs);
97+
p2 = s.get(C_FLOAT, p2_offs);
98+
System.out.println("S_IDF(" + p0 + ";" + p1 + ";" + p2 + ")");
99+
} catch (Throwable t) {
100+
t.printStackTrace();
101+
}
102+
if (p0 != 2 || p1 != 5.0d || p2 != 3.0f) throw new RuntimeException("pass_S_IDF downcall error");
103+
}
104+
105+
// Java version for Upcall test.
106+
public static MemorySegment S_IDF_fun(MemorySegment p) {
107+
int p0 = p.get(C_INT, p0_offs);
108+
double p1 = p.get(platform_C_DOUBLE, p1_offs);
109+
float p2 = p.get(C_FLOAT, p2_offs);
110+
p.set(C_INT, p0_offs, p0 + 1);
111+
p.set(platform_C_DOUBLE, p1_offs, p1 + (double) p2);
112+
return p;
113+
}
114+
115+
@Test
116+
public static void testUpcall() {
117+
int p0 = 0;
118+
double p1 = 0.0d;
119+
float p2 = 0.0f;
120+
try (Arena arena = Arena.ofConfined()) {
121+
MemorySegment s = arena.allocate(platform_S_IDFLayout);
122+
s.set(C_INT, p0_offs, 1);
123+
s.set(platform_C_DOUBLE, p1_offs, 2.0d);
124+
s.set(C_FLOAT, p2_offs, 3.0f);
125+
MethodType mt = MethodType.methodType(MemorySegment.class, MemorySegment.class);
126+
MemorySegment stub = abi.upcallStub(MethodHandles.lookup().findStatic(Test4BAlignedDouble.class, "S_IDF_fun", mt),
127+
fdpass_S_IDF, arena);
128+
s = (MemorySegment) mhpass_S_IDF_fun.invokeExact((SegmentAllocator) arena, stub, s);
129+
p0 = s.get(C_INT, p0_offs);
130+
p1 = s.get(platform_C_DOUBLE, p1_offs);
131+
p2 = s.get(C_FLOAT, p2_offs);
132+
System.out.println("S_IDF(" + p0 + ";" + p1 + ";" + p2 + ")");
133+
} catch (Throwable t) {
134+
t.printStackTrace();
135+
}
136+
if (p0 != 2 || p1 != 5.0d || p2 != 3.0f) throw new RuntimeException("pass_S_IDF upcall error");
137+
}
138+
139+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
3+
* Copyright (c) 2024 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+
#include "export.h"
26+
27+
// This test uses the platform's default alignment rules, no pragma align directive.
28+
struct S_IDF { int p0; double p1; float p2; };
29+
30+
EXPORT struct S_IDF pass_S_IDF(struct S_IDF s) {
31+
s.p0++;
32+
s.p1 += (double)s.p2;
33+
return s;
34+
}
35+
36+
// Upcall version.
37+
EXPORT struct S_IDF call_S_IDF_fun(struct S_IDF (*fun)(struct S_IDF), struct S_IDF s) {
38+
return fun(s);
39+
}

0 commit comments

Comments
 (0)