Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #105743 > unrolled thread
| Started by | Thiago Adams <thiago.adams@gmail.com> |
|---|---|
| First post | 2017-03-10 11:57 -0800 |
| Last post | 2017-03-15 13:39 -0700 |
| Articles | 20 on this page of 107 — 23 participants |
Back to article view | Back to comp.lang.c
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 →
| From | Thiago Adams <thiago.adams@gmail.com> |
|---|---|
| Date | 2017-03-10 11:57 -0800 |
| Subject | va_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]
| From | Thiago Adams <thiago.adams@gmail.com> |
|---|---|
| Date | 2017-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]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2017-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]
| From | "Rick C. Hodgin" <rick.c.hodgin@gmail.com> |
|---|---|
| Date | 2017-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]
| From | Thiago Adams <thiago.adams@gmail.com> |
|---|---|
| Date | 2017-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]
| From | Thiago Adams <thiago.adams@gmail.com> |
|---|---|
| Date | 2017-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]
| From | Robert Wessel <robertwessel2@yahoo.com> |
|---|---|
| Date | 2017-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]
| From | Thiago Adams <thiago.adams@gmail.com> |
|---|---|
| Date | 2017-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]
| From | Robert Wessel <robertwessel2@yahoo.com> |
|---|---|
| Date | 2017-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]
| From | Thiago Adams <thiago.adams@gmail.com> |
|---|---|
| Date | 2017-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]
| From | Thiago Adams <thiago.adams@gmail.com> |
|---|---|
| Date | 2017-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]
| From | scott@slp53.sl.home (Scott Lurndal) |
|---|---|
| Date | 2017-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]
| From | Thiago Adams <thiago.adams@gmail.com> |
|---|---|
| Date | 2017-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]
| From | jacobnavia <jacob@jacob.remcomp.fr> |
|---|---|
| Date | 2017-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]
| From | BartC <bc@freeuk.com> |
|---|---|
| Date | 2017-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]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2017-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]
| From | antispam@math.uni.wroc.pl |
|---|---|
| Date | 2017-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]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2017-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]
| From | BartC <bc@freeuk.com> |
|---|---|
| Date | 2017-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]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2017-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