The following source code causes a wrong assembly output :
1 "main.cpp"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "main.cpp"
# 1 "far_pointers.h" 1
# 13 "far_pointers.h"
# 1 "c:\\mingw\\bin\\../lib/gcc/mingw32/4.5.0/include/stddef.h" 1 3 4
# 149 "c:\\mingw\\bin\\../lib/gcc/mingw32/4.5.0/include/stddef.h" 3 4
typedef int ptrdiff_t;
# 211 "c:\\mingw\\bin\\../lib/gcc/mingw32/4.5.0/include/stddef.h" 3 4
typedef unsigned int size_t;
# 14 "far_pointers.h" 2
template <class T> class far_pointer
{
protected:
unsigned short segmentSelector;
T* offset;
public:
inline far_pointer(unsigned short argSegmentSelector, T* argOffset)
:segmentSelector(argSegmentSelector), offset(argOffset)
{}
template <class Tp> inline operator far_pointer<Tp>()
{
return far_pointer<Tp>(segmentSelector, (Tp*) offset);
}
inline T* getOffset()
{
return offset;
}
inline unsigned short getSegmentselector()
{
return segmentSelector;
}
inline T operator*(void)
{
T item;
__asm__
(
" .intel_syntax noprefix; \n mov gs,
%1; \n mov %0, gs:[%2]; \n
"
:"=q"(item)
:"r"(this->segmentSelector), "g"(this->offset)
);
return item;
}
inline far_pointer<T>& operator++(void)
{
offset++;
return *this;
}
inline far_pointer<T>& operator--(void)
{
offset--;
return *this;
}
inline size_t operator-(far_pointer<T> const& subs)
{
return offset-subs.offset;
}
inline far_pointer operator+(int argDecal)
{
return far_pointer(segmentSelector, offset + argDecal);
}
inline far_pointer operator-(int argDecal)
{
return far_pointer(segmentSelector, offset - argDecal);
}
inline far_pointer operator+(unsigned argDecal)
{
return far_pointer(segmentSelector, offset + argDecal);
}
inline far_pointer operator-(unsigned argDecal)
{
return far_pointer(segmentSelector, offset - argDecal);
}
inline void operator+=(unsigned argDecal)
{
offset += argDecal;
}
inline void operator-=(unsigned argDecal)
{
offset -= argDecal;
}
inline void operator+=(int argDecal)
{
offset += argDecal;
}
inline void operator-=(int argDecal)
{
offset -= argDecal;
}
inline far_pointer operator+(long argDecal)
{
return far_pointer(segmentSelector, offset + argDecal);
}
inline far_pointer operator-(long argDecal)
{
return far_pointer(segmentSelector, offset - argDecal);
}
inline far_pointer operator+(unsigned long argDecal)
{
return far_pointer(segmentSelector, offset + argDecal);
}
inline far_pointer operator-(unsigned long argDecal)
{
return far_pointer(segmentSelector, offset - argDecal);
}
inline void operator+=(unsigned long argDecal)
{
offset += argDecal;
}
inline void operator-=(unsigned long argDecal)
{
offset -= argDecal;
}
inline void operator+=(long argDecal)
{
offset += argDecal;
}
inline void operator-=(long argDecal)
{
offset -= argDecal;
}
inline bool operator<(far_pointer<T> const& ptr)
{
return offset < ptr.offset;
}
inline bool operator>(far_pointer<T> const& ptr)
{
return offset > ptr.offset;
}
inline bool operator<=(far_pointer<T> const& ptr)
{
return offset <= ptr.offset;
}
inline bool operator>=(far_pointer<T> const& ptr)
{
return offset >= ptr.offset;
}
inline bool operator!=(far_pointer<T> const& ptr)
{
return offset != ptr.offset || segmentSelector != ptr.segmentSelector;
}
inline bool operator==(far_pointer<T> const& ptr)
{
return offset == ptr.offset && segmentSelector == ptr.segmentSelector;
}
static const far_pointer<T> NULL_FAR_POINTER;
};
template <class T> const far_pointer<T> far_pointer<T>::NULL_FAR_POINTER(0,(T*)
0);
# 2 "main.cpp" 2
char u;
void toto(far_pointer<unsigned char> pt)
{
u = *pt;
}
int main(int argc, char **argv)
{
unsigned short dataSeg = 0;
asm (
" .intel_syntax
noprefix; \n mov %0, cs; \n
"
: "=r"(dataSeg)
);
far_pointer<unsigned char> pt(dataSeg, (unsigned char*) &main);
toto(pt);
}
--------------------------------------------------------------------------------
COLLECT_GCC_OPTIONS='-c' '-masm=intel' '-save-temps' '-v' '-O1' '-o'
'./Release/main.o' '-I.' '-shared-libgcc' '-mtune=i386' '-march=i386'
c:/mingw/bin/../libexec/gcc/mingw32/4.5.0/cc1plus.exe -fpreprocessed main.ii
-quiet -dumpbase main.cpp -masm=intel -mtune=i386 -march=i386 -auxbase-strip
./Release/main.o -O1 -version -o main.s
GNU C++ (GCC) version 4.5.0 (mingw32)
compiled by GNU C version 4.5.0, GMP version 5.0.1, MPFR version 2.4.1,
MPC version 0.8.1
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
GNU C++ (GCC) version 4.5.0 (mingw32)
compiled by GNU C version 4.5.0, GMP version 5.0.1, MPFR version 2.4.1,
MPC version 0.8.1
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Compiler executable checksum: 639ec8dd7c9bc03705b4424f5e166212
COLLECT_GCC_OPTIONS='-c' '-masm=intel' '-save-temps' '-v' '-O1' '-o'
'./Release/main.o' '-I.' '-shared-libgcc' '-mtune=i386' '-march=i386'
c:/mingw/bin/../lib/gcc/mingw32/4.5.0/../../../../mingw32/bin/as.exe -o
./Release/main.o main.s
main.s: Messages de l'assembleur:
main.s:22: ERREUR: `al' not allowed with `movl'
mingw32-make.exe[1]: *** [Release/main.o] Error 1
"mingw32-make.exe": *** [All] Error 2
The origin is the inlining of T operator*(void) in toto(far_pointer<unsigned
char> pt) in main.ii.
This output is the same whatever optimization level but with -g. In this last
case, there is no error.
A similar ouput is observable on Linux with g++-4.5 (Ubuntu 4.5.0-3ubuntu1)
4.5.1 20100519 (prerelease) with the same command-line.
The error message differs, nevertheless:
main.s: Assembler messages:
main.s:31: Error: operand type mismatch for `movsbl'
main.s:32: Error: no such instruction: `movl %eax,8(%esp)'
main.s:33: Error: no such instruction: `movl $.LC0,4(%esp)'
main.s:34: Error: no such instruction: `movl $1,(%esp)'
main.s:36: Error: no such instruction: `movl $0,%eax'
--
Summary: [Extended inline asm] wrong assembly generation on IA32
Product: gcc
Version: 4.5.0
Status: UNCONFIRMED
Severity: major
Priority: P3
Component: rtl-optimization
AssignedTo: unassigned at gcc dot gnu dot org
ReportedBy: dg dot recrutement31 at gmail dot com
GCC host triplet: Windows Vista 32 bit and Linux 32 bit
GCC target triplet: i386
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44288