public inbox for gcc-prs@sourceware.org
help / color / mirror / Atom feed
* c++/6788: multiple inheritance "non-virtual thunk" assembly incorrect on sparc64-sun-solars2.8
@ 2002-05-23 12:56 spencer
  0 siblings, 0 replies; only message in thread
From: spencer @ 2002-05-23 12:56 UTC (permalink / raw)
  To: gcc-gnats; +Cc: spencer


>Number:         6788
>Category:       c++
>Synopsis:       multiple inheritance "non-virtual thunk" assembly incorrect on sparc64-sun-solars2.8
>Confidential:   no
>Severity:       critical
>Priority:       medium
>Responsible:    unassigned
>State:          open
>Class:          wrong-code
>Submitter-Id:   net
>Arrival-Date:   Thu May 23 12:56:00 PDT 2002
>Closed-Date:
>Last-Modified:
>Originator:     Brad Spencer
>Release:        gcc-3.1
>Organization:
>Environment:
sparc64-sun-solaris (64-bit compile)  More details in description
>Description:
It looks like invalid assembly is being generated for multiple inhertiance where the member data is "big" (i.e. it takes two SPARC assembly instructions to move the this pointer).

The code that's generated looks like it would be right if the registers were 32-bit, but they're not, so it ends up adding a positive (big) number to the this pointer instead of adding a negative (small) number.  I've included code and a walkthough with gdb-5.2 to show how the code could be corrected.  Assembler warnings often (but don't always?) accompany this problem.  The small test case I've included in the "How-to-repeat" section does cause assembler warnings. 
>How-To-Repeat:
netra-map1:~$ cat foo.cc
//*****************************************************************************
// $Id$

static const char *st_ID __attribute__((unused)) =
"$Id$";

class Base
{
public:
  Base() {}

  virtual void baseFunc() = 0;
  char waste[16 * 1024];
};

class Other
{
public:  
  Other() {}
  virtual void func() = 0;
  char waste[16 * 1024];
};

void caller(Other &other)
{
  other.func();
}

class Sub : public Base, private Other
{
public:
  Sub() : Base(), Other() {}

  void preCaller() { caller(*this); }
  
private:
  virtual void func() { member = 1; }
  virtual void baseFunc() { member = 2; }

  int member;
};


int
main()
{
  Sub sub;

  sub.preCaller();
    
  return 0;
}

//*****************************************************************************

netra-map1:~$ uname -a
SunOS netra-map1 5.8 Generic_108528-09 sun4u sparc SUNW,UltraAX-i2
netra-map1:~$ psrinfo -v
Status of processor 0 as of: 05/23/02 16:33:20
  Processor has been on-line since 05/22/02 11:11:40.
  The sparcv9 processor operates at 500 MHz,
        and has a sparcv9 floating point processor.
netra-map1:~$ g++ -v -m64 -Wall -g -o foo foo.cc
Reading specs from /opt/gcc-3.1/lib/gcc-lib/sparc-sun-solaris2.8/3.1/specs
Configured with: ../gcc-3.1/configure --with-dwarf2 --enable-languages=c,c++ --enable-threads=single --disable-shared --with-gnu-as --with-gnu-ld --with-as=/opt/bin/as --with-ld=/opt/bin/ld --prefix=/opt/gcc-3.1
Thread model: single
gcc version 3.1
 /opt/gcc-3.1/lib/gcc-lib/sparc-sun-solaris2.8/3.1/cc1plus -v -iprefix /opt/bin/../lib/gcc-lib/sparc-sun-solaris2.8/3.1/ -D__GNUC__=3 -D__GNUC_MINOR__=1 -D__GNUC_PATCHLEVEL__=0 -Dsparc -Dsun -Dunix -D__svr4__ -D__SVR4 -D__PRAGMA_REDEFINE_EXTNAME -D__sparc__ -D__sun__ -D__unix__ -D__svr4__ -D__SVR4 -D__PRAGMA_REDEFINE_EXTNAME -D__sparc -D__sun -D__unix -Asystem=unix -Asystem=svr4 -D__NO_INLINE__ -D__STDC_HOSTED__=1 -D_XOPEN_SOURCE=500 -D_LARGEFILE_SOURCE=1 -D_LARGEFILE64_SOURCE=1 -D__EXTENSIONS__ -D__SIZE_TYPE__=long unsigned int -D__PTRDIFF_TYPE__=long int -D__WCHAR_TYPE__=int -D__WINT_TYPE__=int -D__arch64__ -Acpu=sparc64 -Amachine=sparcv9 -D__sparcv9 foo.cc -D__GNUG__=3 -D__DEPRECATED -D__EXCEPTIONS -D__GXX_ABI_VERSION=100 -mptr64 -mstack-bias -mno-v8plus -mcpu=v9 -quiet -dumpbase foo.cc -m64 -g -Wall -version -o /var/tmp//ccp2mt4M.s
GNU CPP version 3.1 (cpplib) (sparc ELF)
GNU C++ version 3.1 (sparc-sun-solaris2.8)
        compiled by GNU C version 3.1.
ignoring nonexistent directory "/opt/lib/gcc-lib/sparc-sun-solaris2.8/3.1/../../../../include/g++-v3"
ignoring nonexistent directory "/opt/lib/gcc-lib/sparc-sun-solaris2.8/3.1/../../../../include/g++-v3/sparc-sun-solaris2.8"
ignoring nonexistent directory "/opt/lib/gcc-lib/sparc-sun-solaris2.8/3.1/../../../../include/g++-v3/backward"
ignoring nonexistent directory "/opt/lib/gcc-lib/sparc-sun-solaris2.8/3.1/include"
ignoring nonexistent directory "/opt/lib/gcc-lib/sparc-sun-solaris2.8/3.1/../../../../sparc-sun-solaris2.8/include"
ignoring nonexistent directory "/usr/local/include"
ignoring nonexistent directory "/opt/gcc-3.1/sparc-sun-solaris2.8/include"
#include "..." search starts here:
#include <...> search starts here:
 /opt/gcc-3.1/include/g++-v3
 /opt/gcc-3.1/include/g++-v3/sparc-sun-solaris2.8
 /opt/gcc-3.1/include/g++-v3/backward
 /opt/gcc-3.1/include
 /opt/gcc-3.1/lib/gcc-lib/sparc-sun-solaris2.8/3.1/include
 /usr/include
End of search list.
 /opt/bin/as -V -Qy -s -64 -Av9 -o /var/tmp//ccGfY3zI.o /var/tmp//ccp2mt4M.s
GNU assembler version 2.11.2 (sparc-sun-solaris2.8) using BFD version 2.11.2
/var/tmp//ccp2mt4M.s: Assembler messages:
/var/tmp//ccp2mt4M.s:290: Warning: set: number not in 0..4294967295 range
 /opt/gcc-3.1/lib/gcc-lib/sparc-sun-solaris2.8/3.1/collect2 -V -m elf64_sparc -Y P,/usr/lib/sparcv9 -Qy -o foo /opt/gcc-3.1/lib/gcc-lib/sparc-sun-solaris2.8/3.1/sparcv9/crt1.o /opt/gcc-3.1/lib/gcc-lib/sparc-sun-solaris2.8/3.1/sparcv9/crti.o /usr/lib/sparcv9/values-Xa.o /opt/gcc-3.1/lib/gcc-lib/sparc-sun-solaris2.8/3.1/sparcv9/crtbegin.o -L/opt/gcc-3.1/lib/gcc-lib/sparc-sun-solaris2.8/3.1/sparcv9 -L/opt/gcc-3.1/lib/gcc-lib/sparc-sun-solaris2.8/3.1 -L/usr/ccs/bin/sparcv9 -L/usr/ccs/bin -L/usr/ccs/lib/sparcv9 -L/usr/ccs/lib -L/opt/gcc-3.1/lib/gcc-lib/sparc-sun-solaris2.8/3.1/../../../sparcv9 -L/opt/gcc-3.1/lib/gcc-lib/sparc-sun-solaris2.8/3.1/../../.. -L/lib/sparcv9 -L/usr/lib/sparcv9 /var/tmp//ccGfY3zI.o -lstdc++ -lm -lgcc -lc -lgcc -lc /opt/gcc-3.1/lib/gcc-lib/sparc-sun-solaris2.8/3.1/sparcv9/crtend.o /opt/gcc-3.1/lib/gcc-lib/sparc-sun-solaris2.8/3.1/sparcv9/crtn.o
GNU ld version 2.11.2 (with BFD 2.11.2)
  Supported emulations:
   elf32_sparc
   elf64_sparc
