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