[Vm-dev] Plugin code generation issues
Levente Uzonyi
leves at caesar.elte.hu
Mon Mar 9 17:27:27 UTC 2020
Hi Eliot,
On Mon, 9 Mar 2020, Eliot Miranda wrote:
>
> Hi Levente,
>
>
>> On Mar 9, 2020, at 8:54 AM, Levente Uzonyi <leves at caesar.elte.hu> wrote:
>>
>> Hi All,
>>
>> I wrote a new plugin the other day and found two issues with code generation.
>> The first one, which is less important is related to the inline pragma.
>> I expected that methods marked with <inline: true> will either not be generated at all when the code generator inlines all occurrences of them or they'll be generated as inline C functions. But they are generated as regular static functions even though they are never used.
>
> Slang is not always able to inline. For a example, inlining into conditionals is problematic. For this reason Slang treats <inline: true> as a recommendation. If you want to insist, eliminate the static functions, and deal with any failures to inline by suitable rewrites then use <inline: #always>.
>
> Slang also obeys <inline: #never> which is useful in other ways (for example reducing code duplication).
Thanks. <inline: #always> does just what I need.
>
>> The other one, which is more significant is related to type casts.
>> I've got the following method:
>>
>> rotateRight64: value by: amount
>>
>> <inline: true>
>> <var: #value type: #'unsigned long long'>
>> <returnTypeC: #'unsigned long long'>
>>
>> ^(value >> amount) bitOr: (value << (64 - amount))
>>
>> The code using the above method has the variable declaration
>>
>> <var: #w declareC: 'unsigned long long w[80]'>
>>
>> The method is used with individual elements of w:
>>
>> self rotateRight64: (w at: i - 2) by: 61
>>
>> The generated function gets inlined as expected, but the elements of the array are casted to usqInt before right shifts:
>>
>> ((((usqInt) (w[i2 - 2])) >> 61) | ((w[i2 - 2]) << (3)))
>>
>> This is a problem on 32-bit platforms, because usqInt is unsigned int there, so the upper 32-bits will be lost by the cast.
>>
>> When the method is used with non-array variables, then the generator works as expected:
>>
>> self rotateRight64: a by: 39
>>
>> is generated as:
>>
>> ((a >> 39) | (a << (25)))
>>
>> where a is declared as
>>
>> <var: #a type: #'unsigned long long'>
>>
>> I tried to fix the issue by declaring w as
>>
>> <var: #w type: #'unsigned long long*'>
>>
>> But is didn't make the usqInt casts go away.
>> Is it possible that the code generator doesn't know that the type of w[i] is unsigned long long, when w is unsigned long long*?
>
> I’ll need to take a look at this in detail. For now, try using the type #usqLong and see if it makes a difference.
Unfortunately, the code behaves the same way with #usqLong.
I forgot to mention a third issue. There's no easy way to check the type
of 64-bit and 16-bit arrays. There's #isWords: for 32-bit arrays, and
#isBytes: for 8-bit arrays.
#isWordsOrBytes: is a misnomer now, because it returns true for 8, 16, 32
and 64-bit arrays.
I used the following workaround:
((interpreterProxy isIndexable: hashOop)
and: [ (interpreterProxy isWordsOrBytes: hashOop)
and: [ (interpreterProxy slotSizeOf: hashOop) = 8 ] ])
ifFalse: [ ^interpreterProxy primitiveFailFor: PrimErrBadArgument ].
The first check is probably unnecessary.
SpurMemoryManager understands #isLong64s:, but InterpreterProxy doesn't
have that method.
Also, some implementations in InterpreterProxy may be incorrect. e.g.
#isWordsOrBytes:.
Levenete
>
>> Levente
>>
>> P.S.: The code is available here http://squeaksource.com/Cryptography/CryptographyPlugins-ul.18.mcz .
>> Generate SHA2Plugin to see the problem.
More information about the Vm-dev
mailing list