diff options
Diffstat (limited to 'src/ir/possible-contents.cpp')
-rw-r--r-- | src/ir/possible-contents.cpp | 34 |
1 files changed, 32 insertions, 2 deletions
diff --git a/src/ir/possible-contents.cpp b/src/ir/possible-contents.cpp index e7454c7c6..e5e6cf659 100644 --- a/src/ir/possible-contents.cpp +++ b/src/ir/possible-contents.cpp @@ -1135,8 +1135,38 @@ struct InfoCollector } } void visitTryTable(TryTable* curr) { - // TODO: optimize when possible - addRoot(curr); + receiveChildValue(curr->body, curr); + + // Connect caught tags with their branch targets, and materialize non-null + // exnref values. + auto numTags = curr->catchTags.size(); + for (Index tagIndex = 0; tagIndex < numTags; tagIndex++) { + auto tag = curr->catchTags[tagIndex]; + auto target = curr->catchDests[tagIndex]; + + Index exnrefIndex = 0; + if (tag.is()) { + auto params = getModule()->getTag(tag)->sig.params; + + for (Index i = 0; i < params.size(); i++) { + if (isRelevant(params[i])) { + info.links.push_back( + {TagLocation{tag, i}, + BreakTargetLocation{getFunction(), target, i}}); + } + } + + exnrefIndex = params.size(); + } + + if (curr->catchRefs[tagIndex]) { + auto location = CaughtExnRefLocation{}; + addRoot(location, + PossibleContents::fromType(Type(HeapType::exn, NonNullable))); + info.links.push_back( + {location, BreakTargetLocation{getFunction(), target, exnrefIndex}}); + } + } } void visitThrow(Throw* curr) { auto& operands = curr->operands; |