This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
A serious -fpic and -fomit-frame-pointer bug in egcs 1.0.3/1.1
- To: john at feith dot com (John Wehle)
- Subject: A serious -fpic and -fomit-frame-pointer bug in egcs 1.0.3/1.1
- From: hjl at lucon dot org (H.J. Lu)
- Date: Tue, 16 Jun 1998 11:39:03 -0700 (PDT)
- Cc: egcs-bugs at cygnus dot com
Hi,
There is a serious -fpic and -fomit-frame-pointer bug in egcs 1.0.3/1.1
on x86. Basically, they are not compatible with each other.
The problem is in eliminate_regs called by reload. In egcs 1.0.3,
eliminate_regs is called by reload around line 979. At the time
when you eliminate the frame pointer register with a stack register,
you don't know if PIC will do anything with the stack. Unfortunately,
on x86, the function prologue is expanded
subl $16,%esp
pushl %ebx
call .L23
.L23:
popl %ebx
addl $_GLOBAL_OFFSET_TABLE_+[.-.L23],%ebx
But eliminate_regs knows nothing about
pushl %ebx
call .L23
.L23:
popl %ebx
addl $_GLOBAL_OFFSET_TABLE_+[.-.L23],%ebx
It doesn't know esp is changed in prologue. As the result, the stack
is messed up. I am enclosing a testcase for it.
I can think of 2 approaches to fix the bug:
1. Don't omit frame pointer register for PIC on x86. or
2. Change the function prologue to
pushl %ebx
call .L23
.L23:
popl %ebx
addl $_GLOBAL_OFFSET_TABLE_+[.-.L23],%ebx
subl $16,%esp
In any case, it should fixed for 1.1, and 1.0.x if feasible.
Thanks.
H.J.
----
#!/bin/sh
# This is a shell archive (produced by GNU sharutils 4.2).
# To extract the files from this archive, save it to some FILE, remove
# everything before the `!/bin/sh' line above, then type `sh FILE'.
#
# Made on 1998-06-16 11:26 PDT by <hjl@ocean>.
# Source directory was `/home/hjl/bugs/gcc/pic.1'.
#
# Existing files will *not* be overwritten unless `-c' is specified.
#
# This shar contains:
# length mode name
# ------ ---------- ------------------------------------------
# 739 -rw-r--r-- Makefile
# 225 -rw-r--r-- main.cc
# 1226 -rw-r--r-- cexp.cc
#
save_IFS="${IFS}"
IFS="${IFS}:"
gettext_dir=FAILED
locale_dir=FAILED
first_param="$1"
for dir in $PATH
do
if test "$gettext_dir" = FAILED && test -f $dir/gettext \
&& ($dir/gettext --version >/dev/null 2>&1)
then
set `$dir/gettext --version 2>&1`
if test "$3" = GNU
then
gettext_dir=$dir
fi
fi
if test "$locale_dir" = FAILED && test -f $dir/shar \
&& ($dir/shar --print-text-domain-dir >/dev/null 2>&1)
then
locale_dir=`$dir/shar --print-text-domain-dir`
fi
done
IFS="$save_IFS"
if test "$locale_dir" = FAILED || test "$gettext_dir" = FAILED
then
echo=echo
else
TEXTDOMAINDIR=$locale_dir
export TEXTDOMAINDIR
TEXTDOMAIN=sharutils
export TEXTDOMAIN
echo="$gettext_dir/gettext -s"
fi
touch -am 1231235999 $$.touch >/dev/null 2>&1
if test ! -f 1231235999 && test -f $$.touch; then
shar_touch=touch
else
shar_touch=:
echo
$echo 'WARNING: not restoring timestamps. Consider getting and'
$echo "installing GNU \`touch', distributed in GNU File Utilities..."
echo
fi
rm -f 1231235999 $$.touch
#
if mkdir _sh11095; then
$echo 'x -' 'creating lock directory'
else
$echo 'failed to create lock directory'
exit 1
fi
# ============= Makefile ==============
if test -f 'Makefile' && test "$first_param" != -c; then
$echo 'x -' SKIPPING 'Makefile' '(file already exists)'
else
$echo 'x -' extracting 'Makefile' '(text)'
sed 's/^X//' << 'SHAR_EOF' > 'Makefile' &&
CC=gcc -B/home/work/gnu/bin/egcs/gcc/
CC=gcc -B/home/work/build/bin/egcs/bad/
#CC=gcc -B/home/work/misc/gnu/bin/egcs/gcc/
EXCEPTIONS=-fno-exceptions
CFLAGS=-fomit-frame-pointer -O9 -fpic $(EXCEPTIONS) # -dra
CFLAGS=-fomit-frame-pointer -O3 -fpic $(EXCEPTIONS) # -dra
#CFLAGS=-fno-omit-frame-pointer -O9 -fpic $(EXCEPTIONS) -dra
X
PROGS=main
SRCS=$(PROGS:=.cc) cexp.cc
ASMS=$(PROGS:=.s) cexp.s
X
all: $(PROGS)
X for f in $(PROGS); do echo "Running: $$f"; $$f; \
X if [ $$? != 0 ]; then echo Failed; fi; done
X
asm: $(ASMS)
X
cexp.s: cexp.cc
X $(CC) -S $(CFLAGS) $<
X
main.s: main.cc
X $(CC) -S -O2 $(EXCEPTIONS) $<
X
main: asm
X $(CC) -o $@ $(ASMS)
X
clean:
X $(RM) -f *.s *.cc.* *.c.* $(PROGS) *.o core a.out
X
shar:
X shar Makefile $(SRCS) > shar.out
SHAR_EOF
$shar_touch -am 0616111898 'Makefile' &&
chmod 0644 'Makefile' ||
$echo 'restore of' 'Makefile' 'failed'
if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
&& ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
md5sum -c << SHAR_EOF >/dev/null 2>&1 \
|| $echo 'Makefile:' 'MD5 check failed'
f8a825ffde57ebf50e0dfefdca0e57ce Makefile
SHAR_EOF
else
shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'Makefile'`"
test 739 -eq "$shar_count" ||
$echo 'Makefile:' 'original size' '739,' 'current size' "$shar_count!"
fi
fi
# ============= main.cc ==============
if test -f 'main.cc' && test "$first_param" != -c; then
$echo 'x -' SKIPPING 'main.cc' '(file already exists)'
else
$echo 'x -' extracting 'main.cc' '(text)'
sed 's/^X//' << 'SHAR_EOF' > 'main.cc' &&
// #include <iostream.h>
#include "cexp.h"
X
int
foo (ccr x)
{
// cout << x.real () << ", " << x.imag () << endl;
X return (x.real () == 1.0) + (x.imag () == 1.0);
}
X
int
main ()
{
X c a (2.0, 3.0);
X return foo (exp (a));
}
SHAR_EOF
$shar_touch -am 0616112698 'main.cc' &&
chmod 0644 'main.cc' ||
$echo 'restore of' 'main.cc' 'failed'
if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
&& ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
md5sum -c << SHAR_EOF >/dev/null 2>&1 \
|| $echo 'main.cc:' 'MD5 check failed'
3dbd787e2924a0dbe02b7a3b1560116f main.cc
SHAR_EOF
else
shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'main.cc'`"
test 225 -eq "$shar_count" ||
$echo 'main.cc:' 'original size' '225,' 'current size' "$shar_count!"
fi
fi
# ============= cexp.cc ==============
if test -f 'cexp.cc' && test "$first_param" != -c; then
$echo 'x -' SKIPPING 'cexp.cc' '(file already exists)'
else
$echo 'x -' extracting 'cexp.cc' '(text)'
sed 's/^X//' << 'SHAR_EOF' > 'cexp.cc' &&
#include "cexp.h"
X
__inline double exp (double __x);
__inline double
exp (double __x)
{
X register double __value, __exponent;
#if 1
#if 1
X __asm __volatile__
X ("fldl2e # e^x = 2^(x * log2(e))\n\t"
X "fmul %%st(1) # x * log2(e)\n\t"
X "fstl %%st(1)\n\t"
X "frndint # int(x * log2(e))\n\t"
X "fxch\n\t"
X "fsub %%st(1) # fract(x * log2(e))\n\t"
X "f2xm1 # 2^(fract(x * log2(e))) - 1\n\t"
X : "=t" (__value), "=u" (__exponent) : "0" (__x));
#endif
X __value += 1.0;
X __asm __volatile__
X ("fscale"
X : "=t" (__value) : "0" (__value), "u" (__exponent));
X
X return __value;
#else
X return __x;
#endif
}
__inline double sin (double __x);
__inline double
sin (double __x)
{
#if 1
X register double __value;
X __asm __volatile__
X ("fsin"
X : "=t" (__value) : "0" (__x));
X return __value;
#else
X return __x;
#endif
}
__inline double cos (double __x);
__inline double
cos (double __x)
{
#if 0
X register double __value;
X __asm __volatile__
X ("fcos"
X : "=t" (__value): "0" (__x));
X return __value;
#else
X return __x;
#endif
}
template <class FLOAT> complex<FLOAT>
exp (const complex<FLOAT>& x)
{
X return polar (FLOAT (exp (x.real ())), x.imag ());
}
template c exp (ccr);
SHAR_EOF
$shar_touch -am 0616080098 'cexp.cc' &&
chmod 0644 'cexp.cc' ||
$echo 'restore of' 'cexp.cc' 'failed'
if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
&& ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
md5sum -c << SHAR_EOF >/dev/null 2>&1 \
|| $echo 'cexp.cc:' 'MD5 check failed'
81db6a2f2b1c1e9ee30583e912787461 cexp.cc
SHAR_EOF
else
shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'cexp.cc'`"
test 1226 -eq "$shar_count" ||
$echo 'cexp.cc:' 'original size' '1226,' 'current size' "$shar_count!"
fi
fi
rm -fr _sh11095
exit 0