Closed jckarter closed 12 years ago
Also fails on OSX when compiled with -arch i386
.
Problem is not in digest module. Code that also crashes when compiled with -arch i386
:
main() {
9ul * 8;
}
Thanks @stepancheg . I updated the bug title.
Looks like a bug in overflow checking.
% ./build/compiler/src/clay -Ilib-clay -arch i386 -O0 foo.clay
% ./foo
error: invalid integer math: integerMultiplyWithOverflow(9, 8)
0 foo 0x000680f4 core.errors.backtrace.showBacktrace() clay + 532
1 foo 0x00068a56 core.errors.errorWithPrintfNoThrow(Static[#invalidc32integerc32mathc58c32integerMultiplyWithOverflowc40c37lluc44c32c37lluc41], UInt64, UInt64) clay + 182
2 foo 0x000688cf __main__.main() clay + 191
3 foo 0x00068576 __operators__.callMain(Static[main], Int32, Pointer[Pointer[Int8]]) Int32 clay + 54
4 foo 0x00068512 main + 50
5 libdyld.dylib 0x988a2725 start + 0
zsh: abort ./foo
Looks like LLVM bug. Code:
import printer.*;
foo() --> returned: Int32 __llvm__ {
%result = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 9, i64 8)
%ov = extractvalue { i64, i1 } %result, 1
%ove = zext i1 %ov to i32
store i32 %ove, i32* %returned
ret i8* null
}
main() {
println(foo());
}
prints 0 when compiled for 64-bit and 1 when compiled with -arch i386
.
Yeah, that's what I'm thinking. Here's the i386 assembly:
.align 4, 0x90
"_core.numbers.overflow.overflowIntrinsic(Static[#umul], UInt64, UInt64) UInt64, Bool clay1": ## @"core.numbers.overflow.overflowIntrinsic(Static[#umul], UInt64, UInt64) UInt64, Bool clay1"
.cfi_startproc
## BB#0:
pushl %ebp
Ltmp74:
.cfi_def_cfa_offset 8
Ltmp75:
.cfi_offset %ebp, -8
movl %esp, %ebp
Ltmp76:
.cfi_def_cfa_register %ebp
pushl %ebx
pushl %edi
pushl %esi
subl $28, %esp
Ltmp77:
.cfi_offset %esi, -20
Ltmp78:
.cfi_offset %edi, -16
Ltmp79:
.cfi_offset %ebx, -12
movl 12(%ebp), %eax
movl (%eax), %esi
movl 4(%eax), %eax
movl %eax, -16(%ebp) ## 4-byte Spill
movl 16(%ebp), %eax
movl (%eax), %ecx
movl 4(%eax), %edi
movl %esi, %eax
mull %ecx
movl %eax, (%esp)
movl 20(%ebp), %ebx
movl %eax, (%ebx)
xorl %eax, %eax
movl %ecx, %ebx
orl %edi, %ebx
movl %edi, %ebx
cmovnel %eax, %ebx
movl %ebx, 12(%esp)
movl $1, %eax
cmovel %ecx, %eax
movl %eax, 8(%esp)
imull %esi, %edi
addl %edx, %edi
movl -16(%ebp), %ebx ## 4-byte Reload
imull %ebx, %ecx
addl %edi, %ecx
movl %ecx, 4(%esp)
movl 20(%ebp), %eax
movl %ecx, 4(%eax)
calll ___udivdi3
xorl %ebx, %edx
xorl %esi, %eax
movl 24(%ebp), %ecx
orl %edx, %eax
setne (%ecx)
xorl %eax, %eax
addl $28, %esp
popl %esi
popl %edi
popl %ebx
popl %ebp
ret
.cfi_endproc
The logic at the end where it divides then tests the results to get the overflow condition looks fishy.
Filed LLVM PR13839: http://llvm.org/bugs/show_bug.cgi?id=13839
There's a workaround in place, and the bug is fixed upstream for whenever 3.2/4.0 comes out, so I'll close this.