Hi All,
I'm trying to use clang in Xcode on Mac OS X to compile a new 32-bit VM. One of my installations is Mavericks 10.9 with Xcode 6.2 and clang 6.0. The other is 10.10.5 with Xcode 7.1 and clang 7.0. Both seem to have problems with the integer side of bytecodePrimMultiply, the interpreter's multiplication routine:
CASE(184) /* bytecodePrimMultiply */ { sqInt arg; sqInt rcvr; sqInt result; char *sp;
VM_LABEL(bytecodePrimMultiply); rcvr = longAtPointer(localSP + (1 * BytesPerOop)); arg = longAtPointer(localSP + (0 * BytesPerOop)); if (((rcvr & arg) & 1) != 0) { // both SmallIntegers? rcvr = (rcvr >> 1); // convert from SmallInteger to value arg = (arg >> 1); result = rcvr * arg; // multiply if ((arg == 0) || (((result / arg) == rcvr) // check for overflow && ((((sqInt)(result ^ (result << 1)))) >= 0))) { // check for SmallInteger overflow /* begin internalPop:thenPush: */ longAtPointerput((localSP += (2 - 1) * BytesPerOop), ((result << 1) | 1)); /* begin fetchNextBytecode */ currentBytecode = byteAtPointer(++localIP);
goto l58; } } else {
clang 6 inserts a spurious instruction at 0x36799:
0x36784: 89 ca movl %ecx, %edx // both SmallIntegers? 0x36786: 83 e2 01 andl $0x1, %edx 0x36789: 85 d0 testl %eax, %edx 0x3678b: 74 6b je 0x367f8 0x3678d: d1 f9 sarl %ecx // convert from SmallInteger to value 0x3678f: d1 f8 sarl %eax 0x36791: 0f af c8 imull %eax, %ecx // do the multiply 0x36794: 8d 14 09 leal (%ecx,%ecx), %edx 0x36797: 85 c0 testl %eax, %eax 0x36799: 89 f7 movl %esi, %edi // AFAICS, totally spurious 0x3679b: 74 08 je 0x367a5 0x3679d: 31 d1 xorl %edx, %ecx // check for SmallInteger overflow 0x3679f: 0f 88 96 01 00 00 js 0x3693b 0x367a5: 83 ca 01 orl $0x1, %edx
clang 7 does better: 0x36741: 89 ca movl %ecx, %edx // both SmallIntegers? 0x36743: 83 e2 01 andl $0x1, %edx 0x36746: 85 d0 testl %eax, %edx 0x36748: 74 67 je 0x367b1 0x3674a: d1 f9 sarl %ecx // convert from SmallInteger to value 0x3674c: d1 f8 sarl %eax 0x3674e: 0f af c8 imull %eax, %ecx // do the multiply 0x36751: 8d 14 09 leal (%ecx,%ecx), %edx 0x36754: 85 c0 testl %eax, %eax 0x36756: 74 08 je 0x36760 0x36758: 31 d1 xorl %edx, %ecx // check for SmallInteger overflow 0x3675a: 0f 88 a9 01 00 00 js 0x36909 0x36760: 83 ca 01 orl $0x1, %edx
What I don't understand is how, given
typedef long sqInt; sqInt arg; sqInt rcvr; sqInt result; ... result = rcvr * arg; // multiply
clang reasons it doesn't need to evaluate
|| (((result / arg) == rcvr) // check for overflow
Given that arg and receiver can both have values > 64k, the result can of course overflow and there's no guarantee that because result = rcvr * arg, that (result / arg) == rcvr.
Am I missing something? Are there flags I should be using? This looks like a pretty basic issue.
_,,,^..^,,,_ best, Eliot