Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

va_args (va_start, va_end, va_list ) souce?

12 views
Skip to first unread message

Not Really Me

unread,
Nov 7, 2009, 12:52:20 PM11/7/09
to
I'm trying to make a simplified printf that does not rely on stdarg.h and
its accompanying baggage, so I need the source to the va_args functions.
Including stdarg.h tends to pull in all sorts of extraneous library
functions.

The source for libgcc was my first guess, but good gravy, it could take a
year to unravel that stuff.

Does anyone have a clean va_args source to share, i.e., va_start, va_end,
va_list in source that would be compiler independent?

Scott

__________ Information from ESET NOD32 Antivirus, version of virus signature database 4581 (20091107) __________

The message was checked by ESET NOD32 Antivirus.

http://www.eset.com


Boudewijn Dijkstra

unread,
Nov 7, 2009, 12:57:28 PM11/7/09
to
Op Sat, 07 Nov 2009 18:52:20 +0100 schreef Not Really Me
<sc...@validatedqwertysoftware.xyzzy.com>:

> I'm trying to make a simplified printf that does not rely on stdarg.h and
> its accompanying baggage, so I need the source to the va_args functions.

These are CPU dependent. Some arguments might be in registers, some might
be on the stack.

--
Gemaakt met Opera's revolutionaire e-mailprogramma:
http://www.opera.com/mail/
(remove the obvious prefix to reply by mail)

Jon Kirwan

unread,
Nov 7, 2009, 4:19:28 PM11/7/09
to
On Sat, 07 Nov 2009 18:57:28 +0100, "Boudewijn Dijkstra"
<sp4mtr4p....@indes.com> wrote:

>Op Sat, 07 Nov 2009 18:52:20 +0100 schreef Not Really Me
><sc...@validatedqwertysoftware.xyzzy.com>:
>> I'm trying to make a simplified printf that does not rely on stdarg.h and
>> its accompanying baggage, so I need the source to the va_args functions.
>
>These are CPU dependent. Some arguments might be in registers, some might
>be on the stack.

Worse, this can also depend upon #pragma, extended keywords not
explicitly part of the c standard, and compile options, as well. For
example, parameters may be placed in an XRAM parameter stack on the
8051. Or passed in fixed static memory locations assigned and reused.
Also, parameters can be _spilled_ out of registers by the compiler if
their address is taken in the routine.

As you imply, the OP needs to disclose the compiler toolset and target
before getting closer to a meaningful answer.

Jon

Hans-Bernhard Bröker

unread,
Nov 8, 2009, 9:12:16 AM11/8/09
to
Not Really Me wrote:
> I'm trying to make a simplified printf that does not rely on stdarg.h and
> its accompanying baggage, so I need the source to the va_args functions.

No can do. For starters, the va_args functionality consists of macros,
not functions. I.e. the bulk of it is _in_ <stdarg.h>. Trying to
implement a variadic function without it would be quite exactly like
trying to make omelettes without a pan.

> Including stdarg.h tends to pull in all sorts of extraneous library
> functions.

If so, that'll be because it has to.

Variable argument lists are pretty much by definition totally
system-specific. They depend on the compiler, the switches it was
invoked with, the operating system ABI, and all sorts of other things.

Not Really Me

unread,
Nov 9, 2009, 10:03:20 AM11/9/09
to


grumble, grumble. I suppose you are both right. It really does have to be
processor/compiler specific. Sometimes it is only clear when someone else
points it out.

Thanks,
Scott

__________ Information from ESET NOD32 Antivirus, version of virus signature database 4588 (20091109) __________

Nobody

unread,
Nov 9, 2009, 5:34:47 PM11/9/09
to
On Sat, 07 Nov 2009 10:52:20 -0700, Not Really Me wrote:

> I'm trying to make a simplified printf that does not rely on stdarg.h and
> its accompanying baggage, so I need the source to the va_args functions.

They're macros, not functions. The fact that the second argument to
va_arg() is a type should be a clue (you can't pass a type as a function
argument).

> Including stdarg.h tends to pull in all sorts of extraneous library
> functions.
>
> The source for libgcc was my first guess,

Nope; try the source for gcc itself.

gcc's stdarg.h (it's part of gcc, not libc) defines them as:

#define va_start(v,l) __builtin_va_start(v,l)
#define va_end(v) __builtin_va_end(v)
#define va_arg(v,l) __builtin_va_arg(v,l)

