Skip to content

Fix block-nested Pop in GUFA#8747

Open
tlively wants to merge 1 commit into
mainfrom
fix-gufa-pop-validation
Open

Fix block-nested Pop in GUFA#8747
tlively wants to merge 1 commit into
mainfrom
fix-gufa-pop-validation

Conversation

@tlively
Copy link
Copy Markdown
Member

@tlively tlively commented May 21, 2026

In GUFA, when optimizing RefEq or RefTest expressions, they are replaced by constants if the optimizer can prove the two sides have no intersection. However, if the expression contains side effects (like a Pop), getDroppedChildrenAndAppend is used to preserve them, which wraps the side-effect expressions in a Block.

If the Pop is nested inside this Block, it becomes invalidly nested within the catch block, which violates validation rules. GUFA has a fixup pass (EHUtils::handleBlockNestedPops) designed to fix this by spilling the Pop to a local, but it was not being run because visitRefEq and visitRefTest failed to set the optimized = true flag.

Fix the issue by setting optimized = true when RefEq or RefTest are optimized, ensuring the post-optimization cleanups (including the nested pop fixup) are executed.

Add a regression test to gufa-cast-all.wast.

In GUFA, when optimizing RefEq or RefTest expressions, they are replaced by constants if the optimizer can prove the two sides have no intersection. However, if the expression contains side effects (like a Pop), getDroppedChildrenAndAppend is used to preserve them, which wraps the side-effect expressions in a Block.

If the Pop is nested inside this Block, it becomes invalidly nested within the catch block, which violates validation rules. GUFA has a fixup pass (EHUtils::handleBlockNestedPops) designed to fix this by spilling the Pop to a local, but it was not being run because visitRefEq and visitRefTest failed to set the `optimized = true` flag.

Fix the issue by setting `optimized = true` when RefEq or RefTest are optimized, ensuring the post-optimization cleanups (including the nested pop fixup) are executed.

Add a regression test to gufa-cast-all.wast.
@tlively tlively requested a review from a team as a code owner May 21, 2026 04:59
@tlively tlively requested review from stevenfontanella and removed request for a team May 21, 2026 04:59
Comment thread src/passes/GUFA.cpp
auto* result = Builder(*getModule()).makeConst(Literal(int32_t(0)));
replaceCurrent(getDroppedChildrenAndAppend(
curr, *getModule(), getPassOptions(), result));
optimized = true;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This pass has an override for replaceCurrent, I wonder if we should have that method set optimized by default so that we don't forget other cases? It seems like after this PR, all usages of replaceCurrent set optimized to true. I don't have a strong opinion, I can imagine there might be cases where we don't want to set it to true unintentionally too.

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