Windows integral promotions / uint64_t
Andrew Haley
aph-open at littlepinkcloud.com
Wed May 4 08:41:36 UTC 2022
On 4/28/22 17:14, Kim Barrett wrote:
>> On Apr 28, 2022, at 8:53 AM, Andrew Haley <aph-open at littlepinkcloud.com> wrote:
>>
>> I'm seeing this failure from the Windows/AArch64 C++ compiler:
>>
>> * For target hotspot_variant-server_libjvm_objs_stubGenerator_aarch64.obj:
>> stubGenerator_aarch64.cpp
>> d:\a\jdk\jdk\jdk\src\hotspot\cpu\aarch64\stubGenerator_aarch64.cpp(6524): error C2668: 'MacroAssembler::sub': ambiguous call to overloaded function
>> d:\a\jdk\jdk\jdk\src\hotspot\cpu\aarch64\macroAssembler_aarch64.hpp(1174): note: could be 'void MacroAssembler::sub(Register,Register,Register)'
>> d:\a\jdk\jdk\jdk\src\hotspot\cpu\aarch64\macroAssembler_aarch64.hpp(1174): note: or 'void MacroAssembler::sub(Register,Register,uint64_t)'
>> d:\a\jdk\jdk\jdk\src\hotspot\cpu\aarch64\stubGenerator_aarch64.cpp(6524): note: while trying to match the argument list '(const Register, const Register, unsigned int)'
>> ... (rest of output omitted)
>>
>> 6524: __ sub(sp, rfp, ((unsigned)framesize-4) << LogBytesPerInt); // prolog
>
> I think what may be happening here is that the third argument to sub is a constant expression
> whose value is 0, so is ambiguously either an integral 0 or a null pointer. C++14 says
> only a literal 0 is supposed to be implicitly convertible to a pointer [1], but C++11 and earlier
> allow any constexpr 0 to implicitly convert [2]. And I noticed a while ago that gcc seems to
> have retained the old behavior even in C++14 mode (at least sometimes?). Maybe Visual
> Studio is doing the same?
Ahh, OK. It didn't occur to me that the result of the expression might
be zero. Makes sense.
> But then, why aren’t we seeing similar problems with gcc?
Indeed! :-)
> [1] C++14 4.10/1 A null pointer constant is an integer literal (2.14.2) with value zero …
> [2] C++11 4.10/1 A null pointer constant is an integral constant expression (5.19) prvalue of integer type that evaluates to zero…
>
> A way to deal with this kind of thing is to use templates to inhibit conversions and use SFINAE
> to select and forward to type-specific helpers. So something like
>
> template<typename ThirdArgType, ENABLE_IF(std::is_integral<ThirdArgType>::value)>
> void sub(Register arg0, Register arg1, ThirdArgType arg2) { sub_integral_third_arg(arg0, arg1, arg2); }
>
> template<typename ThirdArgType, ENABLE_IF(std::is_pointer<ThirdArgType>::value)>
> void sub(Register arg0, Register arg1, ThirdArgType arg2) { sub_ponter_third_arg(arg0, arg1, arg2); }
>
> This is obviously pretty ugly, and not something I would really recommend here.
Right.
> Once again the hacky way Register is defined is biting us.
Interesting! This relates to the patch for 8276563 I wrote early this year.
It fixes the Undefined Behaviour of Register, but keeps it as a pointer type.
I did look at making Register a class with a single const field, but the
quality of generated code was poor. In particular, for some reason I don't
understand, Register instances were being passed by reference.
I have it on my list of Things To Do One Day to fix x86 and VMReg in a
similar way.
Thanks,
--
Andrew Haley (he/him)
Java Platform Lead Engineer
Red Hat UK Ltd. <https://www.redhat.com>
https://keybase.io/andrewhaley
EAC8 43EB D3EF DB98 CC77 2FAD A5CD 6035 332F A671
More information about the hotspot-dev
mailing list