the __builtin_* "functions" are rather like what Lisp calls "special
forms": neither functions nor macros, but constructs which the compiler
recognises and handles specially.

If you want to write equivalents, you need to know the details of the
platform's calling convention, i.e. which arguments will be in which
registers, which will be on the stack (and where).

If you're lucky, the compiler will just push all of the unspecified
arguments onto the stack in right-to-left order, so va_arg() is just
essentially "(*((type *)(ap))++)"; most x86 platforms behave like this. If
you're not so lucky, you will have to enumerate all of the possible
combinations of argument types until the registers have been exhausted
(after which, the rest will be on the stack).

Also, some platforms use a different calling convention for variadic
functions (e.g. Windows uses "cdecl" rather than "stdcall"), in which case
the convention for variadic functions is often simpler (e.g. pushing all
unspecified arguments onto the stack rather than using registers).

Chris Giese

unread,
Nov 10, 2009, 6:42:31 PM11/10/09
to

>I'm trying to make a simplified printf that does not rely on stdarg.h and
>its accompanying baggage, so I need the source to the va_args functions.
>Including stdarg.h tends to pull in all sorts of extraneous library
>functions.

http://my.execpc.com/~geezer/code/printf.c

This code assumes arguments on the stack. There are STDARG.H macro
definitions in there, but be sure to check the assumptions I made
with those.

John Devereux

unread,
Nov 11, 2009, 3:00:06 AM11/11/09
to
NoEma...@execpc.com (Chris Giese) writes:

Hi Chris,

Hey, that's the code I used in a lot of my own projects (after I dumped
newlib for small systems).

Thanks for making it available!

--

John Devereux

Not Really Me

unread,
Nov 11, 2009, 9:42:04 AM11/11/09
to

Thanks. It could be real useful in the future. My current project is using
Wind River Compiler for PPC and it uses registers for the first seven
arguments.

As others so helpfully pointed out, that is the reason the _va macros are
compiler specific.

Scott

__________ Information from ESET NOD32 Antivirus, version of virus signature database 4595 (20091111) __________

vladitx

unread,
Nov 11, 2009, 6:28:14 PM11/11/09
to
On Nov 11, 4:42 pm, "Not Really Me"
<sc...@validatedQWERTYsoftware.XYZZY.com> wrote:

> Thanks.  It could be real useful in the future.  My current project is using
> Wind River Compiler for PPC and it uses registers for the first seven
> arguments.
>
> As others so helpfully pointed out, that is the reason the _va macros are
> compiler specific.

Functions with variable number of arguments receive all their variable
arguments through stack. The <stdarg.h> macros dealing with accessing
the arguments on the stack are compiler (and possibly OS, because of
calling conventions) specific, but their purpose is simple enough -
walk through a stack frame.

steve_s...@hotmail.com

unread,
Nov 11, 2009, 7:22:59 PM11/11/09
to
On Nov 11, 6:28 pm, vladitx <vlad...@nucleusys.com> wrote:
> Functions with variable number of arguments receive all their variable
> arguments through stack.

That's compiler dependent and frequently not the case. Even on x86.

Steve

Jon Kirwan

unread,
Nov 11, 2009, 7:34:19 PM11/11/09
to

Usually, the last named parameter at a fixed location marks the start
of the rest. Not _every_ parameter related to the variable argument
list is _always_ on the stack. At least, not right away. And, I
suspect, even the variable parameter list itself can be placed on
specialized software stacks that may be compiler dependent (I think
SDCC supports something like that, but haven't done enough reading to
know.) If the macros for getting started on the list do take the
address of that last named parameter, it will at least get spilled to
some place where an address can be had. But where even that is, isn't
guaranteed by the language.

The basic principle is indeed simple enough. It's just all that hairy
practice of competing in a compiler world that can get in the way and
make something otherwise quite easy to follow, less so in the end.

Best to know what your compiler does and not assume that some one bit
of c code will be able to port across well. The author said, "I'm


trying to make a simplified printf that does not rely on stdarg.h and

its accompanying baggage." I think the OP should at least be aware
that it would be wise to annotate whatever he does decide to do in
that code so that others, perhaps ignorantly, attempting to port it
elsewhere may have a clue what needs to be examined and possibly
modified based upon the circumstances at hand.

Jon

