|
|
Fixes #527
There were a few problem cases for the IR emit logic. The most obvious, which came up in #527 is that a function body with multiple `return` statements would generate invalid code:
```hlsl
int foo()
{
return 1;
int x = 2;
return x;
}
```
In that case the IR for `foo` would have a single block that has two `return` instructions, which is invalid.
Another case that seems to be arising more often, but that had less obvious consequences was when one arm of an `if` statement ends in a `return`:
```hlsl
if(a)
{
return b;
}
else
{
int c = 0;
}
int d = 0;
```
In that case, the `return` instruction for `return b` would be followed by a branch to the end of the `if` (the `int d = 0;` line), because that would be the normal control flow without the early `return`.
The fix implemented here is to have the IR lowering logic be a bit more careful on two fronts:
1. When emitting a branch, check if the block we are emitting into has already been terminated, and if so just don't emit the branch (since we are logically at an unreachable point in the CFG.
2. Whenever we are about to emit code for a (non-empty) statement, ensure that the current block being build is unterminated. If the current block is terminated, then start a new one.
Case (2) will only matter when there is unreachable code (e.g., in the function `foo()`, the declaration of `x` and the second `return` can never be reached), so I added a warning in that case, and included a test case that triggers the new warning (with a function like `foo()` above).
|