Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #105743 > unrolled thread

va_start without the first argument?

Started byThiago Adams <thiago.adams@gmail.com>
First post2017-03-10 11:57 -0800
Last post2017-03-15 13:39 -0700
Articles 20 on this page of 107 — 23 participants

Back to article view | Back to comp.lang.c


Contents

  va_start without the first argument? Thiago Adams <thiago.adams@gmail.com> - 2017-03-10 11:57 -0800
    Re: va_start without the first argument? Thiago Adams <thiago.adams@gmail.com> - 2017-03-10 12:04 -0800
    Re: va_start without the first argument? Keith Thompson <kst-u@mib.org> - 2017-03-10 12:32 -0800
      Re: va_start without the first argument? "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2017-03-10 15:51 -0500
      Re: va_start without the first argument? Thiago Adams <thiago.adams@gmail.com> - 2017-03-10 14:36 -0800
        Re: va_start without the first argument? Thiago Adams <thiago.adams@gmail.com> - 2017-03-10 14:53 -0800
          Re: va_start without the first argument? Robert Wessel <robertwessel2@yahoo.com> - 2017-03-10 17:14 -0600
            Re: va_start without the first argument? Thiago Adams <thiago.adams@gmail.com> - 2017-03-10 15:37 -0800
              Re: va_start without the first argument? Robert Wessel <robertwessel2@yahoo.com> - 2017-03-10 23:12 -0600
                Re: va_start without the first argument? Thiago Adams <thiago.adams@gmail.com> - 2017-03-13 10:29 -0700
                  Re: va_start without the first argument? Thiago Adams <thiago.adams@gmail.com> - 2017-03-13 11:31 -0700
                    Re: va_start without the first argument? scott@slp53.sl.home (Scott Lurndal) - 2017-03-13 18:40 +0000
                      Re: va_start without the first argument? Thiago Adams <thiago.adams@gmail.com> - 2017-03-13 12:31 -0700
              Re: va_start without the first argument? jacobnavia <jacob@jacob.remcomp.fr> - 2017-03-11 19:53 +0100
                Re: va_start without the first argument? BartC <bc@freeuk.com> - 2017-03-11 19:05 +0000
                  Re: va_start without the first argument? Keith Thompson <kst-u@mib.org> - 2017-03-11 11:56 -0800
                Re: va_start without the first argument? antispam@math.uni.wroc.pl - 2017-03-12 05:41 +0000
                Re: va_start without the first argument? David Brown <david.brown@hesbynett.no> - 2017-03-12 13:52 +0100
                  Re: va_start without the first argument? BartC <bc@freeuk.com> - 2017-03-12 14:40 +0000
                    Re: va_start without the first argument? David Brown <david.brown@hesbynett.no> - 2017-03-12 18:13 +0100
                      Re: va_start without the first argument? BartC <bc@freeuk.com> - 2017-03-12 18:04 +0000
                        Re: va_start without the first argument? David Brown <david.brown@hesbynett.no> - 2017-03-12 21:04 +0100
                          Re: va_start without the first argument? BartC <bc@freeuk.com> - 2017-03-12 21:02 +0000
                            Re: va_start without the first argument? David Brown <david.brown@hesbynett.no> - 2017-03-12 22:40 +0100
                              Re: va_start without the first argument? supercat@casperkitty.com - 2017-03-12 15:51 -0700
                                Re: va_start without the first argument? Malcolm McLean <malcolm.mclean5@btinternet.com> - 2017-03-12 16:52 -0700
                                Re: va_start without the first argument? David Brown <david.brown@hesbynett.no> - 2017-03-13 00:56 +0100
                                  Re: va_start without the first argument? supercat@casperkitty.com - 2017-03-13 09:17 -0700
                                    Re: va_start without the first argument? BartC <bc@freeuk.com> - 2017-03-13 17:54 +0000
                                      Re: va_start without the first argument? David Brown <david.brown@hesbynett.no> - 2017-03-13 22:12 +0100
                                        Re: va_start without the first argument? BartC <bc@freeuk.com> - 2017-03-13 22:48 +0000
                                          Re: va_start without the first argument? David Brown <david.brown@hesbynett.no> - 2017-03-14 13:46 +0100
                                            Re: va_start without the first argument? BartC <bc@freeuk.com> - 2017-03-14 13:37 +0000
                                              Re: va_start without the first argument? David Brown <david.brown@hesbynett.no> - 2017-03-14 15:24 +0100
                                                Re: va_start without the first argument? supercat@casperkitty.com - 2017-03-14 08:25 -0700
                                                  Re: va_start without the first argument? David Brown <david.brown@hesbynett.no> - 2017-03-14 17:02 +0100
                                                    Re: va_start without the first argument? supercat@casperkitty.com - 2017-03-14 09:45 -0700
                                              Re: va_start without the first argument? Keith Thompson <kst-u@mib.org> - 2017-03-14 09:15 -0700
                                                Re: va_start without the first argument? supercat@casperkitty.com - 2017-03-14 10:02 -0700
                                                Re: va_start without the first argument? jt@toerring.de (Jens Thoms Toerring) - 2017-03-14 20:32 +0000
                                        Re: va_start without the first argument? raltbos@xs4all.nl (Richard Bos) - 2017-03-14 07:44 +0000
                                          Re: va_start without the first argument? David Brown <david.brown@hesbynett.no> - 2017-03-14 13:38 +0100
                                          Re: va_start without the first argument? Keith Thompson <kst-u@mib.org> - 2017-03-14 08:57 -0700
                                    Re: va_start without the first argument? Keith Thompson <kst-u@mib.org> - 2017-03-13 11:21 -0700
                                      Re: va_start without the first argument? scott@slp53.sl.home (Scott Lurndal) - 2017-03-13 18:33 +0000
                                        Re: va_start without the first argument? David Brown <david.brown@hesbynett.no> - 2017-03-13 22:08 +0100
                                          Re: va_start without the first argument? supercat@casperkitty.com - 2017-03-13 15:23 -0700
                                            Re: va_start without the first argument? David Brown <david.brown@hesbynett.no> - 2017-03-14 13:58 +0100
                                              Re: va_start without the first argument? Keith Thompson <kst-u@mib.org> - 2017-03-14 09:18 -0700
                                                Re: va_start without the first argument? scott@slp53.sl.home (Scott Lurndal) - 2017-03-14 16:52 +0000
                                                  Re: va_start without the first argument? Keith Thompson <kst-u@mib.org> - 2017-03-14 11:34 -0700
                                                    Re: va_start without the first argument? scott@slp53.sl.home (Scott Lurndal) - 2017-03-14 18:54 +0000
                                                    Re: va_start without the first argument? supercat@casperkitty.com - 2017-03-14 13:30 -0700
                                                      Re: va_start without the first argument? Ike Naar <ike@iceland.freeshell.org> - 2017-03-15 21:55 +0000
                                                        Re: va_start without the first argument? supercat@casperkitty.com - 2017-03-15 15:16 -0700
                                                        Re: va_start without the first argument? Philip Lantz <prl@canterey.us> - 2017-03-23 21:04 -0700
                                                Re: va_start without the first argument? David Brown <david.brown@hesbynett.no> - 2017-03-14 21:48 +0100
                                            Re: va_start without the first argument? scott@slp53.sl.home (Scott Lurndal) - 2017-03-14 14:01 +0000
                                              Re: va_start without the first argument? supercat@casperkitty.com - 2017-03-14 07:42 -0700
                                          Re: va_start without the first argument? scott@slp53.sl.home (Scott Lurndal) - 2017-03-14 12:38 +0000
                                Re: va_start without the first argument? jacobnavia <jacob@jacob.remcomp.fr> - 2017-03-13 01:11 +0100
                                  Re: va_start without the first argument? Ian Collins <ian-news@hotmail.com> - 2017-03-13 15:43 +1300
                                    Re: va_start without the first argument? BartC <bc@freeuk.com> - 2017-03-13 10:36 +0000
                                      Re: va_start without the first argument? Ian Collins <ian-news@hotmail.com> - 2017-03-14 07:33 +1300
                                        Re: va_start without the first argument? BartC <bc@freeuk.com> - 2017-03-13 19:00 +0000
                                          Re: va_start without the first argument? Ian Collins <ian-news@hotmail.com> - 2017-03-14 08:05 +1300
                                            Re: va_start without the first argument? BartC <bc@freeuk.com> - 2017-03-13 23:10 +0000
                                              Re: va_start without the first argument? Ian Collins <ian-news@hotmail.com> - 2017-03-14 17:38 +1300
                                                Re: va_start without the first argument? Thiago Adams <thiago.adams@gmail.com> - 2017-03-14 05:48 -0700
                                          Re: va_start without the first argument? Thiago Adams <thiago.adams@gmail.com> - 2017-03-13 12:12 -0700
                  Re: va_start without the first argument? jacobnavia <jacob@jacob.remcomp.fr> - 2017-03-12 19:39 +0100
    Re: va_start without the first argument? jt@toerring.de (Jens Thoms Toerring) - 2017-03-10 20:49 +0000
      Re: va_start without the first argument? Thiago Adams <thiago.adams@gmail.com> - 2017-03-10 14:41 -0800
        Re: va_start without the first argument? John Bode <jfbode1029@gmail.com> - 2017-03-10 16:05 -0800
          Re: va_start without the first argument? jacob navia <jacob@jacob.remcomp.fr> - 2017-03-11 21:47 +0100
            Re: va_start without the first argument? supercat@casperkitty.com - 2017-03-11 13:07 -0800
              Re: va_start without the first argument? jacobnavia <jacob@jacob.remcomp.fr> - 2017-03-11 22:24 +0100
                Re: va_start without the first argument? Thiago Adams <thiago.adams@gmail.com> - 2017-03-13 05:44 -0700
                  Re: va_start without the first argument? Jerry Stuckle <jstucklex@attglobal.net> - 2017-03-13 08:59 -0400
                    Re: va_start without the first argument? Thiago Adams <thiago.adams@gmail.com> - 2017-03-13 06:17 -0700
                      Re: va_start without the first argument? Jerry Stuckle <jstucklex@attglobal.net> - 2017-03-13 13:27 -0400
                        Re: va_start without the first argument? Jerry Stuckle <jstucklex@attglobal.net> - 2017-03-13 13:30 -0400
                          Re: va_start without the first argument? Thiago Adams <thiago.adams@gmail.com> - 2017-03-13 11:00 -0700
                        Re: va_start without the first argument? Thiago Adams <thiago.adams@gmail.com> - 2017-03-13 10:34 -0700
            Re: va_start without the first argument? antispam@math.uni.wroc.pl - 2017-03-12 06:00 +0000
            Re: va_start without the first argument? gordonb.gas5o@burditt.org (Gordon Burditt) - 2017-03-17 09:46 -0500
              Re: va_start without the first argument? supercat@casperkitty.com - 2017-03-17 09:07 -0700
          Re: va_start without the first argument? Thiago Adams <thiago.adams@gmail.com> - 2017-03-13 05:39 -0700
            Re: va_start without the first argument? John Bode <jfbode1029@gmail.com> - 2017-03-13 11:40 -0700
              Re: va_start without the first argument? Thiago Adams <thiago.adams@gmail.com> - 2017-03-13 12:01 -0700
                Re: va_start without the first argument? jacobnavia <jacob@jacob.remcomp.fr> - 2017-03-13 23:17 +0100
                  Re: va_start without the first argument? Thiago Adams <thiago.adams@gmail.com> - 2017-03-13 16:15 -0700
                    Re: va_start without the first argument? jacobnavia <jacob@jacob.remcomp.fr> - 2017-03-14 00:26 +0100
                      Re: va_start without the first argument? kikiins@gmail.com - 2017-03-13 16:51 -0700
                        Re: va_start without the first argument? jacobnavia <jacob@jacob.remcomp.fr> - 2017-03-14 01:12 +0100
                          Re: va_start without the first argument? Thiago Adams <thiago.adams@gmail.com> - 2017-03-13 18:24 -0700
                            Re: va_start without the first argument? Thiago Adams <thiago.adams@gmail.com> - 2017-03-13 18:57 -0700
                    Re: va_start without the first argument? raltbos@xs4all.nl (Richard Bos) - 2017-03-14 07:59 +0000
                      Re: va_start without the first argument? Thiago Adams <thiago.adams@gmail.com> - 2017-03-14 06:45 -0700
                  Re: va_start without the first argument? Robert Wessel <robertwessel2@yahoo.com> - 2017-03-13 18:20 -0500
                    Re: va_start without the first argument? jacobnavia <jacob@jacob.remcomp.fr> - 2017-03-14 00:31 +0100
      Re: va_start without the first argument? raltbos@xs4all.nl (Richard Bos) - 2017-03-13 16:51 +0000
    Re: va_start without the first argument? jacobnavia <jacob@jacob.remcomp.fr> - 2017-03-11 19:29 +0100
    Re: va_start without the first argument? Siri Cruise <chine.bleu@yahoo.com> - 2017-03-11 12:12 -0800
    Re: va_start without the first argument? luser droog <luser.droog@gmail.com> - 2017-03-13 05:37 -0700
      Re: va_start without the first argument? luser droog <luser.droog@gmail.com> - 2017-03-15 11:45 -0700
        Re: va_start without the first argument? Thiago Adams <thiago.adams@gmail.com> - 2017-03-15 13:39 -0700