netra-map1:~$ ./foo 
Segmentation Fault (core dumped)
netra-map1:~$ gdb ./foo core
GNU gdb 5.2
Copyright 2002 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "sparc64-sun-solaris2.8"...
Core was generated by `./foo'.
Program terminated with signal 11, Segmentation fault.
Reading symbols from /usr/lib/64/libm.so.1...done.
Loaded symbols for /usr/lib/64/libm.so.1
Reading symbols from /usr/lib/64/libc.so.1...done.
Loaded symbols for /usr/lib/64/libc.so.1
Reading symbols from /usr/lib/64/libdl.so.1...done.
Loaded symbols for /usr/lib/64/libdl.so.1
Reading symbols from /usr/platform/SUNW,UltraAX-i2/lib/sparcv9/libc_psr.so.1...done.
Loaded symbols for /usr/platform/SUNW,UltraAX-i2/lib/sparcv9/libc_psr.so.1
#0  0x100006180 in Sub::func() (this=0x7fff7810) at foo.cc:37
37        virtual void func() { member = 1; }
(gdb) bt
#0  0x100006180 in Sub::func() (this=0x7fff7810) at foo.cc:37
#1  0x100000bd0 in caller(Other&) (other=@0xffffffff7fffb818) at foo.cc:26
#2  0x1000060ec in Sub::preCaller() (this=0xffffffff7fff7810) at foo.cc:34
#3  0x100000c18 in main () at foo.cc:49
(gdb) b main
Breakpoint 1 at 0x100000be8: file foo.cc, line 47.
(gdb) r
Starting program: /export/spare/live/spencer/foo 

Breakpoint 1, main () at foo.cc:47
47        Sub sub;
(gdb) n
49        sub.preCaller();
(gdb) s
Sub::preCaller() (this=0xffffffff7fff7840) at foo.cc:34
34        void preCaller() { caller(*this); }
(gdb) s
caller(Other&) (other=@0xffffffff7fffb848) at foo.cc:26
26        other.func();
(gdb) s
0x100006190 in non-virtual thunk to Sub::func() () at foo.cc:37
37        virtual void func() { member = 1; }
(gdb) disass
Dump of assembler code for function _ZThn16392_N3Sub4funcEv:
0x100006190 <_ZThn16392_N3Sub4funcEv>:  sethi  %hi(0xffffbc00), %g1
0x100006194 <_ZThn16392_N3Sub4funcEv+4>:        or  %g1, 0x3f8, %g1     ! 0xffffbff8
0x100006198 <_ZThn16392_N3Sub4funcEv+8>:        add  %o0, %g1, %o0
0x10000619c <_ZThn16392_N3Sub4funcEv+12>:       mov  %o7, %g1
0x1000061a0 <_ZThn16392_N3Sub4funcEv+16>:       call  0x100006168 <_ZN3Sub4funcEv>
0x1000061a4 <_ZThn16392_N3Sub4funcEv+20>:       mov  %g1, %o7
End of assembler dump.
(gdb) p/x $o0
$1 = 0xffffffff7fffb848
(gdb) p/x $g1
$2 = 0xffffffffffff7f20
(gdb) si
0x100006194     37        virtual void func() { member = 1; }
(gdb) si
0x100006198     37        virtual void func() { member = 1; }
(gdb) p/x $g1
$3 = 0xffffbff8
(gdb) si
0x10000619c     37        virtual void func() { member = 1; }
(gdb) p/x $o0
$4 = 0x7fff7840
(gdb) c
Continuing.

Program received signal SIGSEGV, Segmentation fault.
0x100006180 in Sub::func() (this=0x7fff7840) at foo.cc:37
37        virtual void func() { member = 1; }
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /export/spare/live/spencer/foo 

Breakpoint 1, main () at foo.cc:47
47        Sub sub;
(gdb) n
49        sub.preCaller();
(gdb) s
Sub::preCaller() (this=0xffffffff7fff7840) at foo.cc:34
34        void preCaller() { caller(*this); }
(gdb) s
caller(Other&) (other=@0xffffffff7fffb848) at foo.cc:26
26        other.func();
(gdb) s
0x100006190 in non-virtual thunk to Sub::func() () at foo.cc:37
37        virtual void func() { member = 1; }
(gdb) disass
Dump of assembler code for function _ZThn16392_N3Sub4funcEv:
0x100006190 <_ZThn16392_N3Sub4funcEv>:  sethi  %hi(0xffffbc00), %g1
0x100006194 <_ZThn16392_N3Sub4funcEv+4>:        or  %g1, 0x3f8, %g1     ! 0xffffbff8
0x100006198 <_ZThn16392_N3Sub4funcEv+8>:        add  %o0, %g1, %o0
0x10000619c <_ZThn16392_N3Sub4funcEv+12>:       mov  %o7, %g1
0x1000061a0 <_ZThn16392_N3Sub4funcEv+16>:       call  0x100006168 <_ZN3Sub4funcEv>
0x1000061a4 <_ZThn16392_N3Sub4funcEv+20>:       mov  %g1, %o7
End of assembler dump.
(gdb) si
0x100006194     37        virtual void func() { member = 1; }
(gdb) si
0x100006198     37        virtual void func() { member = 1; }
(gdb) si
0x10000619c     37        virtual void func() { member = 1; }
(gdb) p/x $o0
$5 = 0x7fff7840
(gdb) set $o0 = 0xffffffff7fff7840
(gdb) p/x $o0
$6 = 0xffffffff7fff7840
(gdb) c
Continuing.

Program exited normally.
(gdb) quit
>Fix:

>Release-Note:
>Audit-Trail:
>Unformatted:


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2002-05-23 19:56 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-05-23 12:56 c++/6788: multiple inheritance "non-virtual thunk" assembly incorrect on sparc64-sun-solars2.8 spencer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).