[Vm-dev] type inferrence for #<< is IMO all wrong...

Eliot Miranda eliot.miranda at gmail.com
Sun Feb 23 19:40:15 UTC 2020


On Sat, Feb 22, 2020 at 1:03 AM Nicolas Cellier <
nicolas.cellier.aka.nice at gmail.com> wrote:

>
> Hi Eliot,
> What we must do is correctly infer the type that we generate.
> Computing the type of (1 << anything) as int is correct if that is what we
> generate.
>
> If it indeed overflows, then we must cast to VM word sqInt at code
> generation and indeed infer
> (((sqInt) 1) << anything) as sqInt.
> But this is invoking UB and potentially many -O compiler problems if left
> operand is negative.
> So I think that we do generate this foolish (but recommended) expression:
> ((sqInt)(((usqInt) x) << anything))
> and must we infer that type to sqInt. Maybe we have another path for
> constants...
>

It appears we do all this.  I'm reading (*my
own?!) generateShiftLeft:on:indent: and it casts to 64-bits if appropriate
and casts to unsigned and back if signed.  It is the second most complex
generation method, after generateInlineCppIfElse:asArgument:on:indent:.

>
>
> Le sam. 22 févr. 2020 à 05:34, Eliot Miranda <eliot.miranda at gmail.com> a
> écrit :
>
>>
>> Hi Nicolas, Hi Clément, Hi Pierre, Hi All,
>>
>>     I'm working again on ARMv8 having got confused and with help clear
>> headed again.  So I'm getting the real system to run (it displays the full
>> desktop before crashing).  One issue is the IMO mis-typing of #<<.
>>
>> The expression in question is
>> 1 << (cogit coInterpreter highBit: cogit methodZone zoneEnd)
>> which is used to determine a type for mask:
>> mask := 1 << (cogit coInterpreter highBit: cogit methodZone zoneEnd) -
>> dataCacheMinLineLength.
>>
>>
>> In Smalltalk this evaluates to something large, and in the real VM it
>> should evaluate to 1 << 39.  However, because in
>> CCodeGenerator>>returnTypeForSend:in:ifNil: we explicitly assume C
>> semantics here:
>>
>> ^kernelReturnTypes
>> at: sel
>> ifAbsent:
>> [sel
>> caseOf: {
>> ...
>> "C99 Sec Bitwise shift operators ... 3 Semantics ...
>> The integer promotions are performed on each of the operands.
>>  The type of the result is that of the promoted left operand..."
>> [#>>] -> [sendNode receiver typeFrom: self in: aTMethod].
>> [#<<] -> [sendNode receiver typeFrom: self in: aTMethod].
>>
>> we compute the type of 1 << anything to be #int, and hence the type of
>> mask to be int, and hence mask is both truncated to 32-bits and later
>> extended to 64-bits by virtue of being passed as an argument to a #sqInt
>> parameter. So instead of generating the mask 16r7FFFFFFFC0 we generate
>> the mask 16rFFFFFFFFFFFFFFC0.  Clearly nonsense.
>>
>> It seems to me that we have the wrong philosophy.
>> In CCodeGenerator>>returnTypeForSend:in:ifNil: we should be computing types
>> that cause the generated C to mimic as closely as possible what happens in
>> Smalltalk, *not* typing according to the C99 standard, which creates
>> unintended incompatibilities between the simulated Slang and the generated
>> Slang.
>>
>> Surely what we should be doing for << is seeing if the right operand is a
>> constant and if so typing according to that, but in general typing << as
>> #sqInt or #usqInt, depending on the type of the left operand.  This is what
>> Smalltalk does; left-shifting a signed value preserves the sign; left
>> shifting a non-negative value always yields a non-negative value.  Yes,
>> eventually we will truncate to the word size, but the word size is sqInt,
>> not int, and we are familiar with the truncation issue.
>>
>> The mistyping of << as int is unexpected and extremely inconvenient.  We
>> force the Slang programmer to type all variables receiving the result of a
>> << explicitly.
>>
>> Do you agree or does my way lead to chaos?
>>
>> _,,,^..^,,,_
>> best, Eliot
>>
>

-- 
_,,,^..^,,,_
best, Eliot
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.squeakfoundation.org/pipermail/vm-dev/attachments/20200223/fd87e564/attachment.html>


More information about the Vm-dev mailing list