Page 1 of 6  [1] 2 3 4 5 6  Next page →


#105743 — va_start without the first argument?

FromThiago Adams <thiago.adams@gmail.com>
Date2017-03-10 11:57 -0800
Subjectva_start without the first argument?
Message-ID<b0f99f2b-09a3-4510-89dd-c3511fba3321@googlegroups.com>
Is it possible to create a var args function without the 
first argument? (firstArgument in va_start)

void F(...)
{
  va_list vl;
  va_start(vl,firstArgument);

  int i1 =va_arg(vl,int);
  int i2 =va_arg(vl,int);

  va_end(vl);
}

int main ()
{
  F(1, 2);
  return 0;
}

[toc] | [next] | [standalone]


#105746

FromThiago Adams <thiago.adams@gmail.com>
Date2017-03-10 12:04 -0800
Message-ID<d0d98476-359f-4a8d-9b74-e78019478d82@googlegroups.com>
In reply to#105743
On Friday, March 10, 2017 at 4:57:27 PM UTC-3, Thiago Adams wrote:
> Is it possible to create a var args function without the 
> first argument? (firstArgument in va_start)

I am asking this because I am experimenting some ways to create 
structs
The other questions is can I put vargs on heap and get back?

C99 has  va_copy. 
http://en.cppreference.com/w/c/variadic/va_copy






[toc] | [prev] | [next] | [standalone]


#105751

FromKeith Thompson <kst-u@mib.org>
Date2017-03-10 12:32 -0800
Message-ID<ln37ekhnzz.fsf@kst-u.example.com>
In reply to#105743
Thiago Adams <thiago.adams@gmail.com> writes:
> Is it possible to create a var args function without the 
> first argument? (firstArgument in va_start)
>
> void F(...)

No.  The va_start macro requires the name of the last non-variadic
parameter, and syntax of a parameter-type-list requires at least one
parameter-declaration (N1570 6.7.6).

[...]

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#105759

