Author Topic: [C] Ow, pointers are making my brain hurt...  (Read 6459 times)

0 Members and 1 Guest are viewing this topic.

Offline Nominal Animal

  • Super Contributor
  • ***
  • Posts: 6262
  • Country: fi
    • My home page and email address
Re: [C] Ow, pointers are making my brain hurt...
« Reply #50 on: November 14, 2021, 08:04:55 pm »
Having to adapt your code style to the underlying ABI is not a fantastic idea IMHO.
No, but it is something that is inherent in non-portable code.  Those who know the ABI will be affected by it, and such approaches spread, like fads.  Anyone doing microbenchmarks verifies "they are better", so an approach gets adopted.  This happens.

It is actually the opposite that I'm interested in: what are the patterns one should avoid in portable code.

(I've mentioned before that whenever I look at e.g. the code generated by my compilers, I'm not really interested whether it is optimal or not, because that way lies madness.  What I am interested in, is whether a compiler or a set of options causes it to generate horrible code.  I prefer an approach that is not optimal, but not horrible anywhere, over approaches that are optimal somewhere but horrible somewhere else, because chasing optimality is a fool's errand, but avoiding horrible behaviour is a sensible precaution.  In my experience and opinion, that is.)

In the olden era of Fortran and compiler-specific ABIs, when parameters were passed on the stack, using global variables instead of passing them as parameters was a way to speed up critical code.  Now, the opposite is true, but old habits die hard, especially since They Are Written In Reliable Books I Trust, So Why Should I Trust Some Pseudonymous Person Saying Otherwise?
« Last Edit: November 14, 2021, 08:09:03 pm by Nominal Animal »
 
The following users thanked this post: cfbsoftware

Offline brucehoult

  • Super Contributor
  • ***
  • Posts: 4036
  • Country: nz
Re: [C] Ow, pointers are making my brain hurt...
« Reply #51 on: November 14, 2021, 08:21:10 pm »
as reference, three different approaches
  • 6800 (only one CPU-register, therefore the ram is massively used)

Two accumulators and one index register.

The concept of ABI hadn't really formed in 6800 / 6502 / 8080 / z80 days and very little code was written using compiled languages. Assembly language programmers felt free to make up whatever calling convention they wanted on a function by function basis, but they definitely used registers as much as they could, certainly for the most low-level functions.

Quote
  • 68k (eight registers for data, eight registers for address, compromise between stack and registers)

The 68000 and x86 calling conventions I remember passed all arguments on the stack, and only return value in a register. Same with PDP-11 and VAX.

If ARM with 16 registers (kind of 8 + 8 for Thumb, though in a different way to 68k) can manage to pass 4 arguments in registers, and x86_64 with 16 registers can manage to pass 4 (Windows) or 6 (everything else) arguments in registers when 68k and VAX should have been able to also. But somehow no one thought of that in the late 1970s.

68k could easily have used, for example, up to three data registers and three address registers for function arguments.
[/list]
 

Online SiliconWizard

  • Super Contributor
  • ***
  • Posts: 14475
  • Country: fr
Re: [C] Ow, pointers are making my brain hurt...
« Reply #52 on: November 14, 2021, 08:32:07 pm »
The 68000 and x86 calling conventions I remember passed all arguments on the stack, and only return value in a register. Same with PDP-11 and VAX.

Well seeing how the x86_64 ABI is different for Windows and SysV, I was precisely wondering if it wasn't just for legacy reasons on Windows, coming from the x86 era?
 

Offline DiTBho

  • Super Contributor
  • ***
  • Posts: 3915
  • Country: gb
Re: [C] Ow, pointers are making my brain hurt...
« Reply #53 on: November 14, 2021, 08:51:41 pm »
Two accumulators and one index register.

I do often program with 68HC11 in assembly. When I use the Avocet C compiler I see that "push" and "pop" uses don't use A(8bit), B(8bit) and A+B=D (16bit) in the same way to pass arguments to a function and, and practically you don't have all the instructions able to use nor B neither IX/IY; the ISA is not orthogonal and the register A is the most supported and used.

Practically in my assembly sources I only use reg A for that. It makes things neat.
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Offline DiTBho

  • Super Contributor
  • ***
  • Posts: 3915
  • Country: gb
Re: [C] Ow, pointers are making my brain hurt...
« Reply #54 on: November 14, 2021, 09:08:56 pm »
The 68000 and x86 calling conventions I remember passed all arguments on the stack, and only return value in a register. Same with PDP-11 and VAX.

My Avocet and Sierra C compilers have two working models
  • if the number of arguments and the number of values returned are less than or equal to 2 (two registers, 32bit each), then the machine layer uses four registers
  • otherwise it passes everything on the stack

My IDT-C for MIPS64 C compiler has similar working models
  • if the number of arguments and the number of values returned are less than or equal to 4 (four registers, 64bit each), then the machine layer uses two registers
  • otherwise it passes everything on the stack
The returned values can be structured.

I find it very nice!
« Last Edit: November 15, 2021, 06:52:08 am by DiTBho »
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Offline DiTBho

  • Super Contributor
  • ***
  • Posts: 3915
  • Country: gb
Re: [C] Ow, pointers are making my brain hurt...
« Reply #55 on: November 14, 2021, 09:11:55 pm »
(this only works for leaf-functions that doesn't need any next calling.
Otherwise they have to save and restore things on the stack before and after the function call.)
« Last Edit: November 14, 2021, 09:46:05 pm by DiTBho »
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 
The following users thanked this post: cfbsoftware

Offline NorthGuy

  • Super Contributor
  • ***
  • Posts: 3146
  • Country: ca
Re: [C] Ow, pointers are making my brain hurt...
« Reply #56 on: November 14, 2021, 09:23:34 pm »
Windows x64 passes up to four 64-bit aggregate arguments in standard registers, and up to four floating-point xmm vectors in xmm registers.

It is more "or" than "and". It passes up to 4 parameters (whether integer or floating-point) in registers. Moreover, the caller must reserve 32 bytes of stack space, which is intended as a place where the callee can save the parameters if needed. Such dedicated space might be useful if the callee wants to produce a pointer to the parameter and pass it somewhere.

Or you can use this space for temporaries, same as you would use the space below the stack pointer on Linux.

Well seeing how the x86_64 ABI is different for Windows and SysV, I was precisely wondering if it wasn't just for legacy reasons on Windows, coming from the x86 era?

No. Nothing in common. There wasn't much of ABI on x86. It was mostly stack based. And there was no single standard. There were C calling conventions, Pascal calling conventions, but also Fast calling conventions which used register - but it was only 7 accessible registers anyway. This was especially weird for C which used C calling conventions for internal functions and Pascal calling conventions to call Windows API. And when calling a DLL you would have to know which calling conventions it uses. At least x64 doesn't have that.

Using registers surely makes things much faster, but not always. Variadic functions become a nightmare, while they were very efficient with the stack.
 

Offline cfbsoftware

  • Regular Contributor
  • *
  • Posts: 117
  • Country: au
    • Astrobe: Oberon IDE for Cortex-M and FPGA Development
Re: [C] Ow, pointers are making my brain hurt...
« Reply #57 on: November 14, 2021, 10:45:53 pm »
as reference, three different approaches
  • 6800 (only one CPU-register, therefore the ram is massively used)
  • 68k (eight registers for data, eight registers for address, compromise between stack and registers)
  • RISCV (31 registers, if the structure is small enough, it's passed via registers)
For those interested in the various arguments for and against, register and / or stack usage when implementing a programming language on CISC and RISC machines see
ETH Technical Report 174: The Oberon System Family

https://www.research-collection.ethz.ch/handle/20.500.11850/68908

It provides a detailed comparison of the various code-generation techniques used for the NS32000, MC68020, SPARC, MIPS, RS/6000 architectures to implement a portable Oberon compiler in the 1990's.
Chris Burrows
CFB Software
https://www.astrobe.com
 
The following users thanked this post: DiTBho

Offline brucehoult

  • Super Contributor
  • ***
  • Posts: 4036
  • Country: nz
Re: [C] Ow, pointers are making my brain hurt...
« Reply #58 on: November 15, 2021, 02:23:46 am »
For those interested in the various arguments for and against, register and / or stack usage when implementing a programming language on CISC and RISC machines see
ETH Technical Report 174: The Oberon System Family

https://www.research-collection.ethz.ch/handle/20.500.11850/68908

It provides a detailed comparison of the various code-generation techniques used for the NS32000, MC68020, SPARC, MIPS, RS/6000 architectures to implement a portable Oberon compiler in the 1990's.

I like Wirth's language designs in general, but especially Oberon. It's simplistic is good ways. The compiler generates quite decent code very very quickly.

Probably the most out of date thing in that paper (and compiler) is the idea that what the programmer calls a "variable" has a fixed location throughout execution of a function -- for example, the idea that a variable lives either in a particular register or at a particular place in the stack frame. Modern practice is to call it a new variable (an "SSA variable" or a "live range") every time it is assigned to -- and sometimes to split the live range at certain important points. All of which allows the register allocator to do a better job, sometimes at the cost of moving a value between memory and a register or between different registers. Conversely, of course, different variables with non-overlapping lifetimes can share the same register at different times.
 

Online SiliconWizard

  • Super Contributor
  • ***
  • Posts: 14475
  • Country: fr
Re: [C] Ow, pointers are making my brain hurt...
« Reply #59 on: November 15, 2021, 02:43:25 am »
Yes of course, it's a bit out-of-date in that area. And regarding register vs stack use, in the end they take a pretty simple approach, which is roughly to favor the stack for target processors with few general-purpose registers, and use registers more for those with more GP registers...

But otherwise yes, it's always a pleasure to read about anything Wirth has done or supervised.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf