summaryrefslogtreecommitdiff
path: root/src/ir/properties.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/ir/properties.h')
-rw-r--r--src/ir/properties.h36
1 files changed, 36 insertions, 0 deletions
diff --git a/src/ir/properties.h b/src/ir/properties.h
index 7cbbe73f0..6848e9481 100644
--- a/src/ir/properties.h
+++ b/src/ir/properties.h
@@ -146,6 +146,42 @@ inline Index getZeroExtBits(Expression* curr) {
return Bits::getMaskedBits(curr->cast<Binary>()->right->cast<Const>()->value.geti32());
}
+// Returns a falling-through value, that is, it looks through a tee_local
+// and other operations that receive a value and let it flow through them.
+inline Expression* getFallthrough(Expression* curr) {
+ // If the current node is unreachable, there is no value
+ // falling through.
+ if (curr->type == unreachable) {
+ return curr;
+ }
+ if (auto* set = curr->dynCast<SetLocal>()) {
+ if (set->isTee()) {
+ return getFallthrough(set->value);
+ }
+ } else if (auto* block = curr->dynCast<Block>()) {
+ // if no name, we can't be broken to, and then can look at the fallthrough
+ if (!block->name.is() && block->list.size() > 0) {
+ return getFallthrough(block->list.back());
+ }
+ } else if (auto* loop = curr->dynCast<Loop>()) {
+ return getFallthrough(loop->body);
+ } else if (auto* iff = curr->dynCast<If>()) {
+ if (iff->ifFalse) {
+ // Perhaps just one of the two actually returns.
+ if (iff->ifTrue->type == unreachable) {
+ return getFallthrough(iff->ifFalse);
+ } else if (iff->ifFalse->type == unreachable) {
+ return getFallthrough(iff->ifTrue);
+ }
+ }
+ } else if (auto* br = curr->dynCast<Break>()) {
+ if (br->condition && br->value) {
+ return getFallthrough(br->value);
+ }
+ }
+ return curr;
+}
+
} // Properties
} // wasm