From"Rick C. Hodgin" <rick.c.hodgin@gmail.com>
Date2017-03-10 15:51 -0500
Message-ID<op.ywwj76oaw6u7nr@rickhodgin.boycesystems.local>
In reply to#105751
> Thiago Adams <thiago.adams@gmail.com> writes:
>> Is it possible to create a var args function without the
>> first argument? (firstArgument in va_start)
>>
>> void F(...)
>
> No.  The va_start macro requires the name of the last non-variadic
> parameter, and syntax of a parameter-type-list requires at least one
> parameter-declaration (N1570 6.7.6).
>
> [...]
>

Note:  This message isn't in reply to the original author, but to the
members of the general C group:

CAlive defines an alternative to variadic macros.  It uses a name to
hold the "array" of variable parameters:

     CAlive to introduce any and allow types:
     https://groups.google.com/d/msg/caliveprogramminglanguage/b52U0R5-gEQ/MF1G7-2tAgAJ

-----[ Begin ]-----

The allow type is used in lieu of "..." to indicate there are additional  
parameters.
It conveys a name through which additional parameters can be accessed at  
runtime,
without requiring a va_args solution (Note: va_args is still supported).

To access each element in an allow, use its name[n] reference beginning at  
n=1.  n=0
is reserved for the allow parameter count, as in name[0].  In addition,  
dot tags are
available which provide typing information for each parameter.  Use of  
name[n].type,
for example, returns an integer which follows back to a litany of  
_LIVECODE_ALLOW_TYPE_*
constants, which resolve to back to their fundamental types (including  
any* for
constructed types of class* or struct*).

-----[ End ]-----

The entire goal of CAlive is to maintain the low-level power of the C  
programming
language, but to provide syntaxes which help human beings relate to the  
underlying
data without the complexities of the conventional C syntax.  CAlive  
intends to
maintain nearly all of the existing C syntaxes as well without explicitly  
stating
that it's compiling a pure C source file (in which case I intend  
eventually to
provide 100% compatibility).

It's a way to make C programming easier, without going into the  
complexities of
C++, and with keeping in mind the fact that GUI editors exist now, able to  
do a
lot of the hard work of presenting source code in various ways based on  
information
the compiler has (as CAlive is a continuous compiler, which re-compiles  
source code
as source code edits are made, introducing something called an "inquiry"  
where it
encounters things that are in error (syntax or other)).

Thank you,
Rick C. Hodgin

[toc] | [prev] | [next] | [standalone]


#105771

FromThiago Adams <thiago.adams@gmail.com>
Date2017-03-10 14:36 -0800
Message-ID<6efb4ec5-8a50-4ecd-95ac-3328682a7a03@googlegroups.com>
In reply to#105751
On Friday, March 10, 2017 at 5:32:05 PM UTC-3, Keith Thompson wrote:
> Thiago Adams writes:
> > Is it possible to create a var args function without the 
> > first argument? (firstArgument in va_start)
> >
> > void F(...)
> 
> No.  The va_start macro requires the name of the last non-variadic
> parameter, and syntax of a parameter-type-list requires at least one
> parameter-declaration (N1570 6.7.6).
> 
> [...]


How it works?
How does it knows the alignment/padding between the arguments?

--
Another question: (maybe not related)
Can I predict the padding for structs?
For instance:

char * p = malloc(sizeof(struct { int i; double d; }));
I want to get i from struct and then d:
int i = GET(p, int);
double d = GET(p, double);
Is it possible to create a macro GET in this case?

[toc] | [prev] | [next] | [standalone]


#105773

FromThiago Adams <thiago.adams@gmail.com>
Date2017-03-10 14:53 -0800
Message-ID<1c6010ab-c0e6-468b-8b9d-94cbe2aa4ac8@googlegroups.com>
In reply to#105771
On Friday, March 10, 2017 at 7:36:37 PM UTC-3, Thiago Adams wrote:
> On Friday, March 10, 2017 at 5:32:05 PM UTC-3, Keith Thompson wrote:
> > Thiago Adams writes:
> > > Is it possible to create a var args function without the 
> > > first argument? (firstArgument in va_start)
> > >
> > > void F(...)
> > 
> > No.  The va_start macro requires the name of the last non-variadic
> > parameter, and syntax of a parameter-type-list requires at least one
> > parameter-declaration (N1570 6.7.6).
> > 
> > [...]
> 
> 
> How it works?
> How does it knows the alignment/padding between the arguments?
> 

I opened the definition of va_list etc from Visual C++ 2017 includes:

typedef char* va_list;


#define _ADDRESSOF(v) (&(v))

#define _INTSIZEOF(n)  ((sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1))

#define __crt_va_start_a(ap, v) ((void)(ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v)))

#define __crt_va_arg(ap, t) (*(t*)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)))


#define __crt_va_end(ap)        ((void)(ap = (va_list)0))

The macro  _INTSIZEOF has some tricks I don't understand.

[toc] | [prev] | [next] | [standalone]


#105775

FromRobert Wessel <robertwessel2@yahoo.com>
Date2017-03-10 17:14 -0600
Message-ID<r5c6cch9bq72g8tk64sl9di7lp67ucm66h@4ax.com>
In reply to#105773
On Fri, 10 Mar 2017 14:53:02 -0800 (PST), Thiago Adams
<thiago.adams@gmail.com> wrote:

>On Friday, March 10, 2017 at 7:36:37 PM UTC-3, Thiago Adams wrote:
>> On Friday, March 10, 2017 at 5:32:05 PM UTC-3, Keith Thompson wrote:
>> > Thiago Adams writes:
>> > > Is it possible to create a var args function without the 
>> > > first argument? (firstArgument in va_start)
>> > >
>> > > void F(...)
>> > 
>> > No.  The va_start macro requires the name of the last non-variadic
>> > parameter, and syntax of a parameter-type-list requires at least one
>> > parameter-declaration (N1570 6.7.6).
>> > 
>> > [...]
>> 
>> 
>> How it works?
>> How does it knows the alignment/padding between the arguments?
>> 
>
>I opened the definition of va_list etc from Visual C++ 2017 includes:
>
>typedef char* va_list;
>
>
>#define _ADDRESSOF(v) (&(v))
>
>#define _INTSIZEOF(n)  ((sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1))
>
>#define __crt_va_start_a(ap, v) ((void)(ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v)))
>
>#define __crt_va_arg(ap, t) (*(t*)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)))
>
>
>#define __crt_va_end(ap)        ((void)(ap = (va_list)0))
>
>The macro  _INTSIZEOF has some tricks I don't understand.


None of what you found in the MSVC headers actually means anything to
you.  *How* va_args is implemented is entirely implementation
dependent, and the above may not even work on the next patch level of
MSVC.  *Some* implementation *is* required, but the innards are secret
magic.  That being said, I suspect a fair number of implementations
are quite similar.

As for what _INTSIZEOF is doing, it's computing the alignment (on the
stack), or effective size, of a parameter on the stack.  Basically it
computes (ceil(sizeof(type)/sizeof(int))*sizeof(int)).  IOW, it rounds
the size up to the next whole numbers of ints.  Which corresponds to
how this implementation lays out parameters on the stack.  And again,
that happens to work for this *one* implementation, at *this* moment.

[toc] | [prev] | [next] | [standalone]


#105776

