Re: reason for having return addresses in parameter stack?
I was asleep when I posted this, so I left out the example code. Don't know why, but I worked out more complete code than the example I failed to give. To keep chatter off the list, I posted it in my blog, if anyone is interested. (Probably not?) http://defining-computers.blogspot.jp/2015/03/splitting-return-addresses-out-of.html -- Joel Rees On Mon, Mar 30, 2015 at 1:08 AM, Joel Rees joel.r...@gmail.com wrote: On Sun, Mar 29, 2015 at 2:50 PM, Philip Guenther guent...@gmail.com wrote: 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, I don't agree with those two assertions, but I'm not really looking at easy or efficient. I'm thinking about return pointers getting walked on. doesn't burn another register for a second stack, I've often pondered on whether the entire reason for having a frame pointer is that you have to have something to lead you around the return pointer. Still, there is no reason to keep the frame link in a register. Dump the saved parameter stack pointer on the flow-of-control stack, paired with the return pointer, and you're done. If you think even that is necessary. Or you could save the previous top of parameter stack below the local variables and temporaries on the parameter stack, which is a little more fragile, if you really want to make it appear to be a linked list. and the ISA (instruction set architecture) may have direct support for it. Looking at all the funky instructions and addressing modes the 68020 and 80286 and 80386 directly supported, but got left behind as CPU advanced, direct instruction support really isn't an argument, to me. 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. Yeah, it does feel like a waste not to use the instructions provided, doesn't it? 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? Well, if we link the frame on one of the stacks instead of in a register, the erstwhile frame pointer register isn't doing anything in particular any more. On i386, you're crying for registers already; losing another would be bad. Back when SP and BP were sixteen bits, and pointed into the same segment unless overridden, there was definitely something unsettling about using them independently, but if you consider that the 6809 was even more restricted in stack space when you used SP and UP for two separate stacks, you remember that, even now, most stacks aren't that big anyway. But that was then, this is now, and %sp and %bp aren't sixteen bits any more. We can define regions that cause access exceptions to help us know when our stacks and heaps collide. And are we still even using the segment registers? I know older MMUs are kind of tight on the number of page tables you can keep active, but are they that tight? This is one of my questions, by the way. 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. My impression was that the register stack backing store was assumed to be allocated with the rest of the procedure frame in the memory stack, but the documentation seems to have been written by lawyers who really didn't want their end users to be able to pierce the patent haze. I couldn't say for sure, and I never had actual hardware to check against, and I really don't want to dig into that dinosaur any more. Intel has always made things harder than necessary. 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. You won't hear me argue with you there. But default to a quarter gig of unallocated logical address space below each stack and only a tiny fraction of programs would need to change that. 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? Well, yeah, I think so. I doubt it. To support exception processing and
Re: reason for having return addresses in parameter stack?
On Sun, Mar 29, 2015 at 2:50 PM, Philip Guenther guent...@gmail.com wrote: 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, I don't agree with those two assertions, but I'm not really looking at easy or efficient. I'm thinking about return pointers getting walked on. doesn't burn another register for a second stack, I've often pondered on whether the entire reason for having a frame pointer is that you have to have something to lead you around the return pointer. Still, there is no reason to keep the frame link in a register. Dump the saved parameter stack pointer on the flow-of-control stack, paired with the return pointer, and you're done. If you think even that is necessary. Or you could save the previous top of parameter stack below the local variables and temporaries on the parameter stack, which is a little more fragile, if you really want to make it appear to be a linked list. and the ISA (instruction set architecture) may have direct support for it. Looking at all the funky instructions and addressing modes the 68020 and 80286 and 80386 directly supported, but got left behind as CPU advanced, direct instruction support really isn't an argument, to me. 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. Yeah, it does feel like a waste not to use the instructions provided, doesn't it? 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? Well, if we link the frame on one of the stacks instead of in a register, the erstwhile frame pointer register isn't doing anything in particular any more. On i386, you're crying for registers already; losing another would be bad. Back when SP and BP were sixteen bits, and pointed into the same segment unless overridden, there was definitely something unsettling about using them independently, but if you consider that the 6809 was even more restricted in stack space when you used SP and UP for two separate stacks, you remember that, even now, most stacks aren't that big anyway. But that was then, this is now, and %sp and %bp aren't sixteen bits any more. We can define regions that cause access exceptions to help us know when our stacks and heaps collide. And are we still even using the segment registers? I know older MMUs are kind of tight on the number of page tables you can keep active, but are they that tight? This is one of my questions, by the way. 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. My impression was that the register stack backing store was assumed to be allocated with the rest of the procedure frame in the memory stack, but the documentation seems to have been written by lawyers who really didn't want their end users to be able to pierce the patent haze. I couldn't say for sure, and I never had actual hardware to check against, and I really don't want to dig into that dinosaur any more. Intel has always made things harder than necessary. 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. You won't hear me argue with you there. But default to a quarter gig of unallocated logical address space below each stack and only a tiny fraction of programs would need to change that. 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? Well, yeah, I think so. 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. On the caller side, push your arguments, perform an unadorned call. Something like SUB SP, parameterbytes On the called side, if the frame is being maintained, save the parameter stack pointer on the flow-of-control stack. Do your stuff. When you're done, if the compiler knows what it has on the stack anyway, you
Re: reason for having return addresses in parameter stack?
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.
reason for having return addresses in parameter stack?
This is a question that has bothered me for more than twenty-five years. Blame it on my being one of those forthies, I guess. Recent posts encourage me to ask again. 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. 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. 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. 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? Or am I speculating about a different world, still? Joel Rees Computer memory is just fancy paper, CPUs just fancy pens. All is a stream of text flowing from the past into the future.