On Sun, 29 Mar 2015, Joel Rees wrote:
> Is there any good reason for interleaving the return addresses with data 
> on the data/parameter stack in C? I know it's the tradition, from back 
> when it was all we could hope for to have one page per process, but that 
> has not been the case for many years, I think.

It's easy, efficient, doesn't burn another register for a second stack, 
and the ISA (instruction set architecture) may have direct support for it.

For example, in both i386 and x86_64 the 'call' and 'ret' instructions 
work with the same stack pointer, %sp, as the various 'push' and 'pop' 
instructions.  If you use %sp for the stack with return addresses so you 
can use 'call' and 'ret', then what is stack pointer for your 
arguments/locals stack?  On i386, you're crying for registers already; 
losing another would be bad.

Hmm, wasn't there a shipping processor which explicitly have two stacks 
something like this?  I have a vague memory that it may have been itanium, 
but that could be a hallucination.


> Adding code to the program preamble to reserve space for another stack 
> with mmap shouldn't be hard at all. Default address separation of about 
> a quarter to a half a gig should be reasonable in 32 bit address space, 
> at any rate. New compiler switches would be needed to tune the 
> separation. I'm pretty sure openbsd has the means to keep a largish 
> no-access region between the stacks.

Ugh, knobs are bad if more than a tiny fraction of program have to use 
them.


> The call protocol itself should be simpler, although I might expect some 
> debate about which stack to push frame pointers to when pushing frame 
> pointers. The problem, I think, is in convincing the compiler to refrain 
> from moving the frame pointer to the stack pointer on function entry. 
> Maybe.

Simpler?  I doubt it.  To support exception processing and debugger 
unwinding of calls and displaying variables from them you'll need some way 
to successively peel call frames off *both* stacks.

> 
> To those on the list who are intimate with the compiler(s), how difficult
> would it be to change the function call protocol to push the program
> counter to a separate stack from the parameters and locals?

Heh, you're talking about creating a new ABI.  For difficultly level, look 
at the x32 ABI in Linux.  It's an alternative ABI for x86-long-mode, 
changing relatively few things from the amd64/x86_64 ABI, and it still 
took a huge effort.

You might want to grab a copy of the ELF ABI for a CPU you're interested 
in, read through it and see what sort of changes would be necessary for 
supporting a two-stack model.  Example code sequences for argument 
passing, relocations, stack unrolling, registers set on process entry,...


Oooh, and then threads come into play, where programs expect to be able to 
specify a single size for the stack, so maybe you should have the two 
stacks grow towards each other from opposite ends of the allocated stack 
memory?


> Or am I speculating about a different world, still?

Tomorrow is a different world, but only slightly so.

Reply via email to