Pelles C forum

Pelles C => Bug reports => Topic started by: jullien on December 02, 2018, 09:03:58 AM

Title: Illegal instruction in double to unsigned conversion
Post by: jullien on December 02, 2018, 09:03:58 AM
With official 9.0 I get:

int
main(int argc, char** argv) {
        int  p1 = 3.14;  // Ok
        unsigned int  p2 = 3.14;  // Internal error
}

f:\PellesC-64\Bin\cc -c foo.c
foo.c(4): fatal error: Internal error: 'Illegal instruction' at 0x00007ff6ed9bb932.
Title: Re: Illegal instruction in double to unsigned conversion
Post by: frankie on December 02, 2018, 11:55:46 AM
Can't reproduce the error.
Tried using the single line invocation as in your example, created a project for X86, X64, with and without MS extensions and with and without optimizations and debug.
Debugging the resulting code (compiled without optimizations) the instructions are compiled correctly (p1 and p2 == 3).
Please check your installation, and verify the attached sample project.
Title: Re: Illegal instruction in double to unsigned conversion
Post by: jullien on December 02, 2018, 06:48:39 PM
Many thanks for the attachment.
I've just installed a fresh copy of Pelles 9.0 in f:\PellesC-64
And tried again with command line.
I also used you project and got the exact same error.
Building IllegalInstDuble2Unsigned.obj.
F:\IllegalInstDuble2Unsigned.c(4): fatal error: Internal error: 'Illegal instruction' at 0x00007ff6ed9bb932.
*** Error code: 1 ***
Done.

I'm running Windows 10 last update on Intel Core i7 which is quite old.
cpu-z reports it as:

        Number of cores         4 (max 4)
        Number of threads       8 (max 8 )
        Name                    Intel Core i7 870
        Codename                Lynnfield
        Specification           Intel(R) Core(TM) i7 CPU         870  @ 2.93GHz
        Package (platform ID)   Socket 1156 LGA (0x1)
        CPUID                   6.E.5
        Extended CPUID          6.1E
        Core Stepping           B1
        Instructions sets       MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, EM64T, VT-x


Is it possible that x64 compiler uses an instruction not available on this machine? Unfortunately I can't test on a more modern machine. Others are on Linux.
Title: Re: Illegal instruction in double to unsigned conversion
Post by: frankie on December 02, 2018, 09:20:29 PM
Really strange.
The program is correctly compiled, this is the dump:
Code: [Select]
Dump of output\IllegalInstDuble2Unsigned.obj

File type: OBJ

1: int main(int argc, char **argv)

main:
  [0000000000000000] 4883EC08                     sub               rsp,8
2: {
3:      int p1 = 3.14;  // Ok
  [0000000000000004] C744240403000000             mov               dword ptr [rsp+4],3
4:      unsigned int p2 = 3.14; // Internal error
  [000000000000000C] C7042403000000               mov               dword ptr [rsp],3
5: }
  [0000000000000013] B800000000                   mov               eax,0
  [0000000000000018] 4883C408                     add               rsp,8
  [000000000000001C] C3                           ret

SUMMARY
     135 .debug$S
      34 .debug$T
      27 .drectve
       C .pdata
      1D .text
       8 .xdata
This kind of errors are related to the compiler execution code that encounters an illegal instruction and crashes. The message comes from exception-catch. It can be due to a memory corruption problem for software  or hardware problems.
If the problem is really the compiler it should be reproducible on any machine, I really don't believe that the code contains an advanced instruction not available on a specific X86-64 chip. Really improbable.
Anyway I have checked again and still can't reproduce the error.
Can you please try the version switch on the command cc as follow:
Code: [Select]
C:\PellesC>cc -v
Pelles Compiler Driver, Version 9.00.0
Copyright (c) Pelle Orinius 2002-2018

Syntax:
CC [options]
   [@commandfile]
   { [compiler options] filename1.c [filename2.c ...] |
     [assembler options] filename1.asm [filename2.asm ...] }
   [filename1.rc [filename2.rc ...]]
   [linker options]
   [options]

Options:
/a             Send assembly files to the C compiler (compatibility)
/c             Compile only, no link
/o<file>       Name the output file; either /Fe or /Fo
/Fe<execfile>  Name the executable file
/Fo<outfile>   Name the output file
/x             Don't set environment from the Registry

Compiler options: see POCC
Assembler options: see POASM
Linker options: see POLINK
To be sure that the invocation is for PellesC V.9.00.

