On Fri, 16 Oct 2026 15:58:14 GMT, Jorn Vernee <[email protected]> wrote:
> Currently we do not directly support unsigned types in the Linker. The > javadoc has this to say about it: > >> A native linker typically does not provide canonical layouts for C's >> unsigned integral > types. Instead, they are modeled using the canonical layouts associated with > their > corresponding signed integral types. For instance, the C type `unsigned long` > maps to the canonical layout for `code long`. > > This was done under the earlier assumption that ABIs treat signed and > unsigned types the same. However, it turns out that we missed certain cases > where this does matter for some ABIs. More concretely: > > - Mac x64 and AArch64 ABIs require integral types smaller than `int` to be > widened to `int` before being passed to a function > [1](https://developer.apple.com/documentation/xcode/writing-64-bit-intel-code-for-apple-platforms), > > [2](https://developer.apple.com/documentation/xcode/writing-arm64-code-for-apple-platforms). > Clang even extends this behavior to Linux x64 (although this appears to be a > bug) > [3](https://mail.openjdk.org/archives/list/[email protected]/message/RJNMKNUXN7R5PSJETZKX3PMBJ7P6GYJG/). > - RISCV requires arguments smaller than XLEN to be extended to 32 bits > according to their sign, and then sign extended to XLEN > [4](https://docs.riscv.org/reference/abi/v1.0/riscv-cc-procedure-calling-convention.html). > - PowerPC requires small integer types (char, short, int, long, enum) to be > extended to long > [5](https://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi-1.9.html#PARAM-PASS). > > In order to address these use cases we need to attach a bit of extra > information to a linkage request that indicates the signedness of certain > arguments. For this patch, we've chosen to attach that information directly > to the argument layouts through a newly introduced `boolean isSigned()` > method on a new `ValueLayout` subclass `OfIntegral` that is implemented by > `OfByte`, `OfShort`, `OfInt`, and `OfLong`. > > This information is potentially used by the linker to implement the correct > extension. In cases where it doesn't affect the way functions are linker the > information is erased in order to provide more efficient caching, since > signed and unsigned types can share the same downcall handle in that case. > > Testing: `jdk_foreign` test suite on Windows/Linux/Mac-x64, > Mac/Linux-AArch64, Linux-x64 using the fallback linker. > > --------- > - [x] I confirm that I make this contribution in accordance with the [OpenJDK > Interim AI Policy](https://openjdk.org/legal/ai). I eye-balled the RISC-V and PPC changes for this. @feilongjiang and @TheRealMDoerr you might want to have a look at this as well. Please let me know if this works. Hey Martin, I think I know what the problem is. That test tries to allocate a downcall stub using the maximum number of arguments. Since I changed the call arranger to pass int and smaller arguments as long, and long takes up more slots, we are running into the argument limit. I think we just have to adjust the test for PowerPC. The problem with handling ABI dependent conversions in the downcall stub is that it would be harder to intrinsify downcalls in C2 (which I still plan to do at some point...). Since C2 would have to replicate what the downcall stub does C2 would start having to keep track of platform specific behavior. The advice I got from C2 engineers back when I started working on the current incarnation of the linker was to put as much of the logic as possible on the Java side to keep what C2 has to do simpler, so doing that would have my preference. (In case you're interested, the code is a bit stale, but this is the prototype I have: https://github.com/openjdk/jdk/compare/master...JornVernee:jdk:NativeIntrinsics) I've implemented the feedback so far. PPC and s390 will now only widen unsigned values to `long`. I'm working out some final details about the design with Maurizio, then I will un-draft the PR. That's a good point. We could move some of this logic to the Windows CallArranger as well, and convert to `long` first using `Double::doubleToRawLongBits`. I prototyped this and it seems to just work. The benefit of doing it in the backend is that we can handle the conversion and move into target register both at once with a single move operation. I think for the intrinsification the important bit is that a move from an FP to GP register has a single implementation in the IR. src/java.base/share/classes/java/lang/foreign/ValueLayout.java line 125: > 123: VarHandle varHandle(); > 124: > 125: /** This doc uses the term 'signedness' as a property of the type. I also considered using just 'sign', but I think that's incorrect. The two polarities of 'sign' or 'positive' and 'negative', whereas the two polarities of 'signedness' are 'signed' and 'unsigned'. See also: https://en.wiktionary.org/wiki/sign#English and https://en.wiktionary.org/wiki/signedness ------------- PR Comment: https://git.openjdk.org/jdk/pull/33417#issuecomment-6219627159 PR Comment: https://git.openjdk.org/jdk/pull/33417#issuecomment-6225429824 PR Comment: https://git.openjdk.org/jdk/pull/33417#issuecomment-6368814610 PR Comment: https://git.openjdk.org/jdk/pull/33417#issuecomment-6451679656 PR Review Comment: https://git.openjdk.org/jdk/pull/33417#discussion_r4402461983