FromThiago Adams <thiago.adams@gmail.com>
Date2017-03-10 15:37 -0800
Message-ID<3fb4148c-8b5b-468c-8399-e5a5fc8575ee@googlegroups.com>
In reply to#105775
On Friday, March 10, 2017 at 8:13:50 PM UTC-3, robert...@yahoo.com wrote:
> On Fri, 10 Mar 2017 14:53:02 -0800 (PST), Thiago Adams
> wrote:
> 
> >On Friday, March 10, 2017 at 7:36:37 PM UTC-3, Thiago Adams wrote:
> >> On Friday, March 10, 2017 at 5:32:05 PM UTC-3, Keith Thompson wrote:
> >> > Thiago Adams writes:
> >> > > Is it possible to create a var args function without the 
> >> > > first argument? (firstArgument in va_start)
> >> > >
> >> > > void F(...)
> >> > 
> >> > No.  The va_start macro requires the name of the last non-variadic
> >> > parameter, and syntax of a parameter-type-list requires at least one
> >> > parameter-declaration (N1570 6.7.6).
> >> > 
> >> > [...]
> >> 
> >> 
> >> How it works?
> >> How does it knows the alignment/padding between the arguments?
> >> 
> >
> >I opened the definition of va_list etc from Visual C++ 2017 includes:
> >
> >typedef char* va_list;
> >
> >
> >#define _ADDRESSOF(v) (&(v))
> >
> >#define _INTSIZEOF(n)  ((sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1))
> >
> >#define __crt_va_start_a(ap, v) ((void)(ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v)))
> >
> >#define __crt_va_arg(ap, t) (*(t*)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)))
> >
> >
> >#define __crt_va_end(ap)        ((void)(ap = (va_list)0))
> >
> >The macro  _INTSIZEOF has some tricks I don't understand.
> 
> 
> None of what you found in the MSVC headers actually means anything to
> you.  *How* va_args is implemented is entirely implementation
> dependent, and the above may not even work on the next patch level of
> MSVC.  *Some* implementation *is* required, but the innards are secret
> magic.  That being said, I suspect a fair number of implementations
> are quite similar.
> 
> As for what _INTSIZEOF is doing, it's computing the alignment (on the
> stack), or effective size, of a parameter on the stack.  Basically it
> computes (ceil(sizeof(type)/sizeof(int))*sizeof(int)).  IOW, it rounds
> the size up to the next whole numbers of ints.  Which corresponds to
> how this implementation lays out parameters on the stack.  And again,
> that happens to work for this *one* implementation, at *this* moment.


I am trying to understand  to create va_list  on heap.
(not working at this moment)



#include <stdarg.h> 
#include <stdlib.h>
#include <stdio.h>

void F2(const char* fmt, va_list vl)
{
    int i = va_arg(vl, int);
    double d = va_arg(vl, double);
    printf("i = %d, d = %lf\n", i, d);
}

void F(const char* fmt, ...)
{
    va_list vl;
    va_start(vl, fmt);
    F2(fmt, vl);
    va_end(vl);
}

va_list Heap(int i, double d)
{
    //not working 
    void* pv = malloc(sizeof(int) + sizeof(double));
    va_list * p = (va_list *)pv;
    //*(int*)p = i;
    //p += _INTSIZEOF(i);
    va_arg(p, int) = i; //walk next
    
    //*(double*)p = d;
    //p += _INTSIZEOF(d);
    va_arg(p, double) = d; //walk next

    return pv;
}

int main()
{
    F("", 1, 2.0);
    F2("", Heap(1, 2.0));
    return 0;
}


[toc] | [prev] | [next] | [standalone]


#105784

FromRobert Wessel <robertwessel2@yahoo.com>
Date2017-03-10 23:12 -0600
Message-ID<2a17cclqhuuefeu73qfko4u75p59986s9j@4ax.com>
In reply to#105776
On Fri, 10 Mar 2017 15:37:34 -0800 (PST), Thiago Adams
<thiago.adams@gmail.com> wrote:

>On Friday, March 10, 2017 at 8:13:50 PM UTC-3, robert...@yahoo.com wrote:
>> On Fri, 10 Mar 2017 14:53:02 -0800 (PST), Thiago Adams
>> wrote:
>> 
>> >On Friday, March 10, 2017 at 7:36:37 PM UTC-3, Thiago Adams wrote:
>> >> On Friday, March 10, 2017 at 5:32:05 PM UTC-3, Keith Thompson wrote:
>> >> > Thiago Adams writes:
>> >> > > Is it possible to create a var args function without the 
>> >> > > first argument? (firstArgument in va_start)
>> >> > >
>> >> > > void F(...)
>> >> > 
>> >> > No.  The va_start macro requires the name of the last non-variadic
>> >> > parameter, and syntax of a parameter-type-list requires at least one
>> >> > parameter-declaration (N1570 6.7.6).
>> >> > 
>> >> > [...]
>> >> 
>> >> 
>> >> How it works?
>> >> How does it knows the alignment/padding between the arguments?
>> >> 
>> >
>> >I opened the definition of va_list etc from Visual C++ 2017 includes:
>> >
>> >typedef char* va_list;
>> >
>> >
>> >#define _ADDRESSOF(v) (&(v))
>> >
>> >#define _INTSIZEOF(n)  ((sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1))
>> >
>> >#define __crt_va_start_a(ap, v) ((void)(ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v)))
>> >
>> >#define __crt_va_arg(ap, t) (*(t*)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)))
>> >
>> >
>> >#define __crt_va_end(ap)        ((void)(ap = (va_list)0))
>> >
>> >The macro  _INTSIZEOF has some tricks I don't understand.
>> 
>> 
>> None of what you found in the MSVC headers actually means anything to
>> you.  *How* va_args is implemented is entirely implementation
>> dependent, and the above may not even work on the next patch level of
>> MSVC.  *Some* implementation *is* required, but the innards are secret
>> magic.  That being said, I suspect a fair number of implementations
>> are quite similar.
>> 
>> As for what _INTSIZEOF is doing, it's computing the alignment (on the
>> stack), or effective size, of a parameter on the stack.  Basically it
>> computes (ceil(sizeof(type)/sizeof(int))*sizeof(int)).  IOW, it rounds
>> the size up to the next whole numbers of ints.  Which corresponds to
>> how this implementation lays out parameters on the stack.  And again,
>> that happens to work for this *one* implementation, at *this* moment.
>
>
>I am trying to understand  to create va_list  on heap.
>(not working at this moment)
>
>
>
>#include <stdarg.h> 
>#include <stdlib.h>
>#include <stdio.h>
>
>void F2(const char* fmt, va_list vl)
>{
>    int i = va_arg(vl, int);
>    double d = va_arg(vl, double);
>    printf("i = %d, d = %lf\n", i, d);
>}
>
>void F(const char* fmt, ...)
>{
>    va_list vl;
>    va_start(vl, fmt);
>    F2(fmt, vl);
>    va_end(vl);
>}
>
>va_list Heap(int i, double d)
>{
>    //not working 
>    void* pv = malloc(sizeof(int) + sizeof(double));
>    va_list * p = (va_list *)pv;
>    //*(int*)p = i;
>    //p += _INTSIZEOF(i);
>    va_arg(p, int) = i; //walk next
>    
>    //*(double*)p = d;
>    //p += _INTSIZEOF(d);
>    va_arg(p, double) = d; //walk next
>
>    return pv;
>}
>
>int main()
>{
>    F("", 1, 2.0);
>    F2("", Heap(1, 2.0));
>    return 0;
>}


