Hi All, I'm being bitten by Slang's treatment of bitShift: & >>. In both cases (generateBitShift:on:indent: & generateShiftRight:on:indent:) Slang generates an unsigned shift by explicitly casting the shifted expression to usqInt. I can understand the benefit of having an unsigned shift. But there are times when one really needs a signed shift. Further, the Smalltalk versions of both bitShift: and >> are signed shifts.
Dare I change e.g. generateShiftRight:on:indent: to leave the expression alone and generate either a signed or an unsigned shift based on the variable's declaration? Or must I live with a maddening cCode: '(signed)' inSmalltalk: [] carbuncle?
E.
|
Er, well the shift left/right assembler operations are signed or unsigned, but TYPED languages usually figure out which one to use based on the type of the operators. But since Smalltalk is type-less, What if you code up a unsigned shift operator so there is no question that you want to do unsigned shifting, which also makes the SLANG coder just a bit more aware he has a choice to make, casting is ok, but people forget. Also I can do senders of, then later wonder why am I not doing that here/there? Having been bitten by signed shifting issues in the past, I can agree it's unpleasant. PS I note we have methods to do unsigned compare logic when dealing with oop address so that *we* know we are doing something special, since people just couldn't manage the casts correctly. On 3-Mar-09, at 11:50 AM, Eliot Miranda wrote: > Hi All, > > I'm being bitten by Slang's treatment of bitShift: & >>. In > both cases (generateBitShift:on:indent: & > generateShiftRight:on:indent:) Slang generates an unsigned shift by > explicitly casting the shifted expression to usqInt. I can > understand the benefit of having an unsigned shift. But there are > times when one really needs a signed shift. Further, the Smalltalk > versions of both bitShift: and >> are signed shifts. > > Dare I change e.g. generateShiftRight:on:indent: to leave the > expression alone and generate either a signed or an unsigned shift > based on the variable's declaration? Or must I live with a > maddening cCode: '(signed)' inSmalltalk: [] carbuncle? > > E. -- = = = ======================================================================== John M. McIntosh <[hidden email]> Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com = = = ======================================================================== |
In reply to this post by Eliot Miranda-2
2009/3/3 Eliot Miranda <[hidden email]>: > > Hi All, > I'm being bitten by Slang's treatment of bitShift: & >>. In both cases (generateBitShift:on:indent: & generateShiftRight:on:indent:) Slang generates an unsigned shift by explicitly casting the shifted expression to usqInt. I can understand the benefit of having an unsigned shift. But there are times when one really needs a signed shift. Further, the Smalltalk versions of both bitShift: and >> are signed shifts. > Dare I change e.g. generateShiftRight:on:indent: to leave the expression alone and generate either a signed or an unsigned shift based on the variable's declaration? Or must I live with a maddening cCode: '(signed)' inSmalltalk: [] carbuncle? > E. > I think an easier way would be to add: #<<+ #generateSignedShiftLeft:on:indent: #>>+ #generateSignedShiftRight:on:indent: in #initializeCTranslationDictionary so you can use: a <<+ b or a >>+ b without writing horrible cCode: -- Best regards, Igor Stasenko AKA sig. |
On Tue, Mar 3, 2009 at 12:09 PM, Igor Stasenko <[hidden email]> wrote:
good work-around. Thanks.
|
In reply to this post by johnmci
On Tue, Mar 3, 2009 at 11:58 AM, John M McIntosh <[hidden email]> wrote:
Forget about assembler. In C "signed >> expr" is an arithmetic (signed) shift; "unsigned >> expr" is a logical (unsigned) one. In Smalltalk "negative bitShift: negative" is an arithmetic shift, "non-negative bitShift: negative" is a logical one. These are perfectly compatible, and both are useful. In Smalltalk you can always write
(foo bitAnd: (1 bitShift: preShiftFieldWidth) - 1) bitShift: expr if you want to perform a logical shift. But since Smalltalk is type-less, No, that's not it. In fact, Smalltalk is strongly typed. Try bit shifting true. Quite possible in C; not possible in Smalltalk. Smalltalk has infinite precision so an unsigned value is simply a non-negative one. The reason, I think, that Slang casts to unsigned is a hack to do with the default type of oops being sqInt (signed). But this is a mistake. Look at the definition of primitiveBitShift and ask yourself why this even works?
primitiveBitShift | integerReceiver integerArgument shifted | integerArgument := self popInteger.
integerReceiver := self popPos32BitInteger. self successful ifTrue: [ integerArgument >= 0 ifTrue: [
"Left shift -- must fail if we lose bits beyond 32" self success: integerArgument <= 31.
shifted := integerReceiver << integerArgument. self success: (shifted >> integerArgument) = integerReceiver.
] ifFalse: [ "Right shift -- OK to lose bits" self success: integerArgument >= -31.
shifted := integerReceiver bitShift: integerArgument. ]. ].
self successful ifTrue: [self push: (self positive32BitIntegerFor: shifted)]
ifFalse: [self unPop: 2] It took me a few minutes of staring at shifted := integerReceiver bitShift: integerArgument.
(which can't possibly work for negative values if Slang, as it does, casts to unsigned) before I realised that integerReceiver := self popPos32BitInteger.
means the primitive simply fails for negative receivers (!!!!!!!!!!!!!). I've noticed this before and I've forgotten it (I'm a bit like a goldfish in that regard) and I find it no less shocking each time I trip over it.
What if you code up a unsigned shift operator so there is no question that you want to do unsigned shifting, which also makes the SLANG coder just a bit more aware he has a choice to make, casting is ok, but people forget. Also I can do senders of, then later wonder why am I not doing that here/there? Right. I've recently added #asUnsignedInteger as a concise cast to unsigned. Having been bitten by signed shifting issues in the past, I can agree it's unpleasant. So look, surely shifts should be signed by default and be unsigned if the argument is unsigned, e.g./i.e.
!Integer methodsFor: '*VMMaker-interpreter simulator' stamp: 'eem 2/19/2009 18:33'! asUnsignedInteger self assert: self >= 0.
^self! ! and in CCodeGenerator>>initializeCTranslationDictionary: ... #asUnsignedInteger #generateAsUnsignedInteger:on:indent:
... and !CCodeGenerator methodsFor: 'C translation' stamp: 'eem 2/15/2009 16:38'! generateAsUnsignedInteger: msgNode on: aStream indent: level
"Generate the C code for this message onto the given stream." aStream nextPutAll:'((usqInt)'.
self emitCExpression: msgNode receiver on: aStream. aStream nextPut: $)! !
and I autochange all senders of >> and bitShift: throughout the plugins, primitives and Interpreter to use asUnsignedInteger. Do I dare? Am I insane?
|
In reply to this post by Eliot Miranda-2
Come on original Slang developers. 'Fess up. I need to know what your thought process was in making shifts unsigned so that I can change it without too much hard work. Pretty please.
On Tue, Mar 3, 2009 at 11:50 AM, Eliot Miranda <[hidden email]> wrote: Hi All, |
On 03.03.2009, at 21:36, Eliot Miranda wrote: > Come on original Slang developers. 'Fess up. I need to know what > your thought process was in making shifts unsigned so that I can > change it without too much hard work. Pretty please. I don't think you will reach them on this list. - Bert - |
In reply to this post by Eliot Miranda-2
2009/3/3 Eliot Miranda <[hidden email]>: > > > > On Tue, Mar 3, 2009 at 12:09 PM, Igor Stasenko <[hidden email]> wrote: >> >> 2009/3/3 Eliot Miranda <[hidden email]>: >> > >> > Hi All, >> > I'm being bitten by Slang's treatment of bitShift: & >>. In both cases (generateBitShift:on:indent: & generateShiftRight:on:indent:) Slang generates an unsigned shift by explicitly casting the shifted expression to usqInt. I can understand the benefit of having an unsigned shift. But there are times when one really needs a signed shift. Further, the Smalltalk versions of both bitShift: and >> are signed shifts. >> > Dare I change e.g. generateShiftRight:on:indent: to leave the expression alone and generate either a signed or an unsigned shift based on the variable's declaration? Or must I live with a maddening cCode: '(signed)' inSmalltalk: [] carbuncle? >> > E. >> > >> >> I think an easier way would be to add: >> >> #<<+ #generateSignedShiftLeft:on:indent: >> #>>+ #generateSignedShiftRight:on:indent: >> >> in #initializeCTranslationDictionary >> so you can use: >> >> a <<+ b >> or >> a >>+ b >> >> without writing horrible cCode: > > good work-around. Thanks. > btw, you not alone noticed that :) I have an incomplete rewrite of code gen.. where i threw away numerous #generateXXX for common binary operators and replaced them with single: #generateBinaryOp: and when i came to shifts it is also makes me wonder, why an argument needs to be converted to unsigned one before shiftting.. One thing, that i may guess, that shitfing is used extensively when dealing with headers.. header := self longAt: oop. type := header bitAnd: TypeMask >> TypeShift. and since all 32 bits of header is used for different purposes, it is better to treat header as an unsigned word for shifting operations. I don't see any other uses of shifts in VM which could/should need casting to unsigned. >> >> -- >> Best regards, >> Igor Stasenko AKA sig. > > > -- Best regards, Igor Stasenko AKA sig. |
2009/3/3 Igor Stasenko <[hidden email]>: > 2009/3/3 Eliot Miranda <[hidden email]>: >> >> >> > - Show quoted text - >> On Tue, Mar 3, 2009 at 12:09 PM, Igor Stasenko <[hidden email]> wrote: >>> >>> 2009/3/3 Eliot Miranda <[hidden email]>: >>> > >>> > Hi All, >>> > I'm being bitten by Slang's treatment of bitShift: & >>. In both cases (generateBitShift:on:indent: & generateShiftRight:on:indent:) Slang generates an unsigned shift by explicitly casting the shifted expression to usqInt. I can understand the benefit of having an unsigned shift. But there are times when one really needs a signed shift. Further, the Smalltalk versions of both bitShift: and >> are signed shifts. >>> > Dare I change e.g. generateShiftRight:on:indent: to leave the expression alone and generate either a signed or an unsigned shift based on the variable's declaration? Or must I live with a maddening cCode: '(signed)' inSmalltalk: [] carbuncle? >>> > E. >>> > >>> >>> I think an easier way would be to add: >>> >>> #<<+ #generateSignedShiftLeft:on:indent: >>> #>>+ #generateSignedShiftRight:on:indent: >>> >>> in #initializeCTranslationDictionary >>> so you can use: >>> >>> a <<+ b >>> or >>> a >>+ b >>> >>> without writing horrible cCode: >> >> good work-around. Thanks. >> > > btw, you not alone noticed that :) > > I have an incomplete rewrite of code gen.. where i threw away numerous > #generateXXX > for common binary operators and replaced them with single: > #generateBinaryOp: > > and when i came to shifts it is also makes me wonder, why an argument > needs to be converted to unsigned one before shiftting.. > > One thing, that i may guess, that shitfing is used extensively when > dealing with headers.. > > header := self longAt: oop. > > type := header bitAnd: TypeMask >> TypeShift. > > and since all 32 bits of header is used for different purposes, it is > better to treat header as an unsigned word for shifting operations. > I don't see any other uses of shifts in VM which could/should need > casting to unsigned. > >>> >>> -- > - Show quoted text - >>> Best regards, >>> Igor Stasenko AKA sig. >> >> >> > > > > -- > Best regards, > Igor Stasenko AKA sig. > -- Best regards, Igor Stasenko AKA sig. |
In reply to this post by Eliot Miranda-2
forgive the duplication. I sent to the wrong list first time around. ---------- Forwarded message ---------- From: Eliot Miranda <[hidden email]> Date: Tue, Mar 3, 2009 at 11:50 AM Subject: urgent info required on Slang's shift treatment... To: Squeak Virtual Machine Development Discussion <[hidden email]> Hi All, I'm being bitten by Slang's treatment of bitShift: & >>. In both cases (generateBitShift:on:indent: & generateShiftRight:on:indent:) Slang generates an unsigned shift by explicitly casting the shifted expression to usqInt. I can understand the benefit of having an unsigned shift. But there are times when one really needs a signed shift. Further, the Smalltalk versions of both bitShift: and >> are signed shifts.
Dare I change e.g. generateShiftRight:on:indent: to leave the expression alone and generate either a signed or an unsigned shift based on the variable's declaration? Or must I live with a maddening cCode: '(signed)' inSmalltalk: [] carbuncle?
E.
|
In reply to this post by Eliot Miranda-2
again forgive the diplication ---------- Forwarded message ---------- From: Eliot Miranda <[hidden email]> Date: Tue, Mar 3, 2009 at 12:22 PM Subject: Re: [Vm-dev] urgent info required on Slang's shift treatment... To: [hidden email], Squeak Virtual Machine Development Discussion <[hidden email]> On Tue, Mar 3, 2009 at 11:58 AM, John M McIntosh <[hidden email]> wrote:
Forget about assembler. In C "signed >> expr" is an arithmetic (signed) shift; "unsigned >> expr" is a logical (unsigned) one. In Smalltalk "negative bitShift: negative" is an arithmetic shift, "non-negative bitShift: negative" is a logical one. These are perfectly compatible, and both are useful. In Smalltalk you can always write
(foo bitAnd: (1 bitShift: preShiftFieldWidth) - 1) bitShift: expr if you want to perform a logical shift. But since Smalltalk is type-less, No, that's not it. In fact, Smalltalk is strongly typed. Try bit shifting true. Quite possible in C; not possible in Smalltalk. Smalltalk has infinite precision so an unsigned value is simply a non-negative one. The reason, I think, that Slang casts to unsigned is a hack to do with the default type of oops being sqInt (signed). But this is a mistake. Look at the definition of primitiveBitShift and ask yourself why this even works?
primitiveBitShift | integerReceiver integerArgument shifted | integerArgument := self popInteger.
integerReceiver := self popPos32BitInteger. self successful ifTrue: [ integerArgument >= 0 ifTrue: [
"Left shift -- must fail if we lose bits beyond 32" self success: integerArgument <= 31.
shifted := integerReceiver << integerArgument. self success: (shifted >> integerArgument) = integerReceiver.
] ifFalse: [ "Right shift -- OK to lose bits" self success: integerArgument >= -31.
shifted := integerReceiver bitShift: integerArgument. ]. ].
self successful ifTrue: [self push: (self positive32BitIntegerFor: shifted)]
ifFalse: [self unPop: 2] It took me a few minutes of staring at shifted := integerReceiver bitShift: integerArgument.
(which can't possibly work for negative values if Slang, as it does, casts to unsigned) before I realised that integerReceiver := self popPos32BitInteger.
means the primitive simply fails for negative receivers (!!!!!!!!!!!!!). I've noticed this before and I've forgotten it (I'm a bit like a goldfish in that regard) and I find it no less shocking each time I trip over it.
What if you code up a unsigned shift operator so there is no question that you want to do unsigned shifting, which also makes the SLANG coder just a bit more aware he has a choice to make, casting is ok, but people forget. Also I can do senders of, then later wonder why am I not doing that here/there? Right. I've recently added #asUnsignedInteger as a concise cast to unsigned. Having been bitten by signed shifting issues in the past, I can agree it's unpleasant. So look, surely shifts should be signed by default and be unsigned if the argument is unsigned, e.g./i.e.
!Integer methodsFor: '*VMMaker-interpreter simulator' stamp: 'eem 2/19/2009 18:33'! asUnsignedInteger self assert: self >= 0.
^self! ! and in CCodeGenerator>>initializeCTranslationDictionary: ... #asUnsignedInteger #generateAsUnsignedInteger:on:indent:
... and !CCodeGenerator methodsFor: 'C translation' stamp: 'eem 2/15/2009 16:38'! generateAsUnsignedInteger: msgNode on: aStream indent: level
"Generate the C code for this message onto the given stream." aStream nextPutAll:'((usqInt)'.
self emitCExpression: msgNode receiver on: aStream. aStream nextPut: $)! !
and I autochange all senders of >> and bitShift: throughout the plugins, primitives and Interpreter to use asUnsignedInteger. Do I dare? Am I insane?
|
In reply to this post by Igor Stasenko
and again, forgive the duplication ---------- Forwarded message ---------- From: Igor Stasenko <[hidden email]> Date: Tue, Mar 3, 2009 at 12:09 PM Subject: Re: [Vm-dev] urgent info required on Slang's shift treatment... To: Squeak Virtual Machine Development Discussion <[hidden email]> 2009/3/3 Eliot Miranda <[hidden email]>: > > Hi All, > I'm being bitten by Slang's treatment of bitShift: & >>. In both cases (generateBitShift:on:indent: & generateShiftRight:on:indent:) Slang generates an unsigned shift by explicitly casting the shifted expression to usqInt. I can understand the benefit of having an unsigned shift. But there are times when one really needs a signed shift. Further, the Smalltalk versions of both bitShift: and >> are signed shifts. > Dare I change e.g. generateShiftRight:on:indent: to leave the expression alone and generate either a signed or an unsigned shift based on the variable's declaration? Or must I live with a maddening cCode: '(signed)' inSmalltalk: [] carbuncle? > E. > #<<+ #generateSignedShiftLeft:on:indent: #>>+ #generateSignedShiftRight:on:indent: in #initializeCTranslationDictionary so you can use: a <<+ b or a >>+ b without writing horrible cCode: -- Best regards, Igor Stasenko AKA sig. |
In reply to this post by Bert Freudenberg
At 9:39 PM +0100 3/3/09, Bert Freudenberg apparently wrote: >On 03.03.2009, at 21:36, Eliot Miranda wrote: > >>Come on original Slang developers. 'Fess up. I need to know what your thought process was in making shifts unsigned so that I can change it without too much hard work. Pretty please. > > >I don't think you will reach them on this list. > >- Bert - Perhaps this could shed some light: Extending the Squeak Virtual Machine Andrew C. Greenberg <http://www.iam.unibe.ch/~ducasse/FreeBooks/CollectiveNBlueBook/greenberg.pdf> "Andrew C. Greenberg" <[hidden email]> (valid in May 2007) Ken G. Brown |
In reply to this post by Bert Freudenberg
On Tue, Mar 3, 2009 at 1:09 PM, Ken G. Brown <[hidden email]> wrote:
No, but thanks for the pointer. "Andrew C. Greenberg" <[hidden email]> (valid in May 2007) |
In reply to this post by Eliot Miranda-2
Don't even think about it. Cheers, - Andreas Eliot Miranda wrote: > > > > ------------------------------------------------------------------------ > > Hi All, > > I'm being bitten by Slang's treatment of bitShift: & >>. In both > cases (generateBitShift:on:indent: & generateShiftRight:on:indent:) > Slang generates an unsigned shift by explicitly casting the shifted > expression to usqInt. I can understand the benefit of having an > unsigned shift. But there are times when one really needs a signed > shift. Further, the Smalltalk versions of both bitShift: and >> are > signed shifts. > > Dare I change e.g. generateShiftRight:on:indent: to leave the expression > alone and generate either a signed or an unsigned shift based on the > variable's declaration? Or must I live with a maddening cCode: > '(signed)' inSmalltalk: [] carbuncle? > > E. |
In reply to this post by Igor Stasenko
On Tue, Mar 3, 2009 at 12:09 PM, Igor Stasenko <[hidden email]> wrote:
OK, my workaround is as follows. I've previously added the "vmClass" to the CCodeGenerator, which is non-nil if translating the Interpreter (also StackInterpreter & CoInterpreter/Cogit). Now the CCodeGenerator asks the vmClass if non-nil whether to genenrate signed shifts and to default to the old behaviour. So I can defer fixing all uses elsewhere and just concentrate on fixing uses in Cog.
|
In reply to this post by Andreas.Raab
On Tue, Mar 3, 2009 at 1:20 PM, Andreas Raab <[hidden email]> wrote:
Too late. I'm testing my workaround, Give us a reason or two and I might recant :) Cheers, |
Eliot Miranda wrote: > On Tue, Mar 3, 2009 at 1:20 PM, Andreas Raab <[hidden email] > <mailto:[hidden email]>> wrote: > > > Don't even think about it. > > > Too late. I'm testing my workaround, Give us a reason or two and I > might recant :) You are creating more instability and risk. We want to ship this thing in a couple of weeks. Introducing subtle bugs like these are most definitely not the path to stabilizing this VM. Cheers, - Andreas > > > Cheers, > - Andreas > > Eliot Miranda wrote: > > > > ------------------------------------------------------------------------ > > > Hi All, > > I'm being bitten by Slang's treatment of bitShift: & >>. In > both cases (generateBitShift:on:indent: & > generateShiftRight:on:indent:) Slang generates an unsigned shift > by explicitly casting the shifted expression to usqInt. I can > understand the benefit of having an unsigned shift. But there > are times when one really needs a signed shift. Further, the > Smalltalk versions of both bitShift: and >> are signed shifts. > > Dare I change e.g. generateShiftRight:on:indent: to leave the > expression alone and generate either a signed or an unsigned > shift based on the variable's declaration? Or must I live with > a maddening cCode: '(signed)' inSmalltalk: [] carbuncle? > > E. > > |
Oops. This was *not* meant to go to the list. My sincerest apologies. - Andreas Andreas Raab wrote: > > Eliot Miranda wrote: >> On Tue, Mar 3, 2009 at 1:20 PM, Andreas Raab <[hidden email] >> <mailto:[hidden email]>> wrote: >> >> >> Don't even think about it. >> >> >> Too late. I'm testing my workaround, Give us a reason or two and I >> might recant :) > > You are creating more instability and risk. We want to ship this thing > in a couple of weeks. Introducing subtle bugs like these are most > definitely not the path to stabilizing this VM. > > Cheers, > - Andreas > >> >> >> Cheers, >> - Andreas >> >> Eliot Miranda wrote: >> >> >> >> ------------------------------------------------------------------------ >> >> >> Hi All, >> >> I'm being bitten by Slang's treatment of bitShift: & >>. In >> both cases (generateBitShift:on:indent: & >> generateShiftRight:on:indent:) Slang generates an unsigned shift >> by explicitly casting the shifted expression to usqInt. I can >> understand the benefit of having an unsigned shift. But there >> are times when one really needs a signed shift. Further, the >> Smalltalk versions of both bitShift: and >> are signed shifts. >> >> Dare I change e.g. generateShiftRight:on:indent: to leave the >> expression alone and generate either a signed or an unsigned >> shift based on the variable's declaration? Or must I live with >> a maddening cCode: '(signed)' inSmalltalk: [] carbuncle? >> >> E. >> >> > |
Free forum by Nabble | Edit this page |