ANSI C standard provides three macros that provide operations for
accessing arguments to a function that allows variable
arguments. These three macros are the va_start(),
va_end(), and va_arg() macros, which each system must
define in <stdarg.h>. The way these operations are implemented
varies greatly from system to system. In most cases, the standard
binary calling conventions dictate particular implementations and
compilers have to use them to be able to link with code produced by
other compilers. On some systems the macros can be mapped to ordinary
C code. On others, no ordinary C code will produce the needed effect.
So on some systems the <stdarg.h> header defines the macros in
terms of ordinary C code and the compiler itself does not need to know
anything about varargs. On other systems, the macros are defined in
terms of special built-in functions that the compiler implements
specifically to make varargs work.
Suif provides the VaStartStatement,
VaEndStatement, and VaArgExpression to do
exactly what the ANSI va_start(), va_end(), and
va_arg() macros do. The front-end for C can use a
<stdarg.h> file that maps each macro to a special built-in
command for the front-end, and these can be mapped to the Standard
SUIF varargs statements and instructions. A back-end can map these
high-level operations to the appropriate machine-specific code.
There is one final complication to the variable argument story. This
complication is that in the days before ANSI C, many compilers had a
<varargs.h> header file that provided va_start(),
va_end(), and va_arg() macros. But unfortunately the
usual way va_start() was defined was different than ANSI's
later va_start() - the old va_start() took one argument
while the ANSI va_start() takes two arguments. There are many
existing programs that use the old-style va_start(), so many
compilers support both <stdarg.h> and <varargs.h>
versions of va_start(), mapping them to different things. So
we have also provided the va_start_old_statement to do exactly
what the <varargs.h> va_start() does.
concrete VaStartStatement : Statement
{
Expression * owner ap_address in source_ops;
ParameterSymbol * reference parmn;
};
concrete VaStartOldStatement : Statement
{
Expression * owner ap_address in source_ops;
};
concrete VaEndStatement : Statement
{
Expression * owner ap_address in source_ops;
};
concrete VaArgExpression : Expression
{
Expression * owner ap_address in source_ops;
};