Re: [Pharo-dev] NB and ASMJit questions

2014-02-17 Thread Igor Stasenko
On 16 February 2014 23:37, Torsten Bergmann  wrote:

> Hi,
>
> I'm trying to mimic the following C/C++ example in NativeBoots to allow
> random number
> generation on windows:
>
>   https://gist.github.com/kbjorklu/6317361
>
> When I combine the flags in Pharo using "|" in the same way like in the
> first function call
> of the example:
>
> acquireContextExample1
>   NBFFICallout stdcall: #(BOOL CryptAcquireContextA(HCRYPTPROV self, 0, 0,
> PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) module: #advapi32
>
> I get an error 'comma expected'. Looks like the NBFnSpecParser does not
> allow
> expression evaluation like CRYPT_VERIFYCONTEXT | CRYPT_SILENT. Will this
> be possible
> in future versions?
>
> Nonetheless I tried to continue and since I defined:
>CRYPT_VERIFYCONTEXT := 16rF000.
>CRYPT_SILENT := 16r0040.
>
> I evaluated manually and tried to use the harcoded value directly:
>
> acquireContextExample2
>
> "Retrieves information about the current console font."
>  
>
> ^ NBFFICallout stdcall: #(BOOL CryptAcquireContextA(HCRYPTPROV
> self, 0, 0, PROV_RSA_FULL, 16rF040)) module: #advapi32
>
>
> but this returns another error when converting using #asDWord:
>
>   (16rF040 i4) exceeds doubleword (32bit) range
>
> in an AJImmediate but 16rF040. Looks like it is treated as unsiged
> since
>
> 16rF040 asUImm32 asDWord
>
> works. How to specifiy the number directly but as unsigned?
>
> To reproduce:
>  - take a fresh Pharo3.0 Latest update: #30759
>  - load "OSWindows" from config browser to get the core and other packages
>  - load "OS-Windows-Cryptography" package/mcz from
> smalltalkhub.com/#!/~OS/OS-Windows
>  - evaluate WinCryptoProvider new acquireContextExample2 or
> WinCryptoProvider new acquireContextExample1
>
> Any helping hand in converting the example would be appreciated.
>
> Thx
> T.
>

Yes, i am aware of this problem.

(16rF040 i4) exceeds doubleword (32bit) range

i4  means signed integer 4 bytes..
the mantissa 16rF040 , simply don't fits, because it is > 2^31-1, which
is max for 32-bit integer.

The class responsible for passing constants is NBFFIConst:

Integer>>asNBExternalType: gen
"integer value in callout argument description array are pushed
directly on stack

#( 100 )  - an integer value argument = 100
"
^ NBFFIConst value: (self )

the code generator, uses:

emitPush: gen

gen asm push: ((gen asm imm: value) size: 4)


and #imm: sends #asImm to the value, which by default turns integer into a
signed immediate:

Integer>>asImm

"Convert integer value into a signed immediate operand"
^ AJImmediate new ivalue: self

unfortunately, there is no easy way to work around this: if you change it
to unsigned (uvalue:),
then you have another problem, but now with all negative integer constants
(like -1).

But you can work that around: use a 32-bit complement
of unsigned 16rF040
to signed one, which ends up with identical 32-bit value:

16rF040 - 16r1  =>  -268435392
test:
(16r1 - 268435392) hex '16rF040'

-- 
Best regards,
Igor Stasenko.


Re: [Pharo-dev] NB and ASMJit questions

2014-02-17 Thread Igor Stasenko
Other solution, is to change NBFFIConst and be more forgiving about
constants range
(so if it sees large positive integer which don't fits into 32-bit signed
integer range, assume it is unsigned 32-but integer
and use proper immediate type during code generation).

I know this could be 'least surprising behavior' , only because this is how
C works by not caring about signed/unsigned value assignments.
But when i was doing it i decided to be more strict, because implicit
conversions have one big downside:
 - if there's a malfunction in your code, you often find yourself in a
position to wonder, whether it breaks because implicit conversion _applied_
in a place where you didn't expected or it is because it is _not applied_
in a place where you actually expected. :)


-- 
Best regards,
Igor Stasenko.