RFR: 7904079: Fix setting up length parameter for CXUnsavedFiles Struct [v4]
Jorn Vernee
jvernee at openjdk.org
Thu Sep 18 15:22:23 UTC 2025
On Thu, 18 Sep 2025 12:17:48 GMT, Varada M <varadam at openjdk.org> wrote:
>> CXUnsavedFile struct contains three members, first two are pointers and last one is unsigned long. When jextract makes downcall to clang_reparseTranslationUnit_Impl it sets up the third parameter in the struct incorrectly. It sets INT instead of LONG so on big endian platform the parameter will be set differently.
>>
>> JBS Issue : [CODETOOLS-7904079](https://bugs.openjdk.org/browse/CODETOOLS-7904079)
>
> Varada M has updated the pull request incrementally with one additional commit since the last revision:
>
> 7904079: Fix setting up length parameter for CXUnsavedFiles Struct
Thanks for the updates! Some more changes are needed though. Tests on Windows currently fail with a class cast exception when initializing the `CXUnsavedFile` class:
...
Caused by: java.lang.ClassCastException: class jdk.internal.foreign.layout.ValueLayouts$OfIntImpl cannot be cast to class java.lang.foreign.ValueLayout$OfLong (jdk.internal.foreign.layout.ValueLayouts$OfIntImpl and java.lang.foreign.ValueLayout$OfLong are in module java.base of loader 'bootstrap')
at org.openjdk.jextract at 23/org.openjdk.jextract.clang.libclang.CXUnsavedFile.<clinit>(CXUnsavedFile.java:156)
... 39 more
I think it would be best to modify `CXUnsavedFile` to tweak the layout based on the size of `C_LONG`. Besides the changes I mentioned inline, I have the following changes locally to make this work:
diff --git a/src/main/java/org/openjdk/jextract/clang/libclang/CXUnsavedFile.java b/src/main/java/org/openjdk/jextract/clang/libclang/CXUnsavedFile.java
index 12d25de..a0ebb98 100644
--- a/src/main/java/org/openjdk/jextract/clang/libclang/CXUnsavedFile.java
+++ b/src/main/java/org/openjdk/jextract/clang/libclang/CXUnsavedFile.java
@@ -52,11 +52,20 @@ public class CXUnsavedFile {
// Should not be called directly
}
- private static final GroupLayout $LAYOUT = MemoryLayout.structLayout(
- Index_h.C_POINTER.withName("Filename"),
- Index_h.C_POINTER.withName("Contents"),
- Index_h.C_LONG.withName("Length")
- ).withName("CXUnsavedFile");
+ private static final GroupLayout $LAYOUT = (switch (Index_h.C_LONG) {
+ case OfInt _ -> MemoryLayout.structLayout(
+ Index_h.C_POINTER.withName("Filename"),
+ Index_h.C_POINTER.withName("Contents"),
+ Index_h.C_LONG.withName("Length"),
+ MemoryLayout.paddingLayout(4)
+ );
+ case OfLong _ -> MemoryLayout.structLayout(
+ Index_h.C_POINTER.withName("Filename"),
+ Index_h.C_POINTER.withName("Contents"),
+ Index_h.C_LONG.withName("Length")
+ );
+ default -> throw new IllegalStateException("Unhandled layout: " + Index_h.C_LONG);
+ }).withName("CXUnsavedFile");
/**
* The layout of this struct
@@ -153,7 +162,7 @@ public class CXUnsavedFile {
struct.set(Contents$LAYOUT, Contents$OFFSET, fieldValue);
}
- private static final OfLong Length$LAYOUT = (OfLong)$LAYOUT.select(groupElement("Length"));
+ private static final ValueLayout Length$LAYOUT = (ValueLayout) $LAYOUT.select(groupElement("Length"));
/**
* Layout for field:
@@ -161,7 +170,7 @@ public class CXUnsavedFile {
* unsigned long Length
* }
*/
- public static final OfLong Length$layout() {
+ public static final ValueLayout Length$layout() {
return Length$LAYOUT;
}
@@ -184,7 +193,11 @@ public class CXUnsavedFile {
* }
*/
public static long Length(MemorySegment struct) {
- return struct.get(Length$LAYOUT, Length$OFFSET);
+ return switch (Length$LAYOUT) {
+ case OfInt l -> struct.get(l, Length$OFFSET);
+ case OfLong l -> struct.get(l, Length$OFFSET);
+ default -> throw new IllegalStateException("Unhandled layout: " + Length$LAYOUT);
+ };
}
/**
@@ -194,7 +207,11 @@ public class CXUnsavedFile {
* }
*/
public static void Length(MemorySegment struct, long fieldValue) {
- struct.set(Length$LAYOUT, Length$OFFSET, fieldValue);
+ switch (Length$LAYOUT) {
+ case OfInt l -> struct.set(l, Length$OFFSET, Math.toIntExact(fieldValue));
+ case OfLong l -> struct.set(l, Length$OFFSET, fieldValue);
+ default -> throw new IllegalStateException("Unhandled layout: " + Length$LAYOUT);
+ }
}
/**
Please also update the copyright years of the edited files.
I'll see about getting the GitHub actions working on Windows again.
src/main/java/org/openjdk/jextract/clang/TranslationUnit.java line 96:
> 94: else {
> 95: start.set((ValueLayout.OfLong) C_LONG, LENGTH_OFFSET, (long) inMemoryFiles[i].contents.length());
> 96: }
There is some history here, but looking at this again, I think it would be better to use the setters that jextract generates here.
CXUnsavedFile.Filename(start, arena.allocateFrom(inMemoryFiles[i].file));
CXUnsavedFile.Contents(start, arena.allocateFrom(inMemoryFiles[i].contents));
CXUnsavedFile.Length(start, inMemoryFiles[i].contents.length());
src/main/java/org/openjdk/jextract/clang/libclang/Index_h.java line 111:
> 109: }
> 110: }
> 111:
I think you can just cast here
Suggestion:
public static final ValueLayout C_LONG = (ValueLayout) Linker.nativeLinker().canonicalLayouts().get("long");
-------------
PR Review: https://git.openjdk.org/jextract/pull/289#pullrequestreview-3239416895
PR Review Comment: https://git.openjdk.org/jextract/pull/289#discussion_r2359484229
PR Review Comment: https://git.openjdk.org/jextract/pull/289#discussion_r2359037109
More information about the jextract-dev
mailing list