Wednesday, April 6, 2022

[SOLVED] marking a function dirty (specifying that caller should save all registers)

Issue

I have a function f() that destroys all registers across the function call, except the stack pointer. How can I convey this to gcc, so that the caller will save all registers it wants to save, before calling f()?

EDIT: I'm writing a coroutine handler, which needs to save state before switching to another coroutine and I'd like to save the minimum state possible. Say we have a function yield(), marked as "dirty", destroying everything except the stack pointer. This function will magically return after control returns to our coroutine, but it would be best if the caller, not the callee (since the caller knows best which registers it needs saved) would save all registers it needs to save before calling yield() and then restore them afterwards.


Solution

The idea violates the principle of least astonishment and therefore should be avoided.

As a caller, I wouldn't expect to have to worry about register contents when calling a function. Furthermore, if you want the caller to handle it, why not handle it inside of f()? Not only will callers not need to be aware, you only need one implementation. With what you're proposing, each caller would need to handle saving/restoring the context, which is likely very error prone.

The basic solution could use RAII to handle this in f(). Something like:

class ContextGuard {
  public:
    // Stores the current context
    ContextGuard() { ... }
    // Restores the current context
    ~ContextGuard() { ... }
  private:
     ...
};

...

void f() {
   ContextGuard contextGuard; // Saves the current context
   ... // Do stuff that mucks with the registers
} <-- contextGuard is destroyed here and the context is restored.

How to handle storing/restoring the context is another matter. Boost.Context may provide you with what you need.

One final point, beyond the stack pointer, there's some other intricacies with respect to registers as well. You'll need to take platform-specific function calling conventions into account here, possibly among other factors. If you are mucking with registers in such a way that you think they need to be restored, you're going to have to really understand the intricacies of all platforms you intend to run this code on.



Answered By - Avi
Answer Checked By - Cary Denson (WPSolving Admin)