Someone get the same error compiling this code?
Title: Re: Illegal instruction in double to unsigned conversion
Post by: jullien on December 03, 2018, 08:12:17 PM
This computer is my work machine. Beside native Windows 10, VMware also runs another Windows x64 instance + Fedora 29. It is rock solid and never crashes (I can't remember when the last BSOD.

Here is the command you asked me:


Pelles Compiler Driver, Version 9.00.0
Copyright (c) Pelle Orinius 2002-2018

Syntax:
CC [options]
   [@commandfile]
   { [compiler options] filename1.c [filename2.c ...] |
     [assembler options] filename1.asm [filename2.asm ...] }
   [filename1.rc [filename2.rc ...]]
   [linker options]
   [options]

Options:
/a             Send assembly files to the C compiler (compatibility)
/c             Compile only, no link
/o<file>       Name the output file; either /Fe or /Fo
/Fe<execfile>  Name the executable file
/Fo<outfile>   Name the output file
/x             Don't set environment from the Registry

Compiler options: see POCC
Assembler options: see POASM
Linker options: see POLINK
Title: Re: Illegal instruction in double to unsigned conversion
Post by: jullien on December 04, 2018, 06:26:16 AM
I can reproduce this error on an even older x64 Intel processor running Windows 7.

My guess, as expression is constant, is the compiler computes the result using its internal machine instruction set (i.e. when computing 3 ctse from 3.14).
Unfortunately, it seems to me that the compiler uses an instruction not recognized by older processor. Do you know which x64 instructions set are used by compiler?
To illustrate this, I wrote:
unsigned int global;

void
foo(double d)
{
        global = d;
}

And tried to compile it with gcc and -mavx2 (my processor does not support). It gives:
foo:
        .seh_endprologue
        vcvttsd2siq     %xmm0, %rax
        movl    %eax, global(%rip)
        ret

Which is for sandybridge avx processor

Without -mavx, it gives:
foo:
        .seh_endprologue
        cvttsd2siq      %xmm0, %rax
        movl    %eax, global(%rip)
        ret

Which is SSE2 X64


Title: Re: Illegal instruction in double to unsigned conversion
Post by: TimoVJL on December 07, 2018, 07:19:46 PM
Same kind of error with pocc.exe in AMD.
fatal error: Internal error: 'Illegal instruction' at 0x000000013f93b932.

Code: [Select]
test_dbl_int.c(4): fatal error: Internal error: 'Illegal instruction' at 0x000000014011b932.WinDbg:
Code: [Select]
Breakpoint 0 hit
image00000001_40000000+0x11b932:
00000001`4011b932 c4e1fb2cc8      vcvttsd2si rcx,xmm0

EDIT: patch pocc.exe 9.0
As jullien pointed the problem, a temporay fix for it:
cvttsd2si rcx,xmm0   ; F2480F2CC8 cvttsd2si rcx, xmm0
vcvttsd2si rcx,xmm0   ; C4E1FB2CC8 vcvttsd2si rcx, xmm0
;0011AD32h C4E1FB -> F2480F
;0011AD8Bh C4E1FB -> F2480F
We have to verify that it don't broke anything else.
Title: Re: Illegal instruction in double to unsigned conversion
Post by: jj2007 on December 07, 2018, 09:04:11 PM
What I usually do in such cases is set OllyDbg (http://www.ollydbg.de/version2.html) as Just-in-time debugger. Then Windows asks me whether to close or to debug, and voilĂ , debug and you can see which instruction is the culprit.

Can you zip the executable and post it here? That would be the easiest test to do. Perhaps it crashes on our machines, perhaps it doesn't - but if it crashes, I can tell you immediately what it was.

P.S.: I just see that Timo has done it already. According to this site (https://www.felixcloutier.com/x86/CVTTSD2SI.html), it's an AVX instruction:

VCVTTSD2SI Convert one double-precision floating-point value from xmm1/m64 to one signed quadword integer in r64 using truncation
Title: Re: Illegal instruction in double to unsigned conversion
Post by: jullien on December 08, 2018, 06:01:18 AM
Thanks Timo,
Your patched pcc.exe fixes this issue.
I can go further with my OpenLisp compiler non-regression test suites but it now hangs somewhere else.
I'm investigation where and, when found, open a new topic if different from this one.

Btw, as OpenLisp compiler has been ported over 150 (sic) systems including all previous Pelles C compiler. I'm quite sure it is another issue.

C.
Title: Re: Illegal instruction in double to unsigned conversion
Post by: frankie on December 08, 2018, 12:56:06 PM
For Pelle,
Maybe it's better to supply a compiler version recompiled without AVX and advanced features so it could be used on all x86-64 machines.
Title: Re: Illegal instruction in double to unsigned conversion
Post by: jullien on December 08, 2018, 05:29:31 PM
Compiler also generates code for avx2 even if I don't ask for it:
#include <stdio.h>

#define FOO 1000

double
todouble(void) {
        return (double)FOO;
}

int
main(int argc, char** argv) {
        printf("cvt doubel -> size_t\n");
        printf("%lld\n", (size_t)todouble());
        printf("Done!\n");

}


Compiled with:

cc -c -std:C11 -Ze -Zx -Gz -W1 -Go -Tx64-coff -Ob1 foo.c

It uses vcvttsd2si which makes generated code hand at runtime:

/usr/jullien/openlisp/src$ objdump.exe -d foo.obj

foo.obj:     file format pe-x86-64


Disassembly of section .text:

0000000000000000 <todouble>:
   0:   f2 0f 10 05 00 00 00    movsd  0x0(%rip),%xmm0        # 8 <todouble+0x8>
   7:   00
   8:   c3                      retq
   9:   c3                      retq

000000000000000a <main>:
   a:   48 83 ec 28             sub    $0x28,%rsp
   e:   48 8d 0d 00 00 00 00    lea    0x0(%rip),%rcx        # 15 <main+0xb>
  15:   e8 00 00 00 00          callq  1a <main+0x10>
  1a:   e8 e1 ff ff ff          callq  0 <todouble>
  1f:   f2 0f 10 25 00 00 00    movsd  0x0(%rip),%xmm4        # 27 <main+0x1d>
  26:   00
  27:   66 0f 2f c4             comisd %xmm4,%xmm0
  2b:   c4 e1 fb 2c d0          vcvttsd2si %xmm0,%rdx
  30:   72 1e                   jb     50 <main+0x46>
  32:   f2 0f 10 e0             movsd  %xmm0,%xmm4
  36:   f2 0f 5c 25 00 00 00    subsd  0x0(%rip),%xmm4        # 3e <main+0x34>
  3d:   00
  3e:   49 ba 00 00 00 00 00    movabs $0x8000000000000000,%r10
  45:   00 00 80
  48:   c4 e1 fb 2c d4          vcvttsd2si %xmm4,%rdx
  4d:   4c 31 d2                xor    %r10,%rdx
  50:   48 8d 0d 00 00 00 00    lea    0x0(%rip),%rcx        # 57 <main+0x4d>
  57:   e8 00 00 00 00          callq  5c <main+0x52>
  5c:   48 8d 0d 00 00 00 00    lea    0x0(%rip),%rcx        # 63 <main+0x59>
  63:   e8 00 00 00 00          callq  68 <main+0x5e>
  68:   b8 00 00 00 00          mov    $0x0,%eax
  6d:   48 83 c4 28             add    $0x28,%rsp
  71:   c3                      retq


Title: Re: Illegal instruction in double to unsigned conversion
Post by: frankie on December 08, 2018, 05:35:32 PM
seems a problem of the 64bits code generator.
The AVX2 instruction is used by default.
Title: Re: Illegal instruction in double to unsigned conversion
Post by: TimoVJL on December 08, 2018, 06:52:03 PM
-Ob1 -Ze defaults to AVX, so have to use -arch:SSE2 to avoid it

EDIT:  fix tests
-Ze Enable Microsoft extensions

cc.exe -c -Ob1 -Tx64-asm foo.c no AVX2
cc.exe -c -Ze -Tx64-asm foo.c AVX2
Title: Re: Illegal instruction in double to unsigned conversion
Post by: frankie on December 08, 2018, 09:15:38 PM
It doesn't make any sense to me that the option to set the code inlining changes the minimum processor architecture.
It should be another bug IMHO.  :P
Title: Re: Illegal instruction in double to unsigned conversion
Post by: jullien on December 09, 2018, 07:15:32 AM
Same issue wo. -Ob1
Title: Re: Illegal instruction in double to unsigned conversion
Post by: frankie on December 09, 2018, 12:31:13 PM
Ok to me this is a compiler bug: mishandling of architecture code generation.  ;)
The help state that the default should be streaming SIMD Extensions 2, but it doesn't seem to be the case.
Title: Re: Illegal instruction in double to unsigned conversion
Post by: Pelle on December 12, 2018, 04:50:32 PM
Confirmed. Cut & paste error with code templates in X64 code generator.

Conversion float -> unsigned long long int and double (=long double) -> unsigned long long int will use AVX instruction in Microsoft mode with SSE architecture (and RIP-relative addressing, but this is non-optional right now).

Will be fixed in some future version.
Title: Re: Illegal instruction in double to unsigned conversion
Post by: jullien on December 13, 2018, 06:25:29 PM
Thanks Pelle,

I switch back to 8.0 until you have time to make a new version.

C.