Date: Wed, 24 Apr 2002 12:13:24 -0400 (EDT) From: Alexander Kabaev <ak03@gte.com> To: FreeBSD-gnats-submit@FreeBSD.org Subject: gnu/37423: GCC C++ frontend fixes for OpenOffice Message-ID: <200204241613.g3OGDOuq028837@kanpc.gte.com>
next in thread | raw e-mail | index | archive | help
>Number: 37423
>Category: gnu
>Synopsis: GCC C++ frontend fixes for OpenOffice
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Wed Apr 24 09:20:01 PDT 2002
>Closed-Date:
>Last-Modified:
>Originator: Alexander N. Kabaev
>Release: FreeBSD 5.0-CURRENT i386
>Organization:
Verizon Data Services
>Environment:
System: FreeBSD kanpc.gte.com 5.0-CURRENT FreeBSD 5.0-CURRENT #6: Tue Apr 16 10:42:42 EDT 2002 root@kanpc.gte.com:/usr/src/sys/i386/compile/KANPC i386
gcc version 2.95.4 20020320 [FreeBSD]
>Description:
I had to make the following changes to our system gcc to stop
it from miscompiling OpenOffice code:
1. Changes to integrate.c deal with the problem, demonstrated
by the code in the How To Repeat section below. If inline
function which uses exception handling is being integrated into
a function, which does not itself contain any try/catch constructs,
several global flags values are not set correctly. The
urrent_function_has_nonlocal_label flags is not getting set in
particular. This allows GCC to allocate registers across function
calls. When exception is thrown in called functions, the exception
handler is reached with global registers (ebx, edi, esi) content
clobbered without gcc ever noticing that. The STLPort test suite
failure was caused by exactly this bug.
2. Changes in expr.c fix the problem demonstrated by the second
code snippet below.
I did not make a complete test case with nice printfs out of it,
but if you compile it with g++ -O -S and then look into assembly
code, you will notice rogue 'add $16, %esp' assembly instruction
in return case. GCC defers adjusting stack pointer after function
calls until absolutely necessary, but sometimes fails to do in at
the right time. In this case, the bogus stack pointer adjustment
is a leftover from a __cp_push_exception call done as a part of
the throw statement processing. In DWARF2 case stack was getting
adjusted at the right time as a side effect of expand_eh_region_end.
sjlj-exceptions do not use this function so I added a call to
do_pending_stack_adjust in its place.
Alternatively, stack adjustment could be done right before a call
to __sjthrow is expanded, but I think the current patch keeps us
closer to DWARF2-based exceptions code flow. One nice side effect
of this approach is that 'add $16, %esp' is getting optimized away
at the first flow optimization pass as non-reachable. This patch
fixes the problem with saxparser found by Martin Blapp.
>How-To-Repeat:
The following code demonstrates the problem #1:
================= Begin ====================
void do_nothing()
{
__asm ("movl $0, %%esi" : : :"%esi");
throw 5;
}
int __inline crash()
{
register int test = 0;
try {
test = 35;
do_nothing();
}
catch(...) {
test--;
}
return test;
}
extern "C"
int printf(const char *, ...);
void main()
{
int ret = crash();
printf("%d\n", ret);
}
================= End ====================
This example demonstrates the problem #2. Not
as complete as the first example, you will need
to compile it to assembly. Look for the following
asembly fragment:
movl -120(%ebp),%edx
movl 4(%edx),%eax
movl 4(%eax),%edx
movl (%edx),%edx
movl %edx,4(%eax)
addl $16,%esp # <== This add is bogus
addl $-12,%esp # Pushing arguments to guard_operate
movl -124(%ebp),%eax # will stomp over saved registers
pushl %eax # Here goes calling function's EBX :)
call guard_operate__FP5Guard
movl -120(%ebp),%edx
movl 4(%edx),%eax
movl (%eax),%eax
movl %eax,4(%edx)
================= Begin ====================
class Guard;
void guard_operate(Guard *pG);
class Guard
{
public:
Guard()
{
guard_operate(this);
}
~Guard()
{
guard_operate(this);
}
};
class SimpleRegistryImpl
{
public:
SimpleRegistryImpl();
~SimpleRegistryImpl();
virtual void open() throw(int);
};
extern int flag;
void SimpleRegistryImpl::open( )
throw(int)
{
__asm("int3;");
Guard aGuard;
if ( flag )
{
return;
}
throw 5;
}
================= End ====================
>Fix:
Index: integrate.c
===================================================================
RCS file: /home/ncvs/src/contrib/gcc.295/integrate.c,v
retrieving revision 1.1.1.3
diff -u -r1.1.1.3 integrate.c
--- integrate.c 16 Oct 1999 06:05:22 -0000 1.1.1.3
+++ integrate.c 31 Mar 2002 05:51:24 -0000
@@ -1608,6 +1608,20 @@
if (FUNCTION_FLAGS (header) & FUNCTION_FLAGS_NEEDS_CONTEXT)
static_chain_value = lookup_static_chain (fndecl);
+ /* If the inline function has these flags sets, that means that
+ coresponding global flags should be set for this function. */
+ if (FUNCTION_FLAGS (header) & FUNCTION_FLAGS_CALLS_SETJMP)
+ current_function_calls_setjmp = 1;
+
+ if (FUNCTION_FLAGS (header) & FUNCTION_FLAGS_CALLS_LONGJMP)
+ current_function_calls_longjmp = 1;
+
+ if (FUNCTION_FLAGS (header) & FUNCTION_FLAGS_HAS_NONLOCAL_LABEL)
+ current_function_has_nonlocal_label = 1;
+
+ if (FUNCTION_FLAGS (header) & FUNCTION_FLAGS_USES_CONST_POOL)
+ current_function_uses_const_pool = 1;
+
if (GET_CODE (parm_insns) == NOTE
&& NOTE_LINE_NUMBER (parm_insns) > 0)
{
Index: stmt.c
===================================================================
RCS file: /home/ncvs/src/contrib/gcc.295/stmt.c,v
retrieving revision 1.1.1.6
diff -u -r1.1.1.6 stmt.c
--- stmt.c 17 Feb 2001 08:36:08 -0000 1.1.1.6
+++ stmt.c 21 Apr 2002 06:07:51 -0000
@@ -4027,6 +4027,10 @@
cleanup = protect_with_terminate (cleanup);
expand_eh_region_end (cleanup);
}
+ else
+ {
+ do_pending_stack_adjust();
+ }
}
if (reachable)
>Release-Note:
>Audit-Trail:
>Unformatted:
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200204241613.g3OGDOuq028837>
