tech-userlevel archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: must use gcc builtin?



Thank you for replies.  In an attempt to respond coherently, I'm
answering various parts of the discussion all in one message.  

The claimed necessity if using gcc builtins rests AIUI on these ideas:

1.  standards compliance
2.  dictates of the processor architecture
3.  efficiency

I will attempt to show why these claims are faulty.  I'm either on very
solid ground, or NetBSD is seriously broken.  Why?  

#ifdef __GNUC__
#define _BSD_VA_LIST_    __builtin_va_list /* GCC built-in type */
#else
#define _BSD_VA_LIST_    char *    /* XXXfvdl should be ok? */ 
#endif

That code doesn't depend on x86.  It depends on GNU.  All I need is
another C compiler for x86, and my va_list is magically char* again.

On Wed, 22 Feb 2012 22:29:02 +0000
David Laight <david%l8s.co.uk@localhost> wrote:
>
> >     return ap - (va_list)o;
> > 
> >     ../../libplan9c/doprint.c:369: error: cast specifies array
> > type
> 
> That code is very, very broken doing things like that just isn't
> allowed. The fact that the code isn't ancient doesn't mean is is well
> written.

That definition of "broken" and "allowed" is controlled by the standard.
I agree that maximum portability usually involves strict adherence to
the standard.  That doesn't mean all standard-compliant use is
portable, or that all nonstandard use isn't.  

The code is being slagged here for being noncompliant.  Before I posted
my message, I took some time to try to "fix" it.  I will show later
that it is quite elegant.  It is not tricky and it is not error-prone.
It deserves emulation, not condemnation.  

On Wed, 22 Feb 2012 07:46:24 +0000
David Holland <dholland-tech%netbsd.org@localhost> wrote:

>  > I would be interested to know more about such an architecture,
>  > though. It's hard for me to see what stdarg does that printf
>  > doesn't.  
> 
> Argument passing in registers.

That's what I thought Joerg was referring to.  It's a mistake to
equate stdarg with "stack", and it's mistake to equate "stack" with
"sequential memory not on the chip".  Therefore it's a mistake to say
stdargs can't be implemented without compiler builtins on any
architecture.  

Imagine an architecture with no stack.  All arguments are passed as
registers; when registers are exhausted, one is used to point to memory
arranged by convention to be understandable to caller and callee.  We
don't need to imagine, really.  It describes the IBM 360, for
instance.  

Can a C compiler be written for such a machine?  Of course.  C is a
machine abstraction, not a machine implementation.  (I know the people
who answered my question know this; I'm just trying to start from a
place we can all agree on.)  

Correctly you will say it is advantageous to use the registers to best
advantage, and that stdargs should facilitate that.  I agree.  Does
that mean va_list cannot be a char*?  It does not.  There is no
necessity for stdarg to emulate the register-use convention implemented
by the compiler.  All that is required is that caller and callee share
an understanding of how it is to be used.  

On Wed, 22 Feb 2012 22:39:47 +0200
Alan Barrett <apb%cequrux.com@localhost> wrote:

> I believe that using a va_list as if it were a pointer, and doing 
> arithmetic on it, is something on which the Standard imposes 
> no requirements, and that the resulting behaviour is therefore 
> undefined.

Quite so.  Why, after all, should the C99 standard -- a *compiler*
standard -- go out of its way to specify a runtime library convention?
The standard is drawn to give the library-writer latitude.  OK, but the
library writer is equally free to use that latitude to give the
application-writer latitude.  It is possible, IOW, to have a
standard-compliant library whose documented behavior permits uses not
discussed by C99.  

On Wed, 22 Feb 2012 22:29:02 +0000
David Laight <david%l8s.co.uk@localhost> wrote:

> For architectures that pass argumets to varargs functions is registers
> and use FP registers for FP values and ALU registers for ints and ptrs
> 'va_list' has to be a compound that remembers which values have been
> used (note that the standard requires the values to be used in
> sequence).
> 
> However the va_list needs to be passable (efficiently) to functions
> like vprintf(). To do this it sometimes defined as an array with one
> member
> - so the definition allocates memory, but the function call passes
> the address.

And now we arrive at the efficiency argument.  

I'm going to go out on a limb and suggest that efficiency is not a
stdargs concern.  We are talking about the likes of printf; we
are very far, I believe, from well defined functions in any
mathematical sense, and very far from any deeply nested inner loop.  We
are in fact very close to I/O, were all machines wait at the same
speed.  If you want top machine speed, IOW, you cannot be putzing with
the "stack" where the compiler can't see you.  

http://www.schemamania.org/wily/doprint.c

I say to you that efficiency, even in C, comes in many forms.  There's
370 lines in that module, and it's hard to see how to improve it.  

I'm not sure of the intention of line 221, 

        int fmt, r;

        f.chr = c;
        fmt = fmttab[c];
        assert(fmt >= F_BI);
        assert(fmtfns[fmt-F_BI] != 0);
        r = fmtfns[fmt-F_BI](ap, &f);
        if (r < 0)
                f.f3 |= ~r;
        else {
                ap += r; /* ap is the local va_list pointer, ahem */ 
                s = f.out; percent = 0;
        }

but I'm discinclined to say it's not good C, or to invalidate it just
because GNU provides a particular implementation.  

To recap, in stack-popping order:

3.  Efficiency of programmer counts for something, particularly around
poorly defined I/O bound functionality.  

2.  Nothing about machine architecture mandates anything about the
implementation of stdargs.  

1.  The C standard is silent on the subject, as it should be.  POSIX
likewise defines *minimum* functionality.  Nothing prevents a more
liberal, useful implementation.  

I'm sympathetic to arguments for minimalism and standards compliance.
But that shouldn't mean that perfectly fine C should not compile just
because the standard doesn't impose the requirement that it be
compilable.  

NetBSD should be a platform to use, not a standards nanny.  It
shouldn't be the eye of a needle through which code must pass on its way
to ... well, to where, exactly?  Isn't this exactly a case for allowing
stupid things to permit clever ones?  

--jkl


Home | Main Index | Thread Index | Old Index