P.S. setjmp() and longjmp() are also pretty easy to follow, in
concept. Then objects in c++ impinge and the whole idea goes down a
nasty rat hole of complexity, if it works at all. Back to the main
point, stdarg.h is what it is for a reason.

vladitx

unread,
Nov 12, 2009, 6:06:27 AM11/12/09
to

I am yet to see something like that. Can you post an example which is
easiest for you to reproduce?

Arlet

unread,
Nov 12, 2009, 6:35:51 AM11/12/09
to

ARM compilers that follow the ARM procedure call standard put the first 4
words of the arguments in registers a1-a4, and the remaining words on the
stack.

It makes sense, because the calling function may not know that the called
function takes a variable number of arguments (if there was no prototype
declaration).

Inside the variadic function, the arguments that were passed in registers
can be pushed on the stack to simplify the va_args macros.

vladitx

unread,
Nov 12, 2009, 6:39:36 AM11/12/09
to
On Nov 12, 2:34 am, Jon Kirwan <j...@infinitefactors.org> wrote:

> On Wed, 11 Nov 2009 15:28:14 -0800 (PST), vladitx <vlad...@nucleusys.com> wrote:
>
> >Functions with variable number of arguments receive all their variable
> >arguments through stack. The <stdarg.h> macros dealing with accessing
> >the arguments on the stack are compiler (and possibly OS, because of
> >calling conventions) specific, but their purpose is simple enough -
> >walk through a stack frame.
>
> Usually, the last named parameter at a fixed location marks the start
> of the rest.

By the standard it's the last named which is passed to the macros. So,
yes, it must lead to the others somehow. I can imagine implementation
in which additional argument is passed which is a pointer to the
varargs frame.

> Not _every_ parameter related to the variable argument
> list is _always_ on the stack.

Related to or included into? I do mean the latter only.

>  At least, not right away.  And, I
> suspect, even the variable parameter list itself can be placed on
> specialized software stacks that may be compiler dependent (I think
> SDCC supports something like that, but haven't done enough reading to
> know.)

Wherever the chunk with varargs goes, it's still a frame that gets
scanned depending on type size/alignment. My use of "stack" is general
for simplicity.

>  If the macros for getting started on the list do take the
> address of that last named parameter, it will at least get spilled to
> some place where an address can be had.  But where even that is, isn't
> guaranteed by the language.

Yes. What I said is that the varargs themselves are grouped together
on the "stack" (taking my previous remark about the general use of
this word) and never passed through registers.

I'd be very interested to see implementation that does otherwise.

> The basic principle is indeed simple enough.  It's just all that hairy
> practice of competing in a compiler world that can get in the way and
> make something otherwise quite easy to follow, less so in the end.

IMHO the <stdarg.h> way of handling varargs is very well thought,
given the great _freedom_ that the 'C' language gives for the
underlying hardware and the even greater implications therefore. You
can have different frame layouts with the same compiler, just a matter
of different options, so there can't be much more elegant solution.

> The author said, "I'm
> trying to make a simplified printf that does not rely on stdarg.h and
> its accompanying baggage."  I think the OP should at least be aware
> that it would be wise to annotate whatever he does decide to do in
> that code so that others, perhaps ignorantly, attempting to port it
> elsewhere may have a clue what needs to be examined and possibly
> modified based upon the circumstances at hand.

The OP can make their own printf() easy enough, but not using
<stdarg.h> is call for disaster if he's going to use it on more than
one combination of CPU/OS/compiler. That's why <stdarg.h> was
standardised in the first place! GNU C even has the macros simply
expand to builtins - try to replace that.

> Back to the main point, stdarg.h is what it is for a reason.

Indeed.

vladitx

unread,
Nov 12, 2009, 7:17:43 AM11/12/09
to
On Nov 12, 1:35 pm, Arlet <usene...@ladybug.xs4all.nl> wrote:

> ARM compilers that follow the ARM procedure call standard put the first 4
> words of the arguments in registers a1-a4, and the remaining words on the
> stack.
>
> It makes sense, because the calling function may not know that the called
> function takes a variable number of arguments (if there was no prototype
> declaration).

Good point.

> Inside the variadic function, the arguments that were passed in registers
> can be pushed on the stack to simplify the va_args macros.

Checked with arm-gcc. Varargs partly get into registers r0..r3 and the
variadic function first does "stmfd sp!, {r0, r1, r2, r3}" so the
frame is contiguous.

Thanks for the example! I stand corrected.

0 new messages