From duke at openjdk.org Tue Nov 4 21:00:33 2025 From: duke at openjdk.org (duke) Date: Tue, 4 Nov 2025 21:00:33 GMT Subject: Withdrawn: 7903947: Access to function pointers in structs could be streamlined In-Reply-To: References: Message-ID: <2hYkSf_5FT_kEKRrbcCcmMmUhKY82SW9YAvdlvgdJBM=.94cc88cb-99d4-40f1-a9cf-5fecbd98d515@github.com> On Wed, 23 Jul 2025 12:37:47 GMT, Nizar Benalla wrote: > Please review this patch to add a new option where you can generate an direct invoker methods. This feature is intended to be used on structs that are just a collection of functions we had like to call. > > If this feature is used, we remove the getter to avoid name collisions as we assume this is similar to an interface. > > Changes to `GUIDE.md` have been intentionally left out from this initial patch to make reviews easier. > > > struct Foo { > struct Bar (*a)(void); > struct Bar (*b)(int); > }; > > > Before > > > var foo = alloc_callback_h.foo(); > > var barA = Foo.a.invoke(Foo.a(foo), arena); > var barB = Foo.b.invoke(Foo.b(foo), arena, 100); > > > After > > > var foo = alloc_callback_h.foo(); > > var barA = Foo.a(foo, arena); > var barB = Foo.b(foo, arena, 100); This pull request has been closed without being integrated. ------------- PR: https://git.openjdk.org/jextract/pull/287 From duke at openjdk.org Sun Nov 9 15:49:36 2025 From: duke at openjdk.org (Vivek Narang) Date: Sun, 9 Nov 2025 15:49:36 GMT Subject: RFR: Generate Java enums In-Reply-To: References: Message-ID: <0GCzcCm8DlpQLf6fHRlK49E7tmo1F3wOg9mBPiy8C7c=.07f17ebb-8651-479d-a38c-9e20a446cdd7@github.com> On Fri, 20 Jun 2025 17:09:19 GMT, Vivek Narang wrote: > We are using jextract in our [cuVS Java](https://github.com/rapidsai/cuvs/tree/branch-25.08/java) project. As of now, jextract generates individual getter functions for the C enums. This results in code where it is difficult to disambiguate which getter functions are logically grouped together for a particular Enum. Additionally, given the lack of this capability, we also have to manually create and maintain Java enums for each enum in the C layer. > > In this PR, I wish to introduce an option to additionally generate Java enums by passing an optional flag `--generate-java-enums`. In case a Java user wishes to use bitwise operations on the enums, they can use the enum's `.ordinal()` method for this. The original static getter methods will still be generated as before. > > Example C enum: > > enum SIZE { > S, > M, > L > }; > > Produces the following with jextract: > > private static final int S = (int)0L; > public static int S() { > return S; > } > > private static final int M = (int)1L; > public static int M() { > return M; > } > > private static final int L = (int)2L; > public static int L() { > return L; > } > > With this feature enabled using the `--generate-java-enums` flag, the following enum is generated (in addition to the above): > > public enum Size { > S(0), > M(1), > L(2); > > private final int value; > > private Size(int value) {; > this.value = value; > } > > public int getValue() { > return this.value; > } > } > > This PR is created against the `jdk22` branch. I will rebase it to `master` branch if needed. Apologies for the significant delay of several weeks on this. I will revisit this feature and the suggestions/feedback and will create a fresh PR (if needed) in the near future. Thanks! ------------- PR Comment: https://git.openjdk.org/jextract/pull/284#issuecomment-3508467013 From duke at openjdk.org Sun Nov 9 15:49:37 2025 From: duke at openjdk.org (Vivek Narang) Date: Sun, 9 Nov 2025 15:49:37 GMT Subject: Withdrawn: Generate Java enums In-Reply-To: References: Message-ID: On Fri, 20 Jun 2025 17:09:19 GMT, Vivek Narang wrote: > We are using jextract in our [cuVS Java](https://github.com/rapidsai/cuvs/tree/branch-25.08/java) project. As of now, jextract generates individual getter functions for the C enums. This results in code where it is difficult to disambiguate which getter functions are logically grouped together for a particular Enum. Additionally, given the lack of this capability, we also have to manually create and maintain Java enums for each enum in the C layer. > > In this PR, I wish to introduce an option to additionally generate Java enums by passing an optional flag `--generate-java-enums`. In case a Java user wishes to use bitwise operations on the enums, they can use the enum's `.ordinal()` method for this. The original static getter methods will still be generated as before. > > Example C enum: > > enum SIZE { > S, > M, > L > }; > > Produces the following with jextract: > > private static final int S = (int)0L; > public static int S() { > return S; > } > > private static final int M = (int)1L; > public static int M() { > return M; > } > > private static final int L = (int)2L; > public static int L() { > return L; > } > > With this feature enabled using the `--generate-java-enums` flag, the following enum is generated (in addition to the above): > > public enum Size { > S(0), > M(1), > L(2); > > private final int value; > > private Size(int value) {; > this.value = value; > } > > public int getValue() { > return this.value; > } > } > > This PR is created against the `jdk22` branch. I will rebase it to `master` branch if needed. This pull request has been closed without being integrated. ------------- PR: https://git.openjdk.org/jextract/pull/284 From duke at openjdk.org Tue Nov 11 19:52:09 2025 From: duke at openjdk.org (devjeonghwan) Date: Tue, 11 Nov 2025 19:52:09 GMT Subject: RFR: Fix incorrect base offset handling in generated array field accessors Message-ID: #### 1. Status Quo Array field accessors generated by jextract (e.g., for `int arr[3]`) currently use a fixed base offset `0L` in `VarHandle.get/set` or `MethodHandle.invokeExact`. This causes all array accesses to start from the beginning of the struct, ignoring the field?s actual offset. #### 2. Problem Because of the missing base offset, writing to array elements in nested structs or unions can overwrite unrelated fields in the same structure. For example, updating `maxBlockDimension[1]` could corrupt `computeCapabilityMajor` or other preceding fields. typedef struct CudaDeviceInfo_st { int id; int computeCapabilityMajor; int computeCapabilityMinor; int multiprocessorCount; int warpSize; int maxThreadsPerBlock; int maxThreadsPerMultiprocessor; int maxBlockDimension[3]; int maxGridDimension[3]; bool unifiedAddressing; bool integratedMemory; } CudaDeviceInfo; #### 3. Fix This patch updates `emitFieldArrayGetter` and `emitFieldArraySetter` to pass the correct field offset (`offsetField`) to all generated array accessors. This ensures correct addressing for both primitive and struct/union element arrays. **Example:** // Before varHandle.get(struct, 0L, index); // After varHandle.get(struct, fieldOffset, index); #### 4. Additional Notes While the more idiomatic FFM approach of generating 'path-based' `VarHandle`s (e.g., `LAYOUT.varHandle(groupElement(...), ...)`) was considered, this patch takes a minimal-change approach. So It retains the existing handle and fixes the bug by passing the `fieldOffset` as the base offset (replacing `0L`). If the path-based `VarHandle` approach is preferred, I can rework this. #### 5. Testing New test cases were added to verify correct offset handling for: * Primitive arrays in structs * Struct arrays in structs * Struct arrays inside unions All tests pass locally. ------------- Commit messages: - Update copyright year to 2025 - Simplify test method names for clarity - Fix nits - Add test for struct and union array field handling - Update parameter type `Variable` to `Declaration.Variable` in `emitFieldArrayGetter` and `emitFieldArraySetter` - Add `offsetField` parameter to emit method for `FieldArray` getter and setter Changes: https://git.openjdk.org/jextract/pull/294/files Webrev: https://webrevs.openjdk.org/?repo=jextract&pr=294&range=00 Stats: 245 lines in 3 files changed: 235 ins; 0 del; 10 mod Patch: https://git.openjdk.org/jextract/pull/294.diff Fetch: git fetch https://git.openjdk.org/jextract.git pull/294/head:pull/294 PR: https://git.openjdk.org/jextract/pull/294 From duke at openjdk.org Tue Nov 11 23:07:39 2025 From: duke at openjdk.org (devjeonghwan) Date: Tue, 11 Nov 2025 23:07:39 GMT Subject: RFR: Fix incorrect base offset handling in generated array field accessors In-Reply-To: References: Message-ID: On Fri, 7 Nov 2025 01:15:32 GMT, devjeonghwan wrote: > #### 1. Status Quo > > Array field accessors generated by jextract (e.g., for `int arr[3]`) currently use a fixed base offset `0L` in `VarHandle.get/set` or `MethodHandle.invokeExact`. > This causes all array accesses to start from the beginning of the struct, ignoring the field?s actual offset. > > #### 2. Problem > > Because of the missing base offset, writing to array elements in nested structs or unions can overwrite unrelated fields in the same structure. > For example, updating `maxBlockDimension[1]` could corrupt `computeCapabilityMajor` or other preceding fields. > > typedef struct CudaDeviceInfo_st > { > int id; > > int computeCapabilityMajor; > int computeCapabilityMinor; > int multiprocessorCount; > > int warpSize; > int maxThreadsPerBlock; > int maxThreadsPerMultiprocessor; > int maxBlockDimension[3]; > int maxGridDimension[3]; > > bool unifiedAddressing; > bool integratedMemory; > } CudaDeviceInfo; > > > #### 3. Fix > > This patch updates `emitFieldArrayGetter` and `emitFieldArraySetter` to pass the correct field offset (`offsetField`) to all generated array accessors. > This ensures correct addressing for both primitive and struct/union element arrays. > > **Example:** > > > // Before > varHandle.get(struct, 0L, index); > > // After > varHandle.get(struct, fieldOffset, index); > > > #### 4. Additional Notes > > While the more idiomatic FFM approach of generating 'path-based' `VarHandle`s (e.g., `LAYOUT.varHandle(groupElement(...), ...)`) was considered, this patch takes a minimal-change approach. So It retains the existing handle and fixes the bug by passing the `fieldOffset` as the base offset (replacing `0L`). > > If the path-based `VarHandle` approach is preferred, I can rework this. > > #### 5. Testing > > New test cases were added to verify correct offset handling for: > > * Primitive arrays in structs > * Struct arrays in structs > * Struct arrays inside unions > > All tests pass locally. Here is path-based?`VarHandle`?approach https://github.com/devjeonghwan/jextract/commit/4d7bcbab98ca71fa626ef86b455126757319aa1f ------------- PR Comment: https://git.openjdk.org/jextract/pull/294#issuecomment-3519062995 From mcimadamore at openjdk.org Wed Nov 12 10:51:43 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Wed, 12 Nov 2025 10:51:43 GMT Subject: RFR: Fix incorrect base offset handling in generated array field accessors In-Reply-To: References: Message-ID: On Fri, 7 Nov 2025 01:15:32 GMT, devjeonghwan wrote: > #### 1. Status Quo > > Array field accessors generated by jextract (e.g., for `int arr[3]`) currently use a fixed base offset `0L` in `VarHandle.get/set` or `MethodHandle.invokeExact`. > This causes all array accesses to start from the beginning of the struct, ignoring the field?s actual offset. > > #### 2. Problem > > Because of the missing base offset, writing to array elements in nested structs or unions can overwrite unrelated fields in the same structure. > For example, updating `maxBlockDimension[1]` could corrupt `computeCapabilityMajor` or other preceding fields. > > typedef struct CudaDeviceInfo_st > { > int id; > > int computeCapabilityMajor; > int computeCapabilityMinor; > int multiprocessorCount; > > int warpSize; > int maxThreadsPerBlock; > int maxThreadsPerMultiprocessor; > int maxBlockDimension[3]; > int maxGridDimension[3]; > > bool unifiedAddressing; > bool integratedMemory; > } CudaDeviceInfo; > > > #### 3. Fix > > This patch updates `emitFieldArrayGetter` and `emitFieldArraySetter` to pass the correct field offset (`offsetField`) to all generated array accessors. > This ensures correct addressing for both primitive and struct/union element arrays. > > **Example:** > > > // Before > varHandle.get(struct, 0L, index); > > // After > varHandle.get(struct, fieldOffset, index); > > > #### 4. Additional Notes > > While the more idiomatic FFM approach of generating 'path-based' `VarHandle`s (e.g., `LAYOUT.varHandle(groupElement(...), ...)`) was considered, this patch takes a minimal-change approach. So It retains the existing handle and fixes the bug by passing the `fieldOffset` as the base offset (replacing `0L`). > > If the path-based `VarHandle` approach is preferred, I can rework this. > > #### 5. Testing > > New test cases were added to verify correct offset handling for: > > * Primitive arrays in structs > * Struct arrays in structs > * Struct arrays inside unions > > All tests pass locally. Good fix, and well spotted! This bug probably sneaked in when we passed from path-based var handles to using offsets. Marked as reviewed by mcimadamore (Reviewer). test/jtreg/generator/testStructArrayFields/TestStructArrayFields.java line 125: > 123: assertTrue(offTail < offFlag); > 124: > 125: assertEquals(3L * Integer.BYTES, Record_st.arr$layout().byteSize()); Maybe better to use C_INT * 3 here? ------------- PR Review: https://git.openjdk.org/jextract/pull/294#pullrequestreview-3452824766 PR Review: https://git.openjdk.org/jextract/pull/294#pullrequestreview-3452829281 PR Review Comment: https://git.openjdk.org/jextract/pull/294#discussion_r2517820621 From duke at openjdk.org Wed Nov 12 11:20:44 2025 From: duke at openjdk.org (devjeonghwan) Date: Wed, 12 Nov 2025 11:20:44 GMT Subject: RFR: Fix incorrect base offset handling in generated array field accessors In-Reply-To: References: Message-ID: <9t2jJ8pdUbCZv-KI0WShT5k0hnFlkxKcZ_RAAY00hIY=.42b2a093-47f6-4d47-964b-55ee4572e32b@github.com> On Wed, 12 Nov 2025 10:49:06 GMT, Maurizio Cimadamore wrote: >> #### 1. Status Quo >> >> Array field accessors generated by jextract (e.g., for `int arr[3]`) currently use a fixed base offset `0L` in `VarHandle.get/set` or `MethodHandle.invokeExact`. >> This causes all array accesses to start from the beginning of the struct, ignoring the field?s actual offset. >> >> #### 2. Problem >> >> Because of the missing base offset, writing to array elements in nested structs or unions can overwrite unrelated fields in the same structure. >> For example, updating `maxBlockDimension[1]` could corrupt `computeCapabilityMajor` or other preceding fields. >> >> typedef struct CudaDeviceInfo_st >> { >> int id; >> >> int computeCapabilityMajor; >> int computeCapabilityMinor; >> int multiprocessorCount; >> >> int warpSize; >> int maxThreadsPerBlock; >> int maxThreadsPerMultiprocessor; >> int maxBlockDimension[3]; >> int maxGridDimension[3]; >> >> bool unifiedAddressing; >> bool integratedMemory; >> } CudaDeviceInfo; >> >> >> #### 3. Fix >> >> This patch updates `emitFieldArrayGetter` and `emitFieldArraySetter` to pass the correct field offset (`offsetField`) to all generated array accessors. >> This ensures correct addressing for both primitive and struct/union element arrays. >> >> **Example:** >> >> >> // Before >> varHandle.get(struct, 0L, index); >> >> // After >> varHandle.get(struct, fieldOffset, index); >> >> >> #### 4. Additional Notes >> >> While the more idiomatic FFM approach of generating 'path-based' `VarHandle`s (e.g., `LAYOUT.varHandle(groupElement(...), ...)`) was considered, this patch takes a minimal-change approach. So It retains the existing handle and fixes the bug by passing the `fieldOffset` as the base offset (replacing `0L`). >> >> If the path-based `VarHandle` approach is preferred, I can rework this. >> >> #### 5. Testing >> >> New test cases were added to verify correct offset handling for: >> >> * Primitive arrays in structs >> * Struct arrays in structs >> * Struct arrays inside unions >> >> All tests pass locally. > > Marked as reviewed by mcimadamore (Reviewer). @mcimadamore Which approach do you think is more correct? `emitFieldArrayGetter`, `emitFieldArraySetter` patch or `VarHandle` patch? > test/jtreg/generator/testStructArrayFields/TestStructArrayFields.java line 125: > >> 123: assertTrue(offTail < offFlag); >> 124: >> 125: assertEquals(3L * Integer.BYTES, Record_st.arr$layout().byteSize()); > > Maybe better to use C_INT * 3 here? Thx! ------------- PR Comment: https://git.openjdk.org/jextract/pull/294#issuecomment-3521425618 PR Review Comment: https://git.openjdk.org/jextract/pull/294#discussion_r2517908751 From mcimadamore at openjdk.org Wed Nov 12 11:39:42 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Wed, 12 Nov 2025 11:39:42 GMT Subject: RFR: Fix incorrect base offset handling in generated array field accessors In-Reply-To: References: Message-ID: On Wed, 12 Nov 2025 10:49:06 GMT, Maurizio Cimadamore wrote: >> #### 1. Status Quo >> >> Array field accessors generated by jextract (e.g., for `int arr[3]`) currently use a fixed base offset `0L` in `VarHandle.get/set` or `MethodHandle.invokeExact`. >> This causes all array accesses to start from the beginning of the struct, ignoring the field?s actual offset. >> >> #### 2. Problem >> >> Because of the missing base offset, writing to array elements in nested structs or unions can overwrite unrelated fields in the same structure. >> For example, updating `maxBlockDimension[1]` could corrupt `computeCapabilityMajor` or other preceding fields. >> >> typedef struct CudaDeviceInfo_st >> { >> int id; >> >> int computeCapabilityMajor; >> int computeCapabilityMinor; >> int multiprocessorCount; >> >> int warpSize; >> int maxThreadsPerBlock; >> int maxThreadsPerMultiprocessor; >> int maxBlockDimension[3]; >> int maxGridDimension[3]; >> >> bool unifiedAddressing; >> bool integratedMemory; >> } CudaDeviceInfo; >> >> >> #### 3. Fix >> >> This patch updates `emitFieldArrayGetter` and `emitFieldArraySetter` to pass the correct field offset (`offsetField`) to all generated array accessors. >> This ensures correct addressing for both primitive and struct/union element arrays. >> >> **Example:** >> >> >> // Before >> varHandle.get(struct, 0L, index); >> >> // After >> varHandle.get(struct, fieldOffset, index); >> >> >> #### 4. Additional Notes >> >> While the more idiomatic FFM approach of generating 'path-based' `VarHandle`s (e.g., `LAYOUT.varHandle(groupElement(...), ...)`) was considered, this patch takes a minimal-change approach. So It retains the existing handle and fixes the bug by passing the `fieldOffset` as the base offset (replacing `0L`). >> >> If the path-based `VarHandle` approach is preferred, I can rework this. >> >> #### 5. Testing >> >> New test cases were added to verify correct offset handling for: >> >> * Primitive arrays in structs >> * Struct arrays in structs >> * Struct arrays inside unions >> >> All tests pass locally. > > Marked as reviewed by mcimadamore (Reviewer). > @mcimadamore Which approach do you think is more correct? `emitFieldArrayGetter`, `emitFieldArraySetter` patch or `VarHandle` patch? I think the one you have in this PR is more consistent with how the rest of jextract code works. If we do a more global switch to path-based var handles, we might reconsider. (the reason we don't use path-based var handle is we'd like to limit the number of dynamic classes being generated -- for big headers it might make a difference) ------------- PR Comment: https://git.openjdk.org/jextract/pull/294#issuecomment-3521487074 From duke at openjdk.org Wed Nov 12 12:03:33 2025 From: duke at openjdk.org (devjeonghwan) Date: Wed, 12 Nov 2025 12:03:33 GMT Subject: RFR: Fix incorrect base offset handling in generated array field accessors [v2] In-Reply-To: References: Message-ID: > #### 1. Status Quo > > Array field accessors generated by jextract (e.g., for `int arr[3]`) currently use a fixed base offset `0L` in `VarHandle.get/set` or `MethodHandle.invokeExact`. > This causes all array accesses to start from the beginning of the struct, ignoring the field?s actual offset. > > #### 2. Problem > > Because of the missing base offset, writing to array elements in nested structs or unions can overwrite unrelated fields in the same structure. > For example, updating `maxBlockDimension[1]` could corrupt `computeCapabilityMajor` or other preceding fields. > > typedef struct CudaDeviceInfo_st > { > int id; > > int computeCapabilityMajor; > int computeCapabilityMinor; > int multiprocessorCount; > > int warpSize; > int maxThreadsPerBlock; > int maxThreadsPerMultiprocessor; > int maxBlockDimension[3]; > int maxGridDimension[3]; > > bool unifiedAddressing; > bool integratedMemory; > } CudaDeviceInfo; > > > #### 3. Fix > > This patch updates `emitFieldArrayGetter` and `emitFieldArraySetter` to pass the correct field offset (`offsetField`) to all generated array accessors. > This ensures correct addressing for both primitive and struct/union element arrays. > > **Example:** > > > // Before > varHandle.get(struct, 0L, index); > > // After > varHandle.get(struct, fieldOffset, index); > > > #### 4. Additional Notes > > While the more idiomatic FFM approach of generating 'path-based' `VarHandle`s (e.g., `LAYOUT.varHandle(groupElement(...), ...)`) was considered, this patch takes a minimal-change approach. So It retains the existing handle and fixes the bug by passing the `fieldOffset` as the base offset (replacing `0L`). > > If the path-based `VarHandle` approach is preferred, I can rework this. > > #### 5. Testing > > New test cases were added to verify correct offset handling for: > > * Primitive arrays in structs > * Struct arrays in structs > * Struct arrays inside unions > > All tests pass locally. devjeonghwan has updated the pull request incrementally with one additional commit since the last revision: Update test to use `C_INT.byteSize()` for array field layout assertions ------------- Changes: - all: https://git.openjdk.org/jextract/pull/294/files - new: https://git.openjdk.org/jextract/pull/294/files/fc604cae..9c4efbf3 Webrevs: - full: https://webrevs.openjdk.org/?repo=jextract&pr=294&range=01 - incr: https://webrevs.openjdk.org/?repo=jextract&pr=294&range=00-01 Stats: 2 lines in 1 file changed: 0 ins; 0 del; 2 mod Patch: https://git.openjdk.org/jextract/pull/294.diff Fetch: git fetch https://git.openjdk.org/jextract.git pull/294/head:pull/294 PR: https://git.openjdk.org/jextract/pull/294 From duke at openjdk.org Wed Nov 12 12:11:00 2025 From: duke at openjdk.org (devjeonghwan) Date: Wed, 12 Nov 2025 12:11:00 GMT Subject: RFR: Fix incorrect base offset handling in generated array field accessors [v3] In-Reply-To: References: Message-ID: <1vru1uityFJvLZmXX0dyL6D4nrHLptl3NdYgVDZXGso=.065af81c-745e-47a0-aae6-96f2f2443a53@github.com> > #### 1. Status Quo > > Array field accessors generated by jextract (e.g., for `int arr[3]`) currently use a fixed base offset `0L` in `VarHandle.get/set` or `MethodHandle.invokeExact`. > This causes all array accesses to start from the beginning of the struct, ignoring the field?s actual offset. > > #### 2. Problem > > Because of the missing base offset, writing to array elements in nested structs or unions can overwrite unrelated fields in the same structure. > For example, updating `maxBlockDimension[1]` could corrupt `computeCapabilityMajor` or other preceding fields. > > typedef struct CudaDeviceInfo_st > { > int id; > > int computeCapabilityMajor; > int computeCapabilityMinor; > int multiprocessorCount; > > int warpSize; > int maxThreadsPerBlock; > int maxThreadsPerMultiprocessor; > int maxBlockDimension[3]; > int maxGridDimension[3]; > > bool unifiedAddressing; > bool integratedMemory; > } CudaDeviceInfo; > > > #### 3. Fix > > This patch updates `emitFieldArrayGetter` and `emitFieldArraySetter` to pass the correct field offset (`offsetField`) to all generated array accessors. > This ensures correct addressing for both primitive and struct/union element arrays. > > **Example:** > > > // Before > varHandle.get(struct, 0L, index); > > // After > varHandle.get(struct, fieldOffset, index); > > > #### 4. Additional Notes > > While the more idiomatic FFM approach of generating 'path-based' `VarHandle`s (e.g., `LAYOUT.varHandle(groupElement(...), ...)`) was considered, this patch takes a minimal-change approach. So It retains the existing handle and fixes the bug by passing the `fieldOffset` as the base offset (replacing `0L`). > > If the path-based `VarHandle` approach is preferred, I can rework this. > > #### 5. Testing > > New test cases were added to verify correct offset handling for: > > * Primitive arrays in structs > * Struct arrays in structs > * Struct arrays inside unions > > All tests pass locally. devjeonghwan has updated the pull request incrementally with one additional commit since the last revision: Import static symbols from `testStructArrayFields_h` in test ------------- Changes: - all: https://git.openjdk.org/jextract/pull/294/files - new: https://git.openjdk.org/jextract/pull/294/files/9c4efbf3..0843631f Webrevs: - full: https://webrevs.openjdk.org/?repo=jextract&pr=294&range=02 - incr: https://webrevs.openjdk.org/?repo=jextract&pr=294&range=01-02 Stats: 1 line in 1 file changed: 1 ins; 0 del; 0 mod Patch: https://git.openjdk.org/jextract/pull/294.diff Fetch: git fetch https://git.openjdk.org/jextract.git pull/294/head:pull/294 PR: https://git.openjdk.org/jextract/pull/294 From jvernee at openjdk.org Wed Nov 12 12:16:48 2025 From: jvernee at openjdk.org (Jorn Vernee) Date: Wed, 12 Nov 2025 12:16:48 GMT Subject: RFR: Fix incorrect base offset handling in generated array field accessors [v2] In-Reply-To: References: Message-ID: <1xDBbYFvt4Tvs6n4ejOX0bClvDN2Wbv8RgjYC1DhfsA=.9fa5984b-9905-4eb6-9f5a-076af4ee482f@github.com> On Wed, 12 Nov 2025 12:03:33 GMT, devjeonghwan wrote: >> #### 1. Status Quo >> >> Array field accessors generated by jextract (e.g., for `int arr[3]`) currently use a fixed base offset `0L` in `VarHandle.get/set` or `MethodHandle.invokeExact`. >> This causes all array accesses to start from the beginning of the struct, ignoring the field?s actual offset. >> >> #### 2. Problem >> >> Because of the missing base offset, writing to array elements in nested structs or unions can overwrite unrelated fields in the same structure. >> For example, updating `maxBlockDimension[1]` could corrupt `computeCapabilityMajor` or other preceding fields. >> >> typedef struct CudaDeviceInfo_st >> { >> int id; >> >> int computeCapabilityMajor; >> int computeCapabilityMinor; >> int multiprocessorCount; >> >> int warpSize; >> int maxThreadsPerBlock; >> int maxThreadsPerMultiprocessor; >> int maxBlockDimension[3]; >> int maxGridDimension[3]; >> >> bool unifiedAddressing; >> bool integratedMemory; >> } CudaDeviceInfo; >> >> >> #### 3. Fix >> >> This patch updates `emitFieldArrayGetter` and `emitFieldArraySetter` to pass the correct field offset (`offsetField`) to all generated array accessors. >> This ensures correct addressing for both primitive and struct/union element arrays. >> >> **Example:** >> >> >> // Before >> varHandle.get(struct, 0L, index); >> >> // After >> varHandle.get(struct, fieldOffset, index); >> >> >> #### 4. Additional Notes >> >> While the more idiomatic FFM approach of generating 'path-based' `VarHandle`s (e.g., `LAYOUT.varHandle(groupElement(...), ...)`) was considered, this patch takes a minimal-change approach. So It retains the existing handle and fixes the bug by passing the `fieldOffset` as the base offset (replacing `0L`). >> >> If the path-based `VarHandle` approach is preferred, I can rework this. >> >> #### 5. Testing >> >> New test cases were added to verify correct offset handling for: >> >> * Primitive arrays in structs >> * Struct arrays in structs >> * Struct arrays inside unions >> >> All tests pass locally. > > devjeonghwan has updated the pull request incrementally with one additional commit since the last revision: > > Update test to use `C_INT.byteSize()` for array field layout assertions Thanks for fixing! I think I've run into this in the past as well, but assumed that the intent was to get the array segment first with the segment getter, and then pass that segment to the array accessor (it didn't really feel right, but then it feel off my radar again). ------------- PR Review: https://git.openjdk.org/jextract/pull/294#pullrequestreview-3453135815 From duke at openjdk.org Wed Nov 12 12:25:49 2025 From: duke at openjdk.org (devjeonghwan) Date: Wed, 12 Nov 2025 12:25:49 GMT Subject: RFR: Fix incorrect base offset handling in generated array field accessors [v2] In-Reply-To: <1xDBbYFvt4Tvs6n4ejOX0bClvDN2Wbv8RgjYC1DhfsA=.9fa5984b-9905-4eb6-9f5a-076af4ee482f@github.com> References: <1xDBbYFvt4Tvs6n4ejOX0bClvDN2Wbv8RgjYC1DhfsA=.9fa5984b-9905-4eb6-9f5a-076af4ee482f@github.com> Message-ID: <5sGXEpK0m-gO5iYPaExl4Lr72kRrw0dfFHgXmw6OjPI=.1aad565a-920a-498d-b7e2-22a4be822b84@github.com> On Wed, 12 Nov 2025 12:13:35 GMT, Jorn Vernee wrote: >> devjeonghwan has updated the pull request incrementally with one additional commit since the last revision: >> >> Update test to use `C_INT.byteSize()` for array field layout assertions > > Thanks for fixing! > > I think I've run into this in the past as well, but assumed that the intent was to get the array segment first with the segment getter, and then pass that segment to the array accessor (it didn't really feel right, but then it feel off my radar again). @JornVernee Yeap, same here. I was using it like this /* TODO: Currently, JExtract has some critical bugs, so I opened an PR to fix them but not yet merged. See also https://github.com/openjdk/jextract/pull/294 */ MemorySegment maxBlockDimensionSlice = this.info.asSlice(CudaDeviceInfo_st.maxBlockDimension$offset()); maxBlockDimensionSlice.setAtIndex(jwcuda.C_INT, 0L, this.descriptor.getMaxBlockDimensionX()); maxBlockDimensionSlice.setAtIndex(jwcuda.C_INT, 1L, this.descriptor.getMaxBlockDimensionY()); maxBlockDimensionSlice.setAtIndex(jwcuda.C_INT, 2L, this.descriptor.getMaxBlockDimensionZ()); ------------- PR Comment: https://git.openjdk.org/jextract/pull/294#issuecomment-3521662010 From duke at openjdk.org Wed Nov 12 12:25:50 2025 From: duke at openjdk.org (devjeonghwan) Date: Wed, 12 Nov 2025 12:25:50 GMT Subject: RFR: Fix incorrect base offset handling in generated array field accessors [v3] In-Reply-To: <1vru1uityFJvLZmXX0dyL6D4nrHLptl3NdYgVDZXGso=.065af81c-745e-47a0-aae6-96f2f2443a53@github.com> References: <1vru1uityFJvLZmXX0dyL6D4nrHLptl3NdYgVDZXGso=.065af81c-745e-47a0-aae6-96f2f2443a53@github.com> Message-ID: On Wed, 12 Nov 2025 12:11:00 GMT, devjeonghwan wrote: >> #### 1. Status Quo >> >> Array field accessors generated by jextract (e.g., for `int arr[3]`) currently use a fixed base offset `0L` in `VarHandle.get/set` or `MethodHandle.invokeExact`. >> This causes all array accesses to start from the beginning of the struct, ignoring the field?s actual offset. >> >> #### 2. Problem >> >> Because of the missing base offset, writing to array elements in nested structs or unions can overwrite unrelated fields in the same structure. >> For example, updating `maxBlockDimension[1]` could corrupt `computeCapabilityMajor` or other preceding fields. >> >> typedef struct CudaDeviceInfo_st >> { >> int id; >> >> int computeCapabilityMajor; >> int computeCapabilityMinor; >> int multiprocessorCount; >> >> int warpSize; >> int maxThreadsPerBlock; >> int maxThreadsPerMultiprocessor; >> int maxBlockDimension[3]; >> int maxGridDimension[3]; >> >> bool unifiedAddressing; >> bool integratedMemory; >> } CudaDeviceInfo; >> >> >> #### 3. Fix >> >> This patch updates `emitFieldArrayGetter` and `emitFieldArraySetter` to pass the correct field offset (`offsetField`) to all generated array accessors. >> This ensures correct addressing for both primitive and struct/union element arrays. >> >> **Example:** >> >> >> // Before >> varHandle.get(struct, 0L, index); >> >> // After >> varHandle.get(struct, fieldOffset, index); >> >> >> #### 4. Additional Notes >> >> While the more idiomatic FFM approach of generating 'path-based' `VarHandle`s (e.g., `LAYOUT.varHandle(groupElement(...), ...)`) was considered, this patch takes a minimal-change approach. So It retains the existing handle and fixes the bug by passing the `fieldOffset` as the base offset (replacing `0L`). >> >> If the path-based `VarHandle` approach is preferred, I can rework this. >> >> #### 5. Testing >> >> New test cases were added to verify correct offset handling for: >> >> * Primitive arrays in structs >> * Struct arrays in structs >> * Struct arrays inside unions >> >> All tests pass locally. > > devjeonghwan has updated the pull request incrementally with one additional commit since the last revision: > > Import static symbols from `testStructArrayFields_h` in test Thanks [mcimadamore](https://github.com/mcimadamore) for the review ------------- PR Comment: https://git.openjdk.org/jextract/pull/294#issuecomment-3521668872 From duke at openjdk.org Wed Nov 12 12:25:51 2025 From: duke at openjdk.org (duke) Date: Wed, 12 Nov 2025 12:25:51 GMT Subject: RFR: Fix incorrect base offset handling in generated array field accessors [v3] In-Reply-To: <1vru1uityFJvLZmXX0dyL6D4nrHLptl3NdYgVDZXGso=.065af81c-745e-47a0-aae6-96f2f2443a53@github.com> References: <1vru1uityFJvLZmXX0dyL6D4nrHLptl3NdYgVDZXGso=.065af81c-745e-47a0-aae6-96f2f2443a53@github.com> Message-ID: <_UiX_tK100DKPpEyk5Y1V5LbPrEUzqqdqpq0h08-63Q=.f19e76fd-45e3-46a0-9bf5-c176e7553b34@github.com> On Wed, 12 Nov 2025 12:11:00 GMT, devjeonghwan wrote: >> #### 1. Status Quo >> >> Array field accessors generated by jextract (e.g., for `int arr[3]`) currently use a fixed base offset `0L` in `VarHandle.get/set` or `MethodHandle.invokeExact`. >> This causes all array accesses to start from the beginning of the struct, ignoring the field?s actual offset. >> >> #### 2. Problem >> >> Because of the missing base offset, writing to array elements in nested structs or unions can overwrite unrelated fields in the same structure. >> For example, updating `maxBlockDimension[1]` could corrupt `computeCapabilityMajor` or other preceding fields. >> >> typedef struct CudaDeviceInfo_st >> { >> int id; >> >> int computeCapabilityMajor; >> int computeCapabilityMinor; >> int multiprocessorCount; >> >> int warpSize; >> int maxThreadsPerBlock; >> int maxThreadsPerMultiprocessor; >> int maxBlockDimension[3]; >> int maxGridDimension[3]; >> >> bool unifiedAddressing; >> bool integratedMemory; >> } CudaDeviceInfo; >> >> >> #### 3. Fix >> >> This patch updates `emitFieldArrayGetter` and `emitFieldArraySetter` to pass the correct field offset (`offsetField`) to all generated array accessors. >> This ensures correct addressing for both primitive and struct/union element arrays. >> >> **Example:** >> >> >> // Before >> varHandle.get(struct, 0L, index); >> >> // After >> varHandle.get(struct, fieldOffset, index); >> >> >> #### 4. Additional Notes >> >> While the more idiomatic FFM approach of generating 'path-based' `VarHandle`s (e.g., `LAYOUT.varHandle(groupElement(...), ...)`) was considered, this patch takes a minimal-change approach. So It retains the existing handle and fixes the bug by passing the `fieldOffset` as the base offset (replacing `0L`). >> >> If the path-based `VarHandle` approach is preferred, I can rework this. >> >> #### 5. Testing >> >> New test cases were added to verify correct offset handling for: >> >> * Primitive arrays in structs >> * Struct arrays in structs >> * Struct arrays inside unions >> >> All tests pass locally. > > devjeonghwan has updated the pull request incrementally with one additional commit since the last revision: > > Import static symbols from `testStructArrayFields_h` in test @devjeonghwan Your change (at version 0843631ffddd76a9e52119990bc7ec8cdde798f4) is now ready to be sponsored by a Committer. ------------- PR Comment: https://git.openjdk.org/jextract/pull/294#issuecomment-3521674239 From duke at openjdk.org Wed Nov 12 13:38:12 2025 From: duke at openjdk.org (devjeonghwan) Date: Wed, 12 Nov 2025 13:38:12 GMT Subject: Integrated: Fix incorrect base offset handling in generated array field accessors In-Reply-To: References: Message-ID: On Fri, 7 Nov 2025 01:15:32 GMT, devjeonghwan wrote: > #### 1. Status Quo > > Array field accessors generated by jextract (e.g., for `int arr[3]`) currently use a fixed base offset `0L` in `VarHandle.get/set` or `MethodHandle.invokeExact`. > This causes all array accesses to start from the beginning of the struct, ignoring the field?s actual offset. > > #### 2. Problem > > Because of the missing base offset, writing to array elements in nested structs or unions can overwrite unrelated fields in the same structure. > For example, updating `maxBlockDimension[1]` could corrupt `computeCapabilityMajor` or other preceding fields. > > typedef struct CudaDeviceInfo_st > { > int id; > > int computeCapabilityMajor; > int computeCapabilityMinor; > int multiprocessorCount; > > int warpSize; > int maxThreadsPerBlock; > int maxThreadsPerMultiprocessor; > int maxBlockDimension[3]; > int maxGridDimension[3]; > > bool unifiedAddressing; > bool integratedMemory; > } CudaDeviceInfo; > > > #### 3. Fix > > This patch updates `emitFieldArrayGetter` and `emitFieldArraySetter` to pass the correct field offset (`offsetField`) to all generated array accessors. > This ensures correct addressing for both primitive and struct/union element arrays. > > **Example:** > > > // Before > varHandle.get(struct, 0L, index); > > // After > varHandle.get(struct, fieldOffset, index); > > > #### 4. Additional Notes > > While the more idiomatic FFM approach of generating 'path-based' `VarHandle`s (e.g., `LAYOUT.varHandle(groupElement(...), ...)`) was considered, this patch takes a minimal-change approach. So It retains the existing handle and fixes the bug by passing the `fieldOffset` as the base offset (replacing `0L`). > > If the path-based `VarHandle` approach is preferred, I can rework this. > > #### 5. Testing > > New test cases were added to verify correct offset handling for: > > * Primitive arrays in structs > * Struct arrays in structs > * Struct arrays inside unions > > All tests pass locally. This pull request has now been integrated. Changeset: 91fc954c Author: devjeonghwan Committer: Jorn Vernee URL: https://git.openjdk.org/jextract/commit/91fc954c46fac907cae6cd1417d835208c9df150 Stats: 246 lines in 3 files changed: 236 ins; 0 del; 10 mod Fix incorrect base offset handling in generated array field accessors Reviewed-by: mcimadamore, jvernee ------------- PR: https://git.openjdk.org/jextract/pull/294 From jvernee at openjdk.org Wed Nov 12 13:38:09 2025 From: jvernee at openjdk.org (Jorn Vernee) Date: Wed, 12 Nov 2025 13:38:09 GMT Subject: RFR: Fix incorrect base offset handling in generated array field accessors [v3] In-Reply-To: <1vru1uityFJvLZmXX0dyL6D4nrHLptl3NdYgVDZXGso=.065af81c-745e-47a0-aae6-96f2f2443a53@github.com> References: <1vru1uityFJvLZmXX0dyL6D4nrHLptl3NdYgVDZXGso=.065af81c-745e-47a0-aae6-96f2f2443a53@github.com> Message-ID: On Wed, 12 Nov 2025 12:11:00 GMT, devjeonghwan wrote: >> #### 1. Status Quo >> >> Array field accessors generated by jextract (e.g., for `int arr[3]`) currently use a fixed base offset `0L` in `VarHandle.get/set` or `MethodHandle.invokeExact`. >> This causes all array accesses to start from the beginning of the struct, ignoring the field?s actual offset. >> >> #### 2. Problem >> >> Because of the missing base offset, writing to array elements in nested structs or unions can overwrite unrelated fields in the same structure. >> For example, updating `maxBlockDimension[1]` could corrupt `computeCapabilityMajor` or other preceding fields. >> >> typedef struct CudaDeviceInfo_st >> { >> int id; >> >> int computeCapabilityMajor; >> int computeCapabilityMinor; >> int multiprocessorCount; >> >> int warpSize; >> int maxThreadsPerBlock; >> int maxThreadsPerMultiprocessor; >> int maxBlockDimension[3]; >> int maxGridDimension[3]; >> >> bool unifiedAddressing; >> bool integratedMemory; >> } CudaDeviceInfo; >> >> >> #### 3. Fix >> >> This patch updates `emitFieldArrayGetter` and `emitFieldArraySetter` to pass the correct field offset (`offsetField`) to all generated array accessors. >> This ensures correct addressing for both primitive and struct/union element arrays. >> >> **Example:** >> >> >> // Before >> varHandle.get(struct, 0L, index); >> >> // After >> varHandle.get(struct, fieldOffset, index); >> >> >> #### 4. Additional Notes >> >> While the more idiomatic FFM approach of generating 'path-based' `VarHandle`s (e.g., `LAYOUT.varHandle(groupElement(...), ...)`) was considered, this patch takes a minimal-change approach. So It retains the existing handle and fixes the bug by passing the `fieldOffset` as the base offset (replacing `0L`). >> >> If the path-based `VarHandle` approach is preferred, I can rework this. >> >> #### 5. Testing >> >> New test cases were added to verify correct offset handling for: >> >> * Primitive arrays in structs >> * Struct arrays in structs >> * Struct arrays inside unions >> >> All tests pass locally. > > devjeonghwan has updated the pull request incrementally with one additional commit since the last revision: > > Import static symbols from `testStructArrayFields_h` in test Marked as reviewed by jvernee (Reviewer). ------------- PR Review: https://git.openjdk.org/jextract/pull/294#pullrequestreview-3453483305 From duke at openjdk.org Thu Nov 13 08:46:50 2025 From: duke at openjdk.org (devjeonghwan) Date: Thu, 13 Nov 2025 08:46:50 GMT Subject: RFR: Add `--library-path-resolver` option for custom library path resolving Message-ID: <81PIUplGb2ogktFvNhH-Q0ou_6554lralRbDQXuwpvU=.67b23d8d-90c0-49d1-ba88-9e017a945ba2@github.com> #### 1. Status Quo Currently, `jextract` generates code using two standard loading mechanisms: 1. **Default:** `SymbolLookup.libraryLookup(System.mapLibraryName("name"), ...)` 2. **With `--use-system-load-library`:** `System.loadLibrary("name")` Both methods depend on static paths (e.g., `java.library.path`) and do not support runtime path resolution (hooking) without manual code modification. #### 2. Problem Standard loading fails in dynamic deployment scenarios: * **Bundled Libraries:** Native libraries inside JARs (extracted to temp directories) require loading from an absolute path. * **Dynamic Paths:** Paths determined at runtime based on OS/Arch cannot be handled by static system properties. Users currently must manually edit the generated source to inject custom loading logic. #### 3. Fix Introduced a new CLI option: `--library-path-resolver`. This option injects a user-defined static method to resolve the library path (or name) at runtime. **Usage:** jextract ... --library-path-resolver com.example.Resolver#resolvePath **Code Generation:** **Case 1: Default (SymbolLookup)** // Before SymbolLookup.libraryLookup(System.mapLibraryName("foo"), ARENA); // After SymbolLookup.libraryLookup(com.example.Resolver.resolvePath("foo"), ARENA); **Case 2: With `--use-system-load-library`** // Before System.loadLibrary("foo"); // After System.load(com.example.Resolver.resolvePath("foo")); #### 4. Additional Notes * **Method Signature:** The resolver method must match `String (String )`. * **Return Value:** * For `--use-system-load-library`: Must return an **absolute path** (required by `System.load()`). * For Default: Returns a path or name accepted by `SymbolLookup`. #### 5. Testing Added `TestLibraryPathResolver`. * Dynamic compilation and loading of a custom resolver class. * Correct code generation when the option is present. * Verifying that the custom resolver is actually invoked and that the native library is successfully loaded and linked via the resolved path All tests pass locally. ------------- Commit messages: - Remove trailing whitespace in `TestLibraryPathResolver.java` - Refactor and rename library path resolver test - Add test for custom library path resolver functionality - Support custom library path resolvers in system library loading Changes: https://git.openjdk.org/jextract/pull/295/files Webrev: https://webrevs.openjdk.org/?repo=jextract&pr=295&range=00 Stats: 193 lines in 10 files changed: 176 ins; 0 del; 17 mod Patch: https://git.openjdk.org/jextract/pull/295.diff Fetch: git fetch https://git.openjdk.org/jextract.git pull/295/head:pull/295 PR: https://git.openjdk.org/jextract/pull/295 From mcimadamore at openjdk.org Thu Nov 13 12:32:47 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Thu, 13 Nov 2025 12:32:47 GMT Subject: RFR: Add `--library-path-resolver` option for custom library path resolving In-Reply-To: <81PIUplGb2ogktFvNhH-Q0ou_6554lralRbDQXuwpvU=.67b23d8d-90c0-49d1-ba88-9e017a945ba2@github.com> References: <81PIUplGb2ogktFvNhH-Q0ou_6554lralRbDQXuwpvU=.67b23d8d-90c0-49d1-ba88-9e017a945ba2@github.com> Message-ID: <1lgN23JrAXwW_AAqhqTTG4Br2DorU3PR-X8dPzM9s00=.c0db5d56-f2b5-4c50-a974-e48c2e0b2a4a@github.com> On Thu, 13 Nov 2025 08:37:25 GMT, devjeonghwan wrote: > #### 1. Status Quo > > Currently, `jextract` generates code using two standard loading mechanisms: > > 1. **Default:** `SymbolLookup.libraryLookup(System.mapLibraryName("name"), ...)` > 2. **With `--use-system-load-library`:** `System.loadLibrary("name")` > > Both methods depend on static paths (e.g., `java.library.path`) and do not support runtime path resolution (hooking) without manual code modification. > > #### 2. Problem > > Standard loading fails in dynamic deployment scenarios: > > * **Bundled Libraries:** Native libraries inside JARs (extracted to temp directories) require loading from an absolute path. > * **Dynamic Paths:** Paths determined at runtime based on OS/Arch cannot be handled by static system properties. > > Users currently must manually edit the generated source to inject custom loading logic. > > #### 3. Fix > > Introduced a new CLI option: `--library-path-resolver`. > This option injects a user-defined static method to resolve the library path (or name) at runtime. > > **Usage:** > > > jextract ... --library-path-resolver com.example.Resolver#resolvePath > > > **Code Generation:** > > **Case 1: Default (SymbolLookup)** > > > // Before > SymbolLookup.libraryLookup(System.mapLibraryName("foo"), ARENA); > > // After > SymbolLookup.libraryLookup(com.example.Resolver.resolvePath("foo"), ARENA); > > > **Case 2: With `--use-system-load-library`** > > > // Before > System.loadLibrary("foo"); > > // After > System.load(com.example.Resolver.resolvePath("foo")); > > > #### 4. Additional Notes > > * **Method Signature:** The resolver method must match `String (String )`. > * **Return Value:** > * For `--use-system-load-library`: Must return an **absolute path** (required by `System.load()`). > * For Default: Returns a path or name accepted by `SymbolLookup`. > > #### 5. Testing > > Added `TestLibraryPathResolver`. > > * Dynamic compilation and loading of a custom resolver class. > * Correct code generation when the option is present. > * Verifying that the custom resolver is actually invoked and that the native library is successfully loaded and linked via the resolved path > > All tests pass locally. Before we jump on a solution, I think it would be better to understand what the problem is. I think for path that depends on OS/Platform, jextract (and FFM) actually has a good solution, which is to just use a dynamic linker name. For instance, the jextract guide has this example: -l :libGL.so.1 Note the `:` prefix -- which basically will avoid the `mapLibraryName` and will just call `libraryLookup` with whatever you put in there (which will then rely on the dynamic linker). But, even when `:` is omitted, if `--use-system-load-library` is `false`, we never use `java.library.path`. So, I believe the problem is mostly with paths that are generated on the fly (e.g. because a library is extracted from the jar, and then moved to some tmp folder). Can you please confirm this is the case? ------------- PR Comment: https://git.openjdk.org/jextract/pull/295#issuecomment-3527590520 From mcimadamore at openjdk.org Thu Nov 13 12:35:56 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Thu, 13 Nov 2025 12:35:56 GMT Subject: RFR: Add `--library-path-resolver` option for custom library path resolving In-Reply-To: <1lgN23JrAXwW_AAqhqTTG4Br2DorU3PR-X8dPzM9s00=.c0db5d56-f2b5-4c50-a974-e48c2e0b2a4a@github.com> References: <81PIUplGb2ogktFvNhH-Q0ou_6554lralRbDQXuwpvU=.67b23d8d-90c0-49d1-ba88-9e017a945ba2@github.com> <1lgN23JrAXwW_AAqhqTTG4Br2DorU3PR-X8dPzM9s00=.c0db5d56-f2b5-4c50-a974-e48c2e0b2a4a@github.com> Message-ID: On Thu, 13 Nov 2025 12:29:35 GMT, Maurizio Cimadamore wrote: > So, I believe the problem is mostly with paths that are generated on the fly (e.g. because a library is extracted from the jar, and then moved to some tmp folder). And, in this case, I believe the solution is to use whatever logic you had before FFM/jextract to extract the library into a tmp folder, then do a `System.load` on that absolute path, and then just have jextract rely on loader lookup. In other words, jextract can be friendly w.r.t. a context where a library is extracted on the fly -- but you need to do the library loading on the application side (which, if you add a "library resolver" you'd be doing anyway?) ------------- PR Comment: https://git.openjdk.org/jextract/pull/295#issuecomment-3527605717 From a.trapletti at ustermetrics.com Thu Nov 13 19:50:53 2025 From: a.trapletti at ustermetrics.com (Adrian Trapletti) Date: Thu, 13 Nov 2025 20:50:53 +0100 Subject: Release frequency for binaries Message-ID: Hi, I am wondering what is the release frequency or strategy for jextract binaries, in particular e.g. after a bug like https://github.com/openjdk/jextract/commit/91fc954c46fac907cae6cd1417d835208c9df150 has been detected and fixed, are you going to provide a new binary release? Best, Adrian *Dr. Adrian Trapletti* CEO *Uster Metrics GmbH *| Steinstrasse 9b, 8610 Uster, Switzerland P +41 32 512 83 63 | M +41 79 103 71 31 a.trapletti at ustermetrics.com | www.ustermetrics.com This email message including any attachments is confidential and may be privileged. It is intended solely for the use of the individual or entity named on this message. It is provided for informational purposes only and does not constitute an offer or invitation to subscribe for or purchase any services or products. Any form of disclosure, copying, modification or distribution is unauthorized. If you are not the intended recipient, you are requested to please notify the sender immediately and delete the message including any attachments from your computer system network. Email transmission cannot be guaranteed to be secure or error free as information could be modified. We therefore do not accept responsibility or liability as to the completeness or accuracy of the information contained in this message or any attachments. -------------- next part -------------- An HTML attachment was scrubbed... URL: From duke at openjdk.org Thu Nov 13 21:28:10 2025 From: duke at openjdk.org (devjeonghwan) Date: Thu, 13 Nov 2025 21:28:10 GMT Subject: RFR: Add `--library-path-resolver` option for custom library path resolving In-Reply-To: References: <81PIUplGb2ogktFvNhH-Q0ou_6554lralRbDQXuwpvU=.67b23d8d-90c0-49d1-ba88-9e017a945ba2@github.com> <1lgN23JrAXwW_AAqhqTTG4Br2DorU3PR-X8dPzM9s00=.c0db5d56-f2b5-4c50-a974-e48c2e0b2a4a@github.com> Message-ID: On Thu, 13 Nov 2025 12:33:14 GMT, Maurizio Cimadamore wrote: >> Before we jump on a solution, I think it would be better to understand what the problem is. I think for path that depends on OS/Platform, jextract (and FFM) actually has a good solution, which is to just use a dynamic linker name. For instance, the jextract guide has this example: >> >> >> -l :libGL.so.1 >> >> Note the `:` prefix -- which basically will avoid the `mapLibraryName` and will just call `libraryLookup` with whatever you put in there (which will then rely on the dynamic linker). But, even when `:` is omitted, if `--use-system-load-library` is `false`, we never use `java.library.path`. >> >> So, I believe the problem is mostly with paths that are generated on the fly (e.g. because a library is extracted from the jar, and then moved to some tmp folder). >> >> Can you please confirm this is the case? > >> So, I believe the problem is mostly with paths that are generated on the fly (e.g. because a library is extracted from the jar, and then moved to some tmp folder). > > And, in this case, I believe the solution is to use whatever logic you had before FFM/jextract to extract the library into a tmp folder, then do a `System.load` on that absolute path, and then just have jextract rely on loader lookup. > > In other words, jextract can be friendly w.r.t. a context where a library is extracted on the fly -- but you need to do the library loading on the application side (which, if you add a "library resolver" you'd be doing anyway?) Thanks for the feedback, @mcimadamore While pre-loading via `System.load` works for application developers, it has clear limitations from a library (framework) distribution perspective. 1. Uncontrollable Class Loading As a library developer, I cannot control the end-user's `main` logic. If the binding class is **class loaded** before the library's initialization method is called, it triggers an immediate `UnsatisfiedLinkError`. 2. Instruction Set Dispatch In HPC scenarios, beyond just OS/Arch, we need to dynamically load optimized libraries(build variants) based on supported **Instruction Sets** (e.g., AVX, SSE) via runtime CPUID checks. Static paths cannot handle this conditional logic. Currently, in the framework I am developing, I am forced to use Regex to manually patch the **binding code generated by jextract** to resolve these issues. This PR aims to eliminate such fragile post-processing. ------------- PR Comment: https://git.openjdk.org/jextract/pull/295#issuecomment-3529766270 From mcimadamore at openjdk.org Fri Nov 14 14:35:32 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Fri, 14 Nov 2025 14:35:32 GMT Subject: RFR: Add `--library-path-resolver` option for custom library path resolving In-Reply-To: References: <81PIUplGb2ogktFvNhH-Q0ou_6554lralRbDQXuwpvU=.67b23d8d-90c0-49d1-ba88-9e017a945ba2@github.com> <1lgN23JrAXwW_AAqhqTTG4Br2DorU3PR-X8dPzM9s00=.c0db5d56-f2b5-4c50-a974-e48c2e0b2a4a@github.com> Message-ID: <6oD6b9dxtB9khwqZIyA9ij3SP3qe-aCmbcJowkBGPZ0=.70859e11-d99c-4a5d-b157-5333ded2ef26@github.com> On Thu, 13 Nov 2025 21:23:22 GMT, devjeonghwan wrote: > 1. Uncontrollable Class Loading Wouldn't it be common to have a class in your library _know_ developers will need to access before doing any native access? In that case, that class can have a static initializer, and you can define jar extraction logic there? > This PR aims to eliminate such fragile post-processing. We have other, slightly different ideas to allow for 3rd party lookups in a more robust way. The main idea is to make bindings _instance_ methods instead of static methods, have a singleton (for easy use cases), and let clients _extend_ the bindings, which might provide opportunities to hook up custom lookups. This is described briefly here: https://mail.openjdk.org/pipermail/jextract-dev/2024-August/001920.html ------------- PR Comment: https://git.openjdk.org/jextract/pull/295#issuecomment-3533071571 From duke at openjdk.org Fri Nov 14 15:51:32 2025 From: duke at openjdk.org (devjeonghwan) Date: Fri, 14 Nov 2025 15:51:32 GMT Subject: RFR: Add `--library-path-resolver` option for custom library path resolving In-Reply-To: <81PIUplGb2ogktFvNhH-Q0ou_6554lralRbDQXuwpvU=.67b23d8d-90c0-49d1-ba88-9e017a945ba2@github.com> References: <81PIUplGb2ogktFvNhH-Q0ou_6554lralRbDQXuwpvU=.67b23d8d-90c0-49d1-ba88-9e017a945ba2@github.com> Message-ID: <8L4LcrAZxW8dvulerQ_llHbEwmxThDb2gLGCJ_W33MM=.0e0ac47d-227b-4eb1-b287-deaad2a25d4e@github.com> On Thu, 13 Nov 2025 08:37:25 GMT, devjeonghwan wrote: > #### 1. Status Quo > > Currently, `jextract` generates code using two standard loading mechanisms: > > 1. **Default:** `SymbolLookup.libraryLookup(System.mapLibraryName("name"), ...)` > 2. **With `--use-system-load-library`:** `System.loadLibrary("name")` > > Both methods depend on static paths (e.g., `java.library.path`) and do not support runtime path resolution (hooking) without manual code modification. > > #### 2. Problem > > Standard loading fails in dynamic deployment scenarios: > > * **Bundled Libraries:** Native libraries inside JARs (extracted to temp directories) require loading from an absolute path. > * **Dynamic Paths:** Paths determined at runtime based on OS/Arch cannot be handled by static system properties. > > Users currently must manually edit the generated source to inject custom loading logic. > > #### 3. Fix > > Introduced a new CLI option: `--library-path-resolver`. > This option injects a user-defined static method to resolve the library path (or name) at runtime. > > **Usage:** > > > jextract ... --library-path-resolver com.example.Resolver#resolvePath > > > **Code Generation:** > > **Case 1: Default (SymbolLookup)** > > > // Before > SymbolLookup.libraryLookup(System.mapLibraryName("foo"), ARENA); > > // After > SymbolLookup.libraryLookup(com.example.Resolver.resolvePath("foo"), ARENA); > > > **Case 2: With `--use-system-load-library`** > > > // Before > System.loadLibrary("foo"); > > // After > System.load(com.example.Resolver.resolvePath("foo")); > > > #### 4. Additional Notes > > * **Method Signature:** The resolver method must match `String (String )`. > * **Return Value:** > * For `--use-system-load-library`: Must return an **absolute path** (required by `System.load()`). > * For Default: Returns a path or name accepted by `SymbolLookup`. > > #### 5. Testing > > Added `TestLibraryPathResolver`. > > * Dynamic compilation and loading of a custom resolver class. > * Correct code generation when the option is present. > * Verifying that the custom resolver is actually invoked and that the native library is successfully loaded and linked via the resolved path > > All tests pass locally. Thanks for the link. The instance-based design looks like the right direction for the future. However, I believe this PR is still necessary as a practical solution for today, for the following reasons: 1. Framework interference (Spring, Jakarta EE, etc..) The "Main Wrapper" approach assumes we control exactly when classes are loaded. In reality, frameworks often scan the classpath and touch classes via `reflection` early at startup. If a framework accesses the jextract-generated class before my Main Wrapper runs its static initializer, the native library is not loaded yet. This causes an `UnsatisfiedLinkError`. 2. Bad API Design Forcing users to `Always initialize Class A or call initialize method before using Class B(binding class)` is a bad API design. The generated code should be self-contained and able to resolve its library path when needed. Since this CLI option is purely optional, it doesn't affect the default behavior. It solves a real pain point for library distributors until the new architecture arrives. ------------- PR Comment: https://git.openjdk.org/jextract/pull/295#issuecomment-3533380496 From maurizio.cimadamore at oracle.com Fri Nov 14 15:56:56 2025 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Fri, 14 Nov 2025 15:56:56 +0000 Subject: Release frequency for binaries In-Reply-To: References: Message-ID: <2928b70c-2fd0-497b-9f9e-f6d2de6a3c7e@oracle.com> Hi Adrian, we used to issue new binaries sparingly, but are working towards improving on that front. Re. the specific bug you mention, I've already brought that to the attenion of the team, as I agree that's serious enoug to warrant a respin. Maurizio On 13/11/2025 19:50, Adrian Trapletti wrote: > Hi, > > I am wondering what is the release frequency or strategy for jextract > binaries, in particular e.g. after a bug like > https://github.com/openjdk/jextract/commit/91fc954c46fac907cae6cd1417d835208c9df150 > has been detected and fixed, are you going to provide a new binary > release? > > Best, > Adrian > > *Dr. Adrian Trapletti* > CEO > > *Uster Metrics GmbH *| ?Steinstrasse 9b, 8610 Uster, Switzerland > P +41 32 512 83 63 ?| M +41 79 103 71 31 > a.trapletti at ustermetrics.com | www.ustermetrics.com > > > > This email message including any attachments is confidential and may > be privileged. It is intended solely for the use of the individual or > entity named on this message. It is provided for informational > purposes only and does not constitute an offer or invitation to > subscribe for or purchase any services or products. Any form of > disclosure, copying, modification or distribution is unauthorized. If > you are not the intended recipient, you are requested to please notify > the sender immediately and delete the message including any > attachments from your computer system network. Email transmission > cannot be guaranteed to be secure or error free as information could > be modified. We therefore do not accept responsibility or liability as > to the completeness or accuracy of the information contained in this > message or any attachments. > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From a.trapletti at ustermetrics.com Fri Nov 14 16:02:04 2025 From: a.trapletti at ustermetrics.com (Adrian Trapletti) Date: Fri, 14 Nov 2025 17:02:04 +0100 Subject: Release frequency for binaries In-Reply-To: <2928b70c-2fd0-497b-9f9e-f6d2de6a3c7e@oracle.com> References: <2928b70c-2fd0-497b-9f9e-f6d2de6a3c7e@oracle.com> Message-ID: Hi Maurizio, That's great to hear! Thx Adrian Dr. Adrian Trapletti CEO Uster Metrics GmbH Steinstrasse 9b 8610 Uster, Switzerland P +41 32 512 83 63 M +41 79 103 71 31 a.trapletti at ustermetrics.com www.ustermetrics.com This email message including any attachments is confidential and may be privileged. It is intended solely for the use of the individual or entity named on this message. It is provided for informational purposes only and does not constitute an offer or invitation to subscribe for or purchase any services or products. Any form of disclosure, copying, modification or distribution is unauthorized. If you are not the intended recipient, you are requested to please notify the sender immediately and delete the message including any attachments from your computer system network. Email transmission cannot be guaranteed to be secure or error free as information could be modified. We therefore do not accept responsibility or liability as to the completeness or accuracy of the information contained in this message or any attachments. On Fri, Nov 14, 2025, 16:57 Maurizio Cimadamore < maurizio.cimadamore at oracle.com> wrote: > Hi Adrian, > we used to issue new binaries sparingly, but are working towards improving > on that front. > > Re. the specific bug you mention, I've already brought that to the > attenion of the team, as I agree that's serious enoug to warrant a respin. > > Maurizio > On 13/11/2025 19:50, Adrian Trapletti wrote: > > Hi, > > I am wondering what is the release frequency or strategy for jextract > binaries, in particular e.g. after a bug like > https://github.com/openjdk/jextract/commit/91fc954c46fac907cae6cd1417d835208c9df150 > has been detected and fixed, are you going to provide a new binary release? > > Best, > Adrian > > *Dr. Adrian Trapletti* > CEO > > *Uster Metrics GmbH *| Steinstrasse 9b, 8610 Uster, Switzerland > P +41 32 512 83 63 | M +41 79 103 71 31 > a.trapletti at ustermetrics.com | www.ustermetrics.com > > > This email message including any attachments is confidential and may be > privileged. It is intended solely for the use of the individual or entity > named on this message. It is provided for informational purposes only and > does not constitute an offer or invitation to subscribe for or purchase > any services or products. Any form of disclosure, copying, modification > or distribution is unauthorized. If you are not the intended recipient, > you are requested to please notify the sender immediately and delete the > message including any attachments from your computer system network. Email > transmission cannot be guaranteed to be secure or error free as information > could be modified. We therefore do not accept responsibility or liability > as to the completeness or accuracy of the information contained in this > message or any attachments. > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From mcimadamore at openjdk.org Fri Nov 14 16:08:03 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Fri, 14 Nov 2025 16:08:03 GMT Subject: RFR: Add `--library-path-resolver` option for custom library path resolving In-Reply-To: <81PIUplGb2ogktFvNhH-Q0ou_6554lralRbDQXuwpvU=.67b23d8d-90c0-49d1-ba88-9e017a945ba2@github.com> References: <81PIUplGb2ogktFvNhH-Q0ou_6554lralRbDQXuwpvU=.67b23d8d-90c0-49d1-ba88-9e017a945ba2@github.com> Message-ID: On Thu, 13 Nov 2025 08:37:25 GMT, devjeonghwan wrote: > #### 1. Status Quo > > Currently, `jextract` generates code using two standard loading mechanisms: > > 1. **Default:** `SymbolLookup.libraryLookup(System.mapLibraryName("name"), ...)` > 2. **With `--use-system-load-library`:** `System.loadLibrary("name")` > > Both methods depend on static paths (e.g., `java.library.path`) and do not support runtime path resolution (hooking) without manual code modification. > > #### 2. Problem > > Standard loading fails in dynamic deployment scenarios: > > * **Bundled Libraries:** Native libraries inside JARs (extracted to temp directories) require loading from an absolute path. > * **Dynamic Paths:** Paths determined at runtime based on OS/Arch cannot be handled by static system properties. > > Users currently must manually edit the generated source to inject custom loading logic. > > #### 3. Fix > > Introduced a new CLI option: `--library-path-resolver`. > This option injects a user-defined static method to resolve the library path (or name) at runtime. > > **Usage:** > > > jextract ... --library-path-resolver com.example.Resolver#resolvePath > > > **Code Generation:** > > **Case 1: Default (SymbolLookup)** > > > // Before > SymbolLookup.libraryLookup(System.mapLibraryName("foo"), ARENA); > > // After > SymbolLookup.libraryLookup(com.example.Resolver.resolvePath("foo"), ARENA); > > > **Case 2: With `--use-system-load-library`** > > > // Before > System.loadLibrary("foo"); > > // After > System.load(com.example.Resolver.resolvePath("foo")); > > > #### 4. Additional Notes > > * **Method Signature:** The resolver method must match `String (String )`. > * **Return Value:** > * For `--use-system-load-library`: Must return an **absolute path** (required by `System.load()`). > * For Default: Returns a path or name accepted by `SymbolLookup`. > > #### 5. Testing > > Added `TestLibraryPathResolver`. > > * Dynamic compilation and loading of a custom resolver class. > * Correct code generation when the option is present. > * Verifying that the custom resolver is actually invoked and that the native library is successfully loaded and linked via the resolved path > > All tests pass locally. I don't dispute that the fix you propose is pragmatic. But it seems a poor man's service provider. It would be nice to use a _real_ service provider to obtain the lookup object to be used by jextract code. But a service provider can't really be used in the jextract case as there's no requirement for generated code to need anything in the classpath in order to work (and we'd like to keep it that way). So, what you have is: jextract will call a "method over there" to do what it needs -- but there's no "structure" to this extension point -- anything goes. So, I don't feel this is good enough for inclusion. Question: who writes the path resolver? The library, or the client of that library? I assume the former, right? If that's the case, I wonder, could we achieve a similar effect by means of some kind of configuration file? Or you really need to run some code? (maybe the configuration file could use some kind of naming scheme so that we'd be able to pick up the correct one?) ------------- PR Comment: https://git.openjdk.org/jextract/pull/295#issuecomment-3533465905 From duke at openjdk.org Fri Nov 14 16:31:01 2025 From: duke at openjdk.org (devjeonghwan) Date: Fri, 14 Nov 2025 16:31:01 GMT Subject: RFR: Add `--library-path-resolver` option for custom library path resolving In-Reply-To: References: <81PIUplGb2ogktFvNhH-Q0ou_6554lralRbDQXuwpvU=.67b23d8d-90c0-49d1-ba88-9e017a945ba2@github.com> Message-ID: On Fri, 14 Nov 2025 16:05:22 GMT, Maurizio Cimadamore wrote: > Question: who writes the path resolver? The library, or the client of that library? I assume the former, right? yes, the library author is the one providing the resolver. Unfortunately, a static configuration file wouldn't be enough because we strictly need to execute code at runtime. For example, we need to check CPU features (like AVX or SSE) to decide which library variant to load, or handle file I/O to extract a library from a JAR to a temp directory. A static config simply can't handle that kind of dynamic logic. I do understand your concern about the lack of structure in my current proposal. Since dynamic execution is mandatory for these use cases, could you suggest a specific architectural pattern that fits better with jextract's design? I?m happy to reimplement it to better fit jextract?s architecture. ------------- PR Comment: https://git.openjdk.org/jextract/pull/295#issuecomment-3533560730 From mcimadamore at openjdk.org Fri Nov 14 18:08:39 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Fri, 14 Nov 2025 18:08:39 GMT Subject: RFR: Add `--library-path-resolver` option for custom library path resolving In-Reply-To: References: <81PIUplGb2ogktFvNhH-Q0ou_6554lralRbDQXuwpvU=.67b23d8d-90c0-49d1-ba88-9e017a945ba2@github.com> Message-ID: On Fri, 14 Nov 2025 18:03:56 GMT, Maurizio Cimadamore wrote: > make bindings instance methods instead of static. And... btw, we didn't start on this, as this depends on [LazyConstant](https://openjdk.org/jeps/526) as well as some [enhancements to final](https://openjdk.org/jeps/500) ------------- PR Comment: https://git.openjdk.org/jextract/pull/295#issuecomment-3533946034 From mcimadamore at openjdk.org Fri Nov 14 18:08:38 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Fri, 14 Nov 2025 18:08:38 GMT Subject: RFR: Add `--library-path-resolver` option for custom library path resolving In-Reply-To: References: <81PIUplGb2ogktFvNhH-Q0ou_6554lralRbDQXuwpvU=.67b23d8d-90c0-49d1-ba88-9e017a945ba2@github.com> Message-ID: On Fri, 14 Nov 2025 16:27:53 GMT, devjeonghwan wrote: > could you suggest a specific architectural pattern that fits better with jextract's design? I?m happy to reimplement it to better fit jextract?s architecture. When we discussed this (many times) in the past, the best thing we could come up with was what I described above -- make bindings instance methods instead of static. I'm a little pessimistic that other "principled" solutions exist. ------------- PR Comment: https://git.openjdk.org/jextract/pull/295#issuecomment-3533939587 From duke at openjdk.org Fri Nov 14 18:43:14 2025 From: duke at openjdk.org (devjeonghwan) Date: Fri, 14 Nov 2025 18:43:14 GMT Subject: RFR: Add `--library-path-resolver` option for custom library path resolving In-Reply-To: <81PIUplGb2ogktFvNhH-Q0ou_6554lralRbDQXuwpvU=.67b23d8d-90c0-49d1-ba88-9e017a945ba2@github.com> References: <81PIUplGb2ogktFvNhH-Q0ou_6554lralRbDQXuwpvU=.67b23d8d-90c0-49d1-ba88-9e017a945ba2@github.com> Message-ID: <78ODdXmE1duOaB12CYVasf-Vft35Z5I1_QpSW254Uhg=.59d198aa-541b-46d1-ab30-176b568dfb63@github.com> On Thu, 13 Nov 2025 08:37:25 GMT, devjeonghwan wrote: > #### 1. Status Quo > > Currently, `jextract` generates code using two standard loading mechanisms: > > 1. **Default:** `SymbolLookup.libraryLookup(System.mapLibraryName("name"), ...)` > 2. **With `--use-system-load-library`:** `System.loadLibrary("name")` > > Both methods depend on static paths (e.g., `java.library.path`) and do not support runtime path resolution (hooking) without manual code modification. > > #### 2. Problem > > Standard loading fails in dynamic deployment scenarios: > > * **Bundled Libraries:** Native libraries inside JARs (extracted to temp directories) require loading from an absolute path. > * **Dynamic Paths:** Paths determined at runtime based on OS/Arch cannot be handled by static system properties. > > Users currently must manually edit the generated source to inject custom loading logic. > > #### 3. Fix > > Introduced a new CLI option: `--library-path-resolver`. > This option injects a user-defined static method to resolve the library path (or name) at runtime. > > **Usage:** > > > jextract ... --library-path-resolver com.example.Resolver#resolvePath > > > **Code Generation:** > > **Case 1: Default (SymbolLookup)** > > > // Before > SymbolLookup.libraryLookup(System.mapLibraryName("foo"), ARENA); > > // After > SymbolLookup.libraryLookup(com.example.Resolver.resolvePath("foo"), ARENA); > > > **Case 2: With `--use-system-load-library`** > > > // Before > System.loadLibrary("foo"); > > // After > System.load(com.example.Resolver.resolvePath("foo")); > > > #### 4. Additional Notes > > * **Method Signature:** The resolver method must match `String (String )`. > * **Return Value:** > * For `--use-system-load-library`: Must return an **absolute path** (required by `System.load()`). > * For Default: Returns a path or name accepted by `SymbolLookup`. > > #### 5. Testing > > Added `TestLibraryPathResolver`. > > * Dynamic compilation and loading of a custom resolver class. > * Correct code generation when the option is present. > * Verifying that the custom resolver is actually invoked and that the native library is successfully loaded and linked via the resolved path > > All tests pass locally. I see.. You are waiting for the Java updates to handle performance issues (maybe like `constant-folding`?). I'll close this PR for now. If I find a better way that fits your design, I'll come back. Thanks for the review. ------------- PR Comment: https://git.openjdk.org/jextract/pull/295#issuecomment-3534080395 From duke at openjdk.org Fri Nov 14 18:43:15 2025 From: duke at openjdk.org (devjeonghwan) Date: Fri, 14 Nov 2025 18:43:15 GMT Subject: Withdrawn: Add `--library-path-resolver` option for custom library path resolving In-Reply-To: <81PIUplGb2ogktFvNhH-Q0ou_6554lralRbDQXuwpvU=.67b23d8d-90c0-49d1-ba88-9e017a945ba2@github.com> References: <81PIUplGb2ogktFvNhH-Q0ou_6554lralRbDQXuwpvU=.67b23d8d-90c0-49d1-ba88-9e017a945ba2@github.com> Message-ID: On Thu, 13 Nov 2025 08:37:25 GMT, devjeonghwan wrote: > #### 1. Status Quo > > Currently, `jextract` generates code using two standard loading mechanisms: > > 1. **Default:** `SymbolLookup.libraryLookup(System.mapLibraryName("name"), ...)` > 2. **With `--use-system-load-library`:** `System.loadLibrary("name")` > > Both methods depend on static paths (e.g., `java.library.path`) and do not support runtime path resolution (hooking) without manual code modification. > > #### 2. Problem > > Standard loading fails in dynamic deployment scenarios: > > * **Bundled Libraries:** Native libraries inside JARs (extracted to temp directories) require loading from an absolute path. > * **Dynamic Paths:** Paths determined at runtime based on OS/Arch cannot be handled by static system properties. > > Users currently must manually edit the generated source to inject custom loading logic. > > #### 3. Fix > > Introduced a new CLI option: `--library-path-resolver`. > This option injects a user-defined static method to resolve the library path (or name) at runtime. > > **Usage:** > > > jextract ... --library-path-resolver com.example.Resolver#resolvePath > > > **Code Generation:** > > **Case 1: Default (SymbolLookup)** > > > // Before > SymbolLookup.libraryLookup(System.mapLibraryName("foo"), ARENA); > > // After > SymbolLookup.libraryLookup(com.example.Resolver.resolvePath("foo"), ARENA); > > > **Case 2: With `--use-system-load-library`** > > > // Before > System.loadLibrary("foo"); > > // After > System.load(com.example.Resolver.resolvePath("foo")); > > > #### 4. Additional Notes > > * **Method Signature:** The resolver method must match `String (String )`. > * **Return Value:** > * For `--use-system-load-library`: Must return an **absolute path** (required by `System.load()`). > * For Default: Returns a path or name accepted by `SymbolLookup`. > > #### 5. Testing > > Added `TestLibraryPathResolver`. > > * Dynamic compilation and loading of a custom resolver class. > * Correct code generation when the option is present. > * Verifying that the custom resolver is actually invoked and that the native library is successfully loaded and linked via the resolved path > > All tests pass locally. This pull request has been closed without being integrated. ------------- PR: https://git.openjdk.org/jextract/pull/295 From mcimadamore at openjdk.org Fri Nov 14 22:16:03 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Fri, 14 Nov 2025 22:16:03 GMT Subject: RFR: Add `--library-path-resolver` option for custom library path resolving In-Reply-To: <78ODdXmE1duOaB12CYVasf-Vft35Z5I1_QpSW254Uhg=.59d198aa-541b-46d1-ab30-176b568dfb63@github.com> References: <81PIUplGb2ogktFvNhH-Q0ou_6554lralRbDQXuwpvU=.67b23d8d-90c0-49d1-ba88-9e017a945ba2@github.com> <78ODdXmE1duOaB12CYVasf-Vft35Z5I1_QpSW254Uhg=.59d198aa-541b-46d1-ab30-176b568dfb63@github.com> Message-ID: On Fri, 14 Nov 2025 18:39:41 GMT, devjeonghwan wrote: > I see.. You are waiting for the Java updates to handle performance issues (maybe like `constant-folding`?). Yes, for instance bindings to be performant (when referenced through some singleton constant -- like `GL.glClear`), we need to be able to reliably constant fold through method handles that stored inside _instance_ fields of the header class. This means we need (a) some way to lazily initialize "constant" instance fields (and that's LazyConstant) and (b) some way for these fields to be "trusted". We're close to getting there, but not 100% there yet... > > I'll close this PR for now. If I find a better way that fits your design, I'll come back. > > Thanks for the review. Thanks -- we'll keep thinking on our side as well, in case something comes up. ------------- PR Comment: https://git.openjdk.org/jextract/pull/295#issuecomment-3534853812 From varadam at openjdk.org Thu Nov 20 14:09:12 2025 From: varadam at openjdk.org (Varada M) Date: Thu, 20 Nov 2025 14:09:12 GMT Subject: RFR: 7904115: Fix for AIX test case failures due to incorrect alignment for double and pointer Message-ID: Total of 10 test failures observed on AIX: jtreg/generator/nestedTypes/TestNestedTypesUnsupported.java jtreg/generator/test8246400/LibTest8246400Test.java jtreg/generator/test8258605/LibTest8258605Test.java jtreg/generator/test8261511/Test8261511.java jtreg/generator/testStruct/LibStructTest.java testng/org/openjdk/jextract/test/toolprovider/ConstantsTest.java testng/org/openjdk/jextract/test/toolprovider/IncompleteArrayTest.java testng/org/openjdk/jextract/test/toolprovider/Test8240811.java testng/org/openjdk/jextract/test/toolprovider/TestClassGeneration.java testng/org/openjdk/jextract/test/toolprovider/nestedAnonOffset/TestNestedAnonOffset.java This PR fixes AIX specific layout generation issues related to incorrect alignment double and pointer types. 1. Structs containing double fields fail with: i. Unsupported layout: 4%D8 ii. Invalid alignment constraint for member layout double in AIX structs has size 8 but alignment 4 (except as first field). AIX specific handling for C_DOUBLE computes the correct alignment. 2. Clang was detected as 32-bit due to missing -m64 during macro extraction, causing inconsistent macros. This caused jextract to interpret pointer constants incorrectly, leading to failures like: expected [-1] but found [4294967295] 3. TestNestedAnonOffset.java test failed on AIX because it also expects more padding similar to platforms like windows and linux After the patch jtreg tests passes successfully. JBS: [CODETOOLS-7904115](https://bugs.openjdk.org/browse/CODETOOLS-7904115) ------------- Commit messages: - testcase fixes for aix - testcase fixes for aix - testcase fixes for aix - testcase fixes for aix Changes: https://git.openjdk.org/jextract/pull/296/files Webrev: https://webrevs.openjdk.org/?repo=jextract&pr=296&range=00 Issue: https://bugs.openjdk.org/browse/CODETOOLS-7904115 Stats: 27 lines in 6 files changed: 24 ins; 0 del; 3 mod Patch: https://git.openjdk.org/jextract/pull/296.diff Fetch: git fetch https://git.openjdk.org/jextract.git pull/296/head:pull/296 PR: https://git.openjdk.org/jextract/pull/296 From sroy at openjdk.org Thu Nov 20 14:24:49 2025 From: sroy at openjdk.org (Suchismith Roy) Date: Thu, 20 Nov 2025 14:24:49 GMT Subject: RFR: Add support for AIX in build process Message-ID: Summary of the issues: 1. There is no support for compiling AIX dynamic .a library and the tool was compiling .so files instead. 2. There is no logic to support libclang.a. 3. There is no support to load shared member of .a dynamic libraries of AIX. JBS Issue: [CODETOOLS-7904116](https://bugs.openjdk.org/browse/CODETOOLS-7904116) ------------- Commit messages: - remove executable - remove extra changes - library loading logic - build file changes - gradle fixes - jextract: Cleanup of Index_h - cmake support - jextract: Enable loading of dynamic archives for AIX Changes: https://git.openjdk.org/jextract/pull/297/files Webrev: https://webrevs.openjdk.org/?repo=jextract&pr=297&range=00 Stats: 416 lines in 7 files changed: 113 ins; 273 del; 30 mod Patch: https://git.openjdk.org/jextract/pull/297.diff Fetch: git fetch https://git.openjdk.org/jextract.git pull/297/head:pull/297 PR: https://git.openjdk.org/jextract/pull/297 From jvernee at openjdk.org Thu Nov 20 14:38:46 2025 From: jvernee at openjdk.org (Jorn Vernee) Date: Thu, 20 Nov 2025 14:38:46 GMT Subject: RFR: 7904115: Fix for AIX test case failures due to incorrect alignment for double and pointer In-Reply-To: References: Message-ID: On Thu, 20 Nov 2025 11:20:46 GMT, Varada M wrote: > Total of 10 test failures observed on AIX: > jtreg/generator/nestedTypes/TestNestedTypesUnsupported.java > jtreg/generator/test8246400/LibTest8246400Test.java > jtreg/generator/test8258605/LibTest8258605Test.java > jtreg/generator/test8261511/Test8261511.java > jtreg/generator/testStruct/LibStructTest.java > testng/org/openjdk/jextract/test/toolprovider/ConstantsTest.java > testng/org/openjdk/jextract/test/toolprovider/IncompleteArrayTest.java > testng/org/openjdk/jextract/test/toolprovider/Test8240811.java > testng/org/openjdk/jextract/test/toolprovider/TestClassGeneration.java > testng/org/openjdk/jextract/test/toolprovider/nestedAnonOffset/TestNestedAnonOffset.java > > This PR fixes AIX specific layout generation issues related to incorrect alignment double and pointer types. > 1. Structs containing double fields fail with: > i. Unsupported layout: 4%D8 > ii. Invalid alignment constraint for member layout > double in AIX structs has size 8 but alignment 4 (except as first field). AIX specific handling for C_DOUBLE computes the correct alignment. > > 2. Clang was detected as 32-bit due to missing -m64 during macro extraction, causing inconsistent macros. This caused jextract to interpret pointer constants incorrectly, leading to failures like: > expected [-1] but found [4294967295] > > 3. TestNestedAnonOffset.java test failed on AIX because it also expects more padding similar to platforms like windows and linux > > > After the patch jtreg tests passes successfully. > > JBS: [CODETOOLS-7904115](https://bugs.openjdk.org/browse/CODETOOLS-7904115) src/main/java/org/openjdk/jextract/impl/ClassSourceBuilder.java line 269: > 267: } else { > 268: yield alignIfNeeded(runtimeHelperName() + ".C_DOUBLE", 4, align); > 269: } Why are there 2 cases here? src/main/java/org/openjdk/jextract/impl/Options.java line 92: > 90: if (TypeImpl.IS_AIX) { > 91: clangArgs.add("-m64"); > 92: } This doesn't look like the right place to add this, as the `-m64` flag would be added for each clang argument. ------------- PR Review Comment: https://git.openjdk.org/jextract/pull/296#discussion_r2546292527 PR Review Comment: https://git.openjdk.org/jextract/pull/296#discussion_r2546280367 From jvernee at openjdk.org Thu Nov 20 14:38:47 2025 From: jvernee at openjdk.org (Jorn Vernee) Date: Thu, 20 Nov 2025 14:38:47 GMT Subject: RFR: 7904115: Fix for AIX test case failures due to incorrect alignment for double and pointer In-Reply-To: References: Message-ID: On Thu, 20 Nov 2025 14:32:11 GMT, Jorn Vernee wrote: >> Total of 10 test failures observed on AIX: >> jtreg/generator/nestedTypes/TestNestedTypesUnsupported.java >> jtreg/generator/test8246400/LibTest8246400Test.java >> jtreg/generator/test8258605/LibTest8258605Test.java >> jtreg/generator/test8261511/Test8261511.java >> jtreg/generator/testStruct/LibStructTest.java >> testng/org/openjdk/jextract/test/toolprovider/ConstantsTest.java >> testng/org/openjdk/jextract/test/toolprovider/IncompleteArrayTest.java >> testng/org/openjdk/jextract/test/toolprovider/Test8240811.java >> testng/org/openjdk/jextract/test/toolprovider/TestClassGeneration.java >> testng/org/openjdk/jextract/test/toolprovider/nestedAnonOffset/TestNestedAnonOffset.java >> >> This PR fixes AIX specific layout generation issues related to incorrect alignment double and pointer types. >> 1. Structs containing double fields fail with: >> i. Unsupported layout: 4%D8 >> ii. Invalid alignment constraint for member layout >> double in AIX structs has size 8 but alignment 4 (except as first field). AIX specific handling for C_DOUBLE computes the correct alignment. >> >> 2. Clang was detected as 32-bit due to missing -m64 during macro extraction, causing inconsistent macros. This caused jextract to interpret pointer constants incorrectly, leading to failures like: >> expected [-1] but found [4294967295] >> >> 3. TestNestedAnonOffset.java test failed on AIX because it also expects more padding similar to platforms like windows and linux >> >> >> After the patch jtreg tests passes successfully. >> >> JBS: [CODETOOLS-7904115](https://bugs.openjdk.org/browse/CODETOOLS-7904115) > > src/main/java/org/openjdk/jextract/impl/ClassSourceBuilder.java line 269: > >> 267: } else { >> 268: yield alignIfNeeded(runtimeHelperName() + ".C_DOUBLE", 4, align); >> 269: } > > Why are there 2 cases here? Couldn't this be: case Double -> alignIfNeeded(runtimeHelperName() + ".C_DOUBLE", (TypeImpl.IS_AIX ? 4 : 8), align); > src/main/java/org/openjdk/jextract/impl/Options.java line 92: > >> 90: if (TypeImpl.IS_AIX) { >> 91: clangArgs.add("-m64"); >> 92: } > > This doesn't look like the right place to add this, as the `-m64` flag would be added for each clang argument. I think an extra call to `addClangArg` should be added to `JextractTool`. ------------- PR Review Comment: https://git.openjdk.org/jextract/pull/296#discussion_r2546294736 PR Review Comment: https://git.openjdk.org/jextract/pull/296#discussion_r2546304464 From sroy at openjdk.org Thu Nov 20 14:45:27 2025 From: sroy at openjdk.org (Suchismith Roy) Date: Thu, 20 Nov 2025 14:45:27 GMT Subject: RFR: Add support for AIX in build process [v2] In-Reply-To: References: Message-ID: > Summary of the issues: > > 1. There is no support for compiling AIX dynamic .a library and the tool was compiling .so files instead. > 2. There is no logic to support libclang.a. > 3. There is no support to load shared member of .a dynamic libraries of AIX. > > JBS Issue: [CODETOOLS-7904116](https://bugs.openjdk.org/browse/CODETOOLS-7904116) Suchismith Roy has updated the pull request incrementally with one additional commit since the last revision: Restore gradlew executable ------------- Changes: - all: https://git.openjdk.org/jextract/pull/297/files - new: https://git.openjdk.org/jextract/pull/297/files/847e9bfe..a94e0a32 Webrevs: - full: https://webrevs.openjdk.org/?repo=jextract&pr=297&range=01 - incr: https://webrevs.openjdk.org/?repo=jextract&pr=297&range=00-01 Stats: 252 lines in 1 file changed: 252 ins; 0 del; 0 mod Patch: https://git.openjdk.org/jextract/pull/297.diff Fetch: git fetch https://git.openjdk.org/jextract.git pull/297/head:pull/297 PR: https://git.openjdk.org/jextract/pull/297 From jvernee at openjdk.org Thu Nov 20 14:53:03 2025 From: jvernee at openjdk.org (Jorn Vernee) Date: Thu, 20 Nov 2025 14:53:03 GMT Subject: RFR: Add support for AIX in build process [v2] In-Reply-To: References: Message-ID: <5fGLnFg1xHomCu4iNljgEcIZmzBz5E4e6lem7I9Yqas=.8cf1ef32-d971-4291-a84f-414f6ea0e8d1@github.com> On Thu, 20 Nov 2025 14:45:27 GMT, Suchismith Roy wrote: >> Summary of the issues: >> >> 1. There is no support for compiling AIX dynamic .a library and the tool was compiling .so files instead. >> 2. There is no logic to support libclang.a. >> 3. There is no support to load shared member of .a dynamic libraries of AIX. >> >> JBS Issue: [CODETOOLS-7904116](https://bugs.openjdk.org/browse/CODETOOLS-7904116) > > Suchismith Roy has updated the pull request incrementally with one additional commit since the last revision: > > Restore gradlew executable Question: Are you planning on using the MakeFile build? We are currently only using this for Oracle internal CI build.gradle line 205: > 203: executable = "cmake" > 204: environment "CC", "/opt/IBM/xlC/13.1.3/bin/xlc" > 205: environment "CXX", "/opt/IBM/xlC/13.1.3/bin/xlC" Leftover from testing I presume? build.gradle line 281: > 279: doLast { > 280: println "[DEBUG] Successfully copied libclang.a to test-lib/libs" > 281: } Leftover? ------------- PR Review: https://git.openjdk.org/jextract/pull/297#pullrequestreview-3488214276 PR Review Comment: https://git.openjdk.org/jextract/pull/297#discussion_r2546316189 PR Review Comment: https://git.openjdk.org/jextract/pull/297#discussion_r2546356820 From sroy at openjdk.org Thu Nov 20 15:01:05 2025 From: sroy at openjdk.org (Suchismith Roy) Date: Thu, 20 Nov 2025 15:01:05 GMT Subject: RFR: Add support for AIX in build process [v3] In-Reply-To: References: Message-ID: <2MBJ7VAY6U_67ePZtbdZlKMgJqoye6JbC_npEDIo-Lk=.134f681c-ecac-4959-b5a1-33e6e3e36a90@github.com> > Summary of the issues: > > 1. There is no support for compiling AIX dynamic .a library and the tool was compiling .so files instead. > 2. There is no logic to support libclang.a. > 3. There is no support to load shared member of .a dynamic libraries of AIX. > > JBS Issue: [CODETOOLS-7904116](https://bugs.openjdk.org/browse/CODETOOLS-7904116) Suchismith Roy has updated the pull request incrementally with one additional commit since the last revision: remove debug codE ------------- Changes: - all: https://git.openjdk.org/jextract/pull/297/files - new: https://git.openjdk.org/jextract/pull/297/files/a94e0a32..73da4b04 Webrevs: - full: https://webrevs.openjdk.org/?repo=jextract&pr=297&range=02 - incr: https://webrevs.openjdk.org/?repo=jextract&pr=297&range=01-02 Stats: 6 lines in 1 file changed: 0 ins; 6 del; 0 mod Patch: https://git.openjdk.org/jextract/pull/297.diff Fetch: git fetch https://git.openjdk.org/jextract.git pull/297/head:pull/297 PR: https://git.openjdk.org/jextract/pull/297 From sroy at openjdk.org Thu Nov 20 15:01:06 2025 From: sroy at openjdk.org (Suchismith Roy) Date: Thu, 20 Nov 2025 15:01:06 GMT Subject: RFR: Add support for AIX in build process [v2] In-Reply-To: <5fGLnFg1xHomCu4iNljgEcIZmzBz5E4e6lem7I9Yqas=.8cf1ef32-d971-4291-a84f-414f6ea0e8d1@github.com> References: <5fGLnFg1xHomCu4iNljgEcIZmzBz5E4e6lem7I9Yqas=.8cf1ef32-d971-4291-a84f-414f6ea0e8d1@github.com> Message-ID: On Thu, 20 Nov 2025 14:50:10 GMT, Jorn Vernee wrote: > Question: Are you planning on using the MakeFile build? We are currently only using this for Oracle internal CI Yes. There was no support for AIX , I had to add the path for libclang.a. ------------- PR Comment: https://git.openjdk.org/jextract/pull/297#issuecomment-3558497439 From varadam at openjdk.org Fri Nov 21 12:57:39 2025 From: varadam at openjdk.org (Varada M) Date: Fri, 21 Nov 2025 12:57:39 GMT Subject: RFR: 7904115: Fix for AIX test case failures due to incorrect alignment for double and pointer [v2] In-Reply-To: References: Message-ID: > Total of 10 test failures observed on AIX: > jtreg/generator/nestedTypes/TestNestedTypesUnsupported.java > jtreg/generator/test8246400/LibTest8246400Test.java > jtreg/generator/test8258605/LibTest8258605Test.java > jtreg/generator/test8261511/Test8261511.java > jtreg/generator/testStruct/LibStructTest.java > testng/org/openjdk/jextract/test/toolprovider/ConstantsTest.java > testng/org/openjdk/jextract/test/toolprovider/IncompleteArrayTest.java > testng/org/openjdk/jextract/test/toolprovider/Test8240811.java > testng/org/openjdk/jextract/test/toolprovider/TestClassGeneration.java > testng/org/openjdk/jextract/test/toolprovider/nestedAnonOffset/TestNestedAnonOffset.java > > This PR fixes AIX specific layout generation issues related to incorrect alignment double and pointer types. > 1. Structs containing double fields fail with: > i. Unsupported layout: 4%D8 > ii. Invalid alignment constraint for member layout > double in AIX structs has size 8 but alignment 4 (except as first field). AIX specific handling for C_DOUBLE computes the correct alignment. > > 2. Clang was detected as 32-bit due to missing -m64 during macro extraction, causing inconsistent macros. This caused jextract to interpret pointer constants incorrectly, leading to failures like: > expected [-1] but found [4294967295] > > 3. TestNestedAnonOffset.java test failed on AIX because it also expects more padding similar to platforms like windows and linux > > > After the patch jtreg tests passes successfully. > > JBS: [CODETOOLS-7904115](https://bugs.openjdk.org/browse/CODETOOLS-7904115) Varada M has updated the pull request incrementally with two additional commits since the last revision: - addition of -m64 at right place - addition of -m64 at right place ------------- Changes: - all: https://git.openjdk.org/jextract/pull/296/files - new: https://git.openjdk.org/jextract/pull/296/files/d4a0f64f..7f1983ba Webrevs: - full: https://webrevs.openjdk.org/?repo=jextract&pr=296&range=01 - incr: https://webrevs.openjdk.org/?repo=jextract&pr=296&range=00-01 Stats: 9 lines in 2 files changed: 5 ins; 4 del; 0 mod Patch: https://git.openjdk.org/jextract/pull/296.diff Fetch: git fetch https://git.openjdk.org/jextract.git pull/296/head:pull/296 PR: https://git.openjdk.org/jextract/pull/296 From varadam at openjdk.org Fri Nov 21 12:57:41 2025 From: varadam at openjdk.org (Varada M) Date: Fri, 21 Nov 2025 12:57:41 GMT Subject: RFR: 7904115: Fix for AIX test case failures due to incorrect alignment for double and pointer [v2] In-Reply-To: References: Message-ID: <5-AIbtzBO_0aDDWUd3OtmTNQCpVA1Ba7vvt3sA4uOKE=.62a83582-7ffa-44e6-8871-602139603147@github.com> On Thu, 20 Nov 2025 14:32:43 GMT, Jorn Vernee wrote: >> src/main/java/org/openjdk/jextract/impl/ClassSourceBuilder.java line 269: >> >>> 267: } else { >>> 268: yield alignIfNeeded(runtimeHelperName() + ".C_DOUBLE", 4, align); >>> 269: } >> >> Why are there 2 cases here? > > Couldn't this be: > > > case Double -> alignIfNeeded(runtimeHelperName() + ".C_DOUBLE", (TypeImpl.IS_AIX ? 4 : 8), align); yes right. These are my findings! `case Double -> alignIfNeeded(runtimeHelperName() + ".C_DOUBLE", (TypeImpl.IS_AIX ? 4 : 8), align);` The above fix solves most of the failures except two of them. This solves the failure like "Unsupported layout: 4%D8" The remaining two test failures are due to 'IllegalArgumentException: Invalid alignment constraint for member layout: D8(d)' I observed that the expected alignment is 8 for them and the ABI expects the alignment constraint for d to be 4, not 8 For one of the test failure : jtreg/generator/testStruct/LibStructTest.java For the [struct AllTypes](https://github.com/varada1110/jextract/blob/91ff2392ac8c3ee7d0906486e8f523fccdf34c44/test/jtreg/generator/testStruct/struct.h#L41), the double d field is not the first field, so according to AIX power mode rules, subsequent doubles are aligned on 4-byte boundaries, not 8 >> src/main/java/org/openjdk/jextract/impl/Options.java line 92: >> >>> 90: if (TypeImpl.IS_AIX) { >>> 91: clangArgs.add("-m64"); >>> 92: } >> >> This doesn't look like the right place to add this, as the `-m64` flag would be added for each clang argument. > > I think an extra call to `addClangArg` should be added to `JextractTool`. Fixed it. Thank you ------------- PR Review Comment: https://git.openjdk.org/jextract/pull/296#discussion_r2549667764 PR Review Comment: https://git.openjdk.org/jextract/pull/296#discussion_r2549675947 From jvernee at openjdk.org Fri Nov 21 13:03:57 2025 From: jvernee at openjdk.org (Jorn Vernee) Date: Fri, 21 Nov 2025 13:03:57 GMT Subject: RFR: 7904115: Fix for AIX test case failures due to incorrect alignment for double and pointer [v2] In-Reply-To: <5-AIbtzBO_0aDDWUd3OtmTNQCpVA1Ba7vvt3sA4uOKE=.62a83582-7ffa-44e6-8871-602139603147@github.com> References: <5-AIbtzBO_0aDDWUd3OtmTNQCpVA1Ba7vvt3sA4uOKE=.62a83582-7ffa-44e6-8871-602139603147@github.com> Message-ID: On Fri, 21 Nov 2025 12:51:03 GMT, Varada M wrote: >> Couldn't this be: >> >> >> case Double -> alignIfNeeded(runtimeHelperName() + ".C_DOUBLE", (TypeImpl.IS_AIX ? 4 : 8), align); > > yes right. > These are my findings! > > `case Double -> alignIfNeeded(runtimeHelperName() + ".C_DOUBLE", (TypeImpl.IS_AIX ? 4 : 8), align);` > The above fix solves most of the failures except two of them. This solves the failure like "Unsupported layout: 4%D8" > > The remaining two test failures are due to 'IllegalArgumentException: Invalid alignment constraint for member layout: D8(d)' > I observed that the expected alignment is 8 for them and the ABI expects the alignment constraint for d to be 4, not 8 > For one of the test failure : jtreg/generator/testStruct/LibStructTest.java > For the [struct AllTypes](https://github.com/varada1110/jextract/blob/91ff2392ac8c3ee7d0906486e8f523fccdf34c44/test/jtreg/generator/testStruct/struct.h#L41), the double d field is not the first field, so according to AIX power mode rules, subsequent doubles are aligned on 4-byte boundaries, not 8 Yes, that's expected, but I think the test should be modified to handle that instead. The issue with the code in this patch is that it adjusts the alignment down to `4` in some cases when the requested alignment is `8`. The requested alignment (i.e. the `align` argument) is always correct here, since that is what we get straight from clang based on alignment specifiers or pack pragmas. For instance, for a struct like this: struct foo { alignas(8) double d; }; `align` would be `8` here for the field `d`, but you overwrite it to `4`, which doesn't seem right. ------------- PR Review Comment: https://git.openjdk.org/jextract/pull/296#discussion_r2549694407 From jvernee at openjdk.org Fri Nov 21 13:10:23 2025 From: jvernee at openjdk.org (Jorn Vernee) Date: Fri, 21 Nov 2025 13:10:23 GMT Subject: RFR: 7904115: Fix for AIX test case failures due to incorrect alignment for double and pointer [v2] In-Reply-To: References: <5-AIbtzBO_0aDDWUd3OtmTNQCpVA1Ba7vvt3sA4uOKE=.62a83582-7ffa-44e6-8871-602139603147@github.com> Message-ID: On Fri, 21 Nov 2025 13:01:07 GMT, Jorn Vernee wrote: >> yes right. >> These are my findings! >> >> `case Double -> alignIfNeeded(runtimeHelperName() + ".C_DOUBLE", (TypeImpl.IS_AIX ? 4 : 8), align);` >> The above fix solves most of the failures except two of them. This solves the failure like "Unsupported layout: 4%D8" >> >> The remaining two test failures are due to 'IllegalArgumentException: Invalid alignment constraint for member layout: D8(d)' >> I observed that the expected alignment is 8 for them and the ABI expects the alignment constraint for d to be 4, not 8 >> For one of the test failure : jtreg/generator/testStruct/LibStructTest.java >> For the [struct AllTypes](https://github.com/varada1110/jextract/blob/91ff2392ac8c3ee7d0906486e8f523fccdf34c44/test/jtreg/generator/testStruct/struct.h#L41), the double d field is not the first field, so according to AIX power mode rules, subsequent doubles are aligned on 4-byte boundaries, not 8 > > Yes, that's expected, but I think the test should be modified to handle that instead. The issue with the code in this patch is that it adjusts the alignment down to `4` in some cases when the requested alignment is `8`. The requested alignment (i.e. the `align` argument) is always correct here, since that is what we get straight from clang based on alignment specifiers or pack pragmas. > > For instance, for a struct like this: > > > struct foo { > alignas(8) double d; > }; > > > `align` would be `8` here for the field `d`, but you overwrite it to `4`, which doesn't seem right. Okay, I had another look at the test, and it looks like it can not really be adjusted, so there might be an issue elsewhere. ------------- PR Review Comment: https://git.openjdk.org/jextract/pull/296#discussion_r2549708230 From jvernee at openjdk.org Fri Nov 21 14:08:47 2025 From: jvernee at openjdk.org (Jorn Vernee) Date: Fri, 21 Nov 2025 14:08:47 GMT Subject: RFR: 7904115: Fix for AIX test case failures due to incorrect alignment for double and pointer [v2] In-Reply-To: References: <5-AIbtzBO_0aDDWUd3OtmTNQCpVA1Ba7vvt3sA4uOKE=.62a83582-7ffa-44e6-8871-602139603147@github.com> Message-ID: On Fri, 21 Nov 2025 13:06:50 GMT, Jorn Vernee wrote: >> Yes, that's expected, but I think the test should be modified to handle that instead. The issue with the code in this patch is that it adjusts the alignment down to `4` in some cases when the requested alignment is `8`. The requested alignment (i.e. the `align` argument) is always correct here, since that is what we get straight from clang based on alignment specifiers or pack pragmas. >> >> For instance, for a struct like this: >> >> >> struct foo { >> alignas(8) double d; >> }; >> >> >> `align` would be `8` here for the field `d`, but you overwrite it to `4`, which doesn't seem right. > > Okay, I had another look at the test, and it looks like it can not really be adjusted, so there might be an issue elsewhere. I did a little debugging, and it looks like clang doesn't attach the alignment specified by `alignas` to the field declaration any ways. So, we can not handle hyper-aligned fields even if we wanted to. In other words, you can disregard the example above. On the other hand, I'm not sure if clang attaches the right alignment to double fields that are not the first field on AIX. Look at the code in `StructBuilder` that generates the layouts for fields: if (member instanceof Variable var) { memberLayout = layoutString(var.type(), align); memberLayout = String.format("%1$s%2$s.withName("%3$s")", indentString(indent + 1), memberLayout, member.name()); } You should be able to get the alignment of the field deceleration using `long fieldAlign = ClangAlignOf.getOrThrow(var) / 8;`. If this is `4` as expected for a non-first double field, then we could just pass that information down to the code that generates the layout string, I think. ------------- PR Review Comment: https://git.openjdk.org/jextract/pull/296#discussion_r2549869717 From jvernee at openjdk.org Fri Nov 21 15:43:26 2025 From: jvernee at openjdk.org (Jorn Vernee) Date: Fri, 21 Nov 2025 15:43:26 GMT Subject: RFR: 7904115: Fix for AIX test case failures due to incorrect alignment for double and pointer [v2] In-Reply-To: References: Message-ID: <6ozZL2ADnfbZeg2EIIidAuaCLPhnx1rNPLXKb7g8xnY=.1a2899e1-90c8-4ed9-9378-a4931ec67904@github.com> On Fri, 21 Nov 2025 12:57:39 GMT, Varada M wrote: >> Total of 10 test failures observed on AIX: >> jtreg/generator/nestedTypes/TestNestedTypesUnsupported.java >> jtreg/generator/test8246400/LibTest8246400Test.java >> jtreg/generator/test8258605/LibTest8258605Test.java >> jtreg/generator/test8261511/Test8261511.java >> jtreg/generator/testStruct/LibStructTest.java >> testng/org/openjdk/jextract/test/toolprovider/ConstantsTest.java >> testng/org/openjdk/jextract/test/toolprovider/IncompleteArrayTest.java >> testng/org/openjdk/jextract/test/toolprovider/Test8240811.java >> testng/org/openjdk/jextract/test/toolprovider/TestClassGeneration.java >> testng/org/openjdk/jextract/test/toolprovider/nestedAnonOffset/TestNestedAnonOffset.java >> >> This PR fixes AIX specific layout generation issues related to incorrect alignment double and pointer types. >> 1. Structs containing double fields fail with: >> i. Unsupported layout: 4%D8 >> ii. Invalid alignment constraint for member layout >> double in AIX structs has size 8 but alignment 4 (except as first field). AIX specific handling for C_DOUBLE computes the correct alignment. >> >> 2. Clang was detected as 32-bit due to missing -m64 during macro extraction, causing inconsistent macros. This caused jextract to interpret pointer constants incorrectly, leading to failures like: >> expected [-1] but found [4294967295] >> >> 3. TestNestedAnonOffset.java test failed on AIX because it also expects more padding similar to platforms like windows and linux >> >> >> After the patch jtreg tests passes successfully. >> >> JBS: [CODETOOLS-7904115](https://bugs.openjdk.org/browse/CODETOOLS-7904115) > > Varada M has updated the pull request incrementally with two additional commits since the last revision: > > - addition of -m64 at right place > - addition of -m64 at right place @varada1110 You could also try the following patch: diff --git a/src/main/java/org/openjdk/jextract/impl/ClassSourceBuilder.java b/src/main/java/org/openjdk/jextract/impl/ClassSourceBuilder.java index 7c1ae3a..a317dc5 100644 --- a/src/main/java/org/openjdk/jextract/impl/ClassSourceBuilder.java +++ b/src/main/java/org/openjdk/jextract/impl/ClassSourceBuilder.java @@ -30,7 +30,6 @@ import org.openjdk.jextract.Type.Declared; import org.openjdk.jextract.Type.Delegated; import org.openjdk.jextract.Type.Function; import org.openjdk.jextract.Type.Primitive; -import org.openjdk.jextract.impl.DeclarationImpl.ClangAlignOf; import org.openjdk.jextract.impl.DeclarationImpl.ClangEnumType; import org.openjdk.jextract.impl.DeclarationImpl.DeclarationString; import org.openjdk.jextract.impl.DeclarationImpl.JavaName; @@ -201,19 +200,25 @@ abstract class ClassSourceBuilder { throw new IllegalArgumentException("Not handled: " + type); } + private static final int NO_ALIGN_REQUIRED_MARKER = -1; + String layoutString(Type type) { - return layoutString(type, Long.MAX_VALUE); + return fieldLayoutString(type, -1, NO_ALIGN_REQUIRED_MARKER); } - String layoutString(Type type, long align) { + String fieldLayoutString(Type type, long typeAlign, long expectedAlign) { return switch (type) { - case Primitive p -> primitiveLayoutString(p, align); - case Declared d when Utils.isEnum(d) -> layoutString(ClangEnumType.get(d.tree()).get(), align); - case Declared d when Utils.isStructOrUnion(d) -> alignIfNeeded(JavaName.getFullNameOrThrow(d.tree()) + ".layout()", ClangAlignOf.getOrThrow(d.tree()) / 8, align); - case Delegated d when d.kind() == Delegated.Kind.POINTER -> alignIfNeeded(runtimeHelperName() + ".C_POINTER", 8, align); - case Delegated d -> layoutString(d.type(), align); - case Function _ -> alignIfNeeded(runtimeHelperName() + ".C_POINTER", 8, align); - case Array a -> String.format("MemoryLayout.sequenceLayout(%1$d, %2$s)", a.elementCount().orElse(0L), layoutString(a.elementType(), align)); + case Primitive p -> primitiveLayoutString(p, typeAlign, expectedAlign); + case Declared d when Utils.isEnum(d) -> + fieldLayoutString(ClangEnumType.get(d.tree()).get(), typeAlign, expectedAlign); + case Declared d when Utils.isStructOrUnion(d) -> + alignIfNeeded(JavaName.getFullNameOrThrow(d.tree()) + ".layout()", typeAlign, expectedAlign); + case Delegated d when d.kind() == Delegated.Kind.POINTER -> + alignIfNeeded(runtimeHelperName() + ".C_POINTER", typeAlign, expectedAlign); + case Delegated d -> fieldLayoutString(d.type(), typeAlign, expectedAlign); + case Function _ -> alignIfNeeded(runtimeHelperName() + ".C_POINTER", typeAlign, expectedAlign); + case Array a -> String.format("MemoryLayout.sequenceLayout(%1$d, %2$s)", a.elementCount().orElse(0L), + fieldLayoutString(a.elementType(), typeAlign, expectedAlign)); default -> throw new UnsupportedOperationException(); }; } @@ -250,18 +255,18 @@ abstract class ClassSourceBuilder { return " ".repeat(size * 4); } - private String primitiveLayoutString(Primitive primitiveType, long align) { + private String primitiveLayoutString(Primitive primitiveType, long defaultAlign, long expectedAlign) { return switch (primitiveType.kind()) { - case Bool -> runtimeHelperName() + ".C_BOOL"; - case Char -> runtimeHelperName() + ".C_CHAR"; - case Short -> alignIfNeeded(runtimeHelperName() + ".C_SHORT", 2, align); - case Int -> alignIfNeeded(runtimeHelperName() + ".C_INT", 4, align); - case Long -> alignIfNeeded(runtimeHelperName() + ".C_LONG", TypeImpl.IS_WINDOWS ? 4 : 8, align); - case LongLong -> alignIfNeeded(runtimeHelperName() + ".C_LONG_LONG", 8, align); - case Float -> alignIfNeeded(runtimeHelperName() + ".C_FLOAT", 4, align); - case Double -> alignIfNeeded(runtimeHelperName() + ".C_DOUBLE", 8, align); + case Bool -> alignIfNeeded(runtimeHelperName() + ".C_BOOL", defaultAlign, expectedAlign); + case Char -> alignIfNeeded(runtimeHelperName() + ".C_CHAR", defaultAlign, expectedAlign); + case Short -> alignIfNeeded(runtimeHelperName() + ".C_SHORT", defaultAlign, expectedAlign); + case Int -> alignIfNeeded(runtimeHelperName() + ".C_INT", defaultAlign, expectedAlign); + case Long -> alignIfNeeded(runtimeHelperName() + ".C_LONG", defaultAlign, expectedAlign); + case LongLong -> alignIfNeeded(runtimeHelperName() + ".C_LONG_LONG", defaultAlign, expectedAlign); + case Float -> alignIfNeeded(runtimeHelperName() + ".C_FLOAT", defaultAlign, expectedAlign); + case Double -> alignIfNeeded(runtimeHelperName() + ".C_DOUBLE", defaultAlign, expectedAlign); case LongDouble -> TypeImpl.IS_WINDOWS ? - alignIfNeeded(runtimeHelperName() + ".C_LONG_DOUBLE", 8, align) : + alignIfNeeded(runtimeHelperName() + ".C_LONG_DOUBLE", defaultAlign, expectedAlign) : paddingLayoutString(8, 0); case HalfFloat, Char16, WChar -> paddingLayoutString(2, 0); // unsupported case Float128, Int128 -> paddingLayoutString(16, 0); // unsupported @@ -269,8 +274,8 @@ abstract class ClassSourceBuilder { }; } - private String alignIfNeeded(String layoutPrefix, long align, long expectedAlign) { - return align > expectedAlign ? + private String alignIfNeeded(String layoutPrefix, long defaultAlign, long expectedAlign) { + return expectedAlign != NO_ALIGN_REQUIRED_MARKER && defaultAlign != expectedAlign ? String.format("%1$s.align(%2$s, %3$d)", runtimeHelperName(), layoutPrefix, expectedAlign) : layoutPrefix; } diff --git a/src/main/java/org/openjdk/jextract/impl/StructBuilder.java b/src/main/java/org/openjdk/jextract/impl/StructBuilder.java index dedad14..3415996 100644 --- a/src/main/java/org/openjdk/jextract/impl/StructBuilder.java +++ b/src/main/java/org/openjdk/jextract/impl/StructBuilder.java @@ -460,7 +460,7 @@ final class StructBuilder extends ClassSourceBuilder implements OutputFactory.Bu boolean isStruct = scoped.kind() == Scoped.Kind.STRUCT; - long align = ClangAlignOf.getOrThrow(scoped) / 8; + long scopedTypeAlign = ClangAlignOf.getOrThrow(scoped) / 8; long offset = base; long size = 0L; // bits @@ -477,7 +477,16 @@ final class StructBuilder extends ClassSourceBuilder implements OutputFactory.Bu } String memberLayout; if (member instanceof Variable var) { - memberLayout = layoutString(var.type(), align); + // FIXME we can not handle hyper-aligned fields here since clang doesn't attach the + // alignment specified by a field alignment specifier to the field declaration cursor. + // + // struct foo { // ClangAlignOf == 8 + // _Alignas(8) int x; // ClangAlignOf == 4 + // }; + long fieldTypeAlign = ClangAlignOf.getOrThrow(var) / 8; + // if struct is packed, adjust expected alignment down + long expectedAlign = Math.min(scopedTypeAlign, fieldTypeAlign); + memberLayout = fieldLayoutString(var.type(), fieldTypeAlign, expectedAlign); memberLayout = String.format("%1$s%2$s.withName("%3$s")", indentString(indent + 1), memberLayout, member.name()); } else { // anon struct And then I think you should be able to just adjust `expectedAlign` in `StructBuilder` for what AIX needs. ------------- PR Comment: https://git.openjdk.org/jextract/pull/296#issuecomment-3563559127 From mcimadamore at openjdk.org Fri Nov 21 16:54:27 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Fri, 21 Nov 2025 16:54:27 GMT Subject: RFR: 7904115: Fix for AIX test case failures due to incorrect alignment for double and pointer [v2] In-Reply-To: References: Message-ID: On Fri, 21 Nov 2025 12:57:39 GMT, Varada M wrote: >> Total of 10 test failures observed on AIX: >> jtreg/generator/nestedTypes/TestNestedTypesUnsupported.java >> jtreg/generator/test8246400/LibTest8246400Test.java >> jtreg/generator/test8258605/LibTest8258605Test.java >> jtreg/generator/test8261511/Test8261511.java >> jtreg/generator/testStruct/LibStructTest.java >> testng/org/openjdk/jextract/test/toolprovider/ConstantsTest.java >> testng/org/openjdk/jextract/test/toolprovider/IncompleteArrayTest.java >> testng/org/openjdk/jextract/test/toolprovider/Test8240811.java >> testng/org/openjdk/jextract/test/toolprovider/TestClassGeneration.java >> testng/org/openjdk/jextract/test/toolprovider/nestedAnonOffset/TestNestedAnonOffset.java >> >> This PR fixes AIX specific layout generation issues related to incorrect alignment double and pointer types. >> 1. Structs containing double fields fail with: >> i. Unsupported layout: 4%D8 >> ii. Invalid alignment constraint for member layout >> double in AIX structs has size 8 but alignment 4 (except as first field). AIX specific handling for C_DOUBLE computes the correct alignment. >> >> 2. Clang was detected as 32-bit due to missing -m64 during macro extraction, causing inconsistent macros. This caused jextract to interpret pointer constants incorrectly, leading to failures like: >> expected [-1] but found [4294967295] >> >> 3. TestNestedAnonOffset.java test failed on AIX because it also expects more padding similar to platforms like windows and linux >> >> >> After the patch jtreg tests passes successfully. >> >> JBS: [CODETOOLS-7904115](https://bugs.openjdk.org/browse/CODETOOLS-7904115) > > Varada M has updated the pull request incrementally with two additional commits since the last revision: > > - addition of -m64 at right place > - addition of -m64 at right place It seems like the issue described in this PR has more to do with libclang not having a way to report the alignment of a specific layout fields (instead, it has only ways to report intrinsic alignment of a type). @varada1110 I wonder if you should perhaps also try to fix this in libclang as well? It seems like a similar problem can also occur with other libclang-dependent tools, such as Rust [bindgen](https://github.com/rust-lang/rust-bindgen) ? ------------- PR Comment: https://git.openjdk.org/jextract/pull/296#issuecomment-3563853688 From mcimadamore at openjdk.org Fri Nov 21 17:08:14 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Fri, 21 Nov 2025 17:08:14 GMT Subject: RFR: 7904115: Fix for AIX test case failures due to incorrect alignment for double and pointer [v2] In-Reply-To: References: Message-ID: On Fri, 21 Nov 2025 12:57:39 GMT, Varada M wrote: >> Total of 10 test failures observed on AIX: >> jtreg/generator/nestedTypes/TestNestedTypesUnsupported.java >> jtreg/generator/test8246400/LibTest8246400Test.java >> jtreg/generator/test8258605/LibTest8258605Test.java >> jtreg/generator/test8261511/Test8261511.java >> jtreg/generator/testStruct/LibStructTest.java >> testng/org/openjdk/jextract/test/toolprovider/ConstantsTest.java >> testng/org/openjdk/jextract/test/toolprovider/IncompleteArrayTest.java >> testng/org/openjdk/jextract/test/toolprovider/Test8240811.java >> testng/org/openjdk/jextract/test/toolprovider/TestClassGeneration.java >> testng/org/openjdk/jextract/test/toolprovider/nestedAnonOffset/TestNestedAnonOffset.java >> >> This PR fixes AIX specific layout generation issues related to incorrect alignment double and pointer types. >> 1. Structs containing double fields fail with: >> i. Unsupported layout: 4%D8 >> ii. Invalid alignment constraint for member layout >> double in AIX structs has size 8 but alignment 4 (except as first field). AIX specific handling for C_DOUBLE computes the correct alignment. >> >> 2. Clang was detected as 32-bit due to missing -m64 during macro extraction, causing inconsistent macros. This caused jextract to interpret pointer constants incorrectly, leading to failures like: >> expected [-1] but found [4294967295] >> >> 3. TestNestedAnonOffset.java test failed on AIX because it also expects more padding similar to platforms like windows and linux >> >> >> After the patch jtreg tests passes successfully. >> >> JBS: [CODETOOLS-7904115](https://bugs.openjdk.org/browse/CODETOOLS-7904115) > > Varada M has updated the pull request incrementally with two additional commits since the last revision: > > - addition of -m64 at right place > - addition of -m64 at right place My 0.02$ on this issue. Jextract code (perhaps incorrectly) hardwrires the expected alignment for common C types. Let's ignore the fact that it's hardwired... The main reason we do this is to avoid redundant call to `align`. Not because it would be inefficient, but simply because it will make layouts unreadable. So, we do: case Double -> alignIfNeeded(runtimeHelperName() + ".C_DOUBLE", 8, align); And then: private String alignIfNeeded(String layoutPrefix, long align, long expectedAlign) { return align > expectedAlign ? String.format("%1$s.align(%2$s, %3$d)", runtimeHelperName(), layoutPrefix, expectedAlign) : layoutPrefix; } ``` What this means is: if the _expected_ alignment requirement is _bigger_ than the alignment of the primitive type, we can safely skip the call to `align` (most of the times). Which means we only need to call `align` when we're trying to, say, put an `int` field in a 2-byte aligned offset -- this will lead to an exception when building the layout, so we need to properly align the layout (to 2 bytes). Now, given the fuzzy nature of double alignment on AIX, perhaps it would be best to skip this "optimization" at least for doubles. That is, we could simply do: case Double -> alignIfNeeded(runtimeHelperName() + ".C_DOUBLE", IS_AIX ? Long.MAX_VALUE : 8, align); What this will do is it will pass a very big intrinsic layout alignment for `double`. This alignment will always be bigger than whatever jextract wants, which means a call to `align` will always be emitted. This seems the path of least resistance? ------------- PR Comment: https://git.openjdk.org/jextract/pull/296#issuecomment-3563909130 From mcimadamore at openjdk.org Fri Nov 21 18:43:23 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Fri, 21 Nov 2025 18:43:23 GMT Subject: RFR: 7904115: Fix for AIX test case failures due to incorrect alignment for double and pointer [v2] In-Reply-To: References: Message-ID: On Fri, 21 Nov 2025 17:04:39 GMT, Maurizio Cimadamore wrote: > My 0.02$ on this issue. I had an offline discussion with @JornVernee --- it seems part of the issue here is caused by the fact that the required alignment we pass is the alignment of the struct as a whole (which takes into account any `pragma pack` directives). In reality it would probably be more robust to figure out what the alignment is based on what is the offset at which clang wants to put the struct field. This should work and only make very minimal assumptions. I also wonder if we should do that as part of this PR, or as a separate PR. ------------- PR Comment: https://git.openjdk.org/jextract/pull/296#issuecomment-3564203711 From varadam at openjdk.org Tue Nov 25 18:41:15 2025 From: varadam at openjdk.org (Varada M) Date: Tue, 25 Nov 2025 18:41:15 GMT Subject: RFR: 7904115: Fix for AIX test case failures due to incorrect alignment for double and pointer [v3] In-Reply-To: References: Message-ID: > Total of 10 test failures observed on AIX: > jtreg/generator/nestedTypes/TestNestedTypesUnsupported.java > jtreg/generator/test8246400/LibTest8246400Test.java > jtreg/generator/test8258605/LibTest8258605Test.java > jtreg/generator/test8261511/Test8261511.java > jtreg/generator/testStruct/LibStructTest.java > testng/org/openjdk/jextract/test/toolprovider/ConstantsTest.java > testng/org/openjdk/jextract/test/toolprovider/IncompleteArrayTest.java > testng/org/openjdk/jextract/test/toolprovider/Test8240811.java > testng/org/openjdk/jextract/test/toolprovider/TestClassGeneration.java > testng/org/openjdk/jextract/test/toolprovider/nestedAnonOffset/TestNestedAnonOffset.java > > This PR fixes AIX specific layout generation issues related to incorrect alignment double and pointer types. > 1. Structs containing double fields fail with: > i. Unsupported layout: 4%D8 > ii. Invalid alignment constraint for member layout > double in AIX structs has size 8 but alignment 4 (except as first field). AIX specific handling for C_DOUBLE computes the correct alignment. > > 2. Clang was detected as 32-bit due to missing -m64 during macro extraction, causing inconsistent macros. This caused jextract to interpret pointer constants incorrectly, leading to failures like: > expected [-1] but found [4294967295] > > 3. TestNestedAnonOffset.java test failed on AIX because it also expects more padding similar to platforms like windows and linux > > > After the patch jtreg tests passes successfully. > > JBS: [CODETOOLS-7904115](https://bugs.openjdk.org/browse/CODETOOLS-7904115) Varada M has updated the pull request incrementally with one additional commit since the last revision: reverted the C_DOUBLE alignment fix ------------- Changes: - all: https://git.openjdk.org/jextract/pull/296/files - new: https://git.openjdk.org/jextract/pull/296/files/7f1983ba..f43b66fb Webrevs: - full: https://webrevs.openjdk.org/?repo=jextract&pr=296&range=02 - incr: https://webrevs.openjdk.org/?repo=jextract&pr=296&range=01-02 Stats: 12 lines in 1 file changed: 0 ins; 11 del; 1 mod Patch: https://git.openjdk.org/jextract/pull/296.diff Fetch: git fetch https://git.openjdk.org/jextract.git pull/296/head:pull/296 PR: https://git.openjdk.org/jextract/pull/296 From varadam at openjdk.org Tue Nov 25 18:41:16 2025 From: varadam at openjdk.org (Varada M) Date: Tue, 25 Nov 2025 18:41:16 GMT Subject: RFR: 7904115: Fix for AIX test case failures due to incorrect alignment for double and pointer [v2] In-Reply-To: <6ozZL2ADnfbZeg2EIIidAuaCLPhnx1rNPLXKb7g8xnY=.1a2899e1-90c8-4ed9-9378-a4931ec67904@github.com> References: <6ozZL2ADnfbZeg2EIIidAuaCLPhnx1rNPLXKb7g8xnY=.1a2899e1-90c8-4ed9-9378-a4931ec67904@github.com> Message-ID: <6zZBMqrpSSPf1NCOMy-Y4VXVSY-lbKFscAq7MyY4Dxo=.66aed83b-5664-41e6-b485-854e9110e4dd@github.com> On Fri, 21 Nov 2025 15:40:01 GMT, Jorn Vernee wrote: >> Varada M has updated the pull request incrementally with two additional commits since the last revision: >> >> - addition of -m64 at right place >> - addition of -m64 at right place > > @varada1110 > > You could also try the following patch: > > > diff --git a/src/main/java/org/openjdk/jextract/impl/ClassSourceBuilder.java b/src/main/java/org/openjdk/jextract/impl/ClassSourceBuilder.java > index 7c1ae3a..a317dc5 100644 > --- a/src/main/java/org/openjdk/jextract/impl/ClassSourceBuilder.java > +++ b/src/main/java/org/openjdk/jextract/impl/ClassSourceBuilder.java > @@ -30,7 +30,6 @@ import org.openjdk.jextract.Type.Declared; > import org.openjdk.jextract.Type.Delegated; > import org.openjdk.jextract.Type.Function; > import org.openjdk.jextract.Type.Primitive; > -import org.openjdk.jextract.impl.DeclarationImpl.ClangAlignOf; > import org.openjdk.jextract.impl.DeclarationImpl.ClangEnumType; > import org.openjdk.jextract.impl.DeclarationImpl.DeclarationString; > import org.openjdk.jextract.impl.DeclarationImpl.JavaName; > @@ -201,19 +200,25 @@ abstract class ClassSourceBuilder { > throw new IllegalArgumentException("Not handled: " + type); > } > > + private static final int NO_ALIGN_REQUIRED_MARKER = -1; > + > String layoutString(Type type) { > - return layoutString(type, Long.MAX_VALUE); > + return fieldLayoutString(type, -1, NO_ALIGN_REQUIRED_MARKER); > } > > - String layoutString(Type type, long align) { > + String fieldLayoutString(Type type, long typeAlign, long expectedAlign) { > return switch (type) { > - case Primitive p -> primitiveLayoutString(p, align); > - case Declared d when Utils.isEnum(d) -> layoutString(ClangEnumType.get(d.tree()).get(), align); > - case Declared d when Utils.isStructOrUnion(d) -> alignIfNeeded(JavaName.getFullNameOrThrow(d.tree()) + ".layout()", ClangAlignOf.getOrThrow(d.tree()) / 8, align); > - case Delegated d when d.kind() == Delegated.Kind.POINTER -> alignIfNeeded(runtimeHelperName() + ".C_POINTER", 8, align); > - case Delegated d -> layoutString(d.type(), align); > - case Function _ -> alignIfNeeded(runtimeHelperName() + ".C_POINTER", 8, align); > - case Array a -> String.format("MemoryLayout.sequenceLayout(%1$d, %2$s)", a.elementCount().orElse(0L), layoutString(a.elementType(), align)); > + case Primitive p -> primitiveLayoutString(p, typeAlign, expectedAlign); > + case Declared d when Utils.isEnum(d) -> > + fieldLayoutString(ClangEnumType.get(d.tree()).get(), typeAlign, expectedAlign); > + case Declared d when Utils.isStructOrUnion(d) -> > + alignIfNeeded(JavaName.getFull... Thank you @JornVernee @mcimadamore . I understood the part; instead of using the struct-level alignment globally, we should compute the alignment of each individual field ! I have tried out the code changes @JornVernee has shared! I do see the same two tests failing again with "Invalid alignment constraint for member layout: D(8)" this time the default and expected alignment is of same value which is 4. I am currently looking into that! I have reverted the changes of C_DOUBLE alignment changes to create separate PR ------------- PR Comment: https://git.openjdk.org/jextract/pull/296#issuecomment-3577025565