[Vm-dev] CCodeGeneration bug or gcc compiler bug?
Nicolas Cellier
nicolas.cellier.aka.nice at gmail.com
Fri Apr 5 20:52:40 UTC 2013
Let me think aloud...
THE CONTEXT:
backport of LargeIntegersPlugin v2.0 (32 bit native word order) to
Interpreter VM
THE BUG:
The Vm crashes with
http://smalltalkhub.com/#!/~nice/NiceVMExperiments/versions/VMMaker-nice.315
THE OFFENDING METHOD:
InterpreterPrimitives>>magnitude64BitIntegerFor: magnitude neg: isNegative
"Return a Large Integer object for the given integer magnitude and sign"
| newLargeInteger largeClass lowWord highWord sz isSmall smallVal
highWord2 |
<var: 'magnitude' type: #usqLong>
<var: 'lowWord' type: #usqInt>
<var: 'highWord' type: #usqInt>
<var: 'highWord2' type: #usqInt>
isSmall := isNegative
ifTrue: [magnitude <= 16r40000000]
ifFalse: [magnitude < 16r40000000].
isSmall ifTrue:
[smallVal := self cCoerceSimple: magnitude to: #sqInt.
isNegative ifTrue: [smallVal := 0 - smallVal].
^objectMemory integerObjectOf: smallVal].
largeClass := isNegative
ifTrue:[self classLargeNegativeInteger]
ifFalse:[self classLargePositiveInteger].
lowWord := magnitude bitAnd: 16rFFFFFFFF.
highWord := magnitude >> 32.
highWord = 0
ifTrue: [sz := 4]
ifFalse:
[sz := 5.
(highWord2 := highWord >> 8) = 0 ifFalse: [sz := sz + 1].
(highWord2 := highWord2 >> 8) = 0 ifFalse: [sz := sz + 1].
(highWord2 := highWord2 >> 8) = 0 ifFalse: [sz := sz + 1].].
newLargeInteger := objectMemory instantiateClass: largeClass
indexableSize: sz.
objectMemory storeLong32: 0 ofObject: newLargeInteger withValue:
lowWord.
sz > 4 ifTrue: [objectMemory storeLong32: 1 ofObject: newLargeInteger
withValue: highWord].
^newLargeInteger
THE CORRECTED METHOD:
just replace the assignment
isNegative
ifTrue:[ largeClass := self classLargeNegativeInteger]
ifFalse:[ largeClass := self classLargePositiveInteger].
THE OFFENDING GENERATED CODE:
in src/vm/interp.c
sqInt magnitude64BitIntegerForneg(usqLong magnitude, sqInt isNegative) {
register struct foo * foo = &fum;
usqInt highWord;
usqInt highWord2;
sqInt isSmall;
sqInt largeClass;
usqInt lowWord;
sqInt newLargeInteger;
sqInt smallVal;
sqInt sz;
sqInt oop;
sqInt oop1;
isSmall = (isNegative
? magnitude <= 1073741824
: magnitude < 1073741824);
if (isSmall) {
smallVal = ((sqInt) magnitude);
if (isNegative) {
smallVal = 0 - smallVal;
}
return ((smallVal << 1) | 1);
}
largeClass = (isNegative
? /* begin fetchPointer:ofObject: */(oop =
foo->specialObjectsOop),longAt((oop + (BASE_HEADER_SIZE)) +
(ClassLargeNegativeInteger << (SHIFT_FOR_WORD)))
: /* begin fetchPointer:ofObject: */(oop1 =
foo->specialObjectsOop),longAt((oop1 + (BASE_HEADER_SIZE)) +
(ClassLargePositiveInteger << (SHIFT_FOR_WORD))));
lowWord = magnitude & 4294967295U;
highWord = magnitude >> 32;
if (highWord == 0) {
sz = 4;
} else {
sz = 5;
if (!(((highWord2 = ((usqInt) highWord) >> 8)) == 0)) {
sz += 1;
}
if (!(((highWord2 = ((usqInt) highWord2) >> 8)) == 0)) {
sz += 1;
}
if (!(((highWord2 = ((usqInt) highWord2) >> 8)) == 0)) {
sz += 1;
}
}
newLargeInteger = instantiateClassindexableSize(largeClass, sz);
long32Atput((newLargeInteger + (BASE_HEADER_SIZE)) + (0 << 2), lowWord);
if (sz > 4) {
long32Atput((newLargeInteger + (BASE_HEADER_SIZE)) + (1 << 2),
highWord);
}
return newLargeInteger;
}
THE CORRECTED GENERATED CODE:
Just change the ()?: assignment:
largeClass = (isNegative
? /* begin fetchPointer:ofObject: */(oop =
foo->specialObjectsOop),longAt((oop + (BASE_HEADER_SIZE)) +
(ClassLargeNegativeInteger << (SHIFT_FOR_WORD)))
: /* begin fetchPointer:ofObject: */(oop1 =
foo->specialObjectsOop),longAt((oop1 + (BASE_HEADER_SIZE)) +
(ClassLargePositiveInteger << (SHIFT_FOR_WORD))));
with an explicit if:
if (isNegative) {
/* begin fetchPointer:ofObject: */
oop = foo->specialObjectsOop;
largeClass = longAt((oop + (BASE_HEADER_SIZE)) +
(ClassLargeNegativeInteger << (SHIFT_FOR_WORD)));
} else {
/* begin fetchPointer:ofObject: */
oop1 = foo->specialObjectsOop;
largeClass = longAt((oop1 + (BASE_HEADER_SIZE)) +
(ClassLargePositiveInteger << (SHIFT_FOR_WORD)));
}
THE OFFENDING METHOD JUST WORKS IN COG BUT GENERATED CODE IS DIFFERENT:
largeClass = (isNegative
? longAt((GIV(specialObjectsOop) + BaseHeaderSize) +
(ClassLargeNegativeInteger << ShiftForWord))
: longAt((GIV(specialObjectsOop) + BaseHeaderSize) +
(ClassLargePositiveInteger << ShiftForWord)));
THE QUESTION:
I just don't understand what is incorrect in the (t)?a,b:c,d; construct...
Could it be that it is interpreted:
((t)?a,b:c),d;
Ah if so, maybe that would explain the warning about oop1 being potentially
used before assigned! (a bulb just enlighten)
In this case we have a bug in the generator (probably a known one since we
rearely ever use x := test ifTrue: [] ifFalse: [] in Slang)...
Nicolas
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.squeakfoundation.org/pipermail/vm-dev/attachments/20130405/ee4d8c16/attachment.htm
More information about the Vm-dev
mailing list