|
22 | 22 | *
|
23 | 23 | */
|
24 | 24 |
|
| 25 | +import java.io.IOException; |
| 26 | +import java.io.PrintStream; |
25 | 27 | import java.lang.foreign.*;
|
26 | 28 |
|
27 | 29 | import java.lang.invoke.MethodHandle;
|
| 30 | +import java.nio.file.Files; |
| 31 | +import java.nio.file.Path; |
28 | 32 | import java.util.ArrayList;
|
29 | 33 | import java.util.List;
|
30 | 34 | import java.util.Stack;
|
@@ -188,136 +192,152 @@ static <Z extends Enum<Z>> String sigCode(List<Z> elems) {
|
188 | 192 | return elems.stream().map(p -> p.name().charAt(0) + "").collect(Collectors.joining());
|
189 | 193 | }
|
190 | 194 |
|
191 |
| - static void generateStructDecl(List<StructFieldType> fields) { |
| 195 | + private static void generateStructDecl(PrintStream out, List<StructFieldType> fields) { |
192 | 196 | String structCode = sigCode(fields);
|
193 | 197 | List<String> fieldDecls = new ArrayList<>();
|
194 | 198 | for (int i = 0 ; i < fields.size() ; i++) {
|
195 | 199 | fieldDecls.add(String.format("%s p%d;", fields.get(i).typeStr, i));
|
196 | 200 | }
|
197 | 201 | String res = String.format("struct S_%s { %s };", structCode,
|
198 | 202 | fieldDecls.stream().collect(Collectors.joining(" ")));
|
199 |
| - System.out.println(res); |
| 203 | + out.println(res); |
200 | 204 | }
|
201 | 205 |
|
202 |
| - /* this can be used to generate the test header/implementation */ |
203 |
| - public static void main(String[] args) { |
204 |
| - boolean header = args.length > 0 && args[0].equals("header"); |
205 |
| - boolean upcall = args.length > 1 && args[1].equals("upcall"); |
206 |
| - if (upcall) { |
207 |
| - generateUpcalls(header); |
208 |
| - } else { |
209 |
| - generateDowncalls(header); |
210 |
| - } |
| 206 | + private static PrintStream printStream(String first) throws IOException { |
| 207 | + return new PrintStream(Files.newOutputStream(Path.of(first))); |
211 | 208 | }
|
212 | 209 |
|
213 |
| - static void generateDowncalls(boolean header) { |
214 |
| - if (header) { |
215 |
| - System.out.println( |
216 |
| - "#include \"export.h\"\n" |
217 |
| - ); |
| 210 | + // This can be used to generate the test implementation. |
| 211 | + // From the test/jdk/java/foreign directory, run this class using: |
| 212 | + // java -cp <jtreg_home>\lib\testng-7.3.0.jar --add-exports java.base/jdk.internal.foreign=ALL-UNNAMED ./CallGeneratorHelper.java |
| 213 | + // Copyright header has to be added manually, and on Windows line endings have to be changed from \r\n to just \n |
| 214 | + public static void main(String[] args) throws IOException { |
| 215 | + try (PrintStream shared = printStream("shared.h"); |
| 216 | + PrintStream libTestDowncall = printStream("libTestDowncall.c"); |
| 217 | + PrintStream libTestDowncallStack = printStream("libTestDowncallStack.c"); |
| 218 | + PrintStream libTestUpcall = printStream("libTestUpcall.c"); |
| 219 | + PrintStream libTestUpcallStack = printStream("libTestUpcallStack.c")) { |
| 220 | + generateShared(shared); |
| 221 | + generateDowncalls(libTestDowncall, false); |
| 222 | + generateDowncalls(libTestDowncallStack, true); |
| 223 | + generateUpcalls(libTestUpcall, false); |
| 224 | + generateUpcalls(libTestUpcallStack, true); |
| 225 | + } |
| 226 | + } |
218 | 227 |
|
219 |
| - for (int j = 1; j <= MAX_FIELDS; j++) { |
220 |
| - for (List<StructFieldType> fields : StructFieldType.perms(j)) { |
221 |
| - generateStructDecl(fields); |
222 |
| - } |
| 228 | + private static void generateShared(PrintStream out) { |
| 229 | + out.println(""" |
| 230 | + #include "export.h" |
| 231 | +
|
| 232 | + #ifdef __clang__ |
| 233 | + #pragma clang optimize off |
| 234 | + #elif defined __GNUC__ |
| 235 | + #pragma GCC optimize ("O0") |
| 236 | + #elif defined _MSC_BUILD |
| 237 | + #pragma optimize( "", off ) |
| 238 | + #endif |
| 239 | +
|
| 240 | + #ifdef _AIX |
| 241 | + #pragma align (natural) |
| 242 | + #endif |
| 243 | + """); |
| 244 | + |
| 245 | + for (int j = 1; j <= MAX_FIELDS; j++) { |
| 246 | + for (List<StructFieldType> fields : StructFieldType.perms(j)) { |
| 247 | + generateStructDecl(out, fields); |
223 | 248 | }
|
224 |
| - } else { |
225 |
| - System.out.println( |
226 |
| - "#include \"libh\"\n" + |
227 |
| - "#ifdef __clang__\n" + |
228 |
| - "#pragma clang optimize off\n" + |
229 |
| - "#elif defined __GNUC__\n" + |
230 |
| - "#pragma GCC optimize (\"O0\")\n" + |
231 |
| - "#elif defined _MSC_BUILD\n" + |
232 |
| - "#pragma optimize( \"\", off )\n" + |
233 |
| - "#endif\n" |
234 |
| - ); |
235 | 249 | }
|
236 | 250 |
|
| 251 | + out.print(""" |
| 252 | +
|
| 253 | + #ifdef _AIX |
| 254 | + #pragma align (reset) |
| 255 | + #endif |
| 256 | + """); |
| 257 | + } |
| 258 | + |
| 259 | + private static void generateDowncalls(PrintStream out, boolean stack) { |
| 260 | + out.println("#include \"shared.h\"\n"); |
| 261 | + |
237 | 262 | for (Object[] downcall : functions()) {
|
238 |
| - String fName = (String)downcall[0]; |
239 |
| - Ret r = (Ret)downcall[1]; |
| 263 | + String fName = (String)downcall[1]; |
| 264 | + Ret r = (Ret)downcall[2]; |
240 | 265 | @SuppressWarnings("unchecked")
|
241 |
| - List<ParamType> ptypes = (List<ParamType>)downcall[2]; |
| 266 | + List<ParamType> ptypes = (List<ParamType>)downcall[3]; |
242 | 267 | @SuppressWarnings("unchecked")
|
243 |
| - List<StructFieldType> fields = (List<StructFieldType>)downcall[3]; |
244 |
| - generateDowncallFunction(fName, r, ptypes, fields, header); |
| 268 | + List<StructFieldType> fields = (List<StructFieldType>)downcall[4]; |
| 269 | + generateDowncallFunction(out, fName, r, ptypes, fields, stack); |
245 | 270 | }
|
246 | 271 | }
|
247 | 272 |
|
248 |
| - static void generateDowncallFunction(String fName, Ret ret, List<ParamType> params, List<StructFieldType> fields, boolean declOnly) { |
| 273 | + private static final List<String> stackParamTypes = Stream.concat(Stream.generate(() -> "long long").limit(8), |
| 274 | + Stream.generate(() -> "double").limit(8)).toList(); |
| 275 | + private static final List<String> stackParamNames = IntStream.range(0, 16).mapToObj(i -> "pf" + i).toList(); |
| 276 | + private static final List<String> stackParamDecls = IntStream.range(0, 16) |
| 277 | + .mapToObj(i -> stackParamTypes.get(i) + " " + stackParamNames.get(i)).toList(); |
| 278 | + |
| 279 | + private static void generateDowncallFunction(PrintStream out, String fName, Ret ret, List<ParamType> params, List<StructFieldType> fields, boolean stack) { |
249 | 280 | String retType = ret == Ret.VOID ? "void" : params.get(0).type(fields);
|
250 | 281 | List<String> paramDecls = new ArrayList<>();
|
| 282 | + if (stack) { |
| 283 | + paramDecls.addAll(stackParamDecls); |
| 284 | + } |
251 | 285 | for (int i = 0 ; i < params.size() ; i++) {
|
252 | 286 | paramDecls.add(String.format("%s p%d", params.get(i).type(fields), i));
|
253 | 287 | }
|
254 | 288 | String sig = paramDecls.isEmpty() ?
|
255 | 289 | "void" :
|
256 | 290 | paramDecls.stream().collect(Collectors.joining(", "));
|
257 | 291 | String body = ret == Ret.VOID ? "{ }" : "{ return p0; }";
|
258 |
| - String res = String.format("EXPORT %s f%s(%s) %s", retType, fName, |
259 |
| - sig, declOnly ? ";" : body); |
260 |
| - System.out.println(res); |
| 292 | + String res = String.format("EXPORT %s %s%s(%s) %s", retType, stack ? "s" : "", fName, |
| 293 | + sig, body); |
| 294 | + out.println(res); |
261 | 295 | }
|
262 | 296 |
|
263 |
| - static void generateUpcalls(boolean header) { |
264 |
| - if (header) { |
265 |
| - System.out.println( |
266 |
| - "#include \"export.h\"\n" |
267 |
| - ); |
268 |
| - |
269 |
| - for (int j = 1; j <= MAX_FIELDS; j++) { |
270 |
| - for (List<StructFieldType> fields : StructFieldType.perms(j)) { |
271 |
| - generateStructDecl(fields); |
272 |
| - } |
273 |
| - } |
274 |
| - } else { |
275 |
| - System.out.println( |
276 |
| - "#include \"libh\"\n" + |
277 |
| - "#ifdef __clang__\n" + |
278 |
| - "#pragma clang optimize off\n" + |
279 |
| - "#elif defined __GNUC__\n" + |
280 |
| - "#pragma GCC optimize (\"O0\")\n" + |
281 |
| - "#elif defined _MSC_BUILD\n" + |
282 |
| - "#pragma optimize( \"\", off )\n" + |
283 |
| - "#endif\n" |
284 |
| - ); |
285 |
| - } |
| 297 | + private static void generateUpcalls(PrintStream out, boolean stack) { |
| 298 | + out.println("#include \"shared.h\"\n"); |
286 | 299 |
|
287 | 300 | for (Object[] downcall : functions()) {
|
288 |
| - String fName = (String)downcall[0]; |
289 |
| - Ret r = (Ret)downcall[1]; |
| 301 | + String fName = (String)downcall[1]; |
| 302 | + Ret r = (Ret)downcall[2]; |
290 | 303 | @SuppressWarnings("unchecked")
|
291 |
| - List<ParamType> ptypes = (List<ParamType>)downcall[2]; |
| 304 | + List<ParamType> ptypes = (List<ParamType>)downcall[3]; |
292 | 305 | @SuppressWarnings("unchecked")
|
293 |
| - List<StructFieldType> fields = (List<StructFieldType>)downcall[3]; |
294 |
| - generateUpcallFunction(fName, r, ptypes, fields, header); |
| 306 | + List<StructFieldType> fields = (List<StructFieldType>)downcall[4]; |
| 307 | + generateUpcallFunction(out, fName, r, ptypes, fields, stack); |
295 | 308 | }
|
296 | 309 | }
|
297 | 310 |
|
298 |
| - static void generateUpcallFunction(String fName, Ret ret, List<ParamType> params, List<StructFieldType> fields, boolean declOnly) { |
| 311 | + private static void generateUpcallFunction(PrintStream out, String fName, Ret ret, List<ParamType> params, List<StructFieldType> fields, boolean stack) { |
299 | 312 | String retType = ret == Ret.VOID ? "void" : params.get(0).type(fields);
|
300 | 313 | List<String> paramDecls = new ArrayList<>();
|
| 314 | + if (stack) { |
| 315 | + paramDecls.addAll(stackParamDecls); |
| 316 | + } |
301 | 317 | for (int i = 0 ; i < params.size() ; i++) {
|
302 | 318 | paramDecls.add(String.format("%s p%d", params.get(i).type(fields), i));
|
303 | 319 | }
|
304 |
| - String paramNames = IntStream.range(0, params.size()) |
305 |
| - .mapToObj(i -> "p" + i) |
306 |
| - .collect(Collectors.joining(",")); |
| 320 | + Stream<String> prefixParamNames = stack ? stackParamNames.stream() : Stream.of(); |
| 321 | + String paramNames = Stream.concat(prefixParamNames, IntStream.range(0, params.size()) |
| 322 | + .mapToObj(i -> "p" + i)) |
| 323 | + .collect(Collectors.joining(", ")); |
307 | 324 | String sig = paramDecls.isEmpty() ?
|
308 | 325 | "" :
|
309 | 326 | paramDecls.stream().collect(Collectors.joining(", ")) + ", ";
|
310 | 327 | String body = String.format(ret == Ret.VOID ? "{ cb(%s); }" : "{ return cb(%s); }", paramNames);
|
311 | 328 | List<String> paramTypes = params.stream().map(p -> p.type(fields)).collect(Collectors.toList());
|
| 329 | + if (stack) { |
| 330 | + paramTypes.addAll(0, stackParamTypes); |
| 331 | + } |
312 | 332 | String cbSig = paramTypes.isEmpty() ?
|
313 | 333 | "void" :
|
314 | 334 | paramTypes.stream().collect(Collectors.joining(", "));
|
315 | 335 | String cbParam = String.format("%s (*cb)(%s)",
|
316 | 336 | retType, cbSig);
|
317 | 337 |
|
318 |
| - String res = String.format("EXPORT %s %s(%s %s) %s", retType, fName, |
319 |
| - sig, cbParam, declOnly ? ";" : body); |
320 |
| - System.out.println(res); |
| 338 | + String res = String.format("EXPORT %s %s%s(%s %s) %s", retType, stack ? "s" : "", fName, |
| 339 | + sig, cbParam, body); |
| 340 | + out.println(res); |
321 | 341 | }
|
322 | 342 |
|
323 | 343 | //helper methods
|
|
1 commit comments
openjdk-notifier[bot] commentedon Jan 13, 2025
Review
Issues