There's certainly no standard way to do anything like that.  Nor am I
aware of any way that's defined to be supported by MSVC.  That being
said, I suspect your definition of p should be just a va_list, not a
pointer to a va_list (it's already a pointer), at least to work with
the macros you posted earlier.  Again, this is almost certainly a bad
idea, there is *nothing* that suggests the above should work in any
given environment, other than some compiler internals which are really
privy to no one other than the MSVC developers.

[toc] | [prev] | [next] | [standalone]


#105920

FromThiago Adams <thiago.adams@gmail.com>
Date2017-03-13 10:29 -0700
Message-ID<80c60d8c-ba95-43fa-b7fa-ce45f1935a14@googlegroups.com>
In reply to#105784
On Saturday, March 11, 2017 at 2:12:34 AM UTC-3, robert...@yahoo.com wrote:
> On Fri, 10 Mar 2017 15:37:34 -0800 (PST), Thiago Adams
>  wrote:
> 
> >On Friday, March 10, 2017 at 8:13:50 PM UTC-3, robert...@yahoo.com wrote:
> >> On Fri, 10 Mar 2017 14:53:02 -0800 (PST), Thiago Adams
> >> wrote:
> >> 
> >> >On Friday, March 10, 2017 at 7:36:37 PM UTC-3, Thiago Adams wrote:
> >> >> On Friday, March 10, 2017 at 5:32:05 PM UTC-3, Keith Thompson wrote:
> >> >> > Thiago Adams writes:
> >> >> > > Is it possible to create a var args function without the 
> >> >> > > first argument? (firstArgument in va_start)
> >> >> > >
> >> >> > > void F(...)
> >> >> > 
> >> >> > No.  The va_start macro requires the name of the last non-variadic
> >> >> > parameter, and syntax of a parameter-type-list requires at least one
> >> >> > parameter-declaration (N1570 6.7.6).
> >> >> > 
> >> >> > [...]
> >> >> 
> >> >> 
> >> >> How it works?
> >> >> How does it knows the alignment/padding between the arguments?
> >> >> 
> >> >
> >> >I opened the definition of va_list etc from Visual C++ 2017 includes:
> >> >
> >> >typedef char* va_list;
> >> >
> >> >
> >> >#define _ADDRESSOF(v) (&(v))
> >> >
> >> >#define _INTSIZEOF(n)  ((sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1))
> >> >
> >> >#define __crt_va_start_a(ap, v) ((void)(ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v)))
> >> >
> >> >#define __crt_va_arg(ap, t) (*(t*)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)))
> >> >
> >> >
> >> >#define __crt_va_end(ap)        ((void)(ap = (va_list)0))
> >> >
> >> >The macro  _INTSIZEOF has some tricks I don't understand.
> >> 
> >> 
> >> None of what you found in the MSVC headers actually means anything to
> >> you.  *How* va_args is implemented is entirely implementation
> >> dependent, and the above may not even work on the next patch level of
> >> MSVC.  *Some* implementation *is* required, but the innards are secret
> >> magic.  That being said, I suspect a fair number of implementations
> >> are quite similar.
> >> 
> >> As for what _INTSIZEOF is doing, it's computing the alignment (on the
> >> stack), or effective size, of a parameter on the stack.  Basically it
> >> computes (ceil(sizeof(type)/sizeof(int))*sizeof(int)).  IOW, it rounds
> >> the size up to the next whole numbers of ints.  Which corresponds to
> >> how this implementation lays out parameters on the stack.  And again,
> >> that happens to work for this *one* implementation, at *this* moment.
> >
> >
> >I am trying to understand  to create va_list  on heap.
> >(not working at this moment)
> >
> >
> >
> >#include <stdarg.h> 
> >#include <stdlib.h>
> >#include <stdio.h>
> >
> >void F2(const char* fmt, va_list vl)
> >{
> >    int i = va_arg(vl, int);
> >    double d = va_arg(vl, double);
> >    printf("i = %d, d = %lf\n", i, d);
> >}
> >
> >void F(const char* fmt, ...)
> >{
> >    va_list vl;
> >    va_start(vl, fmt);
> >    F2(fmt, vl);
> >    va_end(vl);
> >}
> >
> >va_list Heap(int i, double d)
> >{
> >    //not working 
> >    void* pv = malloc(sizeof(int) + sizeof(double));
> >    va_list * p = (va_list *)pv;
> >    //*(int*)p = i;
> >    //p += _INTSIZEOF(i);
> >    va_arg(p, int) = i; //walk next
> >    
> >    //*(double*)p = d;
> >    //p += _INTSIZEOF(d);
> >    va_arg(p, double) = d; //walk next
> >
> >    return pv;
> >}
> >
> >int main()
> >{
> >    F("", 1, 2.0);
> >    F2("", Heap(1, 2.0));
> >    return 0;
> >}
> 
> 
> There's certainly no standard way to do anything like that.  Nor am I
> aware of any way that's defined to be supported by MSVC.  That being
> said, I suspect your definition of p should be just a va_list, not a
> pointer to a va_list (it's already a pointer), at least to work with
> the macros you posted earlier.  Again, this is almost certainly a bad
> idea, there is *nothing* that suggests the above should work in any
> given environment, other than some compiler internals which are really
> privy to no one other than the MSVC developers.



Thanks Robert, the problem was the pointer. (At the end is the code)

I am not going to use this, so I am not worried about the 
different implementations of va_list.

The idea was just to show the concept that could be implemented
in the C language with compiler support.

The usage is for variable captures of lambdas.

I think I need compiler support for 3 functions.

1) _sizeof_va_list(...)
   
 Returns the sizeof required for the va_list

Sample:

 int i; 
 double d;
 static_assert(_sizeof_va_list(i, d) == 12, "");

2_) va_list_init(void* p, ...)

    Init the memory pointed by p with the arguments, creating 
    the va_list.
    p must be have at least _sizeof_va_list bytes.

Sample:

    int i; 
    double d;   
    void* p = malloc(_sizeof_va_list(i, d));
    if (p) 
    {
       va_list_init(p, i, d);
    }
    free(p);



3) va_list_malloc(...)

   Same as:
   int i;
   double d;
   va_list_init(malloc(_sizeof_va_list(i, d)), i, d);


==

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>

void F2(const char* fmt, va_list vl)
{
  int i = va_arg(vl, int);
  double d = va_arg(vl, double);
  printf("i = %d, d = %lf\n", i, d);
}

void F(const char* fmt, ...)
{
  va_list vl;
  va_start(vl, fmt);
  F2(fmt, vl);
  va_end(vl);
}

void va_list_free(va_list args)
{
  free(args);
}


va_list va_list_create(void* pmem, int i, double d)
{
  va_list p = (va_list)pmem;
  va_arg(p, int) = i;
  va_arg(p, double) = d;
  return (va_list)pmem;
}

va_list va_list_malloc(int i, double d)
{
  void* pv = malloc(sizeof(int) + sizeof(double));
  return va_list_create(pv, i, d);  
}

int main()
{
  F("", 1, 2.0);
  va_list args = va_list_malloc(1, 2.0);
  F2("", args);
  va_list_free(args);
  return 0;
}


[toc] | [prev] | [next] | [standalone]


#105926

FromThiago Adams <thiago.adams@gmail.com>
Date2017-03-13 11:31 -0700
Message-ID<338862bf-1ebf-41f0-ac0a-1d9f0fe53b3d@googlegroups.com>
In reply to#105920
On Monday, March 13, 2017 at 2:30:07 PM UTC-3, Thiago Adams wrote:
[...]
> > >> >I opened the definition of va_list etc from Visual C++ 2017 includes:
> > >> >
> > >> >typedef char* va_list;
> > >> >
> > >> >
> > >> >#define _ADDRESSOF(v) (&(v))
> > >> >
> > >> >#define _INTSIZEOF(n)  ((sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1))
> > >> >
> > >> >#define __crt_va_start_a(ap, v) ((void)(ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v)))
> > >> >
> > >> >#define __crt_va_arg(ap, t) (*(t*)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)))
> > >> >
> > >> >
> > >> >#define __crt_va_end(ap)        ((void)(ap = (va_list)0))
> > >> >
> > >> >The macro  _INTSIZEOF has some tricks I don't understand.



If someone is interested.. For x64 


