Path: ...!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail From: bart Newsgroups: comp.lang.c Subject: =?UTF-8?Q?Re=3A_technology_discussion_=E2=86=92_does_the_world_need?= =?UTF-8?B?IGEgIm5ldyIgQyA/?= Date: Tue, 9 Jul 2024 15:54:06 +0100 Organization: A noiseless patient Spider Lines: 60 Message-ID: References: <871q48w98e.fsf@nosuchdomain.example.com> <87wmlzvfqp.fsf@nosuchdomain.example.com> <87h6d2uox5.fsf@nosuchdomain.example.com> <20240707164747.258@kylheku.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit Injection-Date: Tue, 09 Jul 2024 16:54:06 +0200 (CEST) Injection-Info: dont-email.me; posting-host="7c22da865deaeb7152beebd5e4e580c3"; logging-data="1503851"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX19xymNqcKwnXh/5K+7wTjXU" User-Agent: Mozilla Thunderbird Cancel-Lock: sha1:r85Ubx0HUaRss/QLWf5WZvscB+E= Content-Language: en-GB In-Reply-To: Bytes: 3547 On 09/07/2024 15:31, David Brown wrote: > On 08/07/2024 19:39, BGB wrote: >> Though, this one seems to be a common point of divergence between >> "SysV" and "Microsoft" ABIs. Sometimes a target will have an ABI >> defined, and the MS version was almost the same, just typically >> differing in that it passes structs by reference and provides a spill >> space for register arguments. >> > > I don't think it is helpful that you keep mixing /logical/ terms with > /implementation/ terms. > > In C, there is no "pass by reference" or "return by reference".  It is > all done by value. Arrays are passed by reference: void F(int a[20]) {} int main(void) { int x[20]; F(x); } Although the type of 'a' inside 'F' will be int* rather than int(*)[20]. > So if you have these structs and declarations : > > struct small { uint16_t a; uint16_t b; }; > struct big { uint32_t xs[10]; }; > > struct small foos(struct small y); > struct big foob(struct big y); > > Then compilers will typically implement "x = foos(y)" as though it were: > >     extern uint32_t foos(uint32_t ab); >     uint32_t _1 = foos(y.a << 16) | (y.b); >     struct small x = { _1 >> 16, _1 & 0xffff }; > > And they will typically implement "x = foosb(y)" as though it were: > >     extern void foob(struct big * ret, const struct big * xs); >     struct big x; >     foob(&x, &y); From what I've seen, structs that are not small enough to be passed in registers, are copied to a temporary, and the address of that temporary is passed. This seems to be the case even when the struct param is marked 'const'. (My compiler won't create a copy when the parameter is 'const'. I assumed that was how gcc did it; I was wrong.) This is for Win64 ABI, however an ABI will only say they are passed by reference; it will not stipulate making a copy. That is up to the language implementation.