NO

Author Topic: Illegal instruction in double to unsigned conversion  (Read 6951 times)

jullien

  • Guest
Illegal instruction in double to unsigned conversion
« 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.

Offline frankie

  • Global Moderator
  • Member
  • *****
  • Posts: 2113
Re: Illegal instruction in double to unsigned conversion
« Reply #1 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.
"It is better to be hated for what you are than to be loved for what you are not." - Andre Gide

jullien

  • Guest
Re: Illegal instruction in double to unsigned conversion
« Reply #2 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.
« Last Edit: December 03, 2018, 01:13:51 PM by frankie »

Offline frankie

  • Global Moderator
  • Member
  • *****
  • Posts: 2113
Re: Illegal instruction in double to unsigned conversion
« Reply #3 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?
"It is better to be hated for what you are than to be loved for what you are not." - Andre Gide

jullien

  • Guest
Re: Illegal instruction in double to unsigned conversion
« Reply #4 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

jullien

  • Guest
Re: Illegal instruction in double to unsigned conversion
« Reply #5 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



Offline TimoVJL

  • Global Moderator
  • Member
  • *****
  • Posts: 2115
Re: Illegal instruction in double to unsigned conversion
« Reply #6 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.
« Last Edit: December 08, 2018, 09:24:19 AM by TimoVJL »
May the source be with you

Offline jj2007

  • Member
  • *
  • Posts: 536
Re: Illegal instruction in double to unsigned conversion
« Reply #7 on: December 07, 2018, 09:04:11 PM »
What I usually do in such cases is set OllyDbg 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, 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
« Last Edit: December 07, 2018, 09:10:31 PM by jj2007 »

jullien

  • Guest
Re: Illegal instruction in double to unsigned conversion
« Reply #8 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.

Offline frankie

  • Global Moderator
  • Member
  • *****
  • Posts: 2113
Re: Illegal instruction in double to unsigned conversion
« Reply #9 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.
"It is better to be hated for what you are than to be loved for what you are not." - Andre Gide

jullien

  • Guest
Re: Illegal instruction in double to unsigned conversion
« Reply #10 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



Offline frankie

  • Global Moderator
  • Member
  • *****
  • Posts: 2113
Re: Illegal instruction in double to unsigned conversion
« Reply #11 on: December 08, 2018, 05:35:32 PM »
seems a problem of the 64bits code generator.
The AVX2 instruction is used by default.
"It is better to be hated for what you are than to be loved for what you are not." - Andre Gide

Offline TimoVJL

  • Global Moderator
  • Member
  • *****
  • Posts: 2115
Re: Illegal instruction in double to unsigned conversion
« Reply #12 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
« Last Edit: December 09, 2018, 11:19:46 AM by TimoVJL »
May the source be with you

Offline frankie

  • Global Moderator
  • Member
  • *****
  • Posts: 2113
Re: Illegal instruction in double to unsigned conversion
« Reply #13 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
"It is better to be hated for what you are than to be loved for what you are not." - Andre Gide

jullien

  • Guest
Re: Illegal instruction in double to unsigned conversion
« Reply #14 on: December 09, 2018, 07:15:32 AM »
Same issue wo. -Ob1