[llvm-bugs] [Bug 44302] New: Dangerous fld usage

via llvm-bugs llvm-bugs at lists.llvm.org
Sat Dec 14 16:32:43 PST 2019


            Bug ID: 44302
           Summary: Dangerous fld usage
           Product: clang
           Version: trunk
          Hardware: PC
                OS: Linux
            Status: NEW
          Severity: enhancement
          Priority: P
         Component: C++
          Assignee: unassignedclangbugs at nondot.org
          Reporter: zamazan4ik at tut.by
                CC: blitzrakete at gmail.com, dgregor at apple.com,
                    erik.pilkington at gmail.com, llvm-bugs at lists.llvm.org,
                    richard-llvm at metafoo.co.uk

clang(trunk) with '-O3 -m32' for this code:

#include <stdint.h>
typedef int SQObjectType;
typedef int64_t SQInteger;

union SQObjectValue
  SQInteger integer;
  float real;

struct  SQObject
    SQObjectType _type;
    SQObjectValue _unVal;

SQInteger toint(SQObject &i)
    return i._type == 10 ? (SQInteger)(i._unVal.real) :

generates that assembly:

toint(SQObject&):                     # @toint(SQObject&)
        sub     esp, 20
        mov     ecx, dword ptr [esp + 24]
        movss   xmm0, dword ptr [ecx + 4
        movss   dword ptr [esp + 8], xmm0
        fld     dword ptr [esp + 8] #here floating point exception will be
thrown, if provided tagged union is int64_t == -1
        fnstcw  word ptr [esp + 4]
        movzx   eax, word ptr [esp + 4]
        or      eax, 3072
        mov     word ptr [esp + 6], ax
        fldcw   word ptr [esp + 6]
        fistp   qword ptr [esp + 8]
        fldcw   word ptr [esp + 4]
        cmp     dword ptr [ecx], 10
        jne     .LBB0_1
        mov     eax, dword ptr [esp + 8]
        mov     edx, dword ptr [esp + 12]
        add     esp, 20
        mov     eax, dword ptr [ecx + 4]
        mov     edx, dword ptr [ecx + 8]
        add     esp, 20

gcc(trunk) with '-O3 -m32' generates this:

        sub     esp, 20
        mov     eax, DWORD PTR [esp+24]
        cmp     DWORD PTR [eax], 10  #first compare for type, than do float to
int64_t conversion!
        je      .L7
        mov     edx, DWORD PTR [eax+8]
        mov     eax, DWORD PTR [eax+4]
        add     esp, 20
        fld     DWORD PTR [eax+4]
        fnstcw  WORD PTR [esp+14]
        movzx   eax, WORD PTR [esp+14]
        or      ah, 12
        mov     WORD PTR [esp+12], ax
        fldcw   WORD PTR [esp+12]
        fistp   QWORD PTR [esp]
        fldcw   WORD PTR [esp+14]
        mov     eax, DWORD PTR [esp]
        mov     edx, DWORD PTR [esp+4]
        add     esp, 20

So, first of all clang generates dangerous code that will result in
unconditional floating point conversion even if provided SQObject is actually
an Integer (of certain values).
Secondly, gcc code is slightly more optimal (not important).

In addition, version with pointer to SqObject is for some reason works
correctly, unlike reference.
(But it is not possible to workaround buggy code generation by getting pointer
to reference, probably due to inlining).

Live code example : https://godbolt.org/z/gHf9YZ

You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20191215/be8c1f02/attachment.html>

More information about the llvm-bugs mailing list