Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle Duff's device and other unstructured switch statements #459

Merged
merged 5 commits into from
Nov 9, 2022

Conversation

xavierleroy
Copy link
Contributor

This PR introduces a new (unverified) elaboration pass, SwitchNorm, that recognizes structured switch statements and puts them in a normalized form. If selected (language support option -funstructured-switch), other switch statements are turned into a structured switch with goto actions, followed by the original switch body with appropriate labels and goto.

For example, Duff's infamous code

  switch (count % 8) {
    case 0: do { *to++ = *from++;
    case 7:      *to++ = *from++;
    case 6:      *to++ = *from++;
    case 5:      *to++ = *from++;
    case 4:      *to++ = *from++;
    case 3:      *to++ = *from++;
    case 2:      *to++ = *from++;
    case 1:      *to++ = *from++;
            } while (--n > 0);
  }

becomes

  switch (count % 8) {
    default:   goto @9;
    case 0:    goto @1;
    case 7:    goto @2;
    case 6:    goto @3;
    case 5:    goto @4;
    case 4:    goto @5;
    case 3:    goto @6;
    case 2:    goto @7;
    case 1:    goto @8;
  }
  @1:
  do {
    *to++ = *from++;
    @2:    *to++ = *from++;
    @3:    *to++ = *from++;
    @4:    *to++ = *from++;
    @5:    *to++ = *from++;
    @6:    *to++ = *from++;
    @7:    *to++ = *from++;
    @8:    *to++ = *from++;
  } while(--n > 0);
  @9:  /*skip*/;

Other examples can be found in test/regression/switch3.c.

xavierleroy and others added 5 commits September 27, 2022 12:04
Instead of passing a string that encodes the optional source-to-source
transformations to perform, just pass one optional, named argument for
each transformation.  It is clearer and easier to extend this way.
This ensures that normalized switch statements remain normalized.
However, if the label and the labeled statement are on different lines,
add an extra line directive corresponding to the label before the labeled
statement.
- New elaboration pass: SwitchNorm
    - recognizes structured 'switch' statements and puts them in a
      normalized form;
    - if selected, transforms unstructured 'switch' statements into a
      structured switch with goto actions + the original switch body
      with appropriate labels and gotos.

- C2C treatment of 'switch' statements is simplified accordingly.

- New language support option `-funstructured-switch`.

- Some tests were added (test/regression/switch3.c).
…on, `-finput-charset` and other small fixes)
This can occur in debug mode if there are declarations before the
first case, as in
```
  switch (x) {
    int x;
   case 0:
    ...
  }
```
Without this commit, the code above is a structured switch if -g is not given,
and a non-structured switch if -g is given.

Co-authored-by: Michael Schmidt <github@mschmidt.me>
@xavierleroy xavierleroy merged commit abe1f24 into master Nov 9, 2022
@xavierleroy xavierleroy deleted the full-switch branch November 9, 2022 16:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants