[Bug c++/40698] New: Incorrect code generation when compiling c++ source
jacob at jacob dot remcomp dot fr
gcc-bugzilla@gcc.gnu.org
Thu Jul 9 13:13:00 GMT 2009
This bug appears in ALL version of gcc that we tested since gcc 4.1.2
If you see the assembly generated by the cpp source using the
-DNOT_WORKING
option
you will see:
main:
leal 4(%esp), %ecx
andl $-16, %esp
pushl -4(%ecx)
pushl %ebp
movl %esp, %ebp
pushl %esi
pushl %ebx
pushl %ecx
subl $92, %esp
movl -20(%ebp), %eax
movl $0, -44(%ebp)
/*
Here is the bug. The compiler generates code to read
*location -16(%ebp) before anything was written to it!
*/
movl -16(%ebp), %edx
leal -44(%ebp), %esi
movl $0, -40(%ebp)
---------------------------------------------------------
Attached are 3 files:
(1) The cpp source
(2) an associated assembly file needed to link. That code is not
the source of the bug since the bug is in the calling procedure
(3) A shell script exercising the bug and a workaround that masks
the bug.
This is the code that produces the bug:
------------------------------------------------------------------------------
bug.cpp File (1)
------------------------------------------------------------------------------
#include <stdio.h>
#include <sys/types.h>
extern "C" {
extern int64_t __cmpxchg8bytes(volatile int64_t *destination, volatile
int64_t exchange, volatile int64_t compare);
}
#if defined(WORKING)
// there is no error by using the union of data
class TwoPointers
{
public:
TwoPointers() { u1.s1.First = NULL; u1.s1.Second = NULL; }
void* GetFirst() const { return u1.s1.First; }
void* GetSecond() const { return u1.s1.Second; }
void SetFirst(void* ptr) { u1.s1.First = ptr; }
void SetSecond(void* ptr) { u1.s1.Second = ptr; }
union unionData {
struct structData1 {
void* volatile First;
void* volatile Second;
} s1;
long long longlongData;
} u1;
};
__inline TwoPointers InterlockedExchange(TwoPointers* Target, TwoPointers
Value)
{
long long retVal = __cmpxchg8bytes(( long long *)Target, *((long long *)
(&Value.u1.longlongData)), *(long long *) (&Target->u1.longlongData) ) ;
return ( *(TwoPointers *) &retVal ) ;
}
#else // defined(WORKING)
// this generates wrong code
class TwoPointers
{
public:
TwoPointers() { First = NULL; Second = NULL; }
void* GetFirst() const { return First; }
void* GetSecond() const { return Second; }
void SetFirst(void* ptr) { First = ptr; }
void SetSecond(void* ptr) { Second = ptr; }
void* volatile First;
void* volatile Second;
};
__inline TwoPointers InterlockedExchange(TwoPointers* Target, TwoPointers
Value)
{
long long retVal = __cmpxchg8bytes(( long long *)Target, *((long long *)
(&Value)), *(long long *) (&Target) ) ;
return ( *(TwoPointers *) &retVal ) ;
}
#endif // defined(WORKING)
int main()
{
unsigned long long i = 0xdeaddeaddeaddeadll ;
unsigned long long j = 0xbeafbeafbeafbeafll ;
TwoPointers a ;
TwoPointers b ;
a.SetFirst( (void *) 0xdeaddead ) ;
a.SetSecond( ( void *) 0xdeaddead ) ;
b.SetFirst( (void *) 0xbeafbeaf ) ;
b.SetSecond( (void *) 0xbeafbeaf ) ;
InterlockedExchange( &a, b ) ;
if ( a.GetFirst() == b.GetFirst() && a.GetSecond() == b.GetSecond() ) {
printf("Succeeded\n");
} else {
printf("Failed\n");
printf("It should be 0x%016llx\n", *( (long long *)&b) ) ;
printf("Real data is 0x%016llx\n", *( (long long *)&a) ) ;
}
}
-------------------------------------------------------------------------
i386xadd.s File (2)
-------------------------------------------------------------------------
/* BEGIN */
.global __cmpxchg8bytes
.type __cmpxchg8bytes,@function
__cmpxchg8bytes:
pushl %ebp
movl %esp, %ebp
/*
* stack frame layout
* =============
* old (8 byes)
* new (8 bytes)
* ptr (4 bytes)
* rip (4 bytes)
* old ebp
* ============ # ebp and esp point here
*/
/*
* Save ecx, ebx CMPXCHG8B uses them. Save esi, this code uses it.
*/
pushl %ecx
pushl %ebx
pushl %esi
/* move ptr to esi */
movl 8(%ebp), %esi
/* move new to ecx:ebx; low order word at bottom, high word at top */
movl 16(%ebp), %ecx
movl 12(%ebp), %ebx
/* move old to edx:eax; low order word at bottom, high word at top */
movl 24(%ebp), %edx
movl 20(%ebp), %eax
/* magic word */
lock cmpxchg8b (%esi)
/* restore regs and stack */
popl %esi
popl %ebx
popl %ecx
leave
ret
/* END */
--------------------------------------------------------------------
File 3: runit.sh
This script demonstrates the bug
--------------------------------------------------------------------
#!/bin/sh
program="bug"
cmd_as="/usr/local/gcc-4.1.2/bin/gcc -O2 -o i386xadd.o -c i386xadd.s"
echo $cmd_as
$cmd_as
compiler="/usr/local/gcc-4.1.2/bin/g++"
for flags in NOT_WORKING WORKING
do
echo
echo "********** Compile and run with flag $flags turned on **********"
options=" -march=i686 -O3 i386xadd.o -lgcc -lgcc_s -lstdc++"
cmd="$compiler $options -D$flags $program.cpp -o $program"
echo $cmd
$cmd
echo
./$program
echo
done
--
Summary: Incorrect code generation when compiling c++ source
Product: gcc
Version: 4.3.3
Status: UNCONFIRMED
Severity: major
Priority: P3
Component: c++
AssignedTo: unassigned at gcc dot gnu dot org
ReportedBy: jacob at jacob dot remcomp dot fr
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40698
More information about the Gcc-bugs
mailing list