udem-dlteam / pnut

🥜 A Self-Compiling C Transpiler Targeting Human-Readable POSIX Shell
https://pnut.sh
BSD 2-Clause "Simplified" License
425 stars 14 forks source link

Labelled statements and goto support #17

Closed laurenthuberdeau closed 6 months ago

laurenthuberdeau commented 6 months ago

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.

laurenthuberdeau commented 6 months ago

Testing

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