#elif defined _M_X64

    void __cdecl __va_start(va_list* , ...);

    #define __crt_va_start_a(ap, x) ((void)(__va_start(&ap, x)))
    #define __crt_va_arg(ap, t)                                               \
        ((sizeof(t) > sizeof(__int64) || (sizeof(t) & (sizeof(t) - 1)) != 0) \
            ? **(t**)((ap += sizeof(__int64)) - sizeof(__int64))             \
            :  *(t* )((ap += sizeof(__int64)) - sizeof(__int64)))
    #define __crt_va_end(ap)        ((void)(ap = (va_list)0))

#endif

__va_start is not macro.

[toc] | [prev] | [next] | [standalone]


#105929

Fromscott@slp53.sl.home (Scott Lurndal)
Date2017-03-13 18:40 +0000
Message-ID<CIBxA.61777$Bp6.32071@fx36.iad>
In reply to#105926
Thiago Adams <thiago.adams@gmail.com> writes:
>On Monday, March 13, 2017 at 2:30:07 PM UTC-3, Thiago Adams wrote:
>[...]
>> > >> >I opened the definition of va_list etc from Visual C++ 2017 includes:
>> > >> >
>> > >> >typedef char* va_list;
>> > >> >
>> > >> >
>> > >> >#define _ADDRESSOF(v) (&(v))
>> > >> >
>> > >> >#define _INTSIZEOF(n)  ((sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1))
>> > >> >
>> > >> >#define __crt_va_start_a(ap, v) ((void)(ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v)))
>> > >> >
>> > >> >#define __crt_va_arg(ap, t) (*(t*)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)))
>> > >> >
>> > >> >
>> > >> >#define __crt_va_end(ap)        ((void)(ap = (va_list)0))
>> > >> >
>> > >> >The macro  _INTSIZEOF has some tricks I don't understand.
>
>
>
>If someone is interested.. For x64 
>
>
>#elif defined _M_X64
>
>    void __cdecl __va_start(va_list* , ...);
>
>    #define __crt_va_start_a(ap, x) ((void)(__va_start(&ap, x)))
>    #define __crt_va_arg(ap, t)                                               \
>        ((sizeof(t) > sizeof(__int64) || (sizeof(t) & (sizeof(t) - 1)) != 0) \
>            ? **(t**)((ap += sizeof(__int64)) - sizeof(__int64))             \
>            :  *(t* )((ap += sizeof(__int64)) - sizeof(__int64)))
>    #define __crt_va_end(ap)        ((void)(ap = (va_list)0))
>
>#endif
>
>__va_start is not macro.
>
>

You find varargs documented in the processor-specific ABI.  For example,
see: http://refspecs.linuxfoundation.org/elf/x86_64-abi-0.98.pdf (section 3.5.7).

The va_list Type
  The va_list type is an array containing a single element of one structure con-
  taining the necessary information to implement the va_arg macro. The C defi-
  nition of va_list type is given in figure 3.34.
                    
          Figure 3.34: va_list Type Declaration
                     typedef struct {
                          unsigned int gp_offset;
                          unsigned int fp_offset;
                          void *overflow_arg_area;
                          void *reg_save_area;
                     } va_list[1];

...

[toc] | [prev] | [next] | [standalone]


#105935

FromThiago Adams <thiago.adams@gmail.com>
Date2017-03-13 12:31 -0700
Message-ID<2ec6e145-0ae4-4e92-8a3b-cfefdc93cbdb@googlegroups.com>
In reply to#105929
On Monday, March 13, 2017 at 3:40:41 PM UTC-3, Scott Lurndal wrote:
> Thiago Adams  writes:
> >On Monday, March 13, 2017 at 2:30:07 PM UTC-3, Thiago Adams wrote:
> >[...]
> >> > >> >I opened the definition of va_list etc from Visual C++ 2017 includes:
> >> > >> >
> >> > >> >typedef char* va_list;
> >> > >> >
> >> > >> >
> >> > >> >#define _ADDRESSOF(v) (&(v))
> >> > >> >
> >> > >> >#define _INTSIZEOF(n)  ((sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1))
> >> > >> >
> >> > >> >#define __crt_va_start_a(ap, v) ((void)(ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v)))
> >> > >> >
> >> > >> >#define __crt_va_arg(ap, t) (*(t*)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)))
> >> > >> >
> >> > >> >
> >> > >> >#define __crt_va_end(ap)        ((void)(ap = (va_list)0))
> >> > >> >
> >> > >> >The macro  _INTSIZEOF has some tricks I don't understand.
> >
> >
> >
> >If someone is interested.. For x64 
> >
> >
> >#elif defined _M_X64
> >
> >    void __cdecl __va_start(va_list* , ...);
> >
> >    #define __crt_va_start_a(ap, x) ((void)(__va_start(&ap, x)))
> >    #define __crt_va_arg(ap, t)                                               \
> >        ((sizeof(t) > sizeof(__int64) || (sizeof(t) & (sizeof(t) - 1)) != 0) \
> >            ? **(t**)((ap += sizeof(__int64)) - sizeof(__int64))             \
> >            :  *(t* )((ap += sizeof(__int64)) - sizeof(__int64)))
> >    #define __crt_va_end(ap)        ((void)(ap = (va_list)0))
> >
> >#endif
> >
> >__va_start is not macro.
> >
> >
> 
> You find varargs documented in the processor-specific ABI.  For example,
> see: http://refspecs.linuxfoundation.org/elf/x86_64-abi-0.98.pdf (section 3.5.7).
> 
> The va_list Type
>   The va_list type is an array containing a single element of one structure con-
>   taining the necessary information to implement the va_arg macro. The C defi-
>   nition of va_list type is given in figure 3.34.
>                     
>           Figure 3.34: va_list Type Declaration
>                      typedef struct {
>                           unsigned int gp_offset;
>                           unsigned int fp_offset;
>                           void *overflow_arg_area;
>                           void *reg_save_area;
>                      } va_list[1];
> 
> ...

Thanks for the link.
I was trying to use the va_list memory layout just to 
use one exiting concept.
The same function created for it could be used in other context.
No need to learn more concepts.

But, if the price for this is too high, I could use another 
memory layout.
For instance, put everything in char*.

Is char* too bad?

void *p = malloc(sizeof(int) + sizeof(double));
*((*int)p) = 1;
p += sizeof(int);

*((*double)p) = 2.0;
p += sizeof(double);


If not I can just create a new version of macros va_arg, va_start.

[toc] | [prev] | [next] | [standalone]


#105809

Fromjacobnavia <jacob@jacob.remcomp.fr>
Date2017-03-11 19:53 +0100
Message-ID<oa1gud$79a$1@dont-email.me>
In reply to#105776
Le 11/03/2017 à 00:37, Thiago Adams a écrit :
> On Friday, March 10, 2017 at 8:13:50 PM UTC-3, robert...@yahoo.com wrote:
>> On Fri, 10 Mar 2017 14:53:02 -0800 (PST), Thiago Adams
>> wrote:
>>
>>> On Friday, March 10, 2017 at 7:36:37 PM UTC-3, Thiago Adams wrote:
>>>> On Friday, March 10, 2017 at 5:32:05 PM UTC-3, Keith Thompson wrote:
>>>>> Thiago Adams writes:
>>>>>> Is it possible to create a var args function without the
>>>>>> first argument? (firstArgument in va_start)
>>>>>>
>>>>>> void F(...)
>>>>> No.  The va_start macro requires the name of the last non-variadic
>>>>> parameter, and syntax of a parameter-type-list requires at least one
>>>>> parameter-declaration (N1570 6.7.6).
>>>>>
>>>>> [...]
>>>>
>>>> How it works?
>>>> How does it knows the alignment/padding between the arguments?
>>>>
>>> I opened the definition of va_list etc from Visual C++ 2017 includes:
>>>
>>> typedef char* va_list;
>>>
>>>
>>> #define _ADDRESSOF(v) (&(v))
>>>
>>> #define _INTSIZEOF(n)  ((sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1))
>>>
>>> #define __crt_va_start_a(ap, v) ((void)(ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v)))
>>>
>>> #define __crt_va_arg(ap, t) (*(t*)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)))
>>>
>>>
>>> #define __crt_va_end(ap)        ((void)(ap = (va_list)0))
>>>
>>> The macro  _INTSIZEOF has some tricks I don't understand.
>>

