This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
aliasing problem with va_arg
- To: egcs at cygnus dot com
- Subject: aliasing problem with va_arg
- From: Jim Wilson <wilson at cygnus dot com>
- Date: Fri, 23 Oct 1998 17:37:57 -0700
- cc: mark at markmitchell dot com, wilson at cygnus dot com
This testcase gives incorrect code for a sparc-sun-solaris2 target when
compiled with -O2.
#include <stdarg.h>
extern double bar (double);
double foo (va_list ap) {
double d = va_arg (ap, double);
return bar (d);
}
The problem is that a SImode store created by the va_arg expansion is being
moved after the DFmode load of the result. This movement comes from
DIFFERENT_ALIAS_SETS_P which sees that the two MEMs have different
MEM_ALIAS_SET values, and hence assumes that they can't overlap. This macro
already knows that va_arg is unsafe, but it handles va_arg by checking to see
if this is a stdarg or varargs function. That isn't sufficient, because we
can call va_arg from a function that takes a va_list parameter. It is
also overkill since it means there is no aliasing within a stdarg/varargs
function, even though it is only MEMs from va_arg expansion that are unsafe.
Long term, I'd suggest changing how we implement va_arg. Instead of a macro
that expands to complicated non-ISO C code, we should instead have a target
independent macro that expands to a call to a built-in function, e.g.
builtin_va_arg. builtin_va_arg is then implemented by calling a target
dependent function that emits appropriate RTL. When this code generates
RTL, it can set MEM_ALIAS_SET appropriately, which probably means setting it
to zero. It would take a lot of work to convert all of the ports to a new
va_arg scheme though. I did this once for irix6 as an experiment. I can
send the patches if anyone is interested. They would need a lot of work
before they could be checked in.
Short term, I am not sure what to do. We can't easily search the parameter
list for va_list types, because that is a macro that could expand to any
type. We could probably add some GNU C extension used to mark functions
that call va_arg, similar to the ... extension used for marking vararg
functions. That seems like an ugly hack though.
Perhaps we can add code to dynamically enable/disable alias set computations.
E.g. add builtin functions __builtin_disable_aliasing, and
__builtin_enable_aliasing, modify va_arg to call them at the beginning and
end, and then modify get_alias_set to always return zero if
__builtin_disable_aliasing has been called. We could then get rid of
the varargs/stdarg function checks in DIFFERENT_ALIAS_SETS_P, while
fixing va_list functions at the same time.
Jim