The test fails with -2^31 and 2^31-1 It's not so amazing, because when I debug, I find this incorrect version:
64769 sqInt 64770 signed32BitIntegerFor(sqInt integerValue) 64771 { -> 64772 return (((((int) integerValue)) << 3) | 1); 64773 64774 } 64775
of course, the shift will overflow for large positive or large negative 32bits int. But I don't understand how it's been generated... I would expect return ((((usqInt)((int) integerValue)) << 3) | 1);
Indeed:
signed32BitIntegerFor: integerValue "Answer a full 32 bit integer object for the given integer value. N.B. Returning in each arm separately enables Slang inlining. /Don't/ return the ifTrue:ifFalse: unless Slang inlining of conditionals is fixed." <inline: true> objectMemory hasSixtyFourBitImmediates ifTrue: [^objectMemory integerObjectOf: (self cCode: [self cCoerceSimple: integerValue to: #int] inSmalltalk: [(integerValue bitAnd: 16r7FFFFFFF) - ((integerValue >> 31 anyMask: 1) ifTrue: [-16r100000000] ifFalse: [0])])] ifFalse: [^self noInlineSigned32BitIntegerFor: integerValue]
has the cast to int. Then there is another cast here:
integerObjectOf: value "Convert the integer value, assumed to be in SmallInteger range, into a tagged SmallInteger object. In C, use a shift and an add to set the tag bit. In Smalltalk we have to work harder because the simulator works with strictly positive bit patterns." <returnTypeC: #sqInt> ^self cCode: [value asUnsignedInteger << self numTagBits + 1] inSmalltalk: [value << self numTagBits + (value >= 0 ifTrue: [1] ifFalse: [16r10000000000000001])]
and asUnsignedInteger is translated like this by CCodeGenerator:
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: $)
How the hell could the hardcoded (usqInt) be not generated?
Arghh... I forgot this one which is preempting my asUnsignedInteger cast:
generateIntegerObjectOf: msgNode on: aStream indent: level "Generate the C code for this message onto the given stream." | expr castToSqint | expr := msgNode args first. aStream nextPutAll: '(('. "Note that the default type of an integer constant in C is int. Hence we /must/ cast constants to long if in the 64-bit world, since e.g. in 64-bits (int)(16r1FFFFF << 3) = (int)16rFFFFFFF8 = -8 whereas (long)(16r1FFFFF << 3) = (long) 16rFFFFFFF8 = 4294967288." castToSqint := expr isConstant and: [vmClass isNil or: [vmClass objectMemoryClass wordSize = 8]]. castToSqint ifTrue: [aStream nextPutAll: '(sqInt)']. self emitCExpression: expr on: aStream. aStream nextPutAll: ' << '; print: vmClass objectMemoryClass numSmallIntegerTagBits; nextPutAll: ') | 1)'
I think we should completely remove this from translationDictionary... It's not object oriented.
2016-08-18 3:19 GMT+02:00 Nicolas Cellier < nicolas.cellier.aka.nice@gmail.com>:
The test fails with -2^31 and 2^31-1 It's not so amazing, because when I debug, I find this incorrect version:
64769 sqInt 64770 signed32BitIntegerFor(sqInt integerValue) 64771 { -> 64772 return (((((int) integerValue)) << 3) | 1); 64773 64774 } 64775
of course, the shift will overflow for large positive or large negative 32bits int. But I don't understand how it's been generated... I would expect return ((((usqInt)((int) integerValue)) << 3) | 1);
Indeed:
signed32BitIntegerFor: integerValue "Answer a full 32 bit integer object for the given integer value. N.B. Returning in each arm separately enables Slang inlining. /Don't/ return the ifTrue:ifFalse: unless Slang inlining of conditionals is fixed." <inline: true> objectMemory hasSixtyFourBitImmediates ifTrue: [^objectMemory integerObjectOf: (self cCode: [self cCoerceSimple: integerValue to: #int] inSmalltalk: [(integerValue bitAnd: 16r7FFFFFFF) - ((integerValue >> 31 anyMask: 1) ifTrue: [-16r100000000] ifFalse: [0])])] ifFalse: [^self noInlineSigned32BitIntegerFor: integerValue]
has the cast to int. Then there is another cast here:
integerObjectOf: value "Convert the integer value, assumed to be in SmallInteger range, into a tagged SmallInteger object. In C, use a shift and an add to set the tag bit. In Smalltalk we have to work harder because the simulator works with strictly positive bit patterns." <returnTypeC: #sqInt> ^self cCode: [value asUnsignedInteger << self numTagBits + 1] inSmalltalk: [value << self numTagBits + (value >= 0 ifTrue: [1] ifFalse: [16r10000000000000001])]
and asUnsignedInteger is translated like this by CCodeGenerator:
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: $)
How the hell could the hardcoded (usqInt) be not generated?
vm-dev@lists.squeakfoundation.org