Hi Thiago.

Look, conceptually this is very simple. You have:

1) A heap of arguments passed in the stack or in registers. 32 bit 
software passes everything in memory, i.e. in the stack. The x86 had too 
few registers in that time to have a meaningful register passing 
convention.

That meant that everything was just a linear array of bytes with a 
cursor pointing to the position AFTER the va_start. You read one 
argument, then increment the pointer by sizeof argument and go on like that.

That was easy and you have the definitions above in that MSVC file.

Everything changed with 64 bits and Intel coming back to it senses and 
putting more registers in the machine.

GREAT!

After all those years intel put a bit more power in that machine.

So microsoft deviced a simple thing with 4 registers that are passed in 
the integer regs. At most 4 args can be passed in total, if I remember 
correctly.

Gcc followed the much more complicated but more efficient route of 
making 3 different heaps of arguments:

1) Arguments passed in integer registers.
2) Arguments passed in floating point registers.
3) Arguments passed in RAM (stack).

Pointers and integers up to register size go into (1). All floating 
point goes into heap (2) (the xmm registers) and in (3) we find all 
arguments that come after any of the first two is exhausted.

Or such...

as another guy told us several times. :-)

Getting the next argument depends on the state of the cursor (which 
argument are you reading) and in the type of the arguments being passed 
(its size).

This is called the ABI (application binary interface) of the os you are 
running.

The compiler that compiles the OS establishes the ABI. Linux has an ABI 
written by gcc (that compiles linux) and windows has another ABI written 
by the guys of MSVC that compiles windows.



[toc] | [prev] | [next] | [standalone]


#105811

FromBartC <bc@freeuk.com>
Date2017-03-11 19:05 +0000
Message-ID<oa1hko$e7n$1@dont-email.me>
In reply to#105809
On 11/03/2017 18:53, jacobnavia wrote:
> Le 11/03/2017 à 00:37, Thiago Adams a écrit :

> Everything changed with 64 bits and Intel coming back to it senses and
> putting more registers in the machine.
>
> GREAT!

(Actually I'm coding stuff today, and the register-based passing makes 
things harder not easier!)


> So microsoft deviced a simple thing with 4 registers that are passed in
> the integer regs. At most 4 args can be passed in total, if I remember
> correctly.
>
> Gcc followed the much more complicated but more efficient route of
> making 3 different heaps of arguments:
>
> 1) Arguments passed in integer registers.
> 2) Arguments passed in floating point registers.
> 3) Arguments passed in RAM (stack).
>
> Pointers and integers up to register size go into (1). All floating
> point goes into heap

The heap?

  (2) (the xmm registers) and in (3) we find all
> arguments that come after any of the first two is exhausted.
>
> Or such...

I don't think it's specific to gcc, this is the Win64 ABI. And there's a 
further thing with floating arguments to variadic functions: they have 
to be passed in both floating point /and/ integer registers, just for 
good measure.

-- 
bartc

[toc] | [prev] | [next] | [standalone]


#105813

FromKeith Thompson <kst-u@mib.org>
Date2017-03-11 11:56 -0800
Message-ID<lnr323fuyu.fsf@kst-u.example.com>
In reply to#105811
BartC <bc@freeuk.com> writes:
> On 11/03/2017 18:53, jacobnavia wrote:
[...]
>> Gcc followed the much more complicated but more efficient route of
>> making 3 different heaps of arguments:
>>
>> 1) Arguments passed in integer registers.
>> 2) Arguments passed in floating point registers.
>> 3) Arguments passed in RAM (stack).
>>
>> Pointers and integers up to register size go into (1). All floating
>> point goes into heap
>
> The heap?

No.

>   (2) (the xmm registers) and in (3) we find all
>> arguments that come after any of the first two is exhausted.

jacob isn't using the word "heap" in its technical sense.  I think
"group" would have been clearer.  What he said was that "All floating
point goes into heap (2)", i.e., the group of arguments that are
passed in FP registers.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#105847

Fromantispam@math.uni.wroc.pl
Date2017-03-12 05:41 +0000
Message-ID<oa2n1r$eo8$2@z-news.wcss.wroc.pl>
In reply to#105809
jacobnavia <jacob@jacob.remcomp.fr> wrote:
> 
> Everything changed with 64 bits and Intel coming back to it senses and 
> putting more registers in the machine.

Actually, that was AMD

>
> So microsoft deviced a simple thing with 4 registers that are passed in 
> the integer regs. At most 4 args can be passed in total, if I remember 
> correctly.
> 
> Gcc followed

AFAIK gcc convention was published first.

-- 
                              Waldek Hebisch

[toc] | [prev] | [next] | [standalone]


#105855

FromDavid Brown <david.brown@hesbynett.no>
Date2017-03-12 13:52 +0100
Message-ID<oa3g4n$egd$1@dont-email.me>
In reply to#105809
On 11/03/17 19:53, jacobnavia wrote:
> Le 11/03/2017 à 00:37, Thiago Adams a écrit :
>> On Friday, March 10, 2017 at 8:13:50 PM UTC-3, robert...@yahoo.com wrote:
>>> On Fri, 10 Mar 2017 14:53:02 -0800 (PST), Thiago Adams
>>> wrote:
>>>
>>>> On Friday, March 10, 2017 at 7:36:37 PM UTC-3, Thiago Adams wrote:
>>>>> On Friday, March 10, 2017 at 5:32:05 PM UTC-3, Keith Thompson wrote:
>>>>>> Thiago Adams writes:
>>>>>>> Is it possible to create a var args function without the
>>>>>>> first argument? (firstArgument in va_start)
>>>>>>>
>>>>>>> void F(...)
>>>>>> No.  The va_start macro requires the name of the last non-variadic
>>>>>> parameter, and syntax of a parameter-type-list requires at least one
>>>>>> parameter-declaration (N1570 6.7.6).
>>>>>>
>>>>>> [...]
>>>>>
>>>>> How it works?
>>>>> How does it knows the alignment/padding between the arguments?
>>>>>
>>>> I opened the definition of va_list etc from Visual C++ 2017 includes:
>>>>
>>>> typedef char* va_list;
>>>>
>>>>
>>>> #define _ADDRESSOF(v) (&(v))
>>>>
>>>> #define _INTSIZEOF(n)  ((sizeof(n) + sizeof(int) - 1) &
>>>> ~(sizeof(int) - 1))
>>>>
>>>> #define __crt_va_start_a(ap, v) ((void)(ap = (va_list)_ADDRESSOF(v)
>>>> + _INTSIZEOF(v)))
>>>>
>>>> #define __crt_va_arg(ap, t) (*(t*)((ap += _INTSIZEOF(t)) -
>>>> _INTSIZEOF(t)))
>>>>
>>>>
>>>> #define __crt_va_end(ap)        ((void)(ap = (va_list)0))
>>>>
>>>> The macro  _INTSIZEOF has some tricks I don't understand.
>>>
>
> Hi Thiago.
>
> Look, conceptually this is very simple. You have:
>
> 1) A heap of arguments passed in the stack or in registers. 32 bit
> software passes everything in memory, i.e. in the stack. The x86 had too
> few registers in that time to have a meaningful register passing
> convention.

