Closed laurenthuberdeau closed 6 months ago
Tested both forward and backward gotos, with differing frame size between source and destinations:
void putstr(char* str) {
while (*str) {
putchar(*str);
str++;
}
}
void putint_aux(int n) {
if (n <= -10) putint_aux(n / 10);
putchar('0' - (n % 10));
}
void putint(int n) {
if (n < 0) {
putchar('-');
putint_aux(n);
} else {
putint_aux(-n);
}
}
void main() {
int i = 100;
goto skip_first_decrement;
while (i--) {
skip_first_decrement:
i = i;
int j = i;
goto pong;
ping:
if (j % 7 == 0) {
goto clean_up;
after_clean_up:
break;
}
putstr("Next! i: "); putint(i); putchar('\n');
}
return;
{
int j;
int k;
int l;
int m;
pong:
putstr("Value of j: "); putint(j); putchar('\n');
putstr("Value of k: "); putint(k); putchar('\n');
putstr("Value of l: "); putint(l); putchar('\n');
goto ping;
}
clean_up:
putstr("Cleaning up\n");
goto after_clean_up;
}
This print:
> gcc -o pnut.exe -Di386 pnut.c && ./pnut.exe < gotos.c > gotos.exe
> ./gotos.exe
Value of j: 100
Value of k: 100
Value of l: 0
Next! i: 100
Value of j: 99
Value of k: 99
Value of l: 99
Next! i: 99
Value of j: 98
Value of k: 98
Value of l: 98
Cleaning up
Context
Most TCC versions use labelled statement and gotos. This PR adds support for them, using the existing label mechanism to patch up the destination address and for adjusting stack pointer based on the the source and destination frame sizes.
Shell backend
While gotos could possibly be implemented in shell using some sort of trampoline, the resulting code would be unreadable. Because our objective is readability above all, and pnut-exe will not use gotos, they are not needed for our use case and are not supported.