Poppy IR wast parsing and validation#3105
Conversation
Adds and IR Profile to each function so the validator can determine which validation rules to apply and adds an flag to have the wast parser set the profile to Poppy for testing purposes.
|
Is this the same as the PR on your fork from earlier? If so I wonder if this could have been a PR relative to a branch, which is then redirected? That would preserve comments and remember seen files and so forth. |
AFAIK this is possible only if the base branch is in the main repo and not a fork. So it's possible for people who have the write access to the repo. When you create a PR you can make it based on a branch, and you can change that base branch later. |
|
Yes, this is the same PR from before, with comments addressed. I guess I could make branches on the main repo in the future, but that's not my usual workflow :( |
|
Is it not possible to have all the branches on your fork as you always do, and one is relative to the other? You can adjust the target branch and I'm hoping that includes that the target branch is on a fork versus the main repo. |
| bool mayBeUnreachable(Expression* expr) { | ||
| if (Properties::isControlFlowStructure(expr)) { | ||
| return true; | ||
| } |
There was a problem hiding this comment.
Can't this use StackSignature and precisely compute whether it is really unreachable or not?
There was a problem hiding this comment.
We can use StackSignature (or just look at expr->type) to figure out if it is unreachable, but what we want to do in this function is determine if it is allowed to be unreachable.
| // unreachable behavior in WebAssembly may have unreachable type. Blocks may | ||
| // be unreachable when they are not branch targets and when they have an | ||
| // unreachable child. Note that this means a block may be unreachable even | ||
| // if it would otherwise have a concrete type, unlike in Binaryen IR. |
There was a problem hiding this comment.
Where do we do this? Poppy IR doesn't seem to have its own Block::finalize() or something and it shares the parser with Binaryen IR, aren't block types in Poppy IR assigned in the same way as that of Binaryen IR?
There was a problem hiding this comment.
Eventually we will need to add alternate logic to Block::finalize() to handle Poppy IR. The reason I haven't done this yet is because the parser only calls Block::finalize(Type), so none of the tests call Block::finalize(), so we would have no test coverage. The next PR will add the stackification pass, which will call refinalize, so I will implement this with test coverage then.
There was a problem hiding this comment.
For example,
(block (result i32)
(unreachable)
)According to your explanation, this block's type will be i32 in Binaryen IR and unreachable in Poppy IR. This block has a result type so Block::finalize(type) will be called. But the current Block::finalize(type) respects the type given as the argument and does not check instructions inside for unreachables, no?
What I meant was, as you said, given that we only use Block::finalize(type) for now, how we determine the unreachability of a block will be the same for Binaryen IR and Poppy IR, so this comments block does not seem to match the current implementation. I think I might be missing something.
There was a problem hiding this comment.
In both Binaryen IR and Poppy IR, the block in your example can have either i32 or unreachable as its type. In Binaryen IR, the parser will give it i32 type and subsequent optimizations will change it to have unreachable type. In Poppy IR, the parser will similarly give it i32 type, but we don't yet have any code that will change the type to unreachable (even though that would be allowed).
The difference between Poppy IR and Binaryen IR is in a block like this:
(block
(unreachable)
(i32.const 0)
)
In Binaryen IR, it would be illegal for that block to have unreachable type, but in Poppy IR it could still have either unreachable or i32 type.
There was a problem hiding this comment.
I see, thanks. Is there any particular reason for this distinction?
There was a problem hiding this comment.
Yes, it has to do with type inference in Poppy IR, which we don't do in Binaryen IR. Consider the following function:
(func (result i32)
(block $body
(unreachable)
(i32.const 0)
)
)
Binaryen IR unconditionally gives unreachable blocks none type when writing them out, so if $body were allowed to be unreachable in Binaryen IR, there resulting binary would be invalid. In contrast, Poppy IR does type inference before emitting binaries, which correctly gives $body an i32 type.
No, I just verified that this is not possible. I can retarget the PR, but only to branches on the same fork of the repo. This makes sense because retargeting a PR to a different fork would essentially move it to that fork and assign it a new number, so the PR would lose its identity. Edit: Just saw that Heejin tried the same thing. |
| // unreachable behavior in WebAssembly may have unreachable type. Blocks may | ||
| // be unreachable when they are not branch targets and when they have an | ||
| // unreachable child. Note that this means a block may be unreachable even | ||
| // if it would otherwise have a concrete type, unlike in Binaryen IR. |
There was a problem hiding this comment.
I see, thanks. Is there any particular reason for this distinction?
|
|
||
| // Whether `expr` may be unreachable in Poppy IR. True for control flow | ||
| // structures and polymorphic unreachable instructions. | ||
| bool mayBeUnreachable(Expression* expr); |
There was a problem hiding this comment.
I still think my comment about this is relevant: tlively#1 (comment)
The comment here doesn't clearly say which of the two cases it is IMO. If it is "not exited normally" or such, that might be good to clarify?
There was a problem hiding this comment.
I mean, is "unreachable" here referring to a type in the type system, or to a particular property, etc.

Adds an IR Profile to each function so the validator can determine
which validation rules to apply and adds a flag to have the wast
parser set the profile to Poppy for testing purposes. See #3059.