<https://en.wikipedia.org/wiki/X86_calling_conventions>

The most common calling convention in 32-bit x86 is to pass arguments on 
the stack - but there are a dozen different variations in use, some of 
which use registers for a few of the arguments.  Most importantly, the 
calling convention used by the Win32 API is different.


>
> That meant that everything was just a linear array of bytes with a
> cursor pointing to the position AFTER the va_start. You read one
> argument, then increment the pointer by sizeof argument and go on like
> that.
>
> That was easy and you have the definitions above in that MSVC file.
>

Yes - for arguments passed on the stack, va_args is easy.

> Everything changed with 64 bits and Intel coming back to it senses and
> putting more registers in the machine.
>
> GREAT!
>
> After all those years intel put a bit more power in that machine.

You mean AMD?  Intel had refused for years to consider a 64-bit x86 cpu, 
until AMD made the design and Intel had to copy it.

>
> So microsoft deviced a simple thing with 4 registers that are passed in
> the integer regs. At most 4 args can be passed in total, if I remember
> correctly.

MS's x86 calling convention puts the first 4 integer or pointer 
arguments into registers RCX, RDX, R8 and R9, and the first 4 floating 
point arguments into XMM0..XMM3.  Additional arguments go on the stack.

Their calling convention requires space to be left on the stack as 
though the first four arguments were placed there rather than in 
registers.  This makes va_arg functions easy - the function can first 
copy RCX..R9 to this stack space, and then the arguments are all linear 
just like on the most common x86 convention.

It has the side-effect of making every non-vaargs function call 
noticeably slower on 64-bit Windows, and pointlessly wastes precious 
cache space.  But who cares about other functions, as long as printf and 
friends are a few nano seconds faster and the compiler support for va 
args is easier to write?

>
> Gcc followed the much more complicated but more efficient route of
> making 3 different heaps of arguments:

Do you mean /AMD/ picked a different approach when /they/ designed an 
efficient calling convention for the ISA that /they/ were designing? 
AMD discussed calling conventions at length, with their cpu design team, 
OS developers (including Linux, BSD, Solaris, Apple, and MS) and 
compiler developers (including gcc, clang, Sun, Apple, and MS).  They 
came up with a solution aimed at being as efficient as possible for most 
code, at the cost of being more complicated for va args functions which 
are rarely used except for printf and friends.

The System V AMD64 ABI is followed by every x86-64 OS except Windows.

As far as I know, x86-64 compilers all use the ABI for the target OS, 
rather than the idiotic chaos of the x86-32 Windows world with every 
compiler having a different selection of calling conventions and 
different pragmas, keywords and other extensions to choose between them. 
  So gcc on Windows uses the Windows calling conventions for 64-bit x86.

>
> 1) Arguments passed in integer registers.
> 2) Arguments passed in floating point registers.
> 3) Arguments passed in RAM (stack).

Windows does that too - but the System V AMD64 ABI makes better use of 
the registers and does not waste extra stack space.

>
> Pointers and integers up to register size go into (1). All floating
> point goes into heap (2) (the xmm registers) and in (3) we find all
> arguments that come after any of the first two is exhausted.
>

When you say "heap", you really mean "stack".

> Or such...

The details are clearly specified, at least for the System V AMD64 ABI - 
just download the ABI document when you want to see it.  I assume the 
Windows version is equally easy to obtain.

>
> as another guy told us several times. :-)
>
> Getting the next argument depends on the state of the cursor (which
> argument are you reading) and in the type of the arguments being passed
> (its size).
>
> This is called the ABI (application binary interface) of the os you are
> running.
>
> The compiler that compiles the OS establishes the ABI. Linux has an ABI
> written by gcc (that compiles linux) and windows has another ABI written
> by the guys of MSVC that compiles windows.
>

The ABI is usually an agreement between OS designers and compiler 
designers, sometimes with input from the chip designers (especially for 
new cpu designs).  It is rarely determined by the compiler alone, except 
in cases of a new OS using an existing compiler.

[toc] | [prev] | [next] | [standalone]


#105865

FromBartC <bc@freeuk.com>
Date2017-03-12 14:40 +0000
Message-ID<oa3mfq$3m6$1@dont-email.me>
In reply to#105855
On 12/03/2017 12:52, David Brown wrote:

> The ABI is usually an agreement between OS designers and compiler
> designers, sometimes with input from the chip designers (especially for
> new cpu designs).  It is rarely determined by the compiler alone, except
> in cases of a new OS using an existing compiler.

A compiler can do its own thing, and only take note of the official ABI 
when calling external functions (or for callbacks etc).

I've done this and was hoping to use the same approach for compiling C 
(for x64). But it won't work because there is now no distinction between 
C functions which are compiled here, and C functions compiled elsewhere 
by another compiler.

If it was just direct calls, it might still work, but when calling via a 
function pointer, you can't tell how or where the target function was 
compiled. So it has to use the official ABI (either that or create a 
special function pointer that contains extra info, but doing the former 
would be simpler).

(Not that this ABI makes things that much faster, if at all. If I take 
my current project and compile with gcc -O0, then the 32-bit version is 
8% faster than the 64-bit, despite the latter passing parameters in 
registers for most functions.)

-- 
bartc

[toc] | [prev] | [next] | [standalone]


#105872

FromDavid Brown <david.brown@hesbynett.no>
Date2017-03-12 18:13 +0100
Message-ID<oa3vea$39f$1@dont-email.me>
In reply to#105865
On 12/03/17 15:40, BartC wrote:
> On 12/03/2017 12:52, David Brown wrote:
>
>> The ABI is usually an agreement between OS designers and compiler
>> designers, sometimes with input from the chip designers (especially for
>> new cpu designs).  It is rarely determined by the compiler alone, except
>> in cases of a new OS using an existing compiler.
>
> A compiler can do its own thing, and only take note of the official ABI
> when calling external functions (or for callbacks etc).

Of course.  And for internal function calls (compiler library functions, 
static functions, and via more sophisticated link-time optimisation) 
compilers can and do make use of more efficient calling conventions 
tailored to each call.

>
> I've done this and was hoping to use the same approach for compiling C
> (for x64). But it won't work because there is now no distinction between
> C functions which are compiled here, and C functions compiled elsewhere
> by another compiler.

Sure there is - if your compiler is the one compiling a function, and 
you know that all uses of the function are through code that you 
compile, then you can do what you want.  This is usually the case for 
static functions (unless you take their address and pass it outside the 
current translation unit).

>
> If it was just direct calls, it might still work, but when calling via a
> function pointer, you can't tell how or where the target function was
> compiled. So it has to use the official ABI (either that or create a
> special function pointer that contains extra info, but doing the former
> would be simpler).
>
> (Not that this ABI makes things that much faster, if at all. If I take
> my current project and compile with gcc -O0, then the 32-bit version is
> 8% faster than the 64-bit, despite the latter passing parameters in
> registers for most functions.)
>

Speed comparisons without optimisation are /always/ pointless.

And there are a variety of things that can affect the difference in 
speed between 32-bit and 64-bit versions (even when you have allowed the 
compiler to generate decent code by using at least -O1).  Pointers in 
64-bit mode are 64-bit wide - that means more cache is needed, meaning 
more cache misses, and more memory bandwidth is needed.  For some 
applications, the difference here can be significant.  And in Windows, 
the aforementioned idiotic requirement of allocating stack space for the 
arguments passed in registers means wasted time and wasted cache space 
on every function call in 64-bit mode.

[toc] | [prev] | [next] | [standalone]


Page 1 of 6  [1] 2 3 4 5 6  Next page →

Back to top | Article view | comp.lang.c


csiph-web