Close

SSS : the Single-Stack Syndrome

A project log for POSEVEN

A programming model for languages and "application processors", that emphasises speed, safety, security and modularity.

yann-guidon-ygdesYann Guidon / YGDES 09/08/2023 at 17:200 Comments

I remember as a teen, knowing BASIC and PASCAL, I explored the weird world of the 8086 so I could program it efficiently. And I was, and still am, scratching my head over (among other things) the concept of the stack as it was implemented by this CPU...

I knew about stacks already, being familiar with the 6809. Stacks are cool and great. But the 8086 implements frames and contrived, uselessly elaborated. And you know what ? Stacks are one of the main weaknesses of x86, particularly when coupled with C's unbound and unchecked array, it's a highway to bugs.

Stacks are one of the most fundamental structures in computer science and has been studied to death. Having a curiosity of FORTH, I know that a single stack is not a fatality as there are other programming languages with more than one. Indeed FORTH was creating on a computer featuring two stacks. Some languages also implement their own split stack under the hood. And that's very fine. So what happened ?

Well, C happened more than 50 years ago and started on a PDP-7. Belonging to a certain tradition and having to run on tightly limited resources, having only one stack was a compromise that worked well enough for the time, the constraints, so it spread wildly and even overcame PASCAL.

The single stack has one major problem in C : you can't return composite variables on the stack so function must resort to pointers and other stupid workarounds, which makes C a development hell once you go beyond the basic examples. The standard libs are a freak show. And I won't rant again about the insanity that comes from mixing control and variables data.

The thing is : C structures (and the SSS) crystalized in many subsequent designs. Worse : it underpins modern compilers and processor architectures ! The syndrome turns into a plague.


So...

The NPM defines a strict split structure that separates data from control values.

This is expanded in the sub-project #A stack.

This is a way to get both safety (the control stack can't be tampered with by data injection, only by modifying the read-only program) and performance (since separate access increases the ILP and there are fewer indirections due to programming kludges). The user can optimise the data stack(s) at will and even not use one when unneeded. The user stacks can grow up or down, be allocated dynamically...

OTOH the control stack enforces security by using tagged values that define the type of the stack's contents. This is discussed at https://hackaday.io/project/8774-f-cpu/log/222000-tagged-control-stack and will certainly expand. This tagged control stack (TCS ?) can mix critical information of the program's flow state, including error handling, inter- and intra- modules calls, or even outer loops. However registers and other states must be saved through the normal datapath : apart from the Instruction Pointer, there is no provision to save the other states on the TCS, whose name implies it's only for control.

Saving the state of the other data can be performed explicitly by code sequences and/or specific instructions. NPM/POSEVEN does not specify context switches.

Discussions