1 /*
2  *  Copyright (c) 2020, 2021, 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.  Oracle designates this
8  *  particular file as subject to the "Classpath" exception as provided
9  *  by Oracle in the LICENSE file that accompanied this code.
10  *
11  *  This code is distributed in the hope that it will be useful, but WITHOUT
12  *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  *  version 2 for more details (a copy is included in the LICENSE file that
15  *  accompanied this code).
16  *
17  *  You should have received a copy of the GNU General Public License version
18  *  2 along with this work; if not, write to the Free Software Foundation,
19  *  Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  *   Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  *  or visit www.oracle.com if you need additional information or have any
23  *  questions.
24  *
25  */
26 package jdk.internal.foreign;
27 
28 import jdk.incubator.foreign.CLinker;
29 import jdk.incubator.foreign.MemoryLayout;
30 import jdk.incubator.foreign.ValueLayout;
31 
32 import java.nio.ByteOrder;
33 
34 import static java.nio.ByteOrder.LITTLE_ENDIAN;
35 
36 public class PlatformLayouts {
pick(Z sysv, Z win64, Z aarch64)37     public static <Z extends MemoryLayout> Z pick(Z sysv, Z win64, Z aarch64) {
38         return switch (CABI.current()) {
39             case SysV -> sysv;
40             case Win64 -> win64;
41             case LinuxAArch64, MacOsAArch64 -> aarch64;
42         };
43     }
44 
asVarArg(MemoryLayout ml)45     public static MemoryLayout asVarArg(MemoryLayout ml) {
46         return switch (CABI.current()) {
47             case Win64 -> Win64.asVarArg(ml);
48             case MacOsAArch64 -> AArch64.asVarArg(ml);
49             default -> ml;
50         };
51     }
52 
53     private static ValueLayout ofChar(ByteOrder order, long bitSize) {
54         return MemoryLayout.valueLayout(bitSize, order)
55                 .withAttribute(CLinker.TypeKind.ATTR_NAME, CLinker.TypeKind.CHAR);
56     }
57 
58     private static ValueLayout ofShort(ByteOrder order, long bitSize) {
59         return MemoryLayout.valueLayout(bitSize, order)
60                 .withAttribute(CLinker.TypeKind.ATTR_NAME, CLinker.TypeKind.SHORT);
61     }
62 
63     private static ValueLayout ofInt(ByteOrder order, long bitSize) {
64         return MemoryLayout.valueLayout(bitSize, order)
65                 .withAttribute(CLinker.TypeKind.ATTR_NAME, CLinker.TypeKind.INT);
66     }
67 
68     private static ValueLayout ofLong(ByteOrder order, long bitSize) {
69         return MemoryLayout.valueLayout(bitSize, order)
70                 .withAttribute(CLinker.TypeKind.ATTR_NAME, CLinker.TypeKind.LONG);
71     }
72 
73     private static ValueLayout ofLongLong(ByteOrder order, long bitSize) {
74         return MemoryLayout.valueLayout(bitSize, order)
75                 .withAttribute(CLinker.TypeKind.ATTR_NAME, CLinker.TypeKind.LONG_LONG);
76     }
77 
78     private static ValueLayout ofFloat(ByteOrder order, long bitSize) {
79         return MemoryLayout.valueLayout(bitSize, order)
80                 .withAttribute(CLinker.TypeKind.ATTR_NAME, CLinker.TypeKind.FLOAT);
81     }
82 
83     private static ValueLayout ofDouble(ByteOrder order, long bitSize) {
84         return MemoryLayout.valueLayout(bitSize, order)
85                 .withAttribute(CLinker.TypeKind.ATTR_NAME, CLinker.TypeKind.DOUBLE);
86     }
87 
88     private static ValueLayout ofPointer(ByteOrder order, long bitSize) {
89         return MemoryLayout.valueLayout(bitSize, order)
90                 .withAttribute(CLinker.TypeKind.ATTR_NAME, CLinker.TypeKind.POINTER);
91     }
92 
93     public static CLinker.TypeKind getKind(MemoryLayout layout) {
94         return (CLinker.TypeKind)layout.attribute(CLinker.TypeKind.ATTR_NAME).orElseThrow(
95             () -> new IllegalStateException("Unexpected value layout: could not determine ABI class"));
96     }
97 
98     /**
99      * This class defines layout constants modelling standard primitive types supported by the x64 SystemV ABI.
100      */
101     public static final class SysV {
102         private SysV() {
103             //just the one
104         }
105 
106         /**
107          * The {@code char} native type.
108          */
109         public static final ValueLayout C_CHAR = ofChar(LITTLE_ENDIAN, 8);
110 
111         /**
112          * The {@code short} native type.
113          */
114         public static final ValueLayout C_SHORT = ofShort(LITTLE_ENDIAN, 16);
115 
116         /**
117          * The {@code int} native type.
118          */
119         public static final ValueLayout C_INT = ofInt(LITTLE_ENDIAN, 32);
120 
121         /**
122          * The {@code long} native type.
123          */
124         public static final ValueLayout C_LONG = ofLong(LITTLE_ENDIAN, 64);
125 
126         /**
127          * The {@code long long} native type.
128          */
129         public static final ValueLayout C_LONG_LONG = ofLongLong(LITTLE_ENDIAN, 64);
130 
131         /**
132          * The {@code float} native type.
133          */
134         public static final ValueLayout C_FLOAT = ofFloat(LITTLE_ENDIAN, 32);
135 
136         /**
137          * The {@code double} native type.
138          */
139         public static final ValueLayout C_DOUBLE = ofDouble(LITTLE_ENDIAN, 64);
140 
141         /**
142          * The {@code T*} native type.
143          */
144         public static final ValueLayout C_POINTER = ofPointer(LITTLE_ENDIAN, 64);
145 
146         /**
147          * The {@code va_list} native type, as it is passed to a function.
148          */
149         public static final MemoryLayout C_VA_LIST = SysV.C_POINTER;
150     }
151 
152     /**
153      * This class defines layout constants modelling standard primitive types supported by the x64 Windows ABI.
154      */
155     public static final class Win64 {
156 
157         private Win64() {
158             //just the one
159         }
160 
161         /**
162          * The name of the layout attribute (see {@link MemoryLayout#attributes()}) used to mark variadic parameters. The
163          * attribute value must be a boolean.
164          */
165         public static final String VARARGS_ATTRIBUTE_NAME = "abi/windows/varargs";
166 
167         /**
168          * The {@code char} native type.
169          */
170         public static final ValueLayout C_CHAR = ofChar(LITTLE_ENDIAN, 8);
171 
172         /**
173          * The {@code short} native type.
174          */
175         public static final ValueLayout C_SHORT = ofShort(LITTLE_ENDIAN, 16);
176 
177         /**
178          * The {@code int} native type.
179          */
180         public static final ValueLayout C_INT = ofInt(LITTLE_ENDIAN, 32);
181         /**
182          * The {@code long} native type.
183          */
184         public static final ValueLayout C_LONG = ofLong(LITTLE_ENDIAN, 32);
185 
186         /**
187          * The {@code long long} native type.
188          */
189         public static final ValueLayout C_LONG_LONG = ofLongLong(LITTLE_ENDIAN, 64);
190 
191         /**
192          * The {@code float} native type.
193          */
194         public static final ValueLayout C_FLOAT = ofFloat(LITTLE_ENDIAN, 32);
195 
196         /**
197          * The {@code double} native type.
198          */
199         public static final ValueLayout C_DOUBLE = ofDouble(LITTLE_ENDIAN, 64);
200 
201         /**
202          * The {@code T*} native type.
203          */
204         public static final ValueLayout C_POINTER = ofPointer(LITTLE_ENDIAN, 64);
205 
206         /**
207          * The {@code va_list} native type, as it is passed to a function.
208          */
209         public static final MemoryLayout C_VA_LIST = Win64.C_POINTER;
210 
211         /**
212          * Return a new memory layout which describes a variadic parameter to be passed to a function.
213          * @param layout the original parameter layout.
214          * @return a layout which is the same as {@code layout}, except for the extra attribute {@link #VARARGS_ATTRIBUTE_NAME},
215          * which is set to {@code true}.
216          */
217         public static MemoryLayout asVarArg(MemoryLayout layout) {
218             return layout.withAttribute(VARARGS_ATTRIBUTE_NAME, true);
219         }
220     }
221 
222     /**
223      * This class defines layout constants modelling standard primitive types supported by the AArch64 ABI.
224      */
225     public static final class AArch64 {
226 
227         private AArch64() {
228             //just the one
229         }
230 
231         /**
232          * The {@code char} native type.
233          */
234         public static final ValueLayout C_CHAR = ofChar(LITTLE_ENDIAN, 8);
235 
236         /**
237          * The {@code short} native type.
238          */
239         public static final ValueLayout C_SHORT = ofShort(LITTLE_ENDIAN, 16);
240 
241         /**
242          * The {@code int} native type.
243          */
244         public static final ValueLayout C_INT = ofInt(LITTLE_ENDIAN, 32);
245 
246         /**
247          * The {@code long} native type.
248          */
249         public static final ValueLayout C_LONG = ofLong(LITTLE_ENDIAN, 64);
250 
251         /**
252          * The {@code long long} native type.
253          */
254         public static final ValueLayout C_LONG_LONG = ofLongLong(LITTLE_ENDIAN, 64);
255 
256         /**
257          * The {@code float} native type.
258          */
259         public static final ValueLayout C_FLOAT = ofFloat(LITTLE_ENDIAN, 32);
260 
261         /**
262          * The {@code double} native type.
263          */
264         public static final ValueLayout C_DOUBLE = ofDouble(LITTLE_ENDIAN, 64);
265 
266         /**
267          * The {@code T*} native type.
268          */
269         public static final ValueLayout C_POINTER = ofPointer(LITTLE_ENDIAN, 64);
270 
271         /**
272          * The {@code va_list} native type, as it is passed to a function.
273          */
274         public static final MemoryLayout C_VA_LIST = AArch64.C_POINTER;
275 
276         /**
277          * The name of the layout attribute (see {@link MemoryLayout#attributes()})
278          * used to mark variadic parameters on systems such as macOS which pass these
279          * entirely on the stack. The attribute value must be a boolean.
280          */
281         public final static String STACK_VARARGS_ATTRIBUTE_NAME = "abi/aarch64/stack_varargs";
282 
283         /**
284          * Return a new memory layout which describes a variadic parameter to be
285          * passed to a function. This is only required on platforms such as macOS
286          * which pass variadic parameters entirely on the stack.
287          * @param layout the original parameter layout.
288          * @return a layout which is the same as {@code layout}, except for
289          * the extra attribute {@link #STACK_VARARGS_ATTRIBUTE_NAME}, which is set
290          * to {@code true}.
291          */
292         public static MemoryLayout asVarArg(MemoryLayout layout) {
293             return layout.withAttribute(STACK_VARARGS_ATTRIBUTE_NAME, true);
294         }
295     }
296 }
297