Working on a small embedded system, I wanted to experiment with something like C coroutines that you find implemented with switch/case/macro constructs and gcc’s labels as values extension. So I came up with some structures and functions and a pattern so that I could write functions like the following (just a test/example function):
void fiber1(FiberContext *fiber)
{
if (fiber->restore) goto fiber->restore; // initial jump if called for
stateA:
printf("Fiber 1: A state\n");
fiber->misc = &&stateB;
fiber->restore = &&sleep;
return;
stateB:
printf("Fiber 1: A state\n");
fiber->misc = &&stateA;
fiber->restore = &&sleep;
return;
sleep:
fiberSleepTicks(fiber, 1000000);
fiber->restore = fiber->misc ? fiber->misc : &&stateA;
return;
}
However GCC does not like the original goto fiber->restore (restore is a void* member of a FiberContext). My thought had been that basically, I would capture the label to jump to when I returned in an external structure, leave the function, and then come back and jump to the new label.
I think, what I’ve concluded is that GCC doesn’t know how to do that, because the && operator produces an absolute jump address, not one that is relative to the current function stack. So I wouldn’t be able to safely reuse it, because there’s nothing to say I wouldn’t call this function with different stack depths.
So my question is twofold basically. Am I right in my understanding in why it won’t work/compile? OR is it something else, and if so, what am I doing wrong with this feature? I’m compiling with just gcc -std=gnu99.
Try
See
http://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html
Also, the stack depth does not matter for the function code address – only shared library relocations do (the page above also explains how to do that nicely).