-
Notifications
You must be signed in to change notification settings - Fork 15.3k
Description
| Bugzilla Link | 10713 |
| Resolution | FIXED |
| Resolved on | Sep 21, 2011 03:09 |
| Version | trunk |
| OS | Linux |
| Blocks | #11054 |
| Reporter | LLVM Bugzilla Contributor |
| CC | @asl,@efriedma-quic,@rjmccall |
Extended Description
Clang/llvm-gcc and dragonegg all consider a call to a function declared without
any parameters to be a var-args function call. However this gives the wrong
results when using the stdcall calling convention (with stdcall, the callee pops
arguments except if it is a varargs function; so any mistake in the
"var-argness" of a call is fatal, unlike with the usual C convention where it
doesn't make any difference).
Consider the following testcase. (The second call to bar is to make the stack
adjustments or lack of them clearer in the assembler):
#define STDCALL attribute((stdcall))
void STDCALL foo(); // Var-args or not var-args, that is the question!
void STDCALL bar(int); // Definitely not var-args
void STDCALL varg(int, ...); // Definitely var-args
void g(int x, int y)
{
foo(x, y);
bar(x);
varg(x, y);
bar(y);
}
GCC assembler snippets (compiled with: gcc -m32 -O2 -S):
call foo
subl $8, %esp <= Stack adjust, indicates not var-args!
...
call bar
subl $4, %esp <= Stack adjust; not var-args
...
call varg
movl %ebx, (%esp) <= No stack adjust; var-args
...
Clang etc assembler snippets:
calll foo
movl %edi, (%esp) <= No stack adjust, indicates var-args; disagrees with GCC
...
calll bar
subl $4, %esp <= Stack adjust; not var-args; agrees with GCC
...
calll varg
movl %esi, (%esp) <= No stack adjust; var-args; agrees with GCC
...
This difference seems to be the cause of some crashes when running wine compiled
with LLVM.
Note that using C++ and declaring foo "void foo(...)" doesn't make any
difference: GCC still calls it as if it were not var-args!
Digging into the GCC logic, the var-argness of a function type is determined
by the stdarg_p predicate (which returns true for var-args). This special
cases function types with no parameters (as produced by the C front-end for
XYZ foo() and by the C++ front-end for XYZ foo(...